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 |