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

Unified Diff: ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc

Issue 380943003: Do not release capture when transferring capture between Chrome windows on Linux (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
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: {

Powered by Google App Engine
This is Rietveld 408576698