Index: base/message_pump_glib_x.cc |
diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc |
index 78c179933d00a7e5a70d0d94c3675fe7b9dd1379..26c4b87b5e6a43b5a0e14a7e128fff24e9218f5a 100644 |
--- a/base/message_pump_glib_x.cc |
+++ b/base/message_pump_glib_x.cc |
@@ -85,6 +85,8 @@ MessagePumpGlibX::~MessagePumpGlibX() { |
bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { |
GdkDisplay* gdisp = gdk_display_get_default(); |
Display* display = GDK_DISPLAY_XDISPLAY(gdisp); |
+ bool should_quit = false; |
+ |
if (XPending(display)) { |
XEvent xev; |
XPeekEvent(display, &xev); |
@@ -95,10 +97,22 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { |
) { |
XNextEvent(display, &xev); |
- bool processed = static_cast<MessagePumpGlibXDispatcher*> |
+#if defined(HAVE_XINPUT2) |
+ bool have_cookie = false; |
+ if (xev.type == GenericEvent && |
+ XGetEventData(xev.xgeneric.display, &xev.xcookie)) { |
+ have_cookie = true; |
+ } |
+#endif |
+ |
+ MessagePumpGlibXDispatcher::DispatchStatus status = |
+ static_cast<MessagePumpGlibXDispatcher*> |
(GetDispatcher())->Dispatch(&xev); |
- if (!processed) { |
+ if (status == MessagePumpGlibXDispatcher::EVENT_QUIT) { |
+ should_quit = true; |
+ Quit(); |
+ } else if (status == MessagePumpGlibXDispatcher::EVENT_IGNORED) { |
DLOG(WARNING) << "Event (" << xev.type << ") not handled."; |
// TODO(sad): It is necessary to put back the event so that the default |
@@ -106,16 +120,29 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { |
// impossible to use the omnibox at the moment. However, this will |
// eventually be removed once the omnibox code is updated for touchui. |
XPutBackEvent(display, &xev); |
+ if (gdksource_) |
+ gdksource_->source_funcs->dispatch = gdkdispatcher_; |
g_main_context_iteration(context, FALSE); |
} |
+ |
+#if defined(HAVE_XINPUT2) |
+ if (have_cookie) { |
+ XFreeEventData(xev.xgeneric.display, &xev.xcookie); |
+ } |
+#endif |
} else { |
// TODO(sad): A couple of extra events can still sneak in during this. |
// Those should be sent back to the X queue from the dispatcher |
// EventDispatcherX. |
+ if (gdksource_) |
+ gdksource_->source_funcs->dispatch = gdkdispatcher_; |
g_main_context_iteration(context, FALSE); |
} |
} |
+ if (should_quit) |
+ return true; |
+ |
bool retvalue; |
if (gdksource_) { |
// Replace the dispatch callback of the GDK event source temporarily so that |
@@ -178,6 +205,9 @@ void MessagePumpGlibX::InitializeXInput2(void) { |
return; |
} |
+ // TODO(sad): Here, we only setup so that the X windows created by GTK+ are |
+ // setup for XInput2 events. We need a way to listen for XInput2 events for X |
+ // windows created by other means (e.g. for context menus). |
SetupGtkWidgetRealizeNotifier(this); |
// Instead of asking X for the list of devices all the time, let's maintain a |
@@ -242,6 +272,7 @@ 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; |
} else if (!pump_x->IsDispatchingEvent()) { |
if (event->type != GDK_NOTHING && |
pump_x->capture_gdk_events_[event->type]) { |