| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/message_pump_glib_x.h" | 5 #include "base/message_pump_glib_x.h" |
| 6 | 6 |
| 7 #include <gdk/gdkx.h> | 7 #include <gdk/gdkx.h> |
| 8 #if defined(HAVE_XINPUT2) | 8 #if defined(HAVE_XINPUT2) |
| 9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
| 10 #else | 10 #else |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 msgpump->SetupXInput2ForXWindow(GDK_WINDOW_XID(window)); | 42 msgpump->SetupXInput2ForXWindow(GDK_WINDOW_XID(window)); |
| 43 | 43 |
| 44 return true; | 44 return true; |
| 45 } | 45 } |
| 46 | 46 |
| 47 // We need to capture all the GDK windows that get created, and start | 47 // We need to capture all the GDK windows that get created, and start |
| 48 // listening for XInput2 events. So we setup a callback to the 'realize' | 48 // listening for XInput2 events. So we setup a callback to the 'realize' |
| 49 // signal for GTK+ widgets, so that whenever the signal triggers for any | 49 // signal for GTK+ widgets, so that whenever the signal triggers for any |
| 50 // GtkWidget, which means the GtkWidget should now have a GdkWindow, we can | 50 // GtkWidget, which means the GtkWidget should now have a GdkWindow, we can |
| 51 // setup XInput2 events for the GdkWindow. | 51 // setup XInput2 events for the GdkWindow. |
| 52 static guint realize_signal_id = 0; |
| 53 static guint realize_hook_id = 0; |
| 54 |
| 52 void SetupGtkWidgetRealizeNotifier(base::MessagePumpGlibX* msgpump) { | 55 void SetupGtkWidgetRealizeNotifier(base::MessagePumpGlibX* msgpump) { |
| 53 guint signal_id; | |
| 54 gpointer klass = g_type_class_ref(GTK_TYPE_WIDGET); | 56 gpointer klass = g_type_class_ref(GTK_TYPE_WIDGET); |
| 55 | 57 |
| 56 g_signal_parse_name("realize", GTK_TYPE_WIDGET, &signal_id, NULL, FALSE); | 58 g_signal_parse_name("realize", GTK_TYPE_WIDGET, |
| 57 g_signal_add_emission_hook(signal_id, 0, GtkWidgetRealizeCallback, | 59 &realize_signal_id, NULL, FALSE); |
| 58 static_cast<gpointer>(msgpump), NULL); | 60 realize_hook_id = g_signal_add_emission_hook(realize_signal_id, 0, |
| 61 GtkWidgetRealizeCallback, static_cast<gpointer>(msgpump), NULL); |
| 59 | 62 |
| 60 g_type_class_unref(klass); | 63 g_type_class_unref(klass); |
| 61 } | 64 } |
| 62 | 65 |
| 66 void RemoveGtkWidgetRealizeNotifier() { |
| 67 if (realize_signal_id != 0) |
| 68 g_signal_remove_emission_hook(realize_signal_id, realize_hook_id); |
| 69 realize_signal_id = 0; |
| 70 realize_hook_id = 0; |
| 71 } |
| 72 |
| 63 #endif // HAVE_XINPUT2 | 73 #endif // HAVE_XINPUT2 |
| 64 | 74 |
| 65 } // namespace | 75 } // namespace |
| 66 | 76 |
| 67 namespace base { | 77 namespace base { |
| 68 | 78 |
| 69 MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), | 79 MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), |
| 70 #if defined(HAVE_XINPUT2) | 80 #if defined(HAVE_XINPUT2) |
| 71 xiopcode_(-1), | 81 xiopcode_(-1), |
| 72 masters_(), | 82 masters_(), |
| 73 slaves_(), | 83 slaves_(), |
| 74 #endif | 84 #endif |
| 75 gdksource_(NULL), | 85 gdksource_(NULL), |
| 76 dispatching_event_(false), | 86 dispatching_event_(false), |
| 77 capture_x_events_(0), | 87 capture_x_events_(0), |
| 78 capture_gdk_events_(0) { | 88 capture_gdk_events_(0) { |
| 79 gdk_event_handler_set(&EventDispatcherX, this, NULL); | 89 gdk_event_handler_set(&EventDispatcherX, this, NULL); |
| 80 | 90 |
| 81 #if defined(HAVE_XINPUT2) | 91 #if defined(HAVE_XINPUT2) |
| 82 InitializeXInput2(); | 92 InitializeXInput2(); |
| 83 #endif | 93 #endif |
| 84 InitializeEventsToCapture(); | 94 InitializeEventsToCapture(); |
| 85 } | 95 } |
| 86 | 96 |
| 87 MessagePumpGlibX::~MessagePumpGlibX() { | 97 MessagePumpGlibX::~MessagePumpGlibX() { |
| 98 #if defined(HAVE_XINPUT2) |
| 99 RemoveGtkWidgetRealizeNotifier(); |
| 100 #endif |
| 88 } | 101 } |
| 89 | 102 |
| 90 #if defined(HAVE_XINPUT2) | 103 #if defined(HAVE_XINPUT2) |
| 91 void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) { | 104 void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) { |
| 92 Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); | 105 Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); |
| 93 | 106 |
| 94 // Setup mask for mouse events. | 107 // Setup mask for mouse events. |
| 95 unsigned char mask[(XI_LASTEVENT + 7)/8]; | 108 unsigned char mask[(XI_LASTEVENT + 7)/8]; |
| 96 memset(mask, 0, sizeof(mask)); | 109 memset(mask, 0, sizeof(mask)); |
| 97 | 110 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 117 XISelectEvents(xdisplay, xwindow, evmasks, masters_.size()); | 130 XISelectEvents(xdisplay, xwindow, evmasks, masters_.size()); |
| 118 | 131 |
| 119 // TODO(sad): Setup masks for keyboard events. | 132 // TODO(sad): Setup masks for keyboard events. |
| 120 | 133 |
| 121 XFlush(xdisplay); | 134 XFlush(xdisplay); |
| 122 } | 135 } |
| 123 #endif // HAVE_XINPUT2 | 136 #endif // HAVE_XINPUT2 |
| 124 | 137 |
| 125 bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { | 138 bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { |
| 126 GdkDisplay* gdisp = gdk_display_get_default(); | 139 GdkDisplay* gdisp = gdk_display_get_default(); |
| 127 if (!gdisp) | 140 if (!gdisp || !GetDispatcher()) |
| 128 return MessagePumpForUI::RunOnce(context, block); | 141 return MessagePumpForUI::RunOnce(context, block); |
| 129 | 142 |
| 130 Display* display = GDK_DISPLAY_XDISPLAY(gdisp); | 143 Display* display = GDK_DISPLAY_XDISPLAY(gdisp); |
| 131 bool should_quit = false; | 144 bool should_quit = false; |
| 132 | 145 |
| 133 if (XPending(display)) { | 146 if (XPending(display)) { |
| 134 XEvent xev; | 147 XEvent xev; |
| 135 XPeekEvent(display, &xev); | 148 XPeekEvent(display, &xev); |
| 136 if (capture_x_events_[xev.type] | 149 if (capture_x_events_[xev.type] |
| 137 #if defined(HAVE_XINPUT2) | 150 #if defined(HAVE_XINPUT2) |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 XIFreeDeviceInfo(devices); | 305 XIFreeDeviceInfo(devices); |
| 293 | 306 |
| 294 // TODO(sad): Select on root for XI_HierarchyChanged so that slaves_ and | 307 // TODO(sad): Select on root for XI_HierarchyChanged so that slaves_ and |
| 295 // masters_ can be kept up-to-date. This is a relatively rare event, so we can | 308 // masters_ can be kept up-to-date. This is a relatively rare event, so we can |
| 296 // put it off for a later time. | 309 // put it off for a later time. |
| 297 // Note: It is not necessary to listen for XI_DeviceChanged events. | 310 // Note: It is not necessary to listen for XI_DeviceChanged events. |
| 298 } | 311 } |
| 299 #endif // HAVE_XINPUT2 | 312 #endif // HAVE_XINPUT2 |
| 300 | 313 |
| 301 } // namespace base | 314 } // namespace base |
| OLD | NEW |