Index: ui/views/widget/desktop_aura/x11_pointer_grab.cc |
diff --git a/ui/views/widget/desktop_aura/x11_pointer_grab.cc b/ui/views/widget/desktop_aura/x11_pointer_grab.cc |
index 13541599684428769595749d177177207183f77d..26a1c1d643eb2ee95314d64d4a3ecd3d194944da 100644 |
--- a/ui/views/widget/desktop_aura/x11_pointer_grab.cc |
+++ b/ui/views/widget/desktop_aura/x11_pointer_grab.cc |
@@ -3,8 +3,11 @@ |
// found in the LICENSE file. |
#include "base/logging.h" |
+#include "ui/base/x/x11_util.h" |
+#include "ui/events/devices/x11/device_data_manager_x11.h" |
#include "ui/views/widget/desktop_aura/x11_pointer_grab.h" |
+#include <X11/extensions/XInput2.h> |
#include <X11/Xlib.h> |
namespace views { |
@@ -20,10 +23,42 @@ bool g_owner_events = false; |
} // namespace |
int GrabPointer(XID window, bool owner_events, ::Cursor cursor) { |
- int event_mask = PointerMotionMask | ButtonReleaseMask | ButtonPressMask; |
- int result = XGrabPointer(gfx::GetXDisplay(), window, owner_events, |
- event_mask, GrabModeAsync, GrabModeAsync, None, |
- cursor, CurrentTime); |
+ int result = GrabInvalidTime; |
+ if (ui::IsXInput2Available()) { |
+ // Do an XInput2 pointer grab. If there is an active XInput2 pointer grab |
+ // as a result of normal button press, XGrabPointer() will fail. |
+ unsigned char mask[XIMaskLen(XI_LASTEVENT)]; |
+ memset(mask, 0, sizeof(mask)); |
+ XISetMask(mask, XI_ButtonPress); |
+ XISetMask(mask, XI_ButtonRelease); |
+ XISetMask(mask, XI_Motion); |
+ XIEventMask evmask; |
+ evmask.mask_len = sizeof(mask); |
+ evmask.mask = mask; |
+ |
+ const std::vector<int>& master_pointers = |
+ ui::DeviceDataManagerX11::GetInstance()->master_pointers(); |
+ for (int master_pointer : master_pointers) { |
+ evmask.deviceid = master_pointer; |
+ result = XIGrabDevice( |
+ gfx::GetXDisplay(), master_pointer, window, CurrentTime, cursor, |
+ GrabModeAsync, GrabModeAsync, owner_events, &evmask); |
+ // Assume that the grab will succeed on either all or none of the master |
+ // pointers. |
+ if (result != GrabSuccess) { |
+ // Try core pointer grab. |
+ break; |
+ } |
+ } |
+ } |
+ |
+ if (result != GrabSuccess) { |
+ int event_mask = PointerMotionMask | ButtonReleaseMask | ButtonPressMask; |
+ result = |
+ XGrabPointer(gfx::GetXDisplay(), window, owner_events, event_mask, |
+ GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime); |
+ } |
+ |
if (result == GrabSuccess) { |
g_grab_window = window; |
g_owner_events = owner_events; |
@@ -38,6 +73,13 @@ void ChangeActivePointerGrabCursor(::Cursor cursor) { |
void UngrabPointer() { |
g_grab_window = None; |
+ if (ui::IsXInput2Available()) { |
+ const std::vector<int>& master_pointers = |
+ ui::DeviceDataManagerX11::GetInstance()->master_pointers(); |
+ for (int master_pointer : master_pointers) |
+ XIUngrabDevice(gfx::GetXDisplay(), master_pointer, CurrentTime); |
+ } |
+ // Try core pointer ungrab in case the XInput2 pointer ungrab failed. |
XUngrabPointer(gfx::GetXDisplay(), CurrentTime); |
} |