Sort unlaunched apps on app list start page by apps grid order.
[chromium-blink-merge.git] / ui / events / x / events_x.cc
blob6c83976b32e4b3409b5dbf75fb90c0bf9acd97d0
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 <string.h>
8 #include <X11/extensions/XInput.h>
9 #include <X11/extensions/XInput2.h>
10 #include <X11/XKBlib.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <cmath>
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"
30 namespace {
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{
42 public:
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:
50 return ControlMask;
51 case ui::VKEY_SHIFT:
52 return ShiftMask;
53 case ui::VKEY_MENU:
54 return Mod1Mask;
55 case ui::VKEY_CAPITAL:
56 return LockMask;
57 default:
58 return 0;
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) {
70 case KeyPress:
71 state_ = native_event->xkey.state | mask;
72 break;
73 case KeyRelease:
74 state_ = native_event->xkey.state & ~mask;
75 break;
76 case GenericEvent: {
77 XIDeviceEvent* xievent =
78 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
79 switch (xievent->evtype) {
80 case XI_KeyPress:
81 state_ = xievent->mods.effective |= mask;
82 break;
83 case XI_KeyRelease:
84 state_ = xievent->mods.effective &= ~mask;
85 break;
86 default:
87 NOTREACHED();
88 break;
90 break;
92 default:
93 NOTREACHED();
94 break;
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_; }
102 private:
103 friend struct DefaultSingletonTraits<XModifierStateWatcher>;
105 XModifierStateWatcher() : state_(0) { }
107 unsigned int state_;
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
114 // location (0, 0).
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)
125 return false;
127 if (ui::EventLocationFromNative(native_event) != gfx::Point())
128 return false;
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)) {
136 return false;
139 return radius * 2 == max;
142 int GetEventFlagsFromXState(unsigned int state) {
143 int flags = 0;
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;
164 return flags;
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;
172 #else
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;
188 #endif
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) |
195 ime_fabricated_flag;
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) |
205 (IsKeypadKey(
206 XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0))
207 ? ui::EF_NUMPAD_KEY
208 : 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|
218 // would be 3.
219 int GetEventFlagsForButton(int button) {
220 switch (button) {
221 case 1:
222 return ui::EF_LEFT_MOUSE_BUTTON;
223 case 2:
224 return ui::EF_MIDDLE_MOUSE_BUTTON;
225 case 3:
226 return ui::EF_RIGHT_MOUSE_BUTTON;
227 default:
228 return 0;
232 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
233 int buttonflags = 0;
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);
241 return buttonflags;
244 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
245 XIDeviceEvent* event =
246 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
247 switch(event->evtype) {
248 case XI_TouchBegin:
249 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
250 ui::ET_TOUCH_PRESSED;
251 case XI_TouchUpdate:
252 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
253 ui::ET_TOUCH_MOVED;
254 case XI_TouchEnd:
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) {
261 case XI_ButtonPress:
262 return ui::ET_TOUCH_PRESSED;
263 case XI_ButtonRelease:
264 return ui::ET_TOUCH_RELEASED;
265 case XI_Motion:
266 // Should not convert any emulated Motion event from touch device to
267 // touch event.
268 if (!(event->flags & XIPointerEmulated) &&
269 GetButtonMaskForX2Event(event))
270 return ui::ET_TOUCH_MOVED;
271 return ui::ET_UNKNOWN;
272 default:
273 NOTREACHED();
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) {
294 static struct {
295 int ui;
296 int x;
297 } 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;
314 else
315 new_x_flags &= ~flags[i].x;
317 return new_x_flags;
320 unsigned int UpdateX11EventButton(int ui_flag, unsigned int old_x_button) {
321 switch (ui_flag) {
322 case ui::EF_LEFT_MOUSE_BUTTON:
323 return Button1;
324 case ui::EF_MIDDLE_MOUSE_BUTTON:
325 return Button2;
326 case ui::EF_RIGHT_MOUSE_BUTTON:
327 return Button3;
328 default:
329 return old_x_button;
331 NOTREACHED();
334 bool GetGestureTimes(const base::NativeEvent& native_event,
335 double* start_time,
336 double* end_time) {
337 if (!ui::DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event))
338 return false;
340 double start_time_, end_time_;
341 if (!start_time)
342 start_time = &start_time_;
343 if (!end_time)
344 end_time = &end_time_;
346 ui::DeviceDataManagerX11::GetInstance()->GetGestureTimes(
347 native_event, start_time, end_time);
348 return true;
351 } // namespace
353 namespace ui {
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)) {
369 return ET_UNKNOWN;
372 switch (native_event->type) {
373 case KeyPress:
374 return ET_KEY_PRESSED;
375 case KeyRelease:
376 return ET_KEY_RELEASED;
377 case ButtonPress:
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;
382 case ButtonRelease:
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)
386 return ET_UNKNOWN;
387 return ET_MOUSE_RELEASED;
388 case MotionNotify:
389 if (native_event->xmotion.state &
390 (Button1Mask | Button2Mask | Button3Mask))
391 return ET_MOUSE_DRAGGED;
392 return ET_MOUSE_MOVED;
393 case EnterNotify:
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;
398 case LeaveNotify:
399 return ET_MOUSE_EXITED;
400 case GenericEvent: {
401 TouchFactory* factory = TouchFactory::GetInstance();
402 if (!factory->ShouldProcessXI2Event(native_event))
403 return ET_UNKNOWN;
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) {
415 case XI_TouchBegin:
416 return ui::ET_TOUCH_PRESSED;
417 case XI_TouchUpdate:
418 return ui::ET_TOUCH_MOVED;
419 case XI_TouchEnd:
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)
431 return ET_UNKNOWN;
432 return ET_MOUSE_RELEASED;
434 case XI_Motion: {
435 bool is_cancel;
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
441 : ET_MOUSEWHEEL;
443 if (devices->IsCMTMetricsEvent(native_event))
444 return ET_UMA_DATA;
445 if (GetButtonMaskForX2Event(xievent))
446 return ET_MOUSE_DRAGGED;
447 return ET_MOUSE_MOVED;
449 case XI_KeyPress:
450 return ET_KEY_PRESSED;
451 case XI_KeyRelease:
452 return ET_KEY_RELEASED;
455 default:
456 break;
458 return ET_UNKNOWN;
461 int EventFlagsFromNative(const base::NativeEvent& native_event) {
462 switch (native_event->type) {
463 case KeyPress:
464 case KeyRelease: {
465 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event);
466 return GetEventFlagsFromXKeyEvent(native_event);
468 case ButtonPress:
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);
474 return flags;
476 case EnterNotify:
477 case LeaveNotify:
478 return GetEventFlagsFromXState(native_event->xcrossing.state);
479 case MotionNotify:
480 return GetEventFlagsFromXState(native_event->xmotion.state);
481 case GenericEvent: {
482 XIDeviceEvent* xievent =
483 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
485 switch (xievent->evtype) {
486 case XI_TouchBegin:
487 case XI_TouchUpdate:
488 case XI_TouchEnd:
489 return GetButtonMaskForX2Event(xievent) |
490 GetEventFlagsFromXState(xievent->mods.effective) |
491 GetEventFlagsFromXState(
492 XModifierStateWatcher::GetInstance()->state());
493 break;
494 case XI_ButtonPress:
495 case XI_ButtonRelease: {
496 const bool touch =
497 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
498 int flags = GetButtonMaskForX2Event(xievent) |
499 GetEventFlagsFromXState(xievent->mods.effective);
500 if (touch) {
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);
509 return flags;
511 case XI_Motion:
512 return GetButtonMaskForX2Event(xievent) |
513 GetEventFlagsFromXState(xievent->mods.effective);
514 case XI_KeyPress:
515 case XI_KeyRelease: {
516 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
517 native_event);
518 return GetEventFlagsFromXGenericEvent(native_event);
523 return 0;
526 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
527 switch(native_event->type) {
528 case KeyPress:
529 case KeyRelease:
530 return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
531 case ButtonPress:
532 case ButtonRelease:
533 return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
534 break;
535 case MotionNotify:
536 return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
537 break;
538 case EnterNotify:
539 case LeaveNotify:
540 return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
541 break;
542 case GenericEvent: {
543 double start, end;
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(
549 *native_event,
550 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP,
551 &touch_timestamp)) {
552 return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
553 } else {
554 XIDeviceEvent* xide =
555 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
556 return base::TimeDelta::FromMilliseconds(xide->time);
558 break;
561 NOTREACHED();
562 return base::TimeDelta();
565 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
566 switch (native_event->type) {
567 case EnterNotify:
568 case LeaveNotify:
569 return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
570 case ButtonPress:
571 case ButtonRelease:
572 return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
573 case MotionNotify:
574 return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
575 case GenericEvent: {
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) {
582 case XI_TouchBegin:
583 case XI_TouchUpdate:
584 case XI_TouchEnd:
585 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer(
586 xievent->deviceid, &x, &y);
587 break;
588 default:
589 break;
591 #endif // defined(OS_CHROMEOS)
592 return gfx::Point(static_cast<int>(x), static_cast<int>(y));
595 return gfx::Point();
598 gfx::Point EventSystemLocationFromNative(
599 const base::NativeEvent& native_event) {
600 switch (native_event->type) {
601 case EnterNotify:
602 case LeaveNotify: {
603 return gfx::Point(native_event->xcrossing.x_root,
604 native_event->xcrossing.y_root);
606 case ButtonPress:
607 case ButtonRelease: {
608 return gfx::Point(native_event->xbutton.x_root,
609 native_event->xbutton.y_root);
611 case MotionNotify: {
612 return gfx::Point(native_event->xmotion.x_root,
613 native_event->xmotion.y_root);
615 case GenericEvent: {
616 XIDeviceEvent* xievent =
617 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
618 return gfx::Point(xievent->root_x, xievent->root_y);
622 return gfx::Point();
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) {
647 case KeyPress:
648 case KeyRelease:
649 xkey = &native_event->xkey;
650 break;
651 case GenericEvent: {
652 XIDeviceEvent* xievent =
653 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
654 switch (xievent->evtype) {
655 case XI_KeyPress:
656 case XI_KeyRelease:
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;
661 break;
662 default:
663 NOTREACHED();
664 break;
666 break;
668 default:
669 NOTREACHED();
670 break;
672 KeySym keysym = XK_VoidSymbol;
673 if (xkey)
674 XLookupString(xkey, NULL, 0, &keysym, NULL);
675 return keysym;
678 bool IsCharFromNative(const base::NativeEvent& native_event) {
679 return false;
682 int GetChangedMouseButtonFlagsFromNative(
683 const base::NativeEvent& native_event) {
684 switch (native_event->type) {
685 case ButtonPress:
686 case ButtonRelease:
687 return GetEventFlagsFromXState(native_event->xbutton.state);
688 case GenericEvent: {
689 XIDeviceEvent* xievent =
690 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
691 switch (xievent->evtype) {
692 case XI_ButtonPress:
693 case XI_ButtonRelease:
694 return GetEventFlagsForButton(EventButtonFromNative(native_event));
695 default:
696 break;
699 default:
700 break;
702 return 0;
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;
716 switch (button) {
717 case 4:
718 return gfx::Vector2d(0, kWheelScrollAmount);
719 case 5:
720 return gfx::Vector2d(0, -kWheelScrollAmount);
721 case 6:
722 return gfx::Vector2d(kWheelScrollAmount, 0);
723 case 7:
724 return gfx::Vector2d(-kWheelScrollAmount, 0);
725 default:
726 return gfx::Vector2d();
730 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
731 if (!event || event->type == GenericEvent)
732 return NULL;
733 XEvent* copy = new XEvent;
734 *copy = *event;
735 return copy;
738 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
739 delete event;
742 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
743 ui::EventType type = ui::EventTypeFromNative(xev);
744 if (type == ui::ET_TOUCH_CANCELLED ||
745 type == ui::ET_TOUCH_RELEASED) {
746 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
747 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
748 double tracking_id;
749 if (manager->GetEventData(
750 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
751 factory->ReleaseSlotForTrackingID(tracking_id);
756 int GetTouchId(const base::NativeEvent& xev) {
757 double slot = 0;
758 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
759 double tracking_id;
760 if (!manager->GetEventData(
761 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
762 LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
763 } else {
764 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
765 slot = factory->GetSlotForTrackingID(tracking_id);
767 return slot;
770 float GetTouchRadiusX(const base::NativeEvent& native_event) {
771 double radius = GetTouchParamFromXEvent(native_event,
772 ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, 0.0) / 2.0;
773 ScaleTouchRadius(native_event, &radius);
774 return radius;
777 float GetTouchRadiusY(const base::NativeEvent& native_event) {
778 double radius = GetTouchParamFromXEvent(native_event,
779 ui::DeviceDataManagerX11::DT_TOUCH_MINOR, 0.0) / 2.0;
780 ScaleTouchRadius(native_event, &radius);
781 return radius;
784 float GetTouchAngle(const base::NativeEvent& native_event) {
785 return GetTouchParamFromXEvent(native_event,
786 ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
789 float GetTouchForce(const base::NativeEvent& native_event) {
790 double force = 0.0;
791 force = GetTouchParamFromXEvent(native_event,
792 ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, 0.0);
793 unsigned int deviceid =
794 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
795 // Force is normalized to fall into [0, 1]
796 if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData(
797 deviceid, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, &force))
798 force = 0.0;
799 return force;
802 bool GetScrollOffsets(const base::NativeEvent& native_event,
803 float* x_offset,
804 float* y_offset,
805 float* x_offset_ordinal,
806 float* y_offset_ordinal,
807 int* finger_count) {
808 if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event))
809 return false;
811 // Temp values to prevent passing NULLs to DeviceDataManager.
812 float x_offset_, y_offset_;
813 float x_offset_ordinal_, y_offset_ordinal_;
814 int finger_count_;
815 if (!x_offset)
816 x_offset = &x_offset_;
817 if (!y_offset)
818 y_offset = &y_offset_;
819 if (!x_offset_ordinal)
820 x_offset_ordinal = &x_offset_ordinal_;
821 if (!y_offset_ordinal)
822 y_offset_ordinal = &y_offset_ordinal_;
823 if (!finger_count)
824 finger_count = &finger_count_;
826 DeviceDataManagerX11::GetInstance()->GetScrollOffsets(
827 native_event,
828 x_offset, y_offset,
829 x_offset_ordinal, y_offset_ordinal,
830 finger_count);
831 return true;
834 bool GetFlingData(const base::NativeEvent& native_event,
835 float* vx,
836 float* vy,
837 float* vx_ordinal,
838 float* vy_ordinal,
839 bool* is_cancel) {
840 if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event))
841 return false;
843 float vx_, vy_;
844 float vx_ordinal_, vy_ordinal_;
845 bool is_cancel_;
846 if (!vx)
847 vx = &vx_;
848 if (!vy)
849 vy = &vy_;
850 if (!vx_ordinal)
851 vx_ordinal = &vx_ordinal_;
852 if (!vy_ordinal)
853 vy_ordinal = &vy_ordinal_;
854 if (!is_cancel)
855 is_cancel = &is_cancel_;
857 DeviceDataManagerX11::GetInstance()->GetFlingData(
858 native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
859 return true;
862 void UpdateX11EventForFlags(Event* event) {
863 XEvent* xev = event->native_event();
864 if (!xev)
865 return;
866 switch (xev->type) {
867 case KeyPress:
868 case KeyRelease:
869 xev->xkey.state = UpdateX11EventFlags(event->flags(), xev->xkey.state);
870 break;
871 case ButtonPress:
872 case ButtonRelease:
873 xev->xbutton.state =
874 UpdateX11EventFlags(event->flags(), xev->xbutton.state);
875 break;
876 case GenericEvent: {
877 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
878 DCHECK(xievent);
879 xievent->mods.effective =
880 UpdateX11EventFlags(event->flags(), xievent->mods.effective);
881 break;
883 default:
884 break;
888 void UpdateX11EventForChangedButtonFlags(MouseEvent* event) {
889 XEvent* xev = event->native_event();
890 if (!xev)
891 return;
892 switch (xev->type) {
893 case ButtonPress:
894 case ButtonRelease:
895 xev->xbutton.button = UpdateX11EventButton(event->changed_button_flags(),
896 xev->xbutton.button);
897 break;
898 case GenericEvent: {
899 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
900 CHECK(xievent && (xievent->evtype == XI_ButtonPress ||
901 xievent->evtype == XI_ButtonRelease));
902 xievent->detail =
903 UpdateX11EventButton(event->changed_button_flags(), xievent->detail);
904 break;
906 default:
907 break;
911 } // namespace ui