Get foreground tab on Android
[chromium-blink-merge.git] / ui / events / x / events_x.cc
blobf8f2decec66a5a2c2f6715f6a0cda7cb61eebef8
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"
7 #include <cmath>
8 #include <string.h>
9 #include <X11/extensions/XInput.h>
10 #include <X11/extensions/XInput2.h>
11 #include <X11/Xlib.h>
13 #include "base/logging.h"
14 #include "base/memory/singleton.h"
15 #include "base/message_loop/message_pump_x11.h"
16 #include "ui/events/event_utils.h"
17 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
18 #include "ui/events/x/device_data_manager.h"
19 #include "ui/events/x/device_list_cache_x.h"
20 #include "ui/events/x/touch_factory_x11.h"
21 #include "ui/gfx/display.h"
22 #include "ui/gfx/point.h"
23 #include "ui/gfx/rect.h"
24 #include "ui/gfx/screen.h"
25 #include "ui/gfx/x/x11_atom_cache.h"
26 #include "ui/gfx/x/x11_types.h"
28 namespace {
30 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
31 const int kWheelScrollAmount = 53;
33 const int kMinWheelButton = 4;
34 const int kMaxWheelButton = 7;
36 // A class to track current modifier state on master device. Only track ctrl,
37 // alt, shift and caps lock keys currently. The tracked state can then be used
38 // by floating device.
39 class XModifierStateWatcher{
40 public:
41 static XModifierStateWatcher* GetInstance() {
42 return Singleton<XModifierStateWatcher>::get();
45 void UpdateStateFromEvent(const base::NativeEvent& native_event) {
46 // Floating device can't access the modifer state from master device.
47 // We need to track the states of modifier keys in a singleton for
48 // floating devices such as touch screen. Issue 106426 is one example
49 // of why we need the modifier states for floating device.
50 state_ = native_event->xkey.state;
51 // master_state is the state before key press. We need to track the
52 // state after key press for floating device. Currently only ctrl,
53 // shift, alt and caps lock keys are tracked.
54 ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
55 unsigned int mask = 0;
57 switch (keyboard_code) {
58 case ui::VKEY_CONTROL: {
59 mask = ControlMask;
60 break;
62 case ui::VKEY_SHIFT: {
63 mask = ShiftMask;
64 break;
66 case ui::VKEY_MENU: {
67 mask = Mod1Mask;
68 break;
70 case ui::VKEY_CAPITAL: {
71 mask = LockMask;
72 break;
74 default:
75 break;
78 if (native_event->type == KeyPress)
79 state_ |= mask;
80 else
81 state_ &= ~mask;
84 // Returns the current modifer state in master device. It only contains the
85 // state of ctrl, shift, alt and caps lock keys.
86 unsigned int state() { return state_; }
88 private:
89 friend struct DefaultSingletonTraits<XModifierStateWatcher>;
91 XModifierStateWatcher() : state_(0) { }
93 unsigned int state_;
95 DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher);
98 #if defined(USE_XI2_MT)
99 // Detects if a touch event is a driver-generated 'special event'.
100 // A 'special event' is a touch event with maximum radius and pressure at
101 // location (0, 0).
102 // This needs to be done in a cleaner way: http://crbug.com/169256
103 bool TouchEventIsGeneratedHack(const base::NativeEvent& native_event) {
104 XIDeviceEvent* event =
105 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
106 CHECK(event->evtype == XI_TouchBegin ||
107 event->evtype == XI_TouchUpdate ||
108 event->evtype == XI_TouchEnd);
110 // Force is normalized to [0, 1].
111 if (ui::GetTouchForce(native_event) < 1.0f)
112 return false;
114 if (ui::EventLocationFromNative(native_event) != gfx::Point())
115 return false;
117 // Radius is in pixels, and the valuator is the diameter in pixels.
118 double radius = ui::GetTouchRadiusX(native_event), min, max;
119 unsigned int deviceid =
120 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
121 if (!ui::DeviceDataManager::GetInstance()->GetDataRange(
122 deviceid, ui::DeviceDataManager::DT_TOUCH_MAJOR, &min, &max)) {
123 return false;
126 return radius * 2 == max;
128 #endif
130 int GetEventFlagsFromXState(unsigned int state) {
131 int flags = 0;
132 if (state & ControlMask)
133 flags |= ui::EF_CONTROL_DOWN;
134 if (state & ShiftMask)
135 flags |= ui::EF_SHIFT_DOWN;
136 if (state & Mod1Mask)
137 flags |= ui::EF_ALT_DOWN;
138 if (state & LockMask)
139 flags |= ui::EF_CAPS_LOCK_DOWN;
140 if (state & Mod5Mask)
141 flags |= ui::EF_ALTGR_DOWN;
142 if (state & Button1Mask)
143 flags |= ui::EF_LEFT_MOUSE_BUTTON;
144 if (state & Button2Mask)
145 flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
146 if (state & Button3Mask)
147 flags |= ui::EF_RIGHT_MOUSE_BUTTON;
148 return flags;
151 // Get the event flag for the button in XButtonEvent. During a ButtonPress
152 // event, |state| in XButtonEvent does not include the button that has just been
153 // pressed. Instead |state| contains flags for the buttons (if any) that had
154 // already been pressed before the current button, and |button| stores the most
155 // current pressed button. So, if you press down left mouse button, and while
156 // pressing it down, press down the right mouse button, then for the latter
157 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
158 // would be 3.
159 int GetEventFlagsForButton(int button) {
160 switch (button) {
161 case 1:
162 return ui::EF_LEFT_MOUSE_BUTTON;
163 case 2:
164 return ui::EF_MIDDLE_MOUSE_BUTTON;
165 case 3:
166 return ui::EF_RIGHT_MOUSE_BUTTON;
167 default:
168 return 0;
172 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
173 int buttonflags = 0;
174 for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
175 if (XIMaskIsSet(xievent->buttons.mask, i)) {
176 int button = (xievent->sourceid == xievent->deviceid) ?
177 ui::DeviceDataManager::GetInstance()->GetMappedButton(i) : i;
178 buttonflags |= GetEventFlagsForButton(button);
181 return buttonflags;
184 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
185 XIDeviceEvent* event =
186 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
187 #if defined(USE_XI2_MT)
188 switch(event->evtype) {
189 case XI_TouchBegin:
190 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
191 ui::ET_TOUCH_PRESSED;
192 case XI_TouchUpdate:
193 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
194 ui::ET_TOUCH_MOVED;
195 case XI_TouchEnd:
196 return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED :
197 ui::ET_TOUCH_RELEASED;
199 #endif // defined(USE_XI2_MT)
201 DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid));
202 switch (event->evtype) {
203 case XI_ButtonPress:
204 return ui::ET_TOUCH_PRESSED;
205 case XI_ButtonRelease:
206 return ui::ET_TOUCH_RELEASED;
207 case XI_Motion:
208 // Should not convert any emulated Motion event from touch device to
209 // touch event.
210 if (!(event->flags & XIPointerEmulated) &&
211 GetButtonMaskForX2Event(event))
212 return ui::ET_TOUCH_MOVED;
213 return ui::ET_UNKNOWN;
214 default:
215 NOTREACHED();
217 return ui::ET_UNKNOWN;
220 double GetTouchParamFromXEvent(XEvent* xev,
221 ui::DeviceDataManager::DataType val,
222 double default_value) {
223 ui::DeviceDataManager::GetInstance()->GetEventData(
224 *xev, val, &default_value);
225 return default_value;
228 Atom GetNoopEventAtom() {
229 return XInternAtom(gfx::GetXDisplay(), "noop", False);
232 } // namespace
234 namespace ui {
236 void UpdateDeviceList() {
237 XDisplay* display = gfx::GetXDisplay();
238 DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
239 TouchFactory::GetInstance()->UpdateDeviceList(display);
240 DeviceDataManager::GetInstance()->UpdateDeviceList(display);
243 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
244 switch (native_event->type) {
245 case KeyPress:
246 return ET_KEY_PRESSED;
247 case KeyRelease:
248 return ET_KEY_RELEASED;
249 case ButtonPress:
250 if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
251 static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
252 return ET_MOUSEWHEEL;
253 return ET_MOUSE_PRESSED;
254 case ButtonRelease:
255 // Drop wheel events; we should've already scrolled on the press.
256 if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
257 static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
258 return ET_UNKNOWN;
259 return ET_MOUSE_RELEASED;
260 case MotionNotify:
261 if (native_event->xmotion.state &
262 (Button1Mask | Button2Mask | Button3Mask))
263 return ET_MOUSE_DRAGGED;
264 return ET_MOUSE_MOVED;
265 case EnterNotify:
266 // The standard on Windows is to send a MouseMove event when the mouse
267 // first enters a window instead of sending a special mouse enter event.
268 // To be consistent we follow the same style.
269 return ET_MOUSE_MOVED;
270 case LeaveNotify:
271 return ET_MOUSE_EXITED;
272 case GenericEvent: {
273 TouchFactory* factory = TouchFactory::GetInstance();
274 if (!factory->ShouldProcessXI2Event(native_event))
275 return ET_UNKNOWN;
277 XIDeviceEvent* xievent =
278 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
280 if (factory->IsTouchDevice(xievent->sourceid))
281 return GetTouchEventType(native_event);
283 switch (xievent->evtype) {
284 case XI_ButtonPress: {
285 int button = EventButtonFromNative(native_event);
286 if (button >= kMinWheelButton && button <= kMaxWheelButton)
287 return ET_MOUSEWHEEL;
288 return ET_MOUSE_PRESSED;
290 case XI_ButtonRelease: {
291 int button = EventButtonFromNative(native_event);
292 // Drop wheel events; we should've already scrolled on the press.
293 if (button >= kMinWheelButton && button <= kMaxWheelButton)
294 return ET_UNKNOWN;
295 return ET_MOUSE_RELEASED;
297 case XI_Motion: {
298 bool is_cancel;
299 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) {
300 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
301 } else if (DeviceDataManager::GetInstance()->IsScrollEvent(
302 native_event)) {
303 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
304 } else if (DeviceDataManager::GetInstance()->IsCMTMetricsEvent(
305 native_event)) {
306 return ET_UMA_DATA;
307 } else if (GetButtonMaskForX2Event(xievent)) {
308 return ET_MOUSE_DRAGGED;
309 } else {
310 return ET_MOUSE_MOVED;
315 default:
316 break;
318 return ET_UNKNOWN;
321 int EventFlagsFromNative(const base::NativeEvent& native_event) {
322 switch (native_event->type) {
323 case KeyPress:
324 case KeyRelease: {
325 XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event);
326 return GetEventFlagsFromXState(native_event->xkey.state);
328 case ButtonPress:
329 case ButtonRelease: {
330 int flags = GetEventFlagsFromXState(native_event->xbutton.state);
331 const EventType type = EventTypeFromNative(native_event);
332 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
333 flags |= GetEventFlagsForButton(native_event->xbutton.button);
334 return flags;
336 case MotionNotify:
337 return GetEventFlagsFromXState(native_event->xmotion.state);
338 case GenericEvent: {
339 XIDeviceEvent* xievent =
340 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
342 switch (xievent->evtype) {
343 #if defined(USE_XI2_MT)
344 case XI_TouchBegin:
345 case XI_TouchUpdate:
346 case XI_TouchEnd:
347 return GetButtonMaskForX2Event(xievent) |
348 GetEventFlagsFromXState(xievent->mods.effective) |
349 GetEventFlagsFromXState(
350 XModifierStateWatcher::GetInstance()->state());
351 break;
352 #endif
353 case XI_ButtonPress:
354 case XI_ButtonRelease: {
355 const bool touch =
356 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
357 int flags = GetButtonMaskForX2Event(xievent) |
358 GetEventFlagsFromXState(xievent->mods.effective);
359 if (touch) {
360 flags |= GetEventFlagsFromXState(
361 XModifierStateWatcher::GetInstance()->state());
364 const EventType type = EventTypeFromNative(native_event);
365 int button = EventButtonFromNative(native_event);
366 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
367 flags |= GetEventFlagsForButton(button);
368 return flags;
370 case XI_Motion:
371 return GetButtonMaskForX2Event(xievent) |
372 GetEventFlagsFromXState(xievent->mods.effective);
376 return 0;
379 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
380 switch(native_event->type) {
381 case KeyPress:
382 case KeyRelease:
383 return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
384 case ButtonPress:
385 case ButtonRelease:
386 return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
387 break;
388 case MotionNotify:
389 return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
390 break;
391 case EnterNotify:
392 case LeaveNotify:
393 return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
394 break;
395 case GenericEvent: {
396 double start, end;
397 double touch_timestamp;
398 if (GetGestureTimes(native_event, &start, &end)) {
399 // If the driver supports gesture times, use them.
400 return base::TimeDelta::FromMicroseconds(end * 1000000);
401 } else if (DeviceDataManager::GetInstance()->GetEventData(*native_event,
402 DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP, &touch_timestamp)) {
403 return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
404 } else {
405 XIDeviceEvent* xide =
406 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
407 return base::TimeDelta::FromMilliseconds(xide->time);
409 break;
412 NOTREACHED();
413 return base::TimeDelta();
416 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
417 switch (native_event->type) {
418 case EnterNotify:
419 case LeaveNotify:
420 return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
421 case ButtonPress:
422 case ButtonRelease:
423 return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
424 case MotionNotify:
425 return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
426 case GenericEvent: {
427 XIDeviceEvent* xievent =
428 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
429 return gfx::Point(round(xievent->event_x),
430 round(xievent->event_y));
433 return gfx::Point();
436 gfx::Point EventSystemLocationFromNative(
437 const base::NativeEvent& native_event) {
438 switch (native_event->type) {
439 case EnterNotify:
440 case LeaveNotify: {
441 return gfx::Point(native_event->xcrossing.x_root,
442 native_event->xcrossing.y_root);
444 case ButtonPress:
445 case ButtonRelease: {
446 return gfx::Point(native_event->xbutton.x_root,
447 native_event->xbutton.y_root);
449 case MotionNotify: {
450 return gfx::Point(native_event->xmotion.x_root,
451 native_event->xmotion.y_root);
453 case GenericEvent: {
454 XIDeviceEvent* xievent =
455 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
456 return gfx::Point(xievent->root_x, xievent->root_y);
460 return gfx::Point();
463 int EventButtonFromNative(const base::NativeEvent& native_event) {
464 CHECK_EQ(GenericEvent, native_event->type);
465 XIDeviceEvent* xievent =
466 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
467 int button = xievent->detail;
469 return (xievent->sourceid == xievent->deviceid) ?
470 DeviceDataManager::GetInstance()->GetMappedButton(button) : button;
473 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
474 return KeyboardCodeFromXKeyEvent(native_event);
477 bool IsMouseEvent(const base::NativeEvent& native_event) {
478 if (native_event->type == EnterNotify ||
479 native_event->type == LeaveNotify ||
480 native_event->type == ButtonPress ||
481 native_event->type == ButtonRelease ||
482 native_event->type == MotionNotify)
483 return true;
484 if (native_event->type == GenericEvent) {
485 XIDeviceEvent* xievent =
486 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
487 return xievent->evtype == XI_ButtonPress ||
488 xievent->evtype == XI_ButtonRelease ||
489 xievent->evtype == XI_Motion;
491 return false;
494 int GetChangedMouseButtonFlagsFromNative(
495 const base::NativeEvent& native_event) {
496 switch (native_event->type) {
497 case ButtonPress:
498 case ButtonRelease:
499 return GetEventFlagsFromXState(native_event->xbutton.state);
500 case GenericEvent: {
501 XIDeviceEvent* xievent =
502 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
503 switch (xievent->evtype) {
504 case XI_ButtonPress:
505 case XI_ButtonRelease:
506 return GetEventFlagsForButton(EventButtonFromNative(native_event));
507 default:
508 break;
511 default:
512 break;
514 return 0;
517 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
518 float x_offset, y_offset;
519 if (GetScrollOffsets(
520 native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
521 return gfx::Vector2d(static_cast<int>(x_offset),
522 static_cast<int>(y_offset));
525 int button = native_event->type == GenericEvent ?
526 EventButtonFromNative(native_event) : native_event->xbutton.button;
528 switch (button) {
529 case 4:
530 return gfx::Vector2d(0, kWheelScrollAmount);
531 case 5:
532 return gfx::Vector2d(0, -kWheelScrollAmount);
533 default:
534 // TODO(derat): Do something for horizontal scrolls (buttons 6 and 7)?
535 return gfx::Vector2d();
539 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
540 ui::EventType type = ui::EventTypeFromNative(xev);
541 if (type == ui::ET_TOUCH_CANCELLED ||
542 type == ui::ET_TOUCH_RELEASED) {
543 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
544 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
545 double tracking_id;
546 if (manager->GetEventData(
547 *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
548 factory->ReleaseSlotForTrackingID(tracking_id);
553 int GetTouchId(const base::NativeEvent& xev) {
554 double slot = 0;
555 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
556 double tracking_id;
557 if (!manager->GetEventData(
558 *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
559 LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
560 } else {
561 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
562 slot = factory->GetSlotForTrackingID(tracking_id);
564 return slot;
567 float GetTouchRadiusX(const base::NativeEvent& native_event) {
568 return GetTouchParamFromXEvent(native_event,
569 ui::DeviceDataManager::DT_TOUCH_MAJOR, 0.0) / 2.0;
572 float GetTouchRadiusY(const base::NativeEvent& native_event) {
573 return GetTouchParamFromXEvent(native_event,
574 ui::DeviceDataManager::DT_TOUCH_MINOR, 0.0) / 2.0;
577 float GetTouchAngle(const base::NativeEvent& native_event) {
578 return GetTouchParamFromXEvent(native_event,
579 ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
582 float GetTouchForce(const base::NativeEvent& native_event) {
583 double force = 0.0;
584 force = GetTouchParamFromXEvent(native_event,
585 ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0.0);
586 unsigned int deviceid =
587 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
588 // Force is normalized to fall into [0, 1]
589 if (!ui::DeviceDataManager::GetInstance()->NormalizeData(
590 deviceid, ui::DeviceDataManager::DT_TOUCH_PRESSURE, &force))
591 force = 0.0;
592 return force;
595 bool GetScrollOffsets(const base::NativeEvent& native_event,
596 float* x_offset,
597 float* y_offset,
598 float* x_offset_ordinal,
599 float* y_offset_ordinal,
600 int* finger_count) {
601 if (!DeviceDataManager::GetInstance()->IsScrollEvent(native_event))
602 return false;
604 // Temp values to prevent passing NULLs to DeviceDataManager.
605 float x_offset_, y_offset_;
606 float x_offset_ordinal_, y_offset_ordinal_;
607 int finger_count_;
608 if (!x_offset)
609 x_offset = &x_offset_;
610 if (!y_offset)
611 y_offset = &y_offset_;
612 if (!x_offset_ordinal)
613 x_offset_ordinal = &x_offset_ordinal_;
614 if (!y_offset_ordinal)
615 y_offset_ordinal = &y_offset_ordinal_;
616 if (!finger_count)
617 finger_count = &finger_count_;
619 DeviceDataManager::GetInstance()->GetScrollOffsets(
620 native_event,
621 x_offset, y_offset,
622 x_offset_ordinal, y_offset_ordinal,
623 finger_count);
624 return true;
627 bool GetFlingData(const base::NativeEvent& native_event,
628 float* vx,
629 float* vy,
630 float* vx_ordinal,
631 float* vy_ordinal,
632 bool* is_cancel) {
633 if (!DeviceDataManager::GetInstance()->IsFlingEvent(native_event))
634 return false;
636 float vx_, vy_;
637 float vx_ordinal_, vy_ordinal_;
638 bool is_cancel_;
639 if (!vx)
640 vx = &vx_;
641 if (!vy)
642 vy = &vy_;
643 if (!vx_ordinal)
644 vx_ordinal = &vx_ordinal_;
645 if (!vy_ordinal)
646 vy_ordinal = &vy_ordinal_;
647 if (!is_cancel)
648 is_cancel = &is_cancel_;
650 DeviceDataManager::GetInstance()->GetFlingData(
651 native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
652 return true;
655 bool GetGestureTimes(const base::NativeEvent& native_event,
656 double* start_time,
657 double* end_time) {
658 if (!DeviceDataManager::GetInstance()->HasGestureTimes(native_event))
659 return false;
661 double start_time_, end_time_;
662 if (!start_time)
663 start_time = &start_time_;
664 if (!end_time)
665 end_time = &end_time_;
667 DeviceDataManager::GetInstance()->GetGestureTimes(
668 native_event, start_time, end_time);
669 return true;
672 void SetNaturalScroll(bool enabled) {
673 DeviceDataManager::GetInstance()->set_natural_scroll_enabled(enabled);
676 bool IsNaturalScrollEnabled() {
677 return DeviceDataManager::GetInstance()->natural_scroll_enabled();
680 bool IsTouchpadEvent(const base::NativeEvent& event) {
681 return DeviceDataManager::GetInstance()->IsTouchpadXInputEvent(event);
684 bool IsNoopEvent(const base::NativeEvent& event) {
685 return (event->type == ClientMessage &&
686 event->xclient.message_type == GetNoopEventAtom());
689 base::NativeEvent CreateNoopEvent() {
690 static XEvent* noop = NULL;
691 if (!noop) {
692 noop = new XEvent();
693 memset(noop, 0, sizeof(XEvent));
694 noop->xclient.type = ClientMessage;
695 noop->xclient.window = None;
696 noop->xclient.format = 8;
697 DCHECK(!noop->xclient.display);
699 // Make sure we use atom from current xdisplay, which may
700 // change during the test.
701 noop->xclient.message_type = GetNoopEventAtom();
702 return noop;
705 } // namespace ui