1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/ozone/platform/caca/caca_event_factory.h"
10 #include "base/message_loop/message_loop.h"
11 #include "ui/events/event.h"
12 #include "ui/events/keycodes/keyboard_codes.h"
13 #include "ui/ozone/platform/caca/caca_connection.h"
19 ui::KeyboardCode
GetKeyboardCode(const caca_event_t
& event
) {
20 // List of special mappings the Caca provides.
21 static const ui::KeyboardCode kCacaKeyMap
[] = {
74 int key_code
= caca_get_event_key_ch(&event
);
75 if (key_code
>= 'a' && key_code
<= 'z')
76 return static_cast<ui::KeyboardCode
>(key_code
- ('a' - 'A'));
77 if (key_code
>= '0' && key_code
<= 'Z')
78 return static_cast<ui::KeyboardCode
>(key_code
);
79 if (static_cast<unsigned int>(key_code
) < arraysize(kCacaKeyMap
))
80 return kCacaKeyMap
[key_code
];
82 return ui::VKEY_UNKNOWN
;
85 int ModifierFromKey(const caca_event_t
& event
) {
86 int key_code
= caca_get_event_key_ch(&event
);
87 if (key_code
>= 'A' && key_code
<= 'Z')
88 return ui::EF_SHIFT_DOWN
;
89 if ((key_code
>= CACA_KEY_CTRL_A
&& key_code
<= CACA_KEY_CTRL_G
) ||
90 (key_code
>= CACA_KEY_CTRL_J
&& key_code
<= CACA_KEY_CTRL_L
) ||
91 (key_code
>= CACA_KEY_CTRL_N
&& key_code
<= CACA_KEY_CTRL_R
) ||
92 (key_code
>= CACA_KEY_CTRL_T
&& key_code
<= CACA_KEY_CTRL_Z
))
93 return ui::EF_CONTROL_DOWN
;
98 int ModifierFromButton(const caca_event_t
& event
) {
99 switch (caca_get_event_mouse_button(&event
)) {
101 return ui::EF_LEFT_MOUSE_BUTTON
;
103 return ui::EF_RIGHT_MOUSE_BUTTON
;
105 return ui::EF_MIDDLE_MOUSE_BUTTON
;
110 // Translate coordinates to bitmap coordinates.
111 gfx::PointF
TranslateLocation(const gfx::PointF
& location
,
112 CacaConnection
* connection
) {
113 gfx::Size physical_size
= connection
->physical_size();
114 gfx::Size bitmap_size
= connection
->bitmap_size();
116 location
.x() * bitmap_size
.width() / physical_size
.width(),
117 location
.y() * bitmap_size
.height() / physical_size
.height());
120 ui::EventType
GetEventTypeFromNative(const caca_event_t
& event
) {
121 switch (caca_get_event_type(&event
)) {
122 case CACA_EVENT_KEY_PRESS
:
123 return ui::ET_KEY_PRESSED
;
124 case CACA_EVENT_KEY_RELEASE
:
125 return ui::ET_KEY_RELEASED
;
126 case CACA_EVENT_MOUSE_PRESS
:
127 return ui::ET_MOUSE_PRESSED
;
128 case CACA_EVENT_MOUSE_RELEASE
:
129 return ui::ET_MOUSE_RELEASED
;
130 case CACA_EVENT_MOUSE_MOTION
:
131 return ui::ET_MOUSE_MOVED
;
133 return ui::ET_UNKNOWN
;
139 CacaEventFactory::CacaEventFactory(CacaConnection
* connection
)
140 : connection_(connection
),
141 weak_ptr_factory_(this),
142 delay_(base::TimeDelta::FromMilliseconds(10)),
146 CacaEventFactory::~CacaEventFactory() {
149 void CacaEventFactory::WarpCursorTo(gfx::AcceleratedWidget widget
,
150 const gfx::PointF
& location
) {
154 void CacaEventFactory::OnDispatcherListChanged() {
155 ScheduleEventProcessing();
158 void CacaEventFactory::ScheduleEventProcessing() {
159 // Caca uses a poll based event retrieval. Since we don't want to block we'd
160 // either need to spin up a new thread or just poll. For simplicity just poll
161 // for a message every |delay_| time delta.
162 base::MessageLoop::current()->PostDelayedTask(
164 base::Bind(&CacaEventFactory::TryProcessingEvent
,
165 weak_ptr_factory_
.GetWeakPtr()),
169 void CacaEventFactory::TryProcessingEvent() {
171 int event_mask
= CACA_EVENT_KEY_PRESS
| CACA_EVENT_KEY_RELEASE
|
172 CACA_EVENT_MOUSE_PRESS
| CACA_EVENT_MOUSE_RELEASE
|
173 CACA_EVENT_MOUSE_MOTION
;
174 if (connection_
->display() &&
175 caca_get_event(connection_
->display(), event_mask
, &event
, 0)) {
177 ui::EventType type
= GetEventTypeFromNative(event
);
178 bool pressed
= type
== ui::ET_KEY_PRESSED
|| type
== ui::ET_MOUSE_PRESSED
;
181 case ui::ET_KEY_PRESSED
:
182 case ui::ET_KEY_RELEASED
: {
184 modifier_flags_
|= ModifierFromKey(event
);
186 modifier_flags_
&= ~ModifierFromKey(event
);
188 ui::KeyEvent
key_event(
189 type
, GetKeyboardCode(event
), modifier_flags_
, true);
190 DispatchEvent(&key_event
);
193 case ui::ET_MOUSE_MOVED
:
194 last_cursor_location_
.SetPoint(caca_get_event_mouse_x(&event
),
195 caca_get_event_mouse_y(&event
));
196 // Update cursor location.
197 caca_gotoxy(caca_get_canvas(connection_
->display()),
198 last_cursor_location_
.x(),
199 last_cursor_location_
.y());
201 case ui::ET_MOUSE_PRESSED
:
202 case ui::ET_MOUSE_RELEASED
: {
204 int changed_flags
= 0;
205 if (type
!= ui::ET_MOUSE_MOVED
) {
207 changed_flags
= ModifierFromButton(event
);
208 modifier_flags_
|= changed_flags
;
210 modifier_flags_
&= ~changed_flags
;
212 // On release the button pressed is removed from |modifier_flags_|,
213 // but sending the event needs it set.
214 flags
= modifier_flags_
| changed_flags
;
216 gfx::PointF location
= TranslateLocation(last_cursor_location_
,
218 ui::MouseEvent
mouse_event(
219 type
, location
, location
, flags
, changed_flags
);
220 DispatchEvent(&mouse_event
);
229 ScheduleEventProcessing();