Index: base/message_pump_glib_x.cc |
diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc |
index 06a156e67c609e3aaeb8203c3ed8034d17cedbed..35cfc1a533e158cd71b31f57b5501b88feac7c64 100644 |
--- a/base/message_pump_glib_x.cc |
+++ b/base/message_pump_glib_x.cc |
@@ -1,4 +1,4 @@ |
-// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
@@ -80,7 +80,7 @@ MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), |
#if defined(HAVE_XINPUT2) |
xiopcode_(-1), |
masters_(), |
- slaves_(), |
+ floats_(), |
#endif |
gdksource_(NULL), |
dispatching_event_(false), |
@@ -112,22 +112,29 @@ void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) { |
XISetMask(mask, XI_ButtonRelease); |
XISetMask(mask, XI_Motion); |
- // It is necessary to select only for the master devices. XInput2 provides |
- // enough information to the event callback to decide which slave device |
- // triggered the event, thus decide whether the 'pointer event' is a 'mouse |
- // event' or a 'touch event'. So it is not necessary to select for the slave |
- // devices here. |
- XIEventMask evmasks[masters_.size()]; |
+ // It is not necessary to select for slave devices. XInput2 provides enough |
+ // information to the event callback to decide which slave device triggered |
+ // the event, thus decide whether the 'pointer event' is a 'mouse event' or a |
+ // 'touch event'. |
+ // If the touch device has 'GrabDevice' set and 'SendCoreEvents' unset (which |
+ // is possible), then the device is detected as a floating device, and a |
+ // floating device is not connected to a master device. So it is necessary to |
+ // also select on the floating devices. |
+ std::set<int> devices; |
+ std::set_union(masters_.begin(), masters_.end(), |
+ floats_.begin(), floats_.end(), |
+ std::inserter(devices, devices.begin())); |
+ XIEventMask evmasks[devices.size()]; |
int count = 0; |
- for (std::set<int>::const_iterator iter = masters_.begin(); |
- iter != masters_.end(); |
+ for (std::set<int>::const_iterator iter = devices.begin(); |
+ iter != devices.end(); |
++iter, ++count) { |
evmasks[count].deviceid = *iter; |
evmasks[count].mask_len = sizeof(mask); |
evmasks[count].mask = mask; |
} |
- XISelectEvents(xdisplay, xwindow, evmasks, masters_.size()); |
+ XISelectEvents(xdisplay, xwindow, evmasks, devices.size()); |
// TODO(sad): Setup masks for keyboard events. |
@@ -224,7 +231,8 @@ void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) { |
if (!pump_x->gdksource_) { |
pump_x->gdksource_ = g_main_current_source(); |
- pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch; |
+ if (pump_x->gdksource_) |
+ pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch; |
} else if (!pump_x->IsDispatchingEvent()) { |
if (event->type != GDK_NOTHING && |
pump_x->capture_gdk_events_[event->type]) { |
@@ -294,17 +302,15 @@ void MessagePumpGlibX::InitializeXInput2(void) { |
XIDeviceInfo* devices = XIQueryDevice(xdisplay, XIAllDevices, &count); |
for (int i = 0; i < count; i++) { |
XIDeviceInfo* devinfo = devices + i; |
- if (devinfo->use == XISlavePointer) { |
- slaves_.insert(devinfo->deviceid); |
+ if (devinfo->use == XIFloatingSlave) { |
+ floats_.insert(devinfo->deviceid); |
} else if (devinfo->use == XIMasterPointer) { |
masters_.insert(devinfo->deviceid); |
} |
- // We do not need to care about XIFloatingSlave, because the callback for |
- // XI_HierarchyChanged event will take care of it. |
} |
XIFreeDeviceInfo(devices); |
- // TODO(sad): Select on root for XI_HierarchyChanged so that slaves_ and |
+ // TODO(sad): Select on root for XI_HierarchyChanged so that floats_ and |
// masters_ can be kept up-to-date. This is a relatively rare event, so we can |
// put it off for a later time. |
// Note: It is not necessary to listen for XI_DeviceChanged events. |