Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: ui/events/platform/x11/platform_event_utils_x11.cc

Issue 1287103004: Sync ui/events to chromium @ https://codereview.chromium.org/1210203002 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "ui/events/platform/platform_event_utils.h"
6
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>
14
15 #include "base/logging.h"
16 #include "base/memory/singleton.h"
17 #include "ui/events/event.h"
18 #include "ui/events/event_constants.h"
19 #include "ui/events/event_utils.h"
20 #include "ui/events/platform/x11/device_data_manager_x11.h"
21 #include "ui/events/platform/x11/device_list_cache_x.h"
22 #include "ui/events/platform/x11/keyboard_code_conversion_x11.h"
23 #include "ui/events/platform/x11/touch_factory_x11.h"
24 #include "ui/gfx/display.h"
25 #include "ui/gfx/point.h"
26 #include "ui/gfx/rect.h"
27 #include "ui/gfx/x/x11_atom_cache.h"
28 #include "ui/gfx/x/x11_types.h"
29
30 namespace {
31
32 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
33 const int kWheelScrollAmount = 53;
34
35 const int kMinWheelButton = 4;
36 const int kMaxWheelButton = 7;
37
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();
45 }
46
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;
59 }
60 }
61
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;
89 }
90 break;
91 }
92 default:
93 NOTREACHED();
94 break;
95 }
96 }
97
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_; }
101
102 private:
103 friend struct DefaultSingletonTraits<XModifierStateWatcher>;
104
105 XModifierStateWatcher() : state_(0) {}
106
107 unsigned int state_;
108
109 DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher);
110 };
111
112 #if defined(USE_XI2_MT)
113 // Detects if a touch event is a driver-generated 'special event'.
114 // A 'special event' is a touch event with maximum radius and pressure at
115 // location (0, 0).
116 // This needs to be done in a cleaner way: http://crbug.com/169256
117 bool TouchEventIsGeneratedHack(const base::NativeEvent& native_event) {
118 XIDeviceEvent* event =
119 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
120 CHECK(event->evtype == XI_TouchBegin || event->evtype == XI_TouchUpdate ||
121 event->evtype == XI_TouchEnd);
122
123 // Force is normalized to [0, 1].
124 if (ui::GetTouchForce(native_event) < 1.0f)
125 return false;
126
127 if (ui::EventLocationFromNative(native_event) != gfx::Point())
128 return false;
129
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;
137 }
138
139 return radius * 2 == max;
140 }
141 #endif
142
143 int GetEventFlagsFromXState(unsigned int state) {
144 int flags = 0;
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;
165 return flags;
166 }
167
168 int GetEventFlagsFromXKeyEvent(XEvent* xevent) {
169 DCHECK(xevent->type == KeyPress || xevent->type == KeyRelease);
170
171 #if defined(OS_CHROMEOS)
172 const int ime_fabricated_flag = 0;
173 #else
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.
180 //
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 && (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
189
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
193 : 0) |
194 (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_FUNCTION_KEY
195 : 0) |
196 ime_fabricated_flag;
197 }
198
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) |
206 (IsKeypadKey(
207 XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0))
208 ? ui::EF_NUMPAD_KEY
209 : 0);
210 }
211
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|
219 // would be 3.
220 int GetEventFlagsForButton(int button) {
221 switch (button) {
222 case 1:
223 return ui::EF_LEFT_MOUSE_BUTTON;
224 case 2:
225 return ui::EF_MIDDLE_MOUSE_BUTTON;
226 case 3:
227 return ui::EF_RIGHT_MOUSE_BUTTON;
228 default:
229 return 0;
230 }
231 }
232
233 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
234 int buttonflags = 0;
235 for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
236 if (XIMaskIsSet(xievent->buttons.mask, i)) {
237 int button =
238 (xievent->sourceid == xievent->deviceid)
239 ? ui::DeviceDataManagerX11::GetInstance()->GetMappedButton(i)
240 : i;
241 buttonflags |= GetEventFlagsForButton(button);
242 }
243 }
244 return buttonflags;
245 }
246
247 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
248 XIDeviceEvent* event =
249 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
250 #if defined(USE_XI2_MT)
251 switch (event->evtype) {
252 case XI_TouchBegin:
253 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN
254 : ui::ET_TOUCH_PRESSED;
255 case XI_TouchUpdate:
256 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN
257 : ui::ET_TOUCH_MOVED;
258 case XI_TouchEnd:
259 return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED
260 : ui::ET_TOUCH_RELEASED;
261 }
262 #endif // defined(USE_XI2_MT)
263
264 DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid));
265 switch (event->evtype) {
266 case XI_ButtonPress:
267 return ui::ET_TOUCH_PRESSED;
268 case XI_ButtonRelease:
269 return ui::ET_TOUCH_RELEASED;
270 case XI_Motion:
271 // Should not convert any emulated Motion event from touch device to
272 // touch event.
273 if (!(event->flags & XIPointerEmulated) && GetButtonMaskForX2Event(event))
274 return ui::ET_TOUCH_MOVED;
275 return ui::ET_UNKNOWN;
276 default:
277 NOTREACHED();
278 }
279 return ui::ET_UNKNOWN;
280 }
281
282 double GetTouchParamFromXEvent(XEvent* xev,
283 ui::DeviceDataManagerX11::DataType val,
284 double default_value) {
285 ui::DeviceDataManagerX11::GetInstance()->GetEventData(*xev, val,
286 &default_value);
287 return default_value;
288 }
289
290 void ScaleTouchRadius(XEvent* xev, double* radius) {
291 DCHECK_EQ(GenericEvent, xev->type);
292 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
293 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchRadiusScale(xiev->sourceid,
294 radius);
295 }
296
297 bool GetGestureTimes(const base::NativeEvent& native_event,
298 double* start_time,
299 double* end_time) {
300 if (!ui::DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event))
301 return false;
302
303 double start_time_, end_time_;
304 if (!start_time)
305 start_time = &start_time_;
306 if (!end_time)
307 end_time = &end_time_;
308
309 ui::DeviceDataManagerX11::GetInstance()->GetGestureTimes(
310 native_event, start_time, end_time);
311 return true;
312 }
313
314 } // namespace
315
316 namespace ui {
317
318 void UpdateDeviceList() {
319 XDisplay* display = gfx::GetXDisplay();
320 DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
321 TouchFactory::GetInstance()->UpdateDeviceList(display);
322 DeviceDataManagerX11::GetInstance()->UpdateDeviceList(display);
323 }
324
325 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
326 // Allow the DeviceDataManager to block the event. If blocked return
327 // ET_UNKNOWN as the type so this event will not be further processed.
328 // NOTE: During some events unittests there is no device data manager.
329 if (DeviceDataManager::HasInstance() &&
330 static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance())
331 ->IsEventBlocked(native_event)) {
332 return ET_UNKNOWN;
333 }
334
335 switch (native_event->type) {
336 case KeyPress:
337 return ET_KEY_PRESSED;
338 case KeyRelease:
339 return ET_KEY_RELEASED;
340 case ButtonPress:
341 if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
342 static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
343 return ET_MOUSEWHEEL;
344 return ET_MOUSE_PRESSED;
345 case ButtonRelease:
346 // Drop wheel events; we should've already scrolled on the press.
347 if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
348 static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
349 return ET_UNKNOWN;
350 return ET_MOUSE_RELEASED;
351 case MotionNotify:
352 if (native_event->xmotion.state &
353 (Button1Mask | Button2Mask | Button3Mask))
354 return ET_MOUSE_DRAGGED;
355 return ET_MOUSE_MOVED;
356 case EnterNotify:
357 // The standard on Windows is to send a MouseMove event when the mouse
358 // first enters a window instead of sending a special mouse enter event.
359 // To be consistent we follow the same style.
360 return ET_MOUSE_MOVED;
361 case LeaveNotify:
362 return ET_MOUSE_EXITED;
363 case GenericEvent: {
364 TouchFactory* factory = TouchFactory::GetInstance();
365 if (!factory->ShouldProcessXI2Event(native_event))
366 return ET_UNKNOWN;
367
368 XIDeviceEvent* xievent =
369 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
370
371 // This check works only for master and floating slave devices. That is
372 // why it is necessary to check for the XI_Touch* events in the following
373 // switch statement to account for attached-slave touchscreens.
374 if (factory->IsTouchDevice(xievent->sourceid))
375 return GetTouchEventType(native_event);
376
377 switch (xievent->evtype) {
378 case XI_TouchBegin:
379 return ui::ET_TOUCH_PRESSED;
380 case XI_TouchUpdate:
381 return ui::ET_TOUCH_MOVED;
382 case XI_TouchEnd:
383 return ui::ET_TOUCH_RELEASED;
384 case XI_ButtonPress: {
385 int button = EventButtonFromNative(native_event);
386 if (button >= kMinWheelButton && button <= kMaxWheelButton)
387 return ET_MOUSEWHEEL;
388 return ET_MOUSE_PRESSED;
389 }
390 case XI_ButtonRelease: {
391 int button = EventButtonFromNative(native_event);
392 // Drop wheel events; we should've already scrolled on the press.
393 if (button >= kMinWheelButton && button <= kMaxWheelButton)
394 return ET_UNKNOWN;
395 return ET_MOUSE_RELEASED;
396 }
397 case XI_Motion: {
398 bool is_cancel;
399 DeviceDataManagerX11* devices = DeviceDataManagerX11::GetInstance();
400 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel))
401 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
402 if (devices->IsScrollEvent(native_event)) {
403 return devices->IsTouchpadXInputEvent(native_event) ? ET_SCROLL
404 : ET_MOUSEWHEEL;
405 }
406 if (devices->IsCMTMetricsEvent(native_event))
407 return ET_UMA_DATA;
408 if (GetButtonMaskForX2Event(xievent))
409 return ET_MOUSE_DRAGGED;
410 return ET_MOUSE_MOVED;
411 }
412 case XI_KeyPress:
413 return ET_KEY_PRESSED;
414 case XI_KeyRelease:
415 return ET_KEY_RELEASED;
416 }
417 }
418 default:
419 break;
420 }
421 return ET_UNKNOWN;
422 }
423
424 int EventFlagsFromNative(const base::NativeEvent& native_event) {
425 switch (native_event->type) {
426 case KeyPress:
427 case KeyRelease: {
428 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event);
429 return GetEventFlagsFromXKeyEvent(native_event);
430 }
431 case ButtonPress:
432 case ButtonRelease: {
433 int flags = GetEventFlagsFromXState(native_event->xbutton.state);
434 const EventType type = EventTypeFromNative(native_event);
435 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
436 flags |= GetEventFlagsForButton(native_event->xbutton.button);
437 return flags;
438 }
439 case EnterNotify:
440 case LeaveNotify:
441 return GetEventFlagsFromXState(native_event->xcrossing.state);
442 case MotionNotify:
443 return GetEventFlagsFromXState(native_event->xmotion.state);
444 case GenericEvent: {
445 XIDeviceEvent* xievent =
446 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
447
448 switch (xievent->evtype) {
449 #if defined(USE_XI2_MT)
450 case XI_TouchBegin:
451 case XI_TouchUpdate:
452 case XI_TouchEnd:
453 return GetButtonMaskForX2Event(xievent) |
454 GetEventFlagsFromXState(xievent->mods.effective) |
455 GetEventFlagsFromXState(
456 XModifierStateWatcher::GetInstance()->state());
457 break;
458 #endif
459 case XI_ButtonPress:
460 case XI_ButtonRelease: {
461 const bool touch =
462 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
463 int flags = GetButtonMaskForX2Event(xievent) |
464 GetEventFlagsFromXState(xievent->mods.effective);
465 if (touch) {
466 flags |= GetEventFlagsFromXState(
467 XModifierStateWatcher::GetInstance()->state());
468 }
469
470 const EventType type = EventTypeFromNative(native_event);
471 int button = EventButtonFromNative(native_event);
472 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
473 flags |= GetEventFlagsForButton(button);
474 return flags;
475 }
476 case XI_Motion:
477 return GetButtonMaskForX2Event(xievent) |
478 GetEventFlagsFromXState(xievent->mods.effective);
479 case XI_KeyPress:
480 case XI_KeyRelease: {
481 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
482 native_event);
483 return GetEventFlagsFromXGenericEvent(native_event);
484 }
485 }
486 }
487 }
488 return 0;
489 }
490
491 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
492 switch (native_event->type) {
493 case KeyPress:
494 case KeyRelease:
495 return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
496 case ButtonPress:
497 case ButtonRelease:
498 return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
499 break;
500 case MotionNotify:
501 return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
502 break;
503 case EnterNotify:
504 case LeaveNotify:
505 return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
506 break;
507 case GenericEvent: {
508 double start, end;
509 double touch_timestamp;
510 if (GetGestureTimes(native_event, &start, &end)) {
511 // If the driver supports gesture times, use them.
512 return base::TimeDelta::FromMicroseconds(end * 1000000);
513 } else if (DeviceDataManagerX11::GetInstance()->GetEventData(
514 *native_event,
515 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP,
516 &touch_timestamp)) {
517 return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
518 } else {
519 XIDeviceEvent* xide =
520 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
521 return base::TimeDelta::FromMilliseconds(xide->time);
522 }
523 break;
524 }
525 }
526 NOTREACHED();
527 return base::TimeDelta();
528 }
529
530 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
531 switch (native_event->type) {
532 case EnterNotify:
533 case LeaveNotify:
534 return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
535 case ButtonPress:
536 case ButtonRelease:
537 return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
538 case MotionNotify:
539 return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
540 case GenericEvent: {
541 XIDeviceEvent* xievent =
542 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
543 float x = xievent->event_x;
544 float y = xievent->event_y;
545 #if defined(OS_CHROMEOS)
546 switch (xievent->evtype) {
547 case XI_TouchBegin:
548 case XI_TouchUpdate:
549 case XI_TouchEnd:
550 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer(
551 xievent->deviceid, &x, &y);
552 break;
553 default:
554 break;
555 }
556 #endif // defined(OS_CHROMEOS)
557 return gfx::Point(static_cast<int>(x), static_cast<int>(y));
558 }
559 }
560 return gfx::Point();
561 }
562
563 gfx::Point EventSystemLocationFromNative(
564 const base::NativeEvent& native_event) {
565 switch (native_event->type) {
566 case EnterNotify:
567 case LeaveNotify: {
568 return gfx::Point(native_event->xcrossing.x_root,
569 native_event->xcrossing.y_root);
570 }
571 case ButtonPress:
572 case ButtonRelease: {
573 return gfx::Point(native_event->xbutton.x_root,
574 native_event->xbutton.y_root);
575 }
576 case MotionNotify: {
577 return gfx::Point(native_event->xmotion.x_root,
578 native_event->xmotion.y_root);
579 }
580 case GenericEvent: {
581 XIDeviceEvent* xievent =
582 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
583 return gfx::Point(xievent->root_x, xievent->root_y);
584 }
585 }
586
587 return gfx::Point();
588 }
589
590 int EventButtonFromNative(const base::NativeEvent& native_event) {
591 CHECK_EQ(GenericEvent, native_event->type);
592 XIDeviceEvent* xievent =
593 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
594 int button = xievent->detail;
595
596 return (xievent->sourceid == xievent->deviceid)
597 ? DeviceDataManagerX11::GetInstance()->GetMappedButton(button)
598 : button;
599 }
600
601 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
602 return KeyboardCodeFromXKeyEvent(native_event);
603 }
604
605 const char* CodeFromNative(const base::NativeEvent& native_event) {
606 return CodeFromXEvent(native_event);
607 }
608
609 uint32 PlatformKeycodeFromNative(const base::NativeEvent& native_event) {
610 XKeyEvent* xkey = NULL;
611 XEvent xkey_from_xi2;
612 switch (native_event->type) {
613 case KeyPress:
614 case KeyRelease:
615 xkey = &native_event->xkey;
616 break;
617 case GenericEvent: {
618 XIDeviceEvent* xievent =
619 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
620 switch (xievent->evtype) {
621 case XI_KeyPress:
622 case XI_KeyRelease:
623 // Build an XKeyEvent corresponding to the XI2 event,
624 // so that we can call XLookupString on it.
625 InitXKeyEventFromXIDeviceEvent(*native_event, &xkey_from_xi2);
626 xkey = &xkey_from_xi2.xkey;
627 break;
628 default:
629 NOTREACHED();
630 break;
631 }
632 break;
633 }
634 default:
635 NOTREACHED();
636 break;
637 }
638 KeySym keysym = XK_VoidSymbol;
639 if (xkey)
640 XLookupString(xkey, NULL, 0, &keysym, NULL);
641 return keysym;
642 }
643
644 bool IsCharFromNative(const base::NativeEvent& native_event) {
645 return false;
646 }
647
648 int GetChangedMouseButtonFlagsFromNative(
649 const base::NativeEvent& native_event) {
650 switch (native_event->type) {
651 case ButtonPress:
652 case ButtonRelease:
653 return GetEventFlagsFromXState(native_event->xbutton.state);
654 case GenericEvent: {
655 XIDeviceEvent* xievent =
656 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
657 switch (xievent->evtype) {
658 case XI_ButtonPress:
659 case XI_ButtonRelease:
660 return GetEventFlagsForButton(EventButtonFromNative(native_event));
661 default:
662 break;
663 }
664 }
665 default:
666 break;
667 }
668 return 0;
669 }
670
671 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
672 float x_offset, y_offset;
673 if (GetScrollOffsets(native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
674 return gfx::Vector2d(static_cast<int>(x_offset),
675 static_cast<int>(y_offset));
676 }
677
678 int button = native_event->type == GenericEvent
679 ? EventButtonFromNative(native_event)
680 : native_event->xbutton.button;
681
682 switch (button) {
683 case 4:
684 return gfx::Vector2d(0, kWheelScrollAmount);
685 case 5:
686 return gfx::Vector2d(0, -kWheelScrollAmount);
687 case 6:
688 return gfx::Vector2d(kWheelScrollAmount, 0);
689 case 7:
690 return gfx::Vector2d(-kWheelScrollAmount, 0);
691 default:
692 return gfx::Vector2d();
693 }
694 }
695
696 void IncrementTouchIdRefCount(const base::NativeEvent& xev) {
697 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
698 double tracking_id;
699 if (!manager->GetEventData(
700 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
701 return;
702 }
703
704 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
705 factory->AcquireSlotForTrackingID(tracking_id);
706 }
707
708 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
709 ui::EventType type = ui::EventTypeFromNative(xev);
710 if (type == ui::ET_TOUCH_CANCELLED || type == ui::ET_TOUCH_RELEASED) {
711 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
712 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
713 double tracking_id;
714 if (manager->GetEventData(*xev,
715 ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID,
716 &tracking_id)) {
717 factory->ReleaseSlotForTrackingID(tracking_id);
718 }
719 }
720 }
721
722 int GetTouchId(const base::NativeEvent& xev) {
723 double slot = 0;
724 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
725 double tracking_id;
726 if (!manager->GetEventData(
727 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
728 LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
729 } else {
730 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
731 slot = factory->GetSlotForTrackingID(tracking_id);
732 }
733 return slot;
734 }
735
736 float GetTouchRadiusX(const base::NativeEvent& native_event) {
737 double radius =
738 GetTouchParamFromXEvent(native_event,
739 ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, 0.0) /
740 2.0;
741 ScaleTouchRadius(native_event, &radius);
742 return radius;
743 }
744
745 float GetTouchRadiusY(const base::NativeEvent& native_event) {
746 double radius =
747 GetTouchParamFromXEvent(native_event,
748 ui::DeviceDataManagerX11::DT_TOUCH_MINOR, 0.0) /
749 2.0;
750 ScaleTouchRadius(native_event, &radius);
751 return radius;
752 }
753
754 float GetTouchAngle(const base::NativeEvent& native_event) {
755 return GetTouchParamFromXEvent(native_event,
756 ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION,
757 0.0) /
758 2.0;
759 }
760
761 float GetTouchForce(const base::NativeEvent& native_event) {
762 double force = 0.0;
763 force = GetTouchParamFromXEvent(
764 native_event, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, 0.0);
765 unsigned int deviceid =
766 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
767 // Force is normalized to fall into [0, 1]
768 if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData(
769 deviceid, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, &force))
770 force = 0.0;
771 return force;
772 }
773
774 bool GetScrollOffsets(const base::NativeEvent& native_event,
775 float* x_offset,
776 float* y_offset,
777 float* x_offset_ordinal,
778 float* y_offset_ordinal,
779 int* finger_count) {
780 if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event))
781 return false;
782
783 // Temp values to prevent passing NULLs to DeviceDataManager.
784 float x_offset_, y_offset_;
785 float x_offset_ordinal_, y_offset_ordinal_;
786 int finger_count_;
787 if (!x_offset)
788 x_offset = &x_offset_;
789 if (!y_offset)
790 y_offset = &y_offset_;
791 if (!x_offset_ordinal)
792 x_offset_ordinal = &x_offset_ordinal_;
793 if (!y_offset_ordinal)
794 y_offset_ordinal = &y_offset_ordinal_;
795 if (!finger_count)
796 finger_count = &finger_count_;
797
798 DeviceDataManagerX11::GetInstance()->GetScrollOffsets(
799 native_event, x_offset, y_offset, x_offset_ordinal, y_offset_ordinal,
800 finger_count);
801 return true;
802 }
803
804 bool GetFlingData(const base::NativeEvent& native_event,
805 float* vx,
806 float* vy,
807 float* vx_ordinal,
808 float* vy_ordinal,
809 bool* is_cancel) {
810 if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event))
811 return false;
812
813 float vx_, vy_;
814 float vx_ordinal_, vy_ordinal_;
815 bool is_cancel_;
816 if (!vx)
817 vx = &vx_;
818 if (!vy)
819 vy = &vy_;
820 if (!vx_ordinal)
821 vx_ordinal = &vx_ordinal_;
822 if (!vy_ordinal)
823 vy_ordinal = &vy_ordinal_;
824 if (!is_cancel)
825 is_cancel = &is_cancel_;
826
827 DeviceDataManagerX11::GetInstance()->GetFlingData(
828 native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
829 return true;
830 }
831
832 } // namespace ui
OLDNEW
« no previous file with comments | « ui/events/platform/x11/keysym_to_unicode.cc ('k') | ui/events/platform/x11/platform_event_utils_x_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698