1 // Copyright (c) 2012 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/events/event_constants.h"
9 #include <X11/extensions/XInput.h>
10 #include <X11/extensions/XInput2.h>
12 #include <X11/Xutil.h>
13 #include <X11/XKBlib.h>
15 #include "base/logging.h"
16 #include "base/memory/singleton.h"
17 #include "ui/events/event.h"
18 #include "ui/events/event_utils.h"
19 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
20 #include "ui/events/x/device_data_manager_x11.h"
21 #include "ui/events/x/device_list_cache_x.h"
22 #include "ui/events/x/touch_factory_x11.h"
23 #include "ui/gfx/display.h"
24 #include "ui/gfx/point.h"
25 #include "ui/gfx/rect.h"
26 #include "ui/gfx/screen.h"
27 #include "ui/gfx/x/x11_atom_cache.h"
28 #include "ui/gfx/x/x11_types.h"
32 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
33 const int kWheelScrollAmount
= 53;
35 const int kMinWheelButton
= 4;
36 const int kMaxWheelButton
= 7;
38 // A class to track current modifier state on master device. Only track ctrl,
39 // alt, shift and caps lock keys currently. The tracked state can then be used
40 // by floating device.
41 class XModifierStateWatcher
{
43 static XModifierStateWatcher
* GetInstance() {
44 return Singleton
<XModifierStateWatcher
>::get();
47 int StateFromKeyboardCode(ui::KeyboardCode keyboard_code
) {
48 switch (keyboard_code
) {
49 case ui::VKEY_CONTROL
:
55 case ui::VKEY_CAPITAL
:
62 void UpdateStateFromXEvent(const base::NativeEvent
& native_event
) {
63 ui::KeyboardCode keyboard_code
= ui::KeyboardCodeFromNative(native_event
);
64 unsigned int mask
= StateFromKeyboardCode(keyboard_code
);
65 // Floating device can't access the modifer state from master device.
66 // We need to track the states of modifier keys in a singleton for
67 // floating devices such as touch screen. Issue 106426 is one example
68 // of why we need the modifier states for floating device.
69 switch (native_event
->type
) {
71 state_
= native_event
->xkey
.state
| mask
;
74 state_
= native_event
->xkey
.state
& ~mask
;
77 XIDeviceEvent
* xievent
=
78 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
79 switch (xievent
->evtype
) {
81 state_
= xievent
->mods
.effective
|= mask
;
84 state_
= xievent
->mods
.effective
&= ~mask
;
98 // Returns the current modifer state in master device. It only contains the
99 // state of ctrl, shift, alt and caps lock keys.
100 unsigned int state() { return state_
; }
103 friend struct DefaultSingletonTraits
<XModifierStateWatcher
>;
105 XModifierStateWatcher() : state_(0) { }
109 DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher
);
112 #if defined(USE_XI2_MT)
113 // Detects if a touch event is a driver-generated 'special event'.
114 // A 'special event' is a touch event with maximum radius and pressure at
116 // This needs to be done in a cleaner way: http://crbug.com/169256
117 bool TouchEventIsGeneratedHack(const base::NativeEvent
& native_event
) {
118 XIDeviceEvent
* event
=
119 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
120 CHECK(event
->evtype
== XI_TouchBegin
||
121 event
->evtype
== XI_TouchUpdate
||
122 event
->evtype
== XI_TouchEnd
);
124 // Force is normalized to [0, 1].
125 if (ui::GetTouchForce(native_event
) < 1.0f
)
128 if (ui::EventLocationFromNative(native_event
) != gfx::Point())
131 // Radius is in pixels, and the valuator is the diameter in pixels.
132 double radius
= ui::GetTouchRadiusX(native_event
), min
, max
;
133 unsigned int deviceid
=
134 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
)->sourceid
;
135 if (!ui::DeviceDataManagerX11::GetInstance()->GetDataRange(
136 deviceid
, ui::DeviceDataManagerX11::DT_TOUCH_MAJOR
, &min
, &max
)) {
140 return radius
* 2 == max
;
144 int GetEventFlagsFromXState(unsigned int state
) {
146 if (state
& ControlMask
)
147 flags
|= ui::EF_CONTROL_DOWN
;
148 if (state
& ShiftMask
)
149 flags
|= ui::EF_SHIFT_DOWN
;
150 if (state
& Mod1Mask
)
151 flags
|= ui::EF_ALT_DOWN
;
152 if (state
& LockMask
)
153 flags
|= ui::EF_CAPS_LOCK_DOWN
;
154 if (state
& Mod3Mask
)
155 flags
|= ui::EF_MOD3_DOWN
;
156 if (state
& Mod4Mask
)
157 flags
|= ui::EF_COMMAND_DOWN
;
158 if (state
& Mod5Mask
)
159 flags
|= ui::EF_ALTGR_DOWN
;
160 if (state
& Button1Mask
)
161 flags
|= ui::EF_LEFT_MOUSE_BUTTON
;
162 if (state
& Button2Mask
)
163 flags
|= ui::EF_MIDDLE_MOUSE_BUTTON
;
164 if (state
& Button3Mask
)
165 flags
|= ui::EF_RIGHT_MOUSE_BUTTON
;
169 int GetEventFlagsFromXKeyEvent(XEvent
* xevent
) {
170 DCHECK(xevent
->type
== KeyPress
|| xevent
->type
== KeyRelease
);
172 #if defined(OS_CHROMEOS)
173 const int ime_fabricated_flag
= 0;
175 // XIM fabricates key events for the character compositions by XK_Multi_key.
176 // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in
177 // order to input "é", then XIM generates a key event with keycode=0 and
178 // state=0 for the composition, and the sequence of X11 key events will be
179 // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e. If the user used
180 // shift key and/or caps lock key, state can be ShiftMask, LockMask or both.
182 // We have to send these fabricated key events to XIM so it can correctly
183 // handle the character compositions.
184 const unsigned int shift_lock_mask
= ShiftMask
| LockMask
;
185 const bool fabricated_by_xim
=
186 xevent
->xkey
.keycode
== 0 &&
187 (xevent
->xkey
.state
& ~shift_lock_mask
) == 0;
188 const int ime_fabricated_flag
=
189 fabricated_by_xim
? ui::EF_IME_FABRICATED_KEY
: 0;
192 return GetEventFlagsFromXState(xevent
->xkey
.state
) |
193 (xevent
->xkey
.send_event
? ui::EF_FINAL
: 0) |
194 (IsKeypadKey(XLookupKeysym(&xevent
->xkey
, 0)) ? ui::EF_NUMPAD_KEY
: 0) |
195 (IsFunctionKey(XLookupKeysym(&xevent
->xkey
, 0)) ?
196 ui::EF_FUNCTION_KEY
: 0) |
200 int GetEventFlagsFromXGenericEvent(XEvent
* xevent
) {
201 DCHECK(xevent
->type
== GenericEvent
);
202 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xevent
->xcookie
.data
);
203 DCHECK((xievent
->evtype
== XI_KeyPress
) ||
204 (xievent
->evtype
== XI_KeyRelease
));
205 return GetEventFlagsFromXState(xievent
->mods
.effective
) |
206 (xevent
->xkey
.send_event
? ui::EF_FINAL
: 0) |
208 XkbKeycodeToKeysym(xievent
->display
, xievent
->detail
, 0, 0))
213 // Get the event flag for the button in XButtonEvent. During a ButtonPress
214 // event, |state| in XButtonEvent does not include the button that has just been
215 // pressed. Instead |state| contains flags for the buttons (if any) that had
216 // already been pressed before the current button, and |button| stores the most
217 // current pressed button. So, if you press down left mouse button, and while
218 // pressing it down, press down the right mouse button, then for the latter
219 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
221 int GetEventFlagsForButton(int button
) {
224 return ui::EF_LEFT_MOUSE_BUTTON
;
226 return ui::EF_MIDDLE_MOUSE_BUTTON
;
228 return ui::EF_RIGHT_MOUSE_BUTTON
;
234 int GetButtonMaskForX2Event(XIDeviceEvent
* xievent
) {
236 for (int i
= 0; i
< 8 * xievent
->buttons
.mask_len
; i
++) {
237 if (XIMaskIsSet(xievent
->buttons
.mask
, i
)) {
238 int button
= (xievent
->sourceid
== xievent
->deviceid
) ?
239 ui::DeviceDataManagerX11::GetInstance()->GetMappedButton(i
) : i
;
240 buttonflags
|= GetEventFlagsForButton(button
);
246 ui::EventType
GetTouchEventType(const base::NativeEvent
& native_event
) {
247 XIDeviceEvent
* event
=
248 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
249 #if defined(USE_XI2_MT)
250 switch(event
->evtype
) {
252 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_UNKNOWN
:
253 ui::ET_TOUCH_PRESSED
;
255 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_UNKNOWN
:
258 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_TOUCH_CANCELLED
:
259 ui::ET_TOUCH_RELEASED
;
261 #endif // defined(USE_XI2_MT)
263 DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event
->sourceid
));
264 switch (event
->evtype
) {
266 return ui::ET_TOUCH_PRESSED
;
267 case XI_ButtonRelease
:
268 return ui::ET_TOUCH_RELEASED
;
270 // Should not convert any emulated Motion event from touch device to
272 if (!(event
->flags
& XIPointerEmulated
) &&
273 GetButtonMaskForX2Event(event
))
274 return ui::ET_TOUCH_MOVED
;
275 return ui::ET_UNKNOWN
;
279 return ui::ET_UNKNOWN
;
282 double GetTouchParamFromXEvent(XEvent
* xev
,
283 ui::DeviceDataManagerX11::DataType val
,
284 double default_value
) {
285 ui::DeviceDataManagerX11::GetInstance()->GetEventData(
286 *xev
, val
, &default_value
);
287 return default_value
;
290 void ScaleTouchRadius(XEvent
* xev
, double* radius
) {
291 DCHECK_EQ(GenericEvent
, xev
->type
);
292 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
293 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchRadiusScale(
294 xiev
->sourceid
, radius
);
297 unsigned int UpdateX11EventFlags(int ui_flags
, unsigned int old_x_flags
) {
302 {ui::EF_CONTROL_DOWN
, ControlMask
},
303 {ui::EF_SHIFT_DOWN
, ShiftMask
},
304 {ui::EF_ALT_DOWN
, Mod1Mask
},
305 {ui::EF_CAPS_LOCK_DOWN
, LockMask
},
306 {ui::EF_ALTGR_DOWN
, Mod5Mask
},
307 {ui::EF_COMMAND_DOWN
, Mod4Mask
},
308 {ui::EF_MOD3_DOWN
, Mod3Mask
},
309 {ui::EF_NUMPAD_KEY
, Mod2Mask
},
310 {ui::EF_LEFT_MOUSE_BUTTON
, Button1Mask
},
311 {ui::EF_MIDDLE_MOUSE_BUTTON
, Button2Mask
},
312 {ui::EF_RIGHT_MOUSE_BUTTON
, Button3Mask
},
314 unsigned int new_x_flags
= old_x_flags
;
315 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(flags
); ++i
) {
316 if (ui_flags
& flags
[i
].ui
)
317 new_x_flags
|= flags
[i
].x
;
319 new_x_flags
&= ~flags
[i
].x
;
324 unsigned int UpdateX11EventButton(int ui_flag
, unsigned int old_x_button
) {
326 case ui::EF_LEFT_MOUSE_BUTTON
:
328 case ui::EF_MIDDLE_MOUSE_BUTTON
:
330 case ui::EF_RIGHT_MOUSE_BUTTON
:
338 bool GetGestureTimes(const base::NativeEvent
& native_event
,
341 if (!ui::DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event
))
344 double start_time_
, end_time_
;
346 start_time
= &start_time_
;
348 end_time
= &end_time_
;
350 ui::DeviceDataManagerX11::GetInstance()->GetGestureTimes(
351 native_event
, start_time
, end_time
);
359 void UpdateDeviceList() {
360 XDisplay
* display
= gfx::GetXDisplay();
361 DeviceListCacheX::GetInstance()->UpdateDeviceList(display
);
362 TouchFactory::GetInstance()->UpdateDeviceList(display
);
363 DeviceDataManagerX11::GetInstance()->UpdateDeviceList(display
);
366 EventType
EventTypeFromNative(const base::NativeEvent
& native_event
) {
367 // Allow the DeviceDataManager to block the event. If blocked return
368 // ET_UNKNOWN as the type so this event will not be further processed.
369 // NOTE: During some events unittests there is no device data manager.
370 if (DeviceDataManager::HasInstance() &&
371 static_cast<DeviceDataManagerX11
*>(DeviceDataManager::GetInstance())->
372 IsEventBlocked(native_event
)) {
376 switch (native_event
->type
) {
378 return ET_KEY_PRESSED
;
380 return ET_KEY_RELEASED
;
382 if (static_cast<int>(native_event
->xbutton
.button
) >= kMinWheelButton
&&
383 static_cast<int>(native_event
->xbutton
.button
) <= kMaxWheelButton
)
384 return ET_MOUSEWHEEL
;
385 return ET_MOUSE_PRESSED
;
387 // Drop wheel events; we should've already scrolled on the press.
388 if (static_cast<int>(native_event
->xbutton
.button
) >= kMinWheelButton
&&
389 static_cast<int>(native_event
->xbutton
.button
) <= kMaxWheelButton
)
391 return ET_MOUSE_RELEASED
;
393 if (native_event
->xmotion
.state
&
394 (Button1Mask
| Button2Mask
| Button3Mask
))
395 return ET_MOUSE_DRAGGED
;
396 return ET_MOUSE_MOVED
;
398 // The standard on Windows is to send a MouseMove event when the mouse
399 // first enters a window instead of sending a special mouse enter event.
400 // To be consistent we follow the same style.
401 return ET_MOUSE_MOVED
;
403 return ET_MOUSE_EXITED
;
405 TouchFactory
* factory
= TouchFactory::GetInstance();
406 if (!factory
->ShouldProcessXI2Event(native_event
))
409 XIDeviceEvent
* xievent
=
410 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
412 // This check works only for master and floating slave devices. That is
413 // why it is necessary to check for the XI_Touch* events in the following
414 // switch statement to account for attached-slave touchscreens.
415 if (factory
->IsTouchDevice(xievent
->sourceid
))
416 return GetTouchEventType(native_event
);
418 switch (xievent
->evtype
) {
420 return ui::ET_TOUCH_PRESSED
;
422 return ui::ET_TOUCH_MOVED
;
424 return ui::ET_TOUCH_RELEASED
;
425 case XI_ButtonPress
: {
426 int button
= EventButtonFromNative(native_event
);
427 if (button
>= kMinWheelButton
&& button
<= kMaxWheelButton
)
428 return ET_MOUSEWHEEL
;
429 return ET_MOUSE_PRESSED
;
431 case XI_ButtonRelease
: {
432 int button
= EventButtonFromNative(native_event
);
433 // Drop wheel events; we should've already scrolled on the press.
434 if (button
>= kMinWheelButton
&& button
<= kMaxWheelButton
)
436 return ET_MOUSE_RELEASED
;
440 DeviceDataManagerX11
* devices
= DeviceDataManagerX11::GetInstance();
441 if (GetFlingData(native_event
, NULL
, NULL
, NULL
, NULL
, &is_cancel
))
442 return is_cancel
? ET_SCROLL_FLING_CANCEL
: ET_SCROLL_FLING_START
;
443 if (devices
->IsScrollEvent(native_event
)) {
444 return devices
->IsTouchpadXInputEvent(native_event
) ? ET_SCROLL
447 if (devices
->IsCMTMetricsEvent(native_event
))
449 if (GetButtonMaskForX2Event(xievent
))
450 return ET_MOUSE_DRAGGED
;
451 return ET_MOUSE_MOVED
;
454 return ET_KEY_PRESSED
;
456 return ET_KEY_RELEASED
;
465 int EventFlagsFromNative(const base::NativeEvent
& native_event
) {
466 switch (native_event
->type
) {
469 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event
);
470 return GetEventFlagsFromXKeyEvent(native_event
);
473 case ButtonRelease
: {
474 int flags
= GetEventFlagsFromXState(native_event
->xbutton
.state
);
475 const EventType type
= EventTypeFromNative(native_event
);
476 if (type
== ET_MOUSE_PRESSED
|| type
== ET_MOUSE_RELEASED
)
477 flags
|= GetEventFlagsForButton(native_event
->xbutton
.button
);
482 return GetEventFlagsFromXState(native_event
->xcrossing
.state
);
484 return GetEventFlagsFromXState(native_event
->xmotion
.state
);
486 XIDeviceEvent
* xievent
=
487 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
489 switch (xievent
->evtype
) {
490 #if defined(USE_XI2_MT)
494 return GetButtonMaskForX2Event(xievent
) |
495 GetEventFlagsFromXState(xievent
->mods
.effective
) |
496 GetEventFlagsFromXState(
497 XModifierStateWatcher::GetInstance()->state());
501 case XI_ButtonRelease
: {
503 TouchFactory::GetInstance()->IsTouchDevice(xievent
->sourceid
);
504 int flags
= GetButtonMaskForX2Event(xievent
) |
505 GetEventFlagsFromXState(xievent
->mods
.effective
);
507 flags
|= GetEventFlagsFromXState(
508 XModifierStateWatcher::GetInstance()->state());
511 const EventType type
= EventTypeFromNative(native_event
);
512 int button
= EventButtonFromNative(native_event
);
513 if ((type
== ET_MOUSE_PRESSED
|| type
== ET_MOUSE_RELEASED
) && !touch
)
514 flags
|= GetEventFlagsForButton(button
);
518 return GetButtonMaskForX2Event(xievent
) |
519 GetEventFlagsFromXState(xievent
->mods
.effective
);
521 case XI_KeyRelease
: {
522 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
524 return GetEventFlagsFromXGenericEvent(native_event
);
532 base::TimeDelta
EventTimeFromNative(const base::NativeEvent
& native_event
) {
533 switch(native_event
->type
) {
536 return base::TimeDelta::FromMilliseconds(native_event
->xkey
.time
);
539 return base::TimeDelta::FromMilliseconds(native_event
->xbutton
.time
);
542 return base::TimeDelta::FromMilliseconds(native_event
->xmotion
.time
);
546 return base::TimeDelta::FromMilliseconds(native_event
->xcrossing
.time
);
550 double touch_timestamp
;
551 if (GetGestureTimes(native_event
, &start
, &end
)) {
552 // If the driver supports gesture times, use them.
553 return base::TimeDelta::FromMicroseconds(end
* 1000000);
554 } else if (DeviceDataManagerX11::GetInstance()->GetEventData(
556 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
,
558 return base::TimeDelta::FromMicroseconds(touch_timestamp
* 1000000);
560 XIDeviceEvent
* xide
=
561 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
562 return base::TimeDelta::FromMilliseconds(xide
->time
);
568 return base::TimeDelta();
571 gfx::Point
EventLocationFromNative(const base::NativeEvent
& native_event
) {
572 switch (native_event
->type
) {
575 return gfx::Point(native_event
->xcrossing
.x
, native_event
->xcrossing
.y
);
578 return gfx::Point(native_event
->xbutton
.x
, native_event
->xbutton
.y
);
580 return gfx::Point(native_event
->xmotion
.x
, native_event
->xmotion
.y
);
582 XIDeviceEvent
* xievent
=
583 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
584 float x
= xievent
->event_x
;
585 float y
= xievent
->event_y
;
586 #if defined(OS_CHROMEOS)
587 switch (xievent
->evtype
) {
591 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer(
592 xievent
->deviceid
, &x
, &y
);
597 #endif // defined(OS_CHROMEOS)
598 return gfx::Point(static_cast<int>(x
), static_cast<int>(y
));
604 gfx::Point
EventSystemLocationFromNative(
605 const base::NativeEvent
& native_event
) {
606 switch (native_event
->type
) {
609 return gfx::Point(native_event
->xcrossing
.x_root
,
610 native_event
->xcrossing
.y_root
);
613 case ButtonRelease
: {
614 return gfx::Point(native_event
->xbutton
.x_root
,
615 native_event
->xbutton
.y_root
);
618 return gfx::Point(native_event
->xmotion
.x_root
,
619 native_event
->xmotion
.y_root
);
622 XIDeviceEvent
* xievent
=
623 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
624 return gfx::Point(xievent
->root_x
, xievent
->root_y
);
631 int EventButtonFromNative(const base::NativeEvent
& native_event
) {
632 CHECK_EQ(GenericEvent
, native_event
->type
);
633 XIDeviceEvent
* xievent
=
634 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
635 int button
= xievent
->detail
;
637 return (xievent
->sourceid
== xievent
->deviceid
) ?
638 DeviceDataManagerX11::GetInstance()->GetMappedButton(button
) : button
;
641 KeyboardCode
KeyboardCodeFromNative(const base::NativeEvent
& native_event
) {
642 return KeyboardCodeFromXKeyEvent(native_event
);
645 const char* CodeFromNative(const base::NativeEvent
& native_event
) {
646 return CodeFromXEvent(native_event
);
649 uint32
PlatformKeycodeFromNative(const base::NativeEvent
& native_event
) {
650 XKeyEvent
* xkey
= NULL
;
651 XEvent xkey_from_xi2
;
652 switch (native_event
->type
) {
655 xkey
= &native_event
->xkey
;
658 XIDeviceEvent
* xievent
=
659 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
660 switch (xievent
->evtype
) {
663 // Build an XKeyEvent corresponding to the XI2 event,
664 // so that we can call XLookupString on it.
665 InitXKeyEventFromXIDeviceEvent(*native_event
, &xkey_from_xi2
);
666 xkey
= &xkey_from_xi2
.xkey
;
678 KeySym keysym
= XK_VoidSymbol
;
680 XLookupString(xkey
, NULL
, 0, &keysym
, NULL
);
684 bool IsCharFromNative(const base::NativeEvent
& native_event
) {
688 uint32
WindowsKeycodeFromNative(const base::NativeEvent
& native_event
) {
689 int windows_key_code
= ui::KeyboardCodeFromXKeyEvent(native_event
);
690 if (windows_key_code
== ui::VKEY_SHIFT
||
691 windows_key_code
== ui::VKEY_CONTROL
||
692 windows_key_code
== ui::VKEY_MENU
) {
693 // To support DOM3 'location' attribute, we need to lookup an X KeySym and
694 // set ui::VKEY_[LR]XXX instead of ui::VKEY_XXX.
695 KeySym keysym
= XK_VoidSymbol
;
696 XLookupString(&native_event
->xkey
, NULL
, 0, &keysym
, NULL
);
699 return ui::VKEY_LSHIFT
;
701 return ui::VKEY_RSHIFT
;
703 return ui::VKEY_LCONTROL
;
705 return ui::VKEY_RCONTROL
;
708 return ui::VKEY_LMENU
;
711 return ui::VKEY_RMENU
;
714 return windows_key_code
;
717 uint16
TextFromNative(const base::NativeEvent
& native_event
) {
718 int flags
= EventFlagsFromNative(native_event
);
719 if ((flags
& ui::EF_CONTROL_DOWN
) != 0) {
720 int windows_key_code
= WindowsKeycodeFromNative(native_event
);
721 return ui::GetControlCharacterForKeycode(windows_key_code
,
722 flags
& ui::EF_SHIFT_DOWN
);
725 return UnmodifiedTextFromNative(native_event
);
728 uint16
UnmodifiedTextFromNative(const base::NativeEvent
& native_event
) {
729 uint32 keycode
= WindowsKeycodeFromNative(native_event
);
730 if (keycode
== ui::VKEY_RETURN
)
733 return ui::GetCharacterFromXEvent(native_event
);
736 int GetChangedMouseButtonFlagsFromNative(
737 const base::NativeEvent
& native_event
) {
738 switch (native_event
->type
) {
741 return GetEventFlagsFromXState(native_event
->xbutton
.state
);
743 XIDeviceEvent
* xievent
=
744 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
745 switch (xievent
->evtype
) {
747 case XI_ButtonRelease
:
748 return GetEventFlagsForButton(EventButtonFromNative(native_event
));
759 gfx::Vector2d
GetMouseWheelOffset(const base::NativeEvent
& native_event
) {
760 float x_offset
, y_offset
;
761 if (GetScrollOffsets(
762 native_event
, &x_offset
, &y_offset
, NULL
, NULL
, NULL
)) {
763 return gfx::Vector2d(static_cast<int>(x_offset
),
764 static_cast<int>(y_offset
));
767 int button
= native_event
->type
== GenericEvent
?
768 EventButtonFromNative(native_event
) : native_event
->xbutton
.button
;
772 return gfx::Vector2d(0, kWheelScrollAmount
);
774 return gfx::Vector2d(0, -kWheelScrollAmount
);
776 return gfx::Vector2d(kWheelScrollAmount
, 0);
778 return gfx::Vector2d(-kWheelScrollAmount
, 0);
780 return gfx::Vector2d();
784 base::NativeEvent
CopyNativeEvent(const base::NativeEvent
& event
) {
785 if (!event
|| event
->type
== GenericEvent
)
787 XEvent
* copy
= new XEvent
;
792 void ReleaseCopiedNativeEvent(const base::NativeEvent
& event
) {
796 void IncrementTouchIdRefCount(const base::NativeEvent
& xev
) {
797 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
799 if (!manager
->GetEventData(
800 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
804 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
805 factory
->AcquireSlotForTrackingID(tracking_id
);
808 void ClearTouchIdIfReleased(const base::NativeEvent
& xev
) {
809 ui::EventType type
= ui::EventTypeFromNative(xev
);
810 if (type
== ui::ET_TOUCH_CANCELLED
||
811 type
== ui::ET_TOUCH_RELEASED
) {
812 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
813 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
815 if (manager
->GetEventData(
816 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
817 factory
->ReleaseSlotForTrackingID(tracking_id
);
822 int GetTouchId(const base::NativeEvent
& xev
) {
824 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
826 if (!manager
->GetEventData(
827 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
828 LOG(ERROR
) << "Could not get the tracking ID for the event. Using 0.";
830 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
831 slot
= factory
->GetSlotForTrackingID(tracking_id
);
836 float GetTouchRadiusX(const base::NativeEvent
& native_event
) {
837 double radius
= GetTouchParamFromXEvent(native_event
,
838 ui::DeviceDataManagerX11::DT_TOUCH_MAJOR
, 0.0) / 2.0;
839 ScaleTouchRadius(native_event
, &radius
);
843 float GetTouchRadiusY(const base::NativeEvent
& native_event
) {
844 double radius
= GetTouchParamFromXEvent(native_event
,
845 ui::DeviceDataManagerX11::DT_TOUCH_MINOR
, 0.0) / 2.0;
846 ScaleTouchRadius(native_event
, &radius
);
850 float GetTouchAngle(const base::NativeEvent
& native_event
) {
851 return GetTouchParamFromXEvent(native_event
,
852 ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION
, 0.0) / 2.0;
855 float GetTouchForce(const base::NativeEvent
& native_event
) {
857 force
= GetTouchParamFromXEvent(native_event
,
858 ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE
, 0.0);
859 unsigned int deviceid
=
860 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
)->sourceid
;
861 // Force is normalized to fall into [0, 1]
862 if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData(
863 deviceid
, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE
, &force
))
868 bool GetScrollOffsets(const base::NativeEvent
& native_event
,
871 float* x_offset_ordinal
,
872 float* y_offset_ordinal
,
874 if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event
))
877 // Temp values to prevent passing NULLs to DeviceDataManager.
878 float x_offset_
, y_offset_
;
879 float x_offset_ordinal_
, y_offset_ordinal_
;
882 x_offset
= &x_offset_
;
884 y_offset
= &y_offset_
;
885 if (!x_offset_ordinal
)
886 x_offset_ordinal
= &x_offset_ordinal_
;
887 if (!y_offset_ordinal
)
888 y_offset_ordinal
= &y_offset_ordinal_
;
890 finger_count
= &finger_count_
;
892 DeviceDataManagerX11::GetInstance()->GetScrollOffsets(
895 x_offset_ordinal
, y_offset_ordinal
,
900 bool GetFlingData(const base::NativeEvent
& native_event
,
906 if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event
))
910 float vx_ordinal_
, vy_ordinal_
;
917 vx_ordinal
= &vx_ordinal_
;
919 vy_ordinal
= &vy_ordinal_
;
921 is_cancel
= &is_cancel_
;
923 DeviceDataManagerX11::GetInstance()->GetFlingData(
924 native_event
, vx
, vy
, vx_ordinal
, vy_ordinal
, is_cancel
);
928 void UpdateX11EventForFlags(Event
* event
) {
929 XEvent
* xev
= event
->native_event();
935 xev
->xkey
.state
= UpdateX11EventFlags(event
->flags(), xev
->xkey
.state
);
940 UpdateX11EventFlags(event
->flags(), xev
->xbutton
.state
);
943 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
945 xievent
->mods
.effective
=
946 UpdateX11EventFlags(event
->flags(), xievent
->mods
.effective
);
954 void UpdateX11EventForChangedButtonFlags(MouseEvent
* event
) {
955 XEvent
* xev
= event
->native_event();
961 xev
->xbutton
.button
= UpdateX11EventButton(event
->changed_button_flags(),
962 xev
->xbutton
.button
);
965 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
966 CHECK(xievent
&& (xievent
->evtype
== XI_ButtonPress
||
967 xievent
->evtype
== XI_ButtonRelease
));
969 UpdateX11EventButton(event
->changed_button_flags(), xievent
->detail
);