| Index: ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
| diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
| index d428447e84aefcfdd8417359069c6921002b94ac..77c5966f8e4bc873bf5a71e3f306981b1201ecbe 100644
|
| --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
| +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
| @@ -18,6 +18,7 @@
|
| #include "third_party/skia/include/core/SkPath.h"
|
| #include "ui/aura/client/cursor_client.h"
|
| #include "ui/aura/client/focus_client.h"
|
| +#include "ui/aura/client/screen_position_client.h"
|
| #include "ui/aura/window.h"
|
| #include "ui/aura/window_event_dispatcher.h"
|
| #include "ui/aura/window_property.h"
|
| @@ -46,9 +47,9 @@
|
| #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
|
| #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
|
| #include "ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h"
|
| +#include "ui/views/widget/desktop_aura/x11_capture_window.h"
|
| #include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
|
| #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h"
|
| -#include "ui/views/widget/desktop_aura/x11_scoped_capture.h"
|
| #include "ui/views/widget/desktop_aura/x11_window_event_filter.h"
|
| #include "ui/wm/core/compound_event_filter.h"
|
| #include "ui/wm/core/window_util.h"
|
| @@ -901,24 +902,35 @@ gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const {
|
| }
|
|
|
| void DesktopWindowTreeHostX11::SetCapture() {
|
| - // This is vaguely based on the old NativeWidgetGtk implementation.
|
| - //
|
| - // X11's XPointerGrab() shouldn't be used for everything; it doesn't map
|
| - // cleanly to Windows' SetCapture(). GTK only provides a separate concept of
|
| - // a grab that wasn't the X11 pointer grab, but was instead a manual
|
| - // redirection of the event. (You need to drop into GDK if you want to
|
| - // perform a raw X11 grab).
|
| + DesktopWindowTreeHostX11* old_capture = g_current_capture;
|
| + g_current_capture = this;
|
| + if (old_capture) {
|
| + // Take ownership of |old_capture|'s capture window which already has a
|
| + // mouse grab. Because there is no X11 mouse grab or mouse ungrab, the
|
| + // capture change is sychronous.
|
| + capture_window_ = old_capture->ReleaseCaptureWindow().Pass();
|
|
|
| - if (g_current_capture)
|
| - g_current_capture->OnCaptureReleased();
|
| + old_capture->OnHostLostWindowCapture();
|
| + }
|
|
|
| - g_current_capture = this;
|
| - x11_capture_.reset(new X11ScopedCapture(xwindow_));
|
| + if (!capture_window_) {
|
| + // Create an X11CaptureWindow to asynchronously grab the mouse. As
|
| + // |xwindow_| is likely the topmost window underneath the mouse, we will
|
| + // likely not miss any mouse events.
|
| + capture_window_.reset(new X11CaptureWindow);
|
| + }
|
| }
|
|
|
| void DesktopWindowTreeHostX11::ReleaseCapture() {
|
| - if (g_current_capture == this)
|
| - g_current_capture->OnCaptureReleased();
|
| + if (g_current_capture == this) {
|
| + // Release mouse grab asynchronously. |xwindow_| is likely the topmost
|
| + // window underneath the mouse so the capture release being asynchronous is
|
| + // likely inconsequential.
|
| + g_current_capture = NULL;
|
| + capture_window_.reset();
|
| +
|
| + OnHostLostWindowCapture();
|
| + }
|
| }
|
|
|
| void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
|
| @@ -1300,10 +1312,8 @@ void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) {
|
| ResetWindowRegion();
|
| }
|
|
|
| -void DesktopWindowTreeHostX11::OnCaptureReleased() {
|
| - x11_capture_.reset();
|
| - g_current_capture = NULL;
|
| - OnHostLostWindowCapture();
|
| +scoped_ptr<X11CaptureWindow> DesktopWindowTreeHostX11::ReleaseCaptureWindow() {
|
| + return capture_window_.Pass();
|
| }
|
|
|
| void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) {
|
| @@ -1337,17 +1347,27 @@ void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) {
|
| if (event->IsAnyButton() || event->IsMouseWheelEvent())
|
| FlashFrame(false);
|
|
|
| + if (ui::EventTargetFromNative(event->native_event()) != xwindow_) {
|
| + // The event was targeted at |capture_window_|'s X window.
|
| + gfx::Point location =
|
| + ui::EventSystemLocationFromNative(event->native_event());
|
| + aura::client::GetScreenPositionClient(window())->ConvertPointFromScreen(
|
| + window(), &location);
|
| + event->set_location(location);
|
| + }
|
| +
|
| if (!g_current_capture || g_current_capture == this) {
|
| SendEventToProcessor(event);
|
| } else {
|
| - // Another DesktopWindowTreeHostX11 has installed itself as
|
| - // capture. Translate the event's location and dispatch to the other.
|
| + // Another DesktopWindowTreeHostX11 has capture. Translate the event's
|
| + // location and dispatch to the other DesktopWindowTreeHostX11.
|
| event->ConvertLocationToTarget(window(), g_current_capture->window());
|
| g_current_capture->SendEventToProcessor(event);
|
| }
|
| }
|
|
|
| void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) {
|
| + DCHECK_EQ(ui::EventTargetFromNative(event->native_event()), xwindow_);
|
| if (g_current_capture && g_current_capture != this &&
|
| event->type() == ui::ET_TOUCH_PRESSED) {
|
| event->ConvertLocationToTarget(window(), g_current_capture->window());
|
| @@ -1526,9 +1546,9 @@ void DesktopWindowTreeHostX11::Relayout() {
|
|
|
| bool DesktopWindowTreeHostX11::CanDispatchEvent(
|
| const ui::PlatformEvent& event) {
|
| - return event->xany.window == xwindow_ ||
|
| - (event->type == GenericEvent &&
|
| - static_cast<XIDeviceEvent*>(event->xcookie.data)->event == xwindow_);
|
| + XID target = ui::EventTargetFromNative(event);
|
| + return target == xwindow_ ||
|
| + (capture_window_ && target == capture_window_->xwindow());
|
| }
|
|
|
| uint32_t DesktopWindowTreeHostX11::DispatchEvent(
|
| @@ -1554,6 +1574,11 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent(
|
|
|
| ui::MouseEvent mouse_event(xev);
|
| DispatchMouseEvent(&mouse_event);
|
| +
|
| + if (xev->xcrossing.mode == NotifyGrab ||
|
| + xev->xcrossing.mode == NotifyUngrab) {
|
| + ReleaseCapture();
|
| + }
|
| break;
|
| }
|
| case Expose: {
|
|
|