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"
8 #include <X11/extensions/XInput.h>
9 #include <X11/extensions/XInput2.h>
10 #include <X11/XKBlib.h>
12 #include <X11/Xutil.h>
15 #include "base/logging.h"
16 #include "base/memory/singleton.h"
17 #include "ui/events/devices/x11/device_data_manager_x11.h"
18 #include "ui/events/devices/x11/device_list_cache_x11.h"
19 #include "ui/events/devices/x11/touch_factory_x11.h"
20 #include "ui/events/event.h"
21 #include "ui/events/event_utils.h"
22 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
23 #include "ui/gfx/display.h"
24 #include "ui/gfx/geometry/point.h"
25 #include "ui/gfx/geometry/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 // Detects if a touch event is a driver-generated 'special event'.
113 // A 'special event' is a touch event with maximum radius and pressure at
115 // This needs to be done in a cleaner way: http://crbug.com/169256
116 bool TouchEventIsGeneratedHack(const base::NativeEvent
& native_event
) {
117 XIDeviceEvent
* event
=
118 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
119 CHECK(event
->evtype
== XI_TouchBegin
||
120 event
->evtype
== XI_TouchUpdate
||
121 event
->evtype
== XI_TouchEnd
);
123 // Force is normalized to [0, 1].
124 if (ui::GetTouchForce(native_event
) < 1.0f
)
127 if (ui::EventLocationFromNative(native_event
) != gfx::Point())
130 // Radius is in pixels, and the valuator is the diameter in pixels.
131 double radius
= ui::GetTouchRadiusX(native_event
), min
, max
;
132 unsigned int deviceid
=
133 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
)->sourceid
;
134 if (!ui::DeviceDataManagerX11::GetInstance()->GetDataRange(
135 deviceid
, ui::DeviceDataManagerX11::DT_TOUCH_MAJOR
, &min
, &max
)) {
139 return radius
* 2 == max
;
142 int GetEventFlagsFromXState(unsigned int state
) {
144 if (state
& ControlMask
)
145 flags
|= ui::EF_CONTROL_DOWN
;
146 if (state
& ShiftMask
)
147 flags
|= ui::EF_SHIFT_DOWN
;
148 if (state
& Mod1Mask
)
149 flags
|= ui::EF_ALT_DOWN
;
150 if (state
& LockMask
)
151 flags
|= ui::EF_CAPS_LOCK_DOWN
;
152 if (state
& Mod3Mask
)
153 flags
|= ui::EF_MOD3_DOWN
;
154 if (state
& Mod4Mask
)
155 flags
|= ui::EF_COMMAND_DOWN
;
156 if (state
& Mod5Mask
)
157 flags
|= ui::EF_ALTGR_DOWN
;
158 if (state
& Button1Mask
)
159 flags
|= ui::EF_LEFT_MOUSE_BUTTON
;
160 if (state
& Button2Mask
)
161 flags
|= ui::EF_MIDDLE_MOUSE_BUTTON
;
162 if (state
& Button3Mask
)
163 flags
|= ui::EF_RIGHT_MOUSE_BUTTON
;
167 int GetEventFlagsFromXKeyEvent(XEvent
* xevent
) {
168 DCHECK(xevent
->type
== KeyPress
|| xevent
->type
== KeyRelease
);
170 #if defined(OS_CHROMEOS)
171 const int ime_fabricated_flag
= 0;
173 // XIM fabricates key events for the character compositions by XK_Multi_key.
174 // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in
175 // order to input "é", then XIM generates a key event with keycode=0 and
176 // state=0 for the composition, and the sequence of X11 key events will be
177 // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e. If the user used
178 // shift key and/or caps lock key, state can be ShiftMask, LockMask or both.
180 // We have to send these fabricated key events to XIM so it can correctly
181 // handle the character compositions.
182 const unsigned int shift_lock_mask
= ShiftMask
| LockMask
;
183 const bool fabricated_by_xim
=
184 xevent
->xkey
.keycode
== 0 &&
185 (xevent
->xkey
.state
& ~shift_lock_mask
) == 0;
186 const int ime_fabricated_flag
=
187 fabricated_by_xim
? ui::EF_IME_FABRICATED_KEY
: 0;
190 return GetEventFlagsFromXState(xevent
->xkey
.state
) |
191 (xevent
->xkey
.send_event
? ui::EF_FINAL
: 0) |
192 (IsKeypadKey(XLookupKeysym(&xevent
->xkey
, 0)) ? ui::EF_NUMPAD_KEY
: 0) |
193 (IsFunctionKey(XLookupKeysym(&xevent
->xkey
, 0)) ?
194 ui::EF_FUNCTION_KEY
: 0) |
198 int GetEventFlagsFromXGenericEvent(XEvent
* xevent
) {
199 DCHECK(xevent
->type
== GenericEvent
);
200 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xevent
->xcookie
.data
);
201 DCHECK((xievent
->evtype
== XI_KeyPress
) ||
202 (xievent
->evtype
== XI_KeyRelease
));
203 return GetEventFlagsFromXState(xievent
->mods
.effective
) |
204 (xevent
->xkey
.send_event
? ui::EF_FINAL
: 0) |
206 XkbKeycodeToKeysym(xievent
->display
, xievent
->detail
, 0, 0))
211 // Get the event flag for the button in XButtonEvent. During a ButtonPress
212 // event, |state| in XButtonEvent does not include the button that has just been
213 // pressed. Instead |state| contains flags for the buttons (if any) that had
214 // already been pressed before the current button, and |button| stores the most
215 // current pressed button. So, if you press down left mouse button, and while
216 // pressing it down, press down the right mouse button, then for the latter
217 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
219 int GetEventFlagsForButton(int button
) {
222 return ui::EF_LEFT_MOUSE_BUTTON
;
224 return ui::EF_MIDDLE_MOUSE_BUTTON
;
226 return ui::EF_RIGHT_MOUSE_BUTTON
;
232 int GetButtonMaskForX2Event(XIDeviceEvent
* xievent
) {
234 for (int i
= 0; i
< 8 * xievent
->buttons
.mask_len
; i
++) {
235 if (XIMaskIsSet(xievent
->buttons
.mask
, i
)) {
236 int button
= (xievent
->sourceid
== xievent
->deviceid
) ?
237 ui::DeviceDataManagerX11::GetInstance()->GetMappedButton(i
) : i
;
238 buttonflags
|= GetEventFlagsForButton(button
);
244 ui::EventType
GetTouchEventType(const base::NativeEvent
& native_event
) {
245 XIDeviceEvent
* event
=
246 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
247 switch(event
->evtype
) {
249 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_UNKNOWN
:
250 ui::ET_TOUCH_PRESSED
;
252 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_UNKNOWN
:
255 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_TOUCH_CANCELLED
:
256 ui::ET_TOUCH_RELEASED
;
259 DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event
->sourceid
));
260 switch (event
->evtype
) {
262 return ui::ET_TOUCH_PRESSED
;
263 case XI_ButtonRelease
:
264 return ui::ET_TOUCH_RELEASED
;
266 // Should not convert any emulated Motion event from touch device to
268 if (!(event
->flags
& XIPointerEmulated
) &&
269 GetButtonMaskForX2Event(event
))
270 return ui::ET_TOUCH_MOVED
;
271 return ui::ET_UNKNOWN
;
275 return ui::ET_UNKNOWN
;
278 double GetTouchParamFromXEvent(XEvent
* xev
,
279 ui::DeviceDataManagerX11::DataType val
,
280 double default_value
) {
281 ui::DeviceDataManagerX11::GetInstance()->GetEventData(
282 *xev
, val
, &default_value
);
283 return default_value
;
286 void ScaleTouchRadius(XEvent
* xev
, double* radius
) {
287 DCHECK_EQ(GenericEvent
, xev
->type
);
288 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
289 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchRadiusScale(
290 xiev
->sourceid
, radius
);
293 unsigned int UpdateX11EventFlags(int ui_flags
, unsigned int old_x_flags
) {
298 {ui::EF_CONTROL_DOWN
, ControlMask
},
299 {ui::EF_SHIFT_DOWN
, ShiftMask
},
300 {ui::EF_ALT_DOWN
, Mod1Mask
},
301 {ui::EF_CAPS_LOCK_DOWN
, LockMask
},
302 {ui::EF_ALTGR_DOWN
, Mod5Mask
},
303 {ui::EF_COMMAND_DOWN
, Mod4Mask
},
304 {ui::EF_MOD3_DOWN
, Mod3Mask
},
305 {ui::EF_NUMPAD_KEY
, Mod2Mask
},
306 {ui::EF_LEFT_MOUSE_BUTTON
, Button1Mask
},
307 {ui::EF_MIDDLE_MOUSE_BUTTON
, Button2Mask
},
308 {ui::EF_RIGHT_MOUSE_BUTTON
, Button3Mask
},
310 unsigned int new_x_flags
= old_x_flags
;
311 for (size_t i
= 0; i
< arraysize(flags
); ++i
) {
312 if (ui_flags
& flags
[i
].ui
)
313 new_x_flags
|= flags
[i
].x
;
315 new_x_flags
&= ~flags
[i
].x
;
320 unsigned int UpdateX11EventButton(int ui_flag
, unsigned int old_x_button
) {
322 case ui::EF_LEFT_MOUSE_BUTTON
:
324 case ui::EF_MIDDLE_MOUSE_BUTTON
:
326 case ui::EF_RIGHT_MOUSE_BUTTON
:
334 bool GetGestureTimes(const base::NativeEvent
& native_event
,
337 if (!ui::DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event
))
340 double start_time_
, end_time_
;
342 start_time
= &start_time_
;
344 end_time
= &end_time_
;
346 ui::DeviceDataManagerX11::GetInstance()->GetGestureTimes(
347 native_event
, start_time
, end_time
);
355 void UpdateDeviceList() {
356 XDisplay
* display
= gfx::GetXDisplay();
357 DeviceListCacheX11::GetInstance()->UpdateDeviceList(display
);
358 TouchFactory::GetInstance()->UpdateDeviceList(display
);
359 DeviceDataManagerX11::GetInstance()->UpdateDeviceList(display
);
362 EventType
EventTypeFromNative(const base::NativeEvent
& native_event
) {
363 // Allow the DeviceDataManager to block the event. If blocked return
364 // ET_UNKNOWN as the type so this event will not be further processed.
365 // NOTE: During some events unittests there is no device data manager.
366 if (DeviceDataManager::HasInstance() &&
367 static_cast<DeviceDataManagerX11
*>(DeviceDataManager::GetInstance())->
368 IsEventBlocked(native_event
)) {
372 switch (native_event
->type
) {
374 return ET_KEY_PRESSED
;
376 return ET_KEY_RELEASED
;
378 if (static_cast<int>(native_event
->xbutton
.button
) >= kMinWheelButton
&&
379 static_cast<int>(native_event
->xbutton
.button
) <= kMaxWheelButton
)
380 return ET_MOUSEWHEEL
;
381 return ET_MOUSE_PRESSED
;
383 // Drop wheel events; we should've already scrolled on the press.
384 if (static_cast<int>(native_event
->xbutton
.button
) >= kMinWheelButton
&&
385 static_cast<int>(native_event
->xbutton
.button
) <= kMaxWheelButton
)
387 return ET_MOUSE_RELEASED
;
389 if (native_event
->xmotion
.state
&
390 (Button1Mask
| Button2Mask
| Button3Mask
))
391 return ET_MOUSE_DRAGGED
;
392 return ET_MOUSE_MOVED
;
394 // The standard on Windows is to send a MouseMove event when the mouse
395 // first enters a window instead of sending a special mouse enter event.
396 // To be consistent we follow the same style.
397 return ET_MOUSE_MOVED
;
399 return ET_MOUSE_EXITED
;
401 TouchFactory
* factory
= TouchFactory::GetInstance();
402 if (!factory
->ShouldProcessXI2Event(native_event
))
405 XIDeviceEvent
* xievent
=
406 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
408 // This check works only for master and floating slave devices. That is
409 // why it is necessary to check for the XI_Touch* events in the following
410 // switch statement to account for attached-slave touchscreens.
411 if (factory
->IsTouchDevice(xievent
->sourceid
))
412 return GetTouchEventType(native_event
);
414 switch (xievent
->evtype
) {
416 return ui::ET_TOUCH_PRESSED
;
418 return ui::ET_TOUCH_MOVED
;
420 return ui::ET_TOUCH_RELEASED
;
421 case XI_ButtonPress
: {
422 int button
= EventButtonFromNative(native_event
);
423 if (button
>= kMinWheelButton
&& button
<= kMaxWheelButton
)
424 return ET_MOUSEWHEEL
;
425 return ET_MOUSE_PRESSED
;
427 case XI_ButtonRelease
: {
428 int button
= EventButtonFromNative(native_event
);
429 // Drop wheel events; we should've already scrolled on the press.
430 if (button
>= kMinWheelButton
&& button
<= kMaxWheelButton
)
432 return ET_MOUSE_RELEASED
;
436 DeviceDataManagerX11
* devices
= DeviceDataManagerX11::GetInstance();
437 if (GetFlingData(native_event
, NULL
, NULL
, NULL
, NULL
, &is_cancel
))
438 return is_cancel
? ET_SCROLL_FLING_CANCEL
: ET_SCROLL_FLING_START
;
439 if (devices
->IsScrollEvent(native_event
)) {
440 return devices
->IsTouchpadXInputEvent(native_event
) ? ET_SCROLL
443 if (devices
->IsCMTMetricsEvent(native_event
))
445 if (GetButtonMaskForX2Event(xievent
))
446 return ET_MOUSE_DRAGGED
;
447 return ET_MOUSE_MOVED
;
450 return ET_KEY_PRESSED
;
452 return ET_KEY_RELEASED
;
461 int EventFlagsFromNative(const base::NativeEvent
& native_event
) {
462 switch (native_event
->type
) {
465 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event
);
466 return GetEventFlagsFromXKeyEvent(native_event
);
469 case ButtonRelease
: {
470 int flags
= GetEventFlagsFromXState(native_event
->xbutton
.state
);
471 const EventType type
= EventTypeFromNative(native_event
);
472 if (type
== ET_MOUSE_PRESSED
|| type
== ET_MOUSE_RELEASED
)
473 flags
|= GetEventFlagsForButton(native_event
->xbutton
.button
);
478 return GetEventFlagsFromXState(native_event
->xcrossing
.state
);
480 return GetEventFlagsFromXState(native_event
->xmotion
.state
);
482 XIDeviceEvent
* xievent
=
483 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
485 switch (xievent
->evtype
) {
489 return GetButtonMaskForX2Event(xievent
) |
490 GetEventFlagsFromXState(xievent
->mods
.effective
) |
491 GetEventFlagsFromXState(
492 XModifierStateWatcher::GetInstance()->state());
495 case XI_ButtonRelease
: {
497 TouchFactory::GetInstance()->IsTouchDevice(xievent
->sourceid
);
498 int flags
= GetButtonMaskForX2Event(xievent
) |
499 GetEventFlagsFromXState(xievent
->mods
.effective
);
501 flags
|= GetEventFlagsFromXState(
502 XModifierStateWatcher::GetInstance()->state());
505 const EventType type
= EventTypeFromNative(native_event
);
506 int button
= EventButtonFromNative(native_event
);
507 if ((type
== ET_MOUSE_PRESSED
|| type
== ET_MOUSE_RELEASED
) && !touch
)
508 flags
|= GetEventFlagsForButton(button
);
512 return GetButtonMaskForX2Event(xievent
) |
513 GetEventFlagsFromXState(xievent
->mods
.effective
);
515 case XI_KeyRelease
: {
516 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
518 return GetEventFlagsFromXGenericEvent(native_event
);
526 base::TimeDelta
EventTimeFromNative(const base::NativeEvent
& native_event
) {
527 switch(native_event
->type
) {
530 return base::TimeDelta::FromMilliseconds(native_event
->xkey
.time
);
533 return base::TimeDelta::FromMilliseconds(native_event
->xbutton
.time
);
536 return base::TimeDelta::FromMilliseconds(native_event
->xmotion
.time
);
540 return base::TimeDelta::FromMilliseconds(native_event
->xcrossing
.time
);
544 double touch_timestamp
;
545 if (GetGestureTimes(native_event
, &start
, &end
)) {
546 // If the driver supports gesture times, use them.
547 return base::TimeDelta::FromMicroseconds(end
* 1000000);
548 } else if (DeviceDataManagerX11::GetInstance()->GetEventData(
550 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
,
552 return base::TimeDelta::FromMicroseconds(touch_timestamp
* 1000000);
554 XIDeviceEvent
* xide
=
555 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
556 return base::TimeDelta::FromMilliseconds(xide
->time
);
562 return base::TimeDelta();
565 gfx::Point
EventLocationFromNative(const base::NativeEvent
& native_event
) {
566 switch (native_event
->type
) {
569 return gfx::Point(native_event
->xcrossing
.x
, native_event
->xcrossing
.y
);
572 return gfx::Point(native_event
->xbutton
.x
, native_event
->xbutton
.y
);
574 return gfx::Point(native_event
->xmotion
.x
, native_event
->xmotion
.y
);
576 XIDeviceEvent
* xievent
=
577 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
578 float x
= xievent
->event_x
;
579 float y
= xievent
->event_y
;
580 #if defined(OS_CHROMEOS)
581 switch (xievent
->evtype
) {
585 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer(
586 xievent
->deviceid
, &x
, &y
);
591 #endif // defined(OS_CHROMEOS)
592 return gfx::Point(static_cast<int>(x
), static_cast<int>(y
));
598 gfx::Point
EventSystemLocationFromNative(
599 const base::NativeEvent
& native_event
) {
600 switch (native_event
->type
) {
603 return gfx::Point(native_event
->xcrossing
.x_root
,
604 native_event
->xcrossing
.y_root
);
607 case ButtonRelease
: {
608 return gfx::Point(native_event
->xbutton
.x_root
,
609 native_event
->xbutton
.y_root
);
612 return gfx::Point(native_event
->xmotion
.x_root
,
613 native_event
->xmotion
.y_root
);
616 XIDeviceEvent
* xievent
=
617 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
618 return gfx::Point(xievent
->root_x
, xievent
->root_y
);
625 int EventButtonFromNative(const base::NativeEvent
& native_event
) {
626 CHECK_EQ(GenericEvent
, native_event
->type
);
627 XIDeviceEvent
* xievent
=
628 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
629 int button
= xievent
->detail
;
631 return (xievent
->sourceid
== xievent
->deviceid
) ?
632 DeviceDataManagerX11::GetInstance()->GetMappedButton(button
) : button
;
635 KeyboardCode
KeyboardCodeFromNative(const base::NativeEvent
& native_event
) {
636 return KeyboardCodeFromXKeyEvent(native_event
);
639 DomCode
CodeFromNative(const base::NativeEvent
& native_event
) {
640 return CodeFromXEvent(native_event
);
643 uint32
PlatformKeycodeFromNative(const base::NativeEvent
& native_event
) {
644 XKeyEvent
* xkey
= NULL
;
645 XEvent xkey_from_xi2
;
646 switch (native_event
->type
) {
649 xkey
= &native_event
->xkey
;
652 XIDeviceEvent
* xievent
=
653 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
654 switch (xievent
->evtype
) {
657 // Build an XKeyEvent corresponding to the XI2 event,
658 // so that we can call XLookupString on it.
659 InitXKeyEventFromXIDeviceEvent(*native_event
, &xkey_from_xi2
);
660 xkey
= &xkey_from_xi2
.xkey
;
672 KeySym keysym
= XK_VoidSymbol
;
674 XLookupString(xkey
, NULL
, 0, &keysym
, NULL
);
678 bool IsCharFromNative(const base::NativeEvent
& native_event
) {
682 int GetChangedMouseButtonFlagsFromNative(
683 const base::NativeEvent
& native_event
) {
684 switch (native_event
->type
) {
687 return GetEventFlagsFromXState(native_event
->xbutton
.state
);
689 XIDeviceEvent
* xievent
=
690 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
691 switch (xievent
->evtype
) {
693 case XI_ButtonRelease
:
694 return GetEventFlagsForButton(EventButtonFromNative(native_event
));
705 gfx::Vector2d
GetMouseWheelOffset(const base::NativeEvent
& native_event
) {
706 float x_offset
, y_offset
;
707 if (GetScrollOffsets(
708 native_event
, &x_offset
, &y_offset
, NULL
, NULL
, NULL
)) {
709 return gfx::Vector2d(static_cast<int>(x_offset
),
710 static_cast<int>(y_offset
));
713 int button
= native_event
->type
== GenericEvent
?
714 EventButtonFromNative(native_event
) : native_event
->xbutton
.button
;
718 return gfx::Vector2d(0, kWheelScrollAmount
);
720 return gfx::Vector2d(0, -kWheelScrollAmount
);
722 return gfx::Vector2d(kWheelScrollAmount
, 0);
724 return gfx::Vector2d(-kWheelScrollAmount
, 0);
726 return gfx::Vector2d();
730 base::NativeEvent
CopyNativeEvent(const base::NativeEvent
& event
) {
731 if (!event
|| event
->type
== GenericEvent
)
733 XEvent
* copy
= new XEvent
;
738 void ReleaseCopiedNativeEvent(const base::NativeEvent
& event
) {
742 void IncrementTouchIdRefCount(const base::NativeEvent
& xev
) {
743 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
745 if (!manager
->GetEventData(
746 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
750 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
751 factory
->AcquireSlotForTrackingID(tracking_id
);
754 void ClearTouchIdIfReleased(const base::NativeEvent
& xev
) {
755 ui::EventType type
= ui::EventTypeFromNative(xev
);
756 if (type
== ui::ET_TOUCH_CANCELLED
||
757 type
== ui::ET_TOUCH_RELEASED
) {
758 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
759 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
761 if (manager
->GetEventData(
762 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
763 factory
->ReleaseSlotForTrackingID(tracking_id
);
768 int GetTouchId(const base::NativeEvent
& xev
) {
770 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
772 if (!manager
->GetEventData(
773 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
774 LOG(ERROR
) << "Could not get the tracking ID for the event. Using 0.";
776 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
777 slot
= factory
->GetSlotForTrackingID(tracking_id
);
782 float GetTouchRadiusX(const base::NativeEvent
& native_event
) {
783 double radius
= GetTouchParamFromXEvent(native_event
,
784 ui::DeviceDataManagerX11::DT_TOUCH_MAJOR
, 0.0) / 2.0;
785 ScaleTouchRadius(native_event
, &radius
);
789 float GetTouchRadiusY(const base::NativeEvent
& native_event
) {
790 double radius
= GetTouchParamFromXEvent(native_event
,
791 ui::DeviceDataManagerX11::DT_TOUCH_MINOR
, 0.0) / 2.0;
792 ScaleTouchRadius(native_event
, &radius
);
796 float GetTouchAngle(const base::NativeEvent
& native_event
) {
797 return GetTouchParamFromXEvent(native_event
,
798 ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION
, 0.0) / 2.0;
801 float GetTouchForce(const base::NativeEvent
& native_event
) {
803 force
= GetTouchParamFromXEvent(native_event
,
804 ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE
, 0.0);
805 unsigned int deviceid
=
806 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
)->sourceid
;
807 // Force is normalized to fall into [0, 1]
808 if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData(
809 deviceid
, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE
, &force
))
814 bool GetScrollOffsets(const base::NativeEvent
& native_event
,
817 float* x_offset_ordinal
,
818 float* y_offset_ordinal
,
820 if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event
))
823 // Temp values to prevent passing NULLs to DeviceDataManager.
824 float x_offset_
, y_offset_
;
825 float x_offset_ordinal_
, y_offset_ordinal_
;
828 x_offset
= &x_offset_
;
830 y_offset
= &y_offset_
;
831 if (!x_offset_ordinal
)
832 x_offset_ordinal
= &x_offset_ordinal_
;
833 if (!y_offset_ordinal
)
834 y_offset_ordinal
= &y_offset_ordinal_
;
836 finger_count
= &finger_count_
;
838 DeviceDataManagerX11::GetInstance()->GetScrollOffsets(
841 x_offset_ordinal
, y_offset_ordinal
,
846 bool GetFlingData(const base::NativeEvent
& native_event
,
852 if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event
))
856 float vx_ordinal_
, vy_ordinal_
;
863 vx_ordinal
= &vx_ordinal_
;
865 vy_ordinal
= &vy_ordinal_
;
867 is_cancel
= &is_cancel_
;
869 DeviceDataManagerX11::GetInstance()->GetFlingData(
870 native_event
, vx
, vy
, vx_ordinal
, vy_ordinal
, is_cancel
);
874 void UpdateX11EventForFlags(Event
* event
) {
875 XEvent
* xev
= event
->native_event();
881 xev
->xkey
.state
= UpdateX11EventFlags(event
->flags(), xev
->xkey
.state
);
886 UpdateX11EventFlags(event
->flags(), xev
->xbutton
.state
);
889 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
891 xievent
->mods
.effective
=
892 UpdateX11EventFlags(event
->flags(), xievent
->mods
.effective
);
900 void UpdateX11EventForChangedButtonFlags(MouseEvent
* event
) {
901 XEvent
* xev
= event
->native_event();
907 xev
->xbutton
.button
= UpdateX11EventButton(event
->changed_button_flags(),
908 xev
->xbutton
.button
);
911 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
912 CHECK(xievent
&& (xievent
->evtype
== XI_ButtonPress
||
913 xievent
->evtype
== XI_ButtonRelease
));
915 UpdateX11EventButton(event
->changed_button_flags(), xievent
->detail
);