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/event_constants.h" 6 7 #include <cmath> 8 #include <string.h> 9 #include <X11/extensions/XInput.h> 10 #include <X11/extensions/XInput2.h> 11 #include <X11/Xlib.h> 12 #include <X11/Xutil.h> 13 #include <X11/XKBlib.h> 14 15 #include "base/logging.h" 16 #include "base/memory/singleton.h" 17 #include "ui/events/event.h" 18 #include "ui/events/event_utils.h" 19 #include "ui/events/keycodes/keyboard_code_conversion_x.h" 20 #include "ui/events/x/device_data_manager_x11.h" 21 #include "ui/events/x/device_list_cache_x.h" 22 #include "ui/events/x/touch_factory_x11.h" 23 #include "ui/gfx/display.h" 24 #include "ui/gfx/point.h" 25 #include "ui/gfx/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" 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 || 121 event->evtype == XI_TouchUpdate || 122 event->evtype == XI_TouchEnd); 123 124 // Force is normalized to [0, 1]. 125 if (ui::GetTouchForce(native_event) < 1.0f) 126 return false; 127 128 if (ui::EventLocationFromNative(native_event) != gfx::Point()) 129 return false; 130 131 // Radius is in pixels, and the valuator is the diameter in pixels. 132 double radius = ui::GetTouchRadiusX(native_event), min, max; 133 unsigned int deviceid = 134 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid; 135 if (!ui::DeviceDataManagerX11::GetInstance()->GetDataRange( 136 deviceid, ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, &min, &max)) { 137 return false; 138 } 139 140 return radius * 2 == max; 141 } 142 #endif 143 144 int GetEventFlagsFromXState(unsigned int state) { 145 int flags = 0; 146 if (state & ControlMask) 147 flags |= ui::EF_CONTROL_DOWN; 148 if (state & ShiftMask) 149 flags |= ui::EF_SHIFT_DOWN; 150 if (state & Mod1Mask) 151 flags |= ui::EF_ALT_DOWN; 152 if (state & LockMask) 153 flags |= ui::EF_CAPS_LOCK_DOWN; 154 if (state & Mod3Mask) 155 flags |= ui::EF_MOD3_DOWN; 156 if (state & Mod4Mask) 157 flags |= ui::EF_COMMAND_DOWN; 158 if (state & Mod5Mask) 159 flags |= ui::EF_ALTGR_DOWN; 160 if (state & Button1Mask) 161 flags |= ui::EF_LEFT_MOUSE_BUTTON; 162 if (state & Button2Mask) 163 flags |= ui::EF_MIDDLE_MOUSE_BUTTON; 164 if (state & Button3Mask) 165 flags |= ui::EF_RIGHT_MOUSE_BUTTON; 166 return flags; 167 } 168 169 int GetEventFlagsFromXKeyEvent(XEvent* xevent) { 170 DCHECK(xevent->type == KeyPress || xevent->type == KeyRelease); 171 172 #if defined(OS_CHROMEOS) 173 const int ime_fabricated_flag = 0; 174 #else 175 // XIM fabricates key events for the character compositions by XK_Multi_key. 176 // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in 177 // order to input "", then XIM generates a key event with keycode=0 and 178 // state=0 for the composition, and the sequence of X11 key events will be 179 // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e. If the user used 180 // shift key and/or caps lock key, state can be ShiftMask, LockMask or both. 181 // 182 // We have to send these fabricated key events to XIM so it can correctly 183 // handle the character compositions. 184 const unsigned int shift_lock_mask = ShiftMask | LockMask; 185 const bool fabricated_by_xim = 186 xevent->xkey.keycode == 0 && 187 (xevent->xkey.state & ~shift_lock_mask) == 0; 188 const int ime_fabricated_flag = 189 fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0; 190 #endif 191 192 return GetEventFlagsFromXState(xevent->xkey.state) | 193 (xevent->xkey.send_event ? ui::EF_FINAL : 0) | 194 (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) | 195 (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ? 196 ui::EF_FUNCTION_KEY : 0) | 197 ime_fabricated_flag; 198 } 199 200 int GetEventFlagsFromXGenericEvent(XEvent* xevent) { 201 DCHECK(xevent->type == GenericEvent); 202 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); 203 DCHECK((xievent->evtype == XI_KeyPress) || 204 (xievent->evtype == XI_KeyRelease)); 205 return GetEventFlagsFromXState(xievent->mods.effective) | 206 (xevent->xkey.send_event ? ui::EF_FINAL : 0) | 207 (IsKeypadKey( 208 XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0)) 209 ? ui::EF_NUMPAD_KEY 210 : 0); 211 } 212 213 // Get the event flag for the button in XButtonEvent. During a ButtonPress 214 // event, |state| in XButtonEvent does not include the button that has just been 215 // pressed. Instead |state| contains flags for the buttons (if any) that had 216 // already been pressed before the current button, and |button| stores the most 217 // current pressed button. So, if you press down left mouse button, and while 218 // pressing it down, press down the right mouse button, then for the latter 219 // event, |state| would have Button1Mask set but not Button3Mask, and |button| 220 // would be 3. 221 int GetEventFlagsForButton(int button) { 222 switch (button) { 223 case 1: 224 return ui::EF_LEFT_MOUSE_BUTTON; 225 case 2: 226 return ui::EF_MIDDLE_MOUSE_BUTTON; 227 case 3: 228 return ui::EF_RIGHT_MOUSE_BUTTON; 229 default: 230 return 0; 231 } 232 } 233 234 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) { 235 int buttonflags = 0; 236 for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) { 237 if (XIMaskIsSet(xievent->buttons.mask, i)) { 238 int button = (xievent->sourceid == xievent->deviceid) ? 239 ui::DeviceDataManagerX11::GetInstance()->GetMappedButton(i) : i; 240 buttonflags |= GetEventFlagsForButton(button); 241 } 242 } 243 return buttonflags; 244 } 245 246 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) { 247 XIDeviceEvent* event = 248 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 249 #if defined(USE_XI2_MT) 250 switch(event->evtype) { 251 case XI_TouchBegin: 252 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN : 253 ui::ET_TOUCH_PRESSED; 254 case XI_TouchUpdate: 255 return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN : 256 ui::ET_TOUCH_MOVED; 257 case XI_TouchEnd: 258 return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED : 259 ui::ET_TOUCH_RELEASED; 260 } 261 #endif // defined(USE_XI2_MT) 262 263 DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid)); 264 switch (event->evtype) { 265 case XI_ButtonPress: 266 return ui::ET_TOUCH_PRESSED; 267 case XI_ButtonRelease: 268 return ui::ET_TOUCH_RELEASED; 269 case XI_Motion: 270 // Should not convert any emulated Motion event from touch device to 271 // touch event. 272 if (!(event->flags & XIPointerEmulated) && 273 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( 286 *xev, val, &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( 294 xiev->sourceid, radius); 295 } 296 297 unsigned int UpdateX11EventFlags(int ui_flags, unsigned int old_x_flags) { 298 static struct { 299 int ui; 300 int x; 301 } flags[] = { 302 {ui::EF_CONTROL_DOWN, ControlMask}, 303 {ui::EF_SHIFT_DOWN, ShiftMask}, 304 {ui::EF_ALT_DOWN, Mod1Mask}, 305 {ui::EF_CAPS_LOCK_DOWN, LockMask}, 306 {ui::EF_ALTGR_DOWN, Mod5Mask}, 307 {ui::EF_COMMAND_DOWN, Mod4Mask}, 308 {ui::EF_MOD3_DOWN, Mod3Mask}, 309 {ui::EF_NUMPAD_KEY, Mod2Mask}, 310 {ui::EF_LEFT_MOUSE_BUTTON, Button1Mask}, 311 {ui::EF_MIDDLE_MOUSE_BUTTON, Button2Mask}, 312 {ui::EF_RIGHT_MOUSE_BUTTON, Button3Mask}, 313 }; 314 unsigned int new_x_flags = old_x_flags; 315 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) { 316 if (ui_flags & flags[i].ui) 317 new_x_flags |= flags[i].x; 318 else 319 new_x_flags &= ~flags[i].x; 320 } 321 return new_x_flags; 322 } 323 324 unsigned int UpdateX11EventButton(int ui_flag, unsigned int old_x_button) { 325 switch (ui_flag) { 326 case ui::EF_LEFT_MOUSE_BUTTON: 327 return Button1; 328 case ui::EF_MIDDLE_MOUSE_BUTTON: 329 return Button2; 330 case ui::EF_RIGHT_MOUSE_BUTTON: 331 return Button3; 332 default: 333 return old_x_button; 334 } 335 NOTREACHED(); 336 } 337 338 bool GetGestureTimes(const base::NativeEvent& native_event, 339 double* start_time, 340 double* end_time) { 341 if (!ui::DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event)) 342 return false; 343 344 double start_time_, end_time_; 345 if (!start_time) 346 start_time = &start_time_; 347 if (!end_time) 348 end_time = &end_time_; 349 350 ui::DeviceDataManagerX11::GetInstance()->GetGestureTimes( 351 native_event, start_time, end_time); 352 return true; 353 } 354 355 } // namespace 356 357 namespace ui { 358 359 void UpdateDeviceList() { 360 XDisplay* display = gfx::GetXDisplay(); 361 DeviceListCacheX::GetInstance()->UpdateDeviceList(display); 362 TouchFactory::GetInstance()->UpdateDeviceList(display); 363 DeviceDataManagerX11::GetInstance()->UpdateDeviceList(display); 364 } 365 366 EventType EventTypeFromNative(const base::NativeEvent& native_event) { 367 // Allow the DeviceDataManager to block the event. If blocked return 368 // ET_UNKNOWN as the type so this event will not be further processed. 369 // NOTE: During some events unittests there is no device data manager. 370 if (DeviceDataManager::HasInstance() && 371 static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance())-> 372 IsEventBlocked(native_event)) { 373 return ET_UNKNOWN; 374 } 375 376 switch (native_event->type) { 377 case KeyPress: 378 return ET_KEY_PRESSED; 379 case KeyRelease: 380 return ET_KEY_RELEASED; 381 case ButtonPress: 382 if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton && 383 static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton) 384 return ET_MOUSEWHEEL; 385 return ET_MOUSE_PRESSED; 386 case ButtonRelease: 387 // Drop wheel events; we should've already scrolled on the press. 388 if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton && 389 static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton) 390 return ET_UNKNOWN; 391 return ET_MOUSE_RELEASED; 392 case MotionNotify: 393 if (native_event->xmotion.state & 394 (Button1Mask | Button2Mask | Button3Mask)) 395 return ET_MOUSE_DRAGGED; 396 return ET_MOUSE_MOVED; 397 case EnterNotify: 398 // The standard on Windows is to send a MouseMove event when the mouse 399 // first enters a window instead of sending a special mouse enter event. 400 // To be consistent we follow the same style. 401 return ET_MOUSE_MOVED; 402 case LeaveNotify: 403 return ET_MOUSE_EXITED; 404 case GenericEvent: { 405 TouchFactory* factory = TouchFactory::GetInstance(); 406 if (!factory->ShouldProcessXI2Event(native_event)) 407 return ET_UNKNOWN; 408 409 XIDeviceEvent* xievent = 410 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 411 412 // This check works only for master and floating slave devices. That is 413 // why it is necessary to check for the XI_Touch* events in the following 414 // switch statement to account for attached-slave touchscreens. 415 if (factory->IsTouchDevice(xievent->sourceid)) 416 return GetTouchEventType(native_event); 417 418 switch (xievent->evtype) { 419 case XI_TouchBegin: 420 return ui::ET_TOUCH_PRESSED; 421 case XI_TouchUpdate: 422 return ui::ET_TOUCH_MOVED; 423 case XI_TouchEnd: 424 return ui::ET_TOUCH_RELEASED; 425 case XI_ButtonPress: { 426 int button = EventButtonFromNative(native_event); 427 if (button >= kMinWheelButton && button <= kMaxWheelButton) 428 return ET_MOUSEWHEEL; 429 return ET_MOUSE_PRESSED; 430 } 431 case XI_ButtonRelease: { 432 int button = EventButtonFromNative(native_event); 433 // Drop wheel events; we should've already scrolled on the press. 434 if (button >= kMinWheelButton && button <= kMaxWheelButton) 435 return ET_UNKNOWN; 436 return ET_MOUSE_RELEASED; 437 } 438 case XI_Motion: { 439 bool is_cancel; 440 DeviceDataManagerX11* devices = DeviceDataManagerX11::GetInstance(); 441 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) 442 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START; 443 if (devices->IsScrollEvent(native_event)) { 444 return devices->IsTouchpadXInputEvent(native_event) ? ET_SCROLL 445 : ET_MOUSEWHEEL; 446 } 447 if (devices->IsCMTMetricsEvent(native_event)) 448 return ET_UMA_DATA; 449 if (GetButtonMaskForX2Event(xievent)) 450 return ET_MOUSE_DRAGGED; 451 return ET_MOUSE_MOVED; 452 } 453 case XI_KeyPress: 454 return ET_KEY_PRESSED; 455 case XI_KeyRelease: 456 return ET_KEY_RELEASED; 457 } 458 } 459 default: 460 break; 461 } 462 return ET_UNKNOWN; 463 } 464 465 int EventFlagsFromNative(const base::NativeEvent& native_event) { 466 switch (native_event->type) { 467 case KeyPress: 468 case KeyRelease: { 469 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event); 470 return GetEventFlagsFromXKeyEvent(native_event); 471 } 472 case ButtonPress: 473 case ButtonRelease: { 474 int flags = GetEventFlagsFromXState(native_event->xbutton.state); 475 const EventType type = EventTypeFromNative(native_event); 476 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) 477 flags |= GetEventFlagsForButton(native_event->xbutton.button); 478 return flags; 479 } 480 case EnterNotify: 481 case LeaveNotify: 482 return GetEventFlagsFromXState(native_event->xcrossing.state); 483 case MotionNotify: 484 return GetEventFlagsFromXState(native_event->xmotion.state); 485 case GenericEvent: { 486 XIDeviceEvent* xievent = 487 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 488 489 switch (xievent->evtype) { 490 #if defined(USE_XI2_MT) 491 case XI_TouchBegin: 492 case XI_TouchUpdate: 493 case XI_TouchEnd: 494 return GetButtonMaskForX2Event(xievent) | 495 GetEventFlagsFromXState(xievent->mods.effective) | 496 GetEventFlagsFromXState( 497 XModifierStateWatcher::GetInstance()->state()); 498 break; 499 #endif 500 case XI_ButtonPress: 501 case XI_ButtonRelease: { 502 const bool touch = 503 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid); 504 int flags = GetButtonMaskForX2Event(xievent) | 505 GetEventFlagsFromXState(xievent->mods.effective); 506 if (touch) { 507 flags |= GetEventFlagsFromXState( 508 XModifierStateWatcher::GetInstance()->state()); 509 } 510 511 const EventType type = EventTypeFromNative(native_event); 512 int button = EventButtonFromNative(native_event); 513 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch) 514 flags |= GetEventFlagsForButton(button); 515 return flags; 516 } 517 case XI_Motion: 518 return GetButtonMaskForX2Event(xievent) | 519 GetEventFlagsFromXState(xievent->mods.effective); 520 case XI_KeyPress: 521 case XI_KeyRelease: { 522 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent( 523 native_event); 524 return GetEventFlagsFromXGenericEvent(native_event); 525 } 526 } 527 } 528 } 529 return 0; 530 } 531 532 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { 533 switch(native_event->type) { 534 case KeyPress: 535 case KeyRelease: 536 return base::TimeDelta::FromMilliseconds(native_event->xkey.time); 537 case ButtonPress: 538 case ButtonRelease: 539 return base::TimeDelta::FromMilliseconds(native_event->xbutton.time); 540 break; 541 case MotionNotify: 542 return base::TimeDelta::FromMilliseconds(native_event->xmotion.time); 543 break; 544 case EnterNotify: 545 case LeaveNotify: 546 return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time); 547 break; 548 case GenericEvent: { 549 double start, end; 550 double touch_timestamp; 551 if (GetGestureTimes(native_event, &start, &end)) { 552 // If the driver supports gesture times, use them. 553 return base::TimeDelta::FromMicroseconds(end * 1000000); 554 } else if (DeviceDataManagerX11::GetInstance()->GetEventData( 555 *native_event, 556 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP, 557 &touch_timestamp)) { 558 return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000); 559 } else { 560 XIDeviceEvent* xide = 561 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 562 return base::TimeDelta::FromMilliseconds(xide->time); 563 } 564 break; 565 } 566 } 567 NOTREACHED(); 568 return base::TimeDelta(); 569 } 570 571 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { 572 switch (native_event->type) { 573 case EnterNotify: 574 case LeaveNotify: 575 return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y); 576 case ButtonPress: 577 case ButtonRelease: 578 return gfx::Point(native_event->xbutton.x, native_event->xbutton.y); 579 case MotionNotify: 580 return gfx::Point(native_event->xmotion.x, native_event->xmotion.y); 581 case GenericEvent: { 582 XIDeviceEvent* xievent = 583 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 584 float x = xievent->event_x; 585 float y = xievent->event_y; 586 #if defined(OS_CHROMEOS) 587 switch (xievent->evtype) { 588 case XI_TouchBegin: 589 case XI_TouchUpdate: 590 case XI_TouchEnd: 591 ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer( 592 xievent->deviceid, &x, &y); 593 break; 594 default: 595 break; 596 } 597 #endif // defined(OS_CHROMEOS) 598 return gfx::Point(static_cast<int>(x), static_cast<int>(y)); 599 } 600 } 601 return gfx::Point(); 602 } 603 604 gfx::Point EventSystemLocationFromNative( 605 const base::NativeEvent& native_event) { 606 switch (native_event->type) { 607 case EnterNotify: 608 case LeaveNotify: { 609 return gfx::Point(native_event->xcrossing.x_root, 610 native_event->xcrossing.y_root); 611 } 612 case ButtonPress: 613 case ButtonRelease: { 614 return gfx::Point(native_event->xbutton.x_root, 615 native_event->xbutton.y_root); 616 } 617 case MotionNotify: { 618 return gfx::Point(native_event->xmotion.x_root, 619 native_event->xmotion.y_root); 620 } 621 case GenericEvent: { 622 XIDeviceEvent* xievent = 623 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 624 return gfx::Point(xievent->root_x, xievent->root_y); 625 } 626 } 627 628 return gfx::Point(); 629 } 630 631 int EventButtonFromNative(const base::NativeEvent& native_event) { 632 CHECK_EQ(GenericEvent, native_event->type); 633 XIDeviceEvent* xievent = 634 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 635 int button = xievent->detail; 636 637 return (xievent->sourceid == xievent->deviceid) ? 638 DeviceDataManagerX11::GetInstance()->GetMappedButton(button) : button; 639 } 640 641 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) { 642 return KeyboardCodeFromXKeyEvent(native_event); 643 } 644 645 const char* CodeFromNative(const base::NativeEvent& native_event) { 646 return CodeFromXEvent(native_event); 647 } 648 649 uint32 PlatformKeycodeFromNative(const base::NativeEvent& native_event) { 650 XKeyEvent* xkey = NULL; 651 XEvent xkey_from_xi2; 652 switch (native_event->type) { 653 case KeyPress: 654 case KeyRelease: 655 xkey = &native_event->xkey; 656 break; 657 case GenericEvent: { 658 XIDeviceEvent* xievent = 659 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 660 switch (xievent->evtype) { 661 case XI_KeyPress: 662 case XI_KeyRelease: 663 // Build an XKeyEvent corresponding to the XI2 event, 664 // so that we can call XLookupString on it. 665 InitXKeyEventFromXIDeviceEvent(*native_event, &xkey_from_xi2); 666 xkey = &xkey_from_xi2.xkey; 667 break; 668 default: 669 NOTREACHED(); 670 break; 671 } 672 break; 673 } 674 default: 675 NOTREACHED(); 676 break; 677 } 678 KeySym keysym = XK_VoidSymbol; 679 if (xkey) 680 XLookupString(xkey, NULL, 0, &keysym, NULL); 681 return keysym; 682 } 683 684 bool IsCharFromNative(const base::NativeEvent& native_event) { 685 return false; 686 } 687 688 int GetChangedMouseButtonFlagsFromNative( 689 const base::NativeEvent& native_event) { 690 switch (native_event->type) { 691 case ButtonPress: 692 case ButtonRelease: 693 return GetEventFlagsFromXState(native_event->xbutton.state); 694 case GenericEvent: { 695 XIDeviceEvent* xievent = 696 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 697 switch (xievent->evtype) { 698 case XI_ButtonPress: 699 case XI_ButtonRelease: 700 return GetEventFlagsForButton(EventButtonFromNative(native_event)); 701 default: 702 break; 703 } 704 } 705 default: 706 break; 707 } 708 return 0; 709 } 710 711 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) { 712 float x_offset, y_offset; 713 if (GetScrollOffsets( 714 native_event, &x_offset, &y_offset, NULL, NULL, NULL)) { 715 return gfx::Vector2d(static_cast<int>(x_offset), 716 static_cast<int>(y_offset)); 717 } 718 719 int button = native_event->type == GenericEvent ? 720 EventButtonFromNative(native_event) : native_event->xbutton.button; 721 722 switch (button) { 723 case 4: 724 return gfx::Vector2d(0, kWheelScrollAmount); 725 case 5: 726 return gfx::Vector2d(0, -kWheelScrollAmount); 727 case 6: 728 return gfx::Vector2d(kWheelScrollAmount, 0); 729 case 7: 730 return gfx::Vector2d(-kWheelScrollAmount, 0); 731 default: 732 return gfx::Vector2d(); 733 } 734 } 735 736 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) { 737 if (!event || event->type == GenericEvent) 738 return NULL; 739 XEvent* copy = new XEvent; 740 *copy = *event; 741 return copy; 742 } 743 744 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) { 745 delete event; 746 } 747 748 void IncrementTouchIdRefCount(const base::NativeEvent& xev) { 749 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance(); 750 double tracking_id; 751 if (!manager->GetEventData( 752 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) { 753 return; 754 } 755 756 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 757 factory->AcquireSlotForTrackingID(tracking_id); 758 } 759 760 void ClearTouchIdIfReleased(const base::NativeEvent& xev) { 761 ui::EventType type = ui::EventTypeFromNative(xev); 762 if (type == ui::ET_TOUCH_CANCELLED || 763 type == ui::ET_TOUCH_RELEASED) { 764 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 765 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance(); 766 double tracking_id; 767 if (manager->GetEventData( 768 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) { 769 factory->ReleaseSlotForTrackingID(tracking_id); 770 } 771 } 772 } 773 774 int GetTouchId(const base::NativeEvent& xev) { 775 double slot = 0; 776 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance(); 777 double tracking_id; 778 if (!manager->GetEventData( 779 *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) { 780 LOG(ERROR) << "Could not get the tracking ID for the event. Using 0."; 781 } else { 782 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 783 slot = factory->GetSlotForTrackingID(tracking_id); 784 } 785 return slot; 786 } 787 788 float GetTouchRadiusX(const base::NativeEvent& native_event) { 789 double radius = GetTouchParamFromXEvent(native_event, 790 ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, 0.0) / 2.0; 791 ScaleTouchRadius(native_event, &radius); 792 return radius; 793 } 794 795 float GetTouchRadiusY(const base::NativeEvent& native_event) { 796 double radius = GetTouchParamFromXEvent(native_event, 797 ui::DeviceDataManagerX11::DT_TOUCH_MINOR, 0.0) / 2.0; 798 ScaleTouchRadius(native_event, &radius); 799 return radius; 800 } 801 802 float GetTouchAngle(const base::NativeEvent& native_event) { 803 return GetTouchParamFromXEvent(native_event, 804 ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.0) / 2.0; 805 } 806 807 float GetTouchForce(const base::NativeEvent& native_event) { 808 double force = 0.0; 809 force = GetTouchParamFromXEvent(native_event, 810 ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, 0.0); 811 unsigned int deviceid = 812 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid; 813 // Force is normalized to fall into [0, 1] 814 if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData( 815 deviceid, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, &force)) 816 force = 0.0; 817 return force; 818 } 819 820 bool GetScrollOffsets(const base::NativeEvent& native_event, 821 float* x_offset, 822 float* y_offset, 823 float* x_offset_ordinal, 824 float* y_offset_ordinal, 825 int* finger_count) { 826 if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event)) 827 return false; 828 829 // Temp values to prevent passing NULLs to DeviceDataManager. 830 float x_offset_, y_offset_; 831 float x_offset_ordinal_, y_offset_ordinal_; 832 int finger_count_; 833 if (!x_offset) 834 x_offset = &x_offset_; 835 if (!y_offset) 836 y_offset = &y_offset_; 837 if (!x_offset_ordinal) 838 x_offset_ordinal = &x_offset_ordinal_; 839 if (!y_offset_ordinal) 840 y_offset_ordinal = &y_offset_ordinal_; 841 if (!finger_count) 842 finger_count = &finger_count_; 843 844 DeviceDataManagerX11::GetInstance()->GetScrollOffsets( 845 native_event, 846 x_offset, y_offset, 847 x_offset_ordinal, y_offset_ordinal, 848 finger_count); 849 return true; 850 } 851 852 bool GetFlingData(const base::NativeEvent& native_event, 853 float* vx, 854 float* vy, 855 float* vx_ordinal, 856 float* vy_ordinal, 857 bool* is_cancel) { 858 if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event)) 859 return false; 860 861 float vx_, vy_; 862 float vx_ordinal_, vy_ordinal_; 863 bool is_cancel_; 864 if (!vx) 865 vx = &vx_; 866 if (!vy) 867 vy = &vy_; 868 if (!vx_ordinal) 869 vx_ordinal = &vx_ordinal_; 870 if (!vy_ordinal) 871 vy_ordinal = &vy_ordinal_; 872 if (!is_cancel) 873 is_cancel = &is_cancel_; 874 875 DeviceDataManagerX11::GetInstance()->GetFlingData( 876 native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel); 877 return true; 878 } 879 880 void UpdateX11EventForFlags(Event* event) { 881 XEvent* xev = event->native_event(); 882 if (!xev) 883 return; 884 switch (xev->type) { 885 case KeyPress: 886 case KeyRelease: 887 xev->xkey.state = UpdateX11EventFlags(event->flags(), xev->xkey.state); 888 break; 889 case ButtonPress: 890 case ButtonRelease: 891 xev->xbutton.state = 892 UpdateX11EventFlags(event->flags(), xev->xbutton.state); 893 break; 894 case GenericEvent: { 895 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); 896 DCHECK(xievent); 897 xievent->mods.effective = 898 UpdateX11EventFlags(event->flags(), xievent->mods.effective); 899 break; 900 } 901 default: 902 break; 903 } 904 } 905 906 void UpdateX11EventForChangedButtonFlags(MouseEvent* event) { 907 XEvent* xev = event->native_event(); 908 if (!xev) 909 return; 910 switch (xev->type) { 911 case ButtonPress: 912 case ButtonRelease: 913 xev->xbutton.button = UpdateX11EventButton(event->changed_button_flags(), 914 xev->xbutton.button); 915 break; 916 case GenericEvent: { 917 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); 918 CHECK(xievent && (xievent->evtype == XI_ButtonPress || 919 xievent->evtype == XI_ButtonRelease)); 920 xievent->detail = 921 UpdateX11EventButton(event->changed_button_flags(), xievent->detail); 922 break; 923 } 924 default: 925 break; 926 } 927 } 928 929 } // namespace ui 930