Chromium Code Reviews| 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 e0245f98cbdbe34e75b87c26d2a3309ccc992e3b..19a47f89c59dae64865b3d0075175a6e4794f567 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" |
| @@ -121,6 +122,13 @@ const char* kAtomsToCache[] = { |
| NULL |
| }; |
| +// Returns |native_event|'s target. |
| +XID EventTargetFromNative(const base::NativeEvent& native_event) { |
| + return (native_event->type == GenericEvent) ? |
| + static_cast<XIDeviceEvent*>(native_event->xcookie.data)->event : |
| + native_event->xany.window; |
| +} |
| + |
| } // namespace |
| //////////////////////////////////////////////////////////////////////////////// |
| @@ -903,24 +911,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) { |
| @@ -1333,10 +1352,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) { |
| @@ -1370,17 +1387,33 @@ void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) { |
| if (event->IsAnyButton() || event->IsMouseWheelEvent()) |
| FlashFrame(false); |
| + if (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_root_location(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. |
| - event->ConvertLocationToTarget(window(), g_current_capture->window()); |
| + // Another DesktopWindowTreeHostX11 has capture. Translate the event's |
| + // location and dispatch to the other DesktopWindowTreeHostX11. |
| + gfx::Point location = event->location(); |
| + aura::Window::ConvertPointToTarget(window(), |
| + g_current_capture->window(), |
| + &location); |
| + event->set_root_location(location); |
| + event->set_location(location); |
|
sadrul
2014/07/29 18:47:50
ConvertLocationToTarget() should work correctly he
pkotwicz
2014/08/01 03:35:00
I am splitting this change out to a different CL b
pkotwicz
2014/08/01 04:32:14
You are right ConvertLocationToTarget() does work
|
| g_current_capture->SendEventToProcessor(event); |
| } |
| } |
| void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) { |
| + DCHECK_EQ(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()); |
| @@ -1559,9 +1592,8 @@ 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_); |
| + return EventTargetFromNative(event) == xwindow_ || |
| + (capture_window_ && capture_window_->CanDispatchEventToOwner(event)); |
| } |
| uint32_t DesktopWindowTreeHostX11::DispatchEvent( |
| @@ -1585,8 +1617,13 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent( |
| if (xev->xcrossing.detail == NotifyInferior) |
| break; |
| - ui::MouseEvent mouse_event(xev); |
| - DispatchMouseEvent(&mouse_event); |
| + if (xev->xcrossing.mode == NotifyGrab || |
| + xev->xcrossing.mode == NotifyUngrab) { |
| + ReleaseCapture(); |
|
sadrul
2014/07/29 18:47:50
Should NotifyGrab really trigger ReleaseCapture()?
pkotwicz
2014/08/01 03:35:00
I am going to differ releasing capture as a result
|
| + } else { |
| + ui::MouseEvent mouse_event(xev); |
| + DispatchMouseEvent(&mouse_event); |
| + } |
| break; |
| } |
| case Expose: { |