| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/aura/window_tree_host_x11.h" | 5 #include "ui/aura/window_tree_host_x11.h" |
| 6 | 6 |
| 7 #include <strings.h> | 7 #include <strings.h> |
| 8 #include <X11/cursorfont.h> | 8 #include <X11/cursorfont.h> |
| 9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
| 10 #include <X11/extensions/Xrandr.h> | 10 #include <X11/extensions/Xrandr.h> |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 } | 323 } |
| 324 | 324 |
| 325 uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) { | 325 uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) { |
| 326 XEvent* xev = event; | 326 XEvent* xev = event; |
| 327 if (FindEventTarget(xev) == x_root_window_) { | 327 if (FindEventTarget(xev) == x_root_window_) { |
| 328 if (xev->type == GenericEvent) | 328 if (xev->type == GenericEvent) |
| 329 DispatchXI2Event(xev); | 329 DispatchXI2Event(xev); |
| 330 return ui::POST_DISPATCH_NONE; | 330 return ui::POST_DISPATCH_NONE; |
| 331 } | 331 } |
| 332 | 332 |
| 333 if (xev->type == MotionNotify) { |
| 334 // Discard all but the most recent motion event that targets the same |
| 335 // window with unchanged state. |
| 336 XEvent last_event; |
| 337 while (XPending(xev->xany.display)) { |
| 338 XEvent next_event; |
| 339 XPeekEvent(xev->xany.display, &next_event); |
| 340 if (next_event.type == MotionNotify && |
| 341 next_event.xmotion.window == xev->xmotion.window && |
| 342 next_event.xmotion.subwindow == xev->xmotion.subwindow && |
| 343 next_event.xmotion.state == xev->xmotion.state) { |
| 344 XNextEvent(xev->xany.display, &last_event); |
| 345 xev = &last_event; |
| 346 } else { |
| 347 break; |
| 348 } |
| 349 } |
| 350 } |
| 351 |
| 352 if ((xev->type == EnterNotify || xev->type == LeaveNotify) && |
| 353 xev->xcrossing.detail == NotifyInferior) { |
| 354 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|. |
| 355 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. |
| 356 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is |
| 357 // necessary. crbug.com/385716 |
| 358 return ui::POST_DISPATCH_STOP_PROPAGATION; |
| 359 } |
| 360 |
| 361 if (xev->type == EnterNotify || |
| 362 xev->type == LeaveNotify || |
| 363 xev->type == KeyPress || |
| 364 xev->type == KeyRelease || |
| 365 xev->type == ButtonPress || |
| 366 xev->type == ButtonRelease || |
| 367 xev->type == MotionNotify) { |
| 368 switch (ui::EventTypeFromNative(xev)) { |
| 369 case ui::ET_KEY_PRESSED: |
| 370 case ui::ET_KEY_RELEASED: { |
| 371 ui::KeyEvent keydown_event(xev, false); |
| 372 SendEventToProcessor(&keydown_event); |
| 373 break; |
| 374 } |
| 375 case ui::ET_MOUSE_MOVED: |
| 376 case ui::ET_MOUSE_DRAGGED: |
| 377 case ui::ET_MOUSE_ENTERED: |
| 378 case ui::ET_MOUSE_EXITED: |
| 379 case ui::ET_MOUSE_PRESSED: |
| 380 case ui::ET_MOUSE_RELEASED: { |
| 381 ui::MouseEvent mouse_event(xev); |
| 382 if (xev->type == EnterNotify) { |
| 383 aura::Window* root_window = window(); |
| 384 client::CursorClient* cursor_client = |
| 385 client::GetCursorClient(root_window); |
| 386 if (cursor_client) { |
| 387 const gfx::Display display = gfx::Screen::GetScreenFor( |
| 388 root_window)->GetDisplayNearestWindow(root_window); |
| 389 cursor_client->SetDisplay(display); |
| 390 } |
| 391 // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is |
| 392 // not a real mouse move event. |
| 393 mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED); |
| 394 } |
| 395 |
| 396 TranslateAndDispatchLocatedEvent(&mouse_event); |
| 397 break; |
| 398 } |
| 399 case ui::ET_MOUSEWHEEL: { |
| 400 ui::MouseWheelEvent mouseev(xev); |
| 401 TranslateAndDispatchLocatedEvent(&mouseev); |
| 402 break; |
| 403 } |
| 404 case ui::ET_UNKNOWN: |
| 405 // No event is created for X11-release events for mouse-wheel buttons. |
| 406 break; |
| 407 default: |
| 408 NOTREACHED(); |
| 409 } |
| 410 return ui::POST_DISPATCH_STOP_PROPAGATION; |
| 411 } |
| 412 |
| 333 switch (xev->type) { | 413 switch (xev->type) { |
| 334 case EnterNotify: { | |
| 335 // Ignore EventNotify events from children of |xwindow_|. | |
| 336 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. | |
| 337 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is | |
| 338 // necessary. crbug.com/385716 | |
| 339 if (xev->xcrossing.detail == NotifyInferior) | |
| 340 break; | |
| 341 | |
| 342 aura::Window* root_window = window(); | |
| 343 client::CursorClient* cursor_client = | |
| 344 client::GetCursorClient(root_window); | |
| 345 if (cursor_client) { | |
| 346 const gfx::Display display = gfx::Screen::GetScreenFor(root_window)-> | |
| 347 GetDisplayNearestWindow(root_window); | |
| 348 cursor_client->SetDisplay(display); | |
| 349 } | |
| 350 ui::MouseEvent mouse_event(xev); | |
| 351 // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is not | |
| 352 // real mouse move event. | |
| 353 mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED); | |
| 354 TranslateAndDispatchLocatedEvent(&mouse_event); | |
| 355 break; | |
| 356 } | |
| 357 case LeaveNotify: { | |
| 358 // Ignore LeaveNotify events from children of |xwindow_|. | |
| 359 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. | |
| 360 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is | |
| 361 // necessary. crbug.com/385716 | |
| 362 if (xev->xcrossing.detail == NotifyInferior) | |
| 363 break; | |
| 364 | |
| 365 ui::MouseEvent mouse_event(xev); | |
| 366 TranslateAndDispatchLocatedEvent(&mouse_event); | |
| 367 break; | |
| 368 } | |
| 369 case Expose: { | 414 case Expose: { |
| 370 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, | 415 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, |
| 371 xev->xexpose.width, xev->xexpose.height); | 416 xev->xexpose.width, xev->xexpose.height); |
| 372 compositor()->ScheduleRedrawRect(damage_rect); | 417 compositor()->ScheduleRedrawRect(damage_rect); |
| 373 break; | 418 break; |
| 374 } | 419 } |
| 375 case KeyPress: { | 420 |
| 376 ui::KeyEvent keydown_event(xev, false); | |
| 377 SendEventToProcessor(&keydown_event); | |
| 378 break; | |
| 379 } | |
| 380 case KeyRelease: { | |
| 381 ui::KeyEvent keyup_event(xev, false); | |
| 382 SendEventToProcessor(&keyup_event); | |
| 383 break; | |
| 384 } | |
| 385 case ButtonPress: | |
| 386 case ButtonRelease: { | |
| 387 switch (ui::EventTypeFromNative(xev)) { | |
| 388 case ui::ET_MOUSEWHEEL: { | |
| 389 ui::MouseWheelEvent mouseev(xev); | |
| 390 TranslateAndDispatchLocatedEvent(&mouseev); | |
| 391 break; | |
| 392 } | |
| 393 case ui::ET_MOUSE_PRESSED: | |
| 394 case ui::ET_MOUSE_RELEASED: { | |
| 395 ui::MouseEvent mouseev(xev); | |
| 396 TranslateAndDispatchLocatedEvent(&mouseev); | |
| 397 break; | |
| 398 } | |
| 399 case ui::ET_UNKNOWN: | |
| 400 // No event is created for X11-release events for mouse-wheel buttons. | |
| 401 break; | |
| 402 default: | |
| 403 NOTREACHED(); | |
| 404 } | |
| 405 break; | |
| 406 } | |
| 407 case FocusOut: | 421 case FocusOut: |
| 408 if (xev->xfocus.mode != NotifyGrab) | 422 if (xev->xfocus.mode != NotifyGrab) |
| 409 OnHostLostWindowCapture(); | 423 OnHostLostWindowCapture(); |
| 410 break; | 424 break; |
| 411 case ConfigureNotify: { | 425 case ConfigureNotify: { |
| 412 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 426 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 413 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 427 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 414 // It's possible that the X window may be resized by some other means | 428 // It's possible that the X window may be resized by some other means |
| 415 // than from within aura (e.g. the X window manager can change the | 429 // than from within aura (e.g. the X window manager can change the |
| 416 // size). Make sure the root window size is maintained properly. | 430 // size). Make sure the root window size is maintained properly. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 break; | 469 break; |
| 456 case MappingPointer: | 470 case MappingPointer: |
| 457 ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap(); | 471 ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap(); |
| 458 break; | 472 break; |
| 459 default: | 473 default: |
| 460 NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request; | 474 NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request; |
| 461 break; | 475 break; |
| 462 } | 476 } |
| 463 break; | 477 break; |
| 464 } | 478 } |
| 465 case MotionNotify: { | |
| 466 // Discard all but the most recent motion event that targets the same | |
| 467 // window with unchanged state. | |
| 468 XEvent last_event; | |
| 469 while (XPending(xev->xany.display)) { | |
| 470 XEvent next_event; | |
| 471 XPeekEvent(xev->xany.display, &next_event); | |
| 472 if (next_event.type == MotionNotify && | |
| 473 next_event.xmotion.window == xev->xmotion.window && | |
| 474 next_event.xmotion.subwindow == xev->xmotion.subwindow && | |
| 475 next_event.xmotion.state == xev->xmotion.state) { | |
| 476 XNextEvent(xev->xany.display, &last_event); | |
| 477 xev = &last_event; | |
| 478 } else { | |
| 479 break; | |
| 480 } | |
| 481 } | |
| 482 | |
| 483 ui::MouseEvent mouseev(xev); | |
| 484 TranslateAndDispatchLocatedEvent(&mouseev); | |
| 485 break; | |
| 486 } | |
| 487 } | 479 } |
| 488 return ui::POST_DISPATCH_STOP_PROPAGATION; | 480 return ui::POST_DISPATCH_STOP_PROPAGATION; |
| 489 } | 481 } |
| 490 | 482 |
| 491 ui::EventSource* WindowTreeHostX11::GetEventSource() { | 483 ui::EventSource* WindowTreeHostX11::GetEventSource() { |
| 492 return this; | 484 return this; |
| 493 } | 485 } |
| 494 | 486 |
| 495 gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() { | 487 gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() { |
| 496 return xwindow_; | 488 return xwindow_; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 XEvent* xev = event; | 638 XEvent* xev = event; |
| 647 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 639 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| 648 if (!factory->ShouldProcessXI2Event(xev)) | 640 if (!factory->ShouldProcessXI2Event(xev)) |
| 649 return; | 641 return; |
| 650 | 642 |
| 651 TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event", | 643 TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event", |
| 652 "event_latency_us", | 644 "event_latency_us", |
| 653 (ui::EventTimeForNow() - ui::EventTimeFromNative(event)). | 645 (ui::EventTimeForNow() - ui::EventTimeFromNative(event)). |
| 654 InMicroseconds()); | 646 InMicroseconds()); |
| 655 | 647 |
| 648 int num_coalesced = 0; |
| 649 XEvent last_event; |
| 650 if (xev->xgeneric.evtype == XI_Motion) { |
| 651 // If this is a motion event, we want to coalesce all pending motion |
| 652 // events that are at the top of the queue. Note, we don't coalesce |
| 653 // touch update events here. |
| 654 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); |
| 655 if (num_coalesced > 0) |
| 656 xev = &last_event; |
| 657 } |
| 656 ui::EventType type = ui::EventTypeFromNative(xev); | 658 ui::EventType type = ui::EventTypeFromNative(xev); |
| 657 XEvent last_event; | |
| 658 int num_coalesced = 0; | |
| 659 | 659 |
| 660 switch (type) { | 660 switch (type) { |
| 661 case ui::ET_TOUCH_MOVED: | 661 case ui::ET_TOUCH_MOVED: |
| 662 case ui::ET_TOUCH_PRESSED: | 662 case ui::ET_TOUCH_PRESSED: |
| 663 case ui::ET_TOUCH_CANCELLED: | 663 case ui::ET_TOUCH_CANCELLED: |
| 664 case ui::ET_TOUCH_RELEASED: { | 664 case ui::ET_TOUCH_RELEASED: { |
| 665 ui::TouchEvent touchev(xev); | 665 ui::TouchEvent touchev(xev); |
| 666 if (ui::DeviceDataManagerX11::GetInstance()->TouchEventNeedsCalibrate( | 666 if (ui::DeviceDataManagerX11::GetInstance()->TouchEventNeedsCalibrate( |
| 667 xiev->deviceid)) { | 667 xiev->deviceid)) { |
| 668 touch_calibrate_->Calibrate(&touchev, bounds_); | 668 touch_calibrate_->Calibrate(&touchev, bounds_); |
| 669 } | 669 } |
| 670 TranslateAndDispatchLocatedEvent(&touchev); | 670 TranslateAndDispatchLocatedEvent(&touchev); |
| 671 break; | 671 break; |
| 672 } | 672 } |
| 673 case ui::ET_MOUSE_MOVED: | 673 case ui::ET_MOUSE_MOVED: |
| 674 case ui::ET_MOUSE_DRAGGED: | 674 case ui::ET_MOUSE_DRAGGED: |
| 675 case ui::ET_MOUSE_PRESSED: | 675 case ui::ET_MOUSE_PRESSED: |
| 676 case ui::ET_MOUSE_RELEASED: | 676 case ui::ET_MOUSE_RELEASED: |
| 677 case ui::ET_MOUSE_ENTERED: | 677 case ui::ET_MOUSE_ENTERED: |
| 678 case ui::ET_MOUSE_EXITED: { | 678 case ui::ET_MOUSE_EXITED: { |
| 679 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { | |
| 680 // If this is a motion event, we want to coalesce all pending motion | |
| 681 // events that are at the top of the queue. | |
| 682 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); | |
| 683 if (num_coalesced > 0) | |
| 684 xev = &last_event; | |
| 685 } | |
| 686 ui::MouseEvent mouseev(xev); | 679 ui::MouseEvent mouseev(xev); |
| 687 TranslateAndDispatchLocatedEvent(&mouseev); | 680 TranslateAndDispatchLocatedEvent(&mouseev); |
| 688 break; | 681 break; |
| 689 } | 682 } |
| 690 case ui::ET_MOUSEWHEEL: { | 683 case ui::ET_MOUSEWHEEL: { |
| 691 ui::MouseWheelEvent mouseev(xev); | 684 ui::MouseWheelEvent mouseev(xev); |
| 692 TranslateAndDispatchLocatedEvent(&mouseev); | 685 TranslateAndDispatchLocatedEvent(&mouseev); |
| 693 break; | 686 break; |
| 694 } | 687 } |
| 695 case ui::ET_SCROLL_FLING_START: | 688 case ui::ET_SCROLL_FLING_START: |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 } | 728 } |
| 736 | 729 |
| 737 namespace test { | 730 namespace test { |
| 738 | 731 |
| 739 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { | 732 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { |
| 740 default_override_redirect = override_redirect; | 733 default_override_redirect = override_redirect; |
| 741 } | 734 } |
| 742 | 735 |
| 743 } // namespace test | 736 } // namespace test |
| 744 } // namespace aura | 737 } // namespace aura |
| OLD | NEW |