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_utils.h"
18 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
19 #include "ui/events/x/device_data_manager_x11.h"
20 #include "ui/events/x/device_list_cache_x.h"
21 #include "ui/events/x/touch_factory_x11.h"
22 #include "ui/gfx/display.h"
23 #include "ui/gfx/point.h"
24 #include "ui/gfx/rect.h"
25 #include "ui/gfx/screen.h"
26 #include "ui/gfx/x/x11_atom_cache.h"
27 #include "ui/gfx/x/x11_types.h"
31 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
32 const int kWheelScrollAmount
= 53;
34 const int kMinWheelButton
= 4;
35 const int kMaxWheelButton
= 7;
37 // A class to track current modifier state on master device. Only track ctrl,
38 // alt, shift and caps lock keys currently. The tracked state can then be used
39 // by floating device.
40 class XModifierStateWatcher
{
42 static XModifierStateWatcher
* GetInstance() {
43 return Singleton
<XModifierStateWatcher
>::get();
46 int StateFromKeyboardCode(ui::KeyboardCode keyboard_code
) {
47 switch (keyboard_code
) {
48 case ui::VKEY_CONTROL
:
54 case ui::VKEY_CAPITAL
:
61 void UpdateStateFromXEvent(const base::NativeEvent
& native_event
) {
62 ui::KeyboardCode keyboard_code
= ui::KeyboardCodeFromNative(native_event
);
63 unsigned int mask
= StateFromKeyboardCode(keyboard_code
);
64 // Floating device can't access the modifer state from master device.
65 // We need to track the states of modifier keys in a singleton for
66 // floating devices such as touch screen. Issue 106426 is one example
67 // of why we need the modifier states for floating device.
68 switch (native_event
->type
) {
70 state_
= native_event
->xkey
.state
| mask
;
73 state_
= native_event
->xkey
.state
& ~mask
;
76 XIDeviceEvent
* xievent
=
77 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
78 switch (xievent
->evtype
) {
80 state_
= xievent
->mods
.effective
|= mask
;
83 state_
= xievent
->mods
.effective
&= ~mask
;
97 // Returns the current modifer state in master device. It only contains the
98 // state of ctrl, shift, alt and caps lock keys.
99 unsigned int state() { return state_
; }
102 friend struct DefaultSingletonTraits
<XModifierStateWatcher
>;
104 XModifierStateWatcher() : state_(0) { }
108 DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher
);
111 #if defined(USE_XI2_MT)
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
;
143 int GetEventFlagsFromXState(unsigned int state
) {
145 if (state
& ControlMask
)
146 flags
|= ui::EF_CONTROL_DOWN
;
147 if (state
& ShiftMask
)
148 flags
|= ui::EF_SHIFT_DOWN
;
149 if (state
& Mod1Mask
)
150 flags
|= ui::EF_ALT_DOWN
;
151 if (state
& LockMask
)
152 flags
|= ui::EF_CAPS_LOCK_DOWN
;
153 if (state
& Mod3Mask
)
154 flags
|= ui::EF_MOD3_DOWN
;
155 if (state
& Mod4Mask
)
156 flags
|= ui::EF_COMMAND_DOWN
;
157 if (state
& Mod5Mask
)
158 flags
|= ui::EF_ALTGR_DOWN
;
159 if (state
& Button1Mask
)
160 flags
|= ui::EF_LEFT_MOUSE_BUTTON
;
161 if (state
& Button2Mask
)
162 flags
|= ui::EF_MIDDLE_MOUSE_BUTTON
;
163 if (state
& Button3Mask
)
164 flags
|= ui::EF_RIGHT_MOUSE_BUTTON
;
168 int GetEventFlagsFromXKeyEvent(XEvent
* xevent
) {
169 DCHECK(xevent
->type
== KeyPress
|| xevent
->type
== KeyRelease
);
171 #if defined(OS_CHROMEOS)
172 const int ime_fabricated_flag
= 0;
174 // XIM fabricates key events for the character compositions by XK_Multi_key.
175 // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in
176 // order to input "é", then XIM generates a key event with keycode=0 and
177 // state=0 for the composition, and the sequence of X11 key events will be
178 // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e. If the user used
179 // shift key and/or caps lock key, state can be ShiftMask, LockMask or both.
181 // We have to send these fabricated key events to XIM so it can correctly
182 // handle the character compositions.
183 const unsigned int shift_lock_mask
= ShiftMask
| LockMask
;
184 const bool fabricated_by_xim
=
185 xevent
->xkey
.keycode
== 0 &&
186 (xevent
->xkey
.state
& ~shift_lock_mask
) == 0;
187 const int ime_fabricated_flag
=
188 fabricated_by_xim
? ui::EF_IME_FABRICATED_KEY
: 0;
191 return GetEventFlagsFromXState(xevent
->xkey
.state
) |
192 (xevent
->xkey
.send_event
? ui::EF_FINAL
: 0) |
193 (IsKeypadKey(XLookupKeysym(&xevent
->xkey
, 0)) ? ui::EF_NUMPAD_KEY
: 0) |
194 (IsFunctionKey(XLookupKeysym(&xevent
->xkey
, 0)) ?
195 ui::EF_FUNCTION_KEY
: 0) |
199 int GetEventFlagsFromXGenericEvent(XEvent
* xevent
) {
200 DCHECK(xevent
->type
== GenericEvent
);
201 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(xevent
->xcookie
.data
);
202 DCHECK((xievent
->evtype
== XI_KeyPress
) ||
203 (xievent
->evtype
== XI_KeyRelease
));
204 return GetEventFlagsFromXState(xievent
->mods
.effective
) |
205 (xevent
->xkey
.send_event
? ui::EF_FINAL
: 0) |
207 XkbKeycodeToKeysym(xievent
->display
, xievent
->detail
, 0, 0))
212 // Get the event flag for the button in XButtonEvent. During a ButtonPress
213 // event, |state| in XButtonEvent does not include the button that has just been
214 // pressed. Instead |state| contains flags for the buttons (if any) that had
215 // already been pressed before the current button, and |button| stores the most
216 // current pressed button. So, if you press down left mouse button, and while
217 // pressing it down, press down the right mouse button, then for the latter
218 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
220 int GetEventFlagsForButton(int button
) {
223 return ui::EF_LEFT_MOUSE_BUTTON
;
225 return ui::EF_MIDDLE_MOUSE_BUTTON
;
227 return ui::EF_RIGHT_MOUSE_BUTTON
;
233 int GetButtonMaskForX2Event(XIDeviceEvent
* xievent
) {
235 for (int i
= 0; i
< 8 * xievent
->buttons
.mask_len
; i
++) {
236 if (XIMaskIsSet(xievent
->buttons
.mask
, i
)) {
237 int button
= (xievent
->sourceid
== xievent
->deviceid
) ?
238 ui::DeviceDataManagerX11::GetInstance()->GetMappedButton(i
) : i
;
239 buttonflags
|= GetEventFlagsForButton(button
);
245 ui::EventType
GetTouchEventType(const base::NativeEvent
& native_event
) {
246 XIDeviceEvent
* event
=
247 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
248 #if defined(USE_XI2_MT)
249 switch(event
->evtype
) {
251 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_UNKNOWN
:
252 ui::ET_TOUCH_PRESSED
;
254 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_UNKNOWN
:
257 return TouchEventIsGeneratedHack(native_event
) ? ui::ET_TOUCH_CANCELLED
:
258 ui::ET_TOUCH_RELEASED
;
260 #endif // defined(USE_XI2_MT)
262 DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event
->sourceid
));
263 switch (event
->evtype
) {
265 return ui::ET_TOUCH_PRESSED
;
266 case XI_ButtonRelease
:
267 return ui::ET_TOUCH_RELEASED
;
269 // Should not convert any emulated Motion event from touch device to
271 if (!(event
->flags
& XIPointerEmulated
) &&
272 GetButtonMaskForX2Event(event
))
273 return ui::ET_TOUCH_MOVED
;
274 return ui::ET_UNKNOWN
;
278 return ui::ET_UNKNOWN
;
281 double GetTouchParamFromXEvent(XEvent
* xev
,
282 ui::DeviceDataManagerX11::DataType val
,
283 double default_value
) {
284 ui::DeviceDataManagerX11::GetInstance()->GetEventData(
285 *xev
, val
, &default_value
);
286 return default_value
;
293 void UpdateDeviceList() {
294 XDisplay
* display
= gfx::GetXDisplay();
295 DeviceListCacheX::GetInstance()->UpdateDeviceList(display
);
296 TouchFactory::GetInstance()->UpdateDeviceList(display
);
297 DeviceDataManagerX11::GetInstance()->UpdateDeviceList(display
);
300 EventType
EventTypeFromNative(const base::NativeEvent
& native_event
) {
301 // Allow the DeviceDataManager to block the event. If blocked return
302 // ET_UNKNOWN as the type so this event will not be further processed.
303 // NOTE: During some events unittests there is no device data manager.
304 if (DeviceDataManager::HasInstance() &&
305 static_cast<DeviceDataManagerX11
*>(DeviceDataManager::GetInstance())->
306 IsEventBlocked(native_event
)) {
310 switch (native_event
->type
) {
312 return ET_KEY_PRESSED
;
314 return ET_KEY_RELEASED
;
316 if (static_cast<int>(native_event
->xbutton
.button
) >= kMinWheelButton
&&
317 static_cast<int>(native_event
->xbutton
.button
) <= kMaxWheelButton
)
318 return ET_MOUSEWHEEL
;
319 return ET_MOUSE_PRESSED
;
321 // Drop wheel events; we should've already scrolled on the press.
322 if (static_cast<int>(native_event
->xbutton
.button
) >= kMinWheelButton
&&
323 static_cast<int>(native_event
->xbutton
.button
) <= kMaxWheelButton
)
325 return ET_MOUSE_RELEASED
;
327 if (native_event
->xmotion
.state
&
328 (Button1Mask
| Button2Mask
| Button3Mask
))
329 return ET_MOUSE_DRAGGED
;
330 return ET_MOUSE_MOVED
;
332 // The standard on Windows is to send a MouseMove event when the mouse
333 // first enters a window instead of sending a special mouse enter event.
334 // To be consistent we follow the same style.
335 return ET_MOUSE_MOVED
;
337 return ET_MOUSE_EXITED
;
339 TouchFactory
* factory
= TouchFactory::GetInstance();
340 if (!factory
->ShouldProcessXI2Event(native_event
))
343 XIDeviceEvent
* xievent
=
344 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
346 // This check works only for master and floating slave devices. That is
347 // why it is necessary to check for the XI_Touch* events in the following
348 // switch statement to account for attached-slave touchscreens.
349 if (factory
->IsTouchDevice(xievent
->sourceid
))
350 return GetTouchEventType(native_event
);
352 switch (xievent
->evtype
) {
354 return ui::ET_TOUCH_PRESSED
;
356 return ui::ET_TOUCH_MOVED
;
358 return ui::ET_TOUCH_RELEASED
;
359 case XI_ButtonPress
: {
360 int button
= EventButtonFromNative(native_event
);
361 if (button
>= kMinWheelButton
&& button
<= kMaxWheelButton
)
362 return ET_MOUSEWHEEL
;
363 return ET_MOUSE_PRESSED
;
365 case XI_ButtonRelease
: {
366 int button
= EventButtonFromNative(native_event
);
367 // Drop wheel events; we should've already scrolled on the press.
368 if (button
>= kMinWheelButton
&& button
<= kMaxWheelButton
)
370 return ET_MOUSE_RELEASED
;
374 DeviceDataManagerX11
* devices
= DeviceDataManagerX11::GetInstance();
375 if (GetFlingData(native_event
, NULL
, NULL
, NULL
, NULL
, &is_cancel
))
376 return is_cancel
? ET_SCROLL_FLING_CANCEL
: ET_SCROLL_FLING_START
;
377 if (devices
->IsScrollEvent(native_event
)) {
378 return devices
->IsTouchpadXInputEvent(native_event
) ? ET_SCROLL
381 if (devices
->IsCMTMetricsEvent(native_event
))
383 if (GetButtonMaskForX2Event(xievent
))
384 return ET_MOUSE_DRAGGED
;
385 return ET_MOUSE_MOVED
;
388 return ET_KEY_PRESSED
;
390 return ET_KEY_RELEASED
;
399 int EventFlagsFromNative(const base::NativeEvent
& native_event
) {
400 switch (native_event
->type
) {
403 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event
);
404 return GetEventFlagsFromXKeyEvent(native_event
);
407 case ButtonRelease
: {
408 int flags
= GetEventFlagsFromXState(native_event
->xbutton
.state
);
409 const EventType type
= EventTypeFromNative(native_event
);
410 if (type
== ET_MOUSE_PRESSED
|| type
== ET_MOUSE_RELEASED
)
411 flags
|= GetEventFlagsForButton(native_event
->xbutton
.button
);
416 return GetEventFlagsFromXState(native_event
->xcrossing
.state
);
418 return GetEventFlagsFromXState(native_event
->xmotion
.state
);
420 XIDeviceEvent
* xievent
=
421 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
423 switch (xievent
->evtype
) {
424 #if defined(USE_XI2_MT)
428 return GetButtonMaskForX2Event(xievent
) |
429 GetEventFlagsFromXState(xievent
->mods
.effective
) |
430 GetEventFlagsFromXState(
431 XModifierStateWatcher::GetInstance()->state());
435 case XI_ButtonRelease
: {
437 TouchFactory::GetInstance()->IsTouchDevice(xievent
->sourceid
);
438 int flags
= GetButtonMaskForX2Event(xievent
) |
439 GetEventFlagsFromXState(xievent
->mods
.effective
);
441 flags
|= GetEventFlagsFromXState(
442 XModifierStateWatcher::GetInstance()->state());
445 const EventType type
= EventTypeFromNative(native_event
);
446 int button
= EventButtonFromNative(native_event
);
447 if ((type
== ET_MOUSE_PRESSED
|| type
== ET_MOUSE_RELEASED
) && !touch
)
448 flags
|= GetEventFlagsForButton(button
);
452 return GetButtonMaskForX2Event(xievent
) |
453 GetEventFlagsFromXState(xievent
->mods
.effective
);
455 case XI_KeyRelease
: {
456 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
458 return GetEventFlagsFromXGenericEvent(native_event
);
466 base::TimeDelta
EventTimeFromNative(const base::NativeEvent
& native_event
) {
467 switch(native_event
->type
) {
470 return base::TimeDelta::FromMilliseconds(native_event
->xkey
.time
);
473 return base::TimeDelta::FromMilliseconds(native_event
->xbutton
.time
);
476 return base::TimeDelta::FromMilliseconds(native_event
->xmotion
.time
);
480 return base::TimeDelta::FromMilliseconds(native_event
->xcrossing
.time
);
484 double touch_timestamp
;
485 if (GetGestureTimes(native_event
, &start
, &end
)) {
486 // If the driver supports gesture times, use them.
487 return base::TimeDelta::FromMicroseconds(end
* 1000000);
488 } else if (DeviceDataManagerX11::GetInstance()->GetEventData(
490 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
,
492 return base::TimeDelta::FromMicroseconds(touch_timestamp
* 1000000);
494 XIDeviceEvent
* xide
=
495 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
496 return base::TimeDelta::FromMilliseconds(xide
->time
);
502 return base::TimeDelta();
505 gfx::Point
EventLocationFromNative(const base::NativeEvent
& native_event
) {
506 switch (native_event
->type
) {
509 return gfx::Point(native_event
->xcrossing
.x
, native_event
->xcrossing
.y
);
512 return gfx::Point(native_event
->xbutton
.x
, native_event
->xbutton
.y
);
514 return gfx::Point(native_event
->xmotion
.x
, native_event
->xmotion
.y
);
516 XIDeviceEvent
* xievent
=
517 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
518 float x
= xievent
->event_x
;
519 float y
= xievent
->event_y
;
520 #if defined(OS_CHROMEOS)
521 switch (xievent
->evtype
) {
525 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer(
526 xievent
->deviceid
, &x
, &y
);
531 #endif // defined(OS_CHROMEOS)
532 return gfx::Point(static_cast<int>(x
), static_cast<int>(y
));
538 gfx::Point
EventSystemLocationFromNative(
539 const base::NativeEvent
& native_event
) {
540 switch (native_event
->type
) {
543 return gfx::Point(native_event
->xcrossing
.x_root
,
544 native_event
->xcrossing
.y_root
);
547 case ButtonRelease
: {
548 return gfx::Point(native_event
->xbutton
.x_root
,
549 native_event
->xbutton
.y_root
);
552 return gfx::Point(native_event
->xmotion
.x_root
,
553 native_event
->xmotion
.y_root
);
556 XIDeviceEvent
* xievent
=
557 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
558 return gfx::Point(xievent
->root_x
, xievent
->root_y
);
565 int EventButtonFromNative(const base::NativeEvent
& native_event
) {
566 CHECK_EQ(GenericEvent
, native_event
->type
);
567 XIDeviceEvent
* xievent
=
568 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
569 int button
= xievent
->detail
;
571 return (xievent
->sourceid
== xievent
->deviceid
) ?
572 DeviceDataManagerX11::GetInstance()->GetMappedButton(button
) : button
;
575 KeyboardCode
KeyboardCodeFromNative(const base::NativeEvent
& native_event
) {
576 return KeyboardCodeFromXKeyEvent(native_event
);
579 const char* CodeFromNative(const base::NativeEvent
& native_event
) {
580 return CodeFromXEvent(native_event
);
583 uint32
PlatformKeycodeFromNative(const base::NativeEvent
& native_event
) {
584 XKeyEvent
* xkey
= NULL
;
585 XEvent xkey_from_xi2
;
586 switch (native_event
->type
) {
589 xkey
= &native_event
->xkey
;
592 XIDeviceEvent
* xievent
=
593 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
594 switch (xievent
->evtype
) {
597 // Build an XKeyEvent corresponding to the XI2 event,
598 // so that we can call XLookupString on it.
599 InitXKeyEventFromXIDeviceEvent(*native_event
, &xkey_from_xi2
);
600 xkey
= &xkey_from_xi2
.xkey
;
612 KeySym keysym
= XK_VoidSymbol
;
614 XLookupString(xkey
, NULL
, 0, &keysym
, NULL
);
618 int GetChangedMouseButtonFlagsFromNative(
619 const base::NativeEvent
& native_event
) {
620 switch (native_event
->type
) {
623 return GetEventFlagsFromXState(native_event
->xbutton
.state
);
625 XIDeviceEvent
* xievent
=
626 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
627 switch (xievent
->evtype
) {
629 case XI_ButtonRelease
:
630 return GetEventFlagsForButton(EventButtonFromNative(native_event
));
641 gfx::Vector2d
GetMouseWheelOffset(const base::NativeEvent
& native_event
) {
642 float x_offset
, y_offset
;
643 if (GetScrollOffsets(
644 native_event
, &x_offset
, &y_offset
, NULL
, NULL
, NULL
)) {
645 return gfx::Vector2d(static_cast<int>(x_offset
),
646 static_cast<int>(y_offset
));
649 int button
= native_event
->type
== GenericEvent
?
650 EventButtonFromNative(native_event
) : native_event
->xbutton
.button
;
654 return gfx::Vector2d(0, kWheelScrollAmount
);
656 return gfx::Vector2d(0, -kWheelScrollAmount
);
658 return gfx::Vector2d(kWheelScrollAmount
, 0);
660 return gfx::Vector2d(-kWheelScrollAmount
, 0);
662 return gfx::Vector2d();
666 base::NativeEvent
CopyNativeEvent(const base::NativeEvent
& event
) {
667 if (!event
|| event
->type
== GenericEvent
)
669 XEvent
* copy
= new XEvent
;
674 void ReleaseCopiedNativeEvent(const base::NativeEvent
& event
) {
678 void ClearTouchIdIfReleased(const base::NativeEvent
& xev
) {
679 ui::EventType type
= ui::EventTypeFromNative(xev
);
680 if (type
== ui::ET_TOUCH_CANCELLED
||
681 type
== ui::ET_TOUCH_RELEASED
) {
682 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
683 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
685 if (manager
->GetEventData(
686 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
687 factory
->ReleaseSlotForTrackingID(tracking_id
);
692 int GetTouchId(const base::NativeEvent
& xev
) {
694 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
696 if (!manager
->GetEventData(
697 *xev
, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID
, &tracking_id
)) {
698 LOG(ERROR
) << "Could not get the tracking ID for the event. Using 0.";
700 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
701 slot
= factory
->GetSlotForTrackingID(tracking_id
);
706 float GetTouchRadiusX(const base::NativeEvent
& native_event
) {
707 return GetTouchParamFromXEvent(native_event
,
708 ui::DeviceDataManagerX11::DT_TOUCH_MAJOR
, 0.0) / 2.0;
711 float GetTouchRadiusY(const base::NativeEvent
& native_event
) {
712 return GetTouchParamFromXEvent(native_event
,
713 ui::DeviceDataManagerX11::DT_TOUCH_MINOR
, 0.0) / 2.0;
716 float GetTouchAngle(const base::NativeEvent
& native_event
) {
717 return GetTouchParamFromXEvent(native_event
,
718 ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION
, 0.0) / 2.0;
721 float GetTouchForce(const base::NativeEvent
& native_event
) {
723 force
= GetTouchParamFromXEvent(native_event
,
724 ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE
, 0.0);
725 unsigned int deviceid
=
726 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
)->sourceid
;
727 // Force is normalized to fall into [0, 1]
728 if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData(
729 deviceid
, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE
, &force
))
734 bool GetScrollOffsets(const base::NativeEvent
& native_event
,
737 float* x_offset_ordinal
,
738 float* y_offset_ordinal
,
740 if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event
))
743 // Temp values to prevent passing NULLs to DeviceDataManager.
744 float x_offset_
, y_offset_
;
745 float x_offset_ordinal_
, y_offset_ordinal_
;
748 x_offset
= &x_offset_
;
750 y_offset
= &y_offset_
;
751 if (!x_offset_ordinal
)
752 x_offset_ordinal
= &x_offset_ordinal_
;
753 if (!y_offset_ordinal
)
754 y_offset_ordinal
= &y_offset_ordinal_
;
756 finger_count
= &finger_count_
;
758 DeviceDataManagerX11::GetInstance()->GetScrollOffsets(
761 x_offset_ordinal
, y_offset_ordinal
,
766 bool GetFlingData(const base::NativeEvent
& native_event
,
772 if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event
))
776 float vx_ordinal_
, vy_ordinal_
;
783 vx_ordinal
= &vx_ordinal_
;
785 vy_ordinal
= &vy_ordinal_
;
787 is_cancel
= &is_cancel_
;
789 DeviceDataManagerX11::GetInstance()->GetFlingData(
790 native_event
, vx
, vy
, vx_ordinal
, vy_ordinal
, is_cancel
);
794 bool GetGestureTimes(const base::NativeEvent
& native_event
,
797 if (!DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event
))
800 double start_time_
, end_time_
;
802 start_time
= &start_time_
;
804 end_time
= &end_time_
;
806 DeviceDataManagerX11::GetInstance()->GetGestureTimes(
807 native_event
, start_time
, end_time
);