OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_x.h" | 5 #include "base/message_pump_x.h" |
6 | 6 |
7 #include <gdk/gdkx.h> | |
8 #include <X11/extensions/XInput2.h> | 7 #include <X11/extensions/XInput2.h> |
9 | 8 |
10 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
11 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
12 | 11 |
| 12 #if defined(TOOLKIT_USES_GTK) |
| 13 #include <gdk/gdkx.h> |
| 14 #endif |
| 15 |
13 namespace { | 16 namespace { |
14 | 17 |
15 gboolean XSourcePrepare(GSource* source, gint* timeout_ms) { | 18 gboolean XSourcePrepare(GSource* source, gint* timeout_ms) { |
16 if (XPending(base::MessagePumpX::GetDefaultXDisplay())) | 19 if (XPending(base::MessagePumpX::GetDefaultXDisplay())) |
17 *timeout_ms = 0; | 20 *timeout_ms = 0; |
18 else | 21 else |
19 *timeout_ms = -1; | 22 *timeout_ms = -1; |
20 return FALSE; | 23 return FALSE; |
21 } | 24 } |
22 | 25 |
(...skipping 10 matching lines...) Expand all Loading... |
33 return TRUE; | 36 return TRUE; |
34 } | 37 } |
35 | 38 |
36 GSourceFuncs XSourceFuncs = { | 39 GSourceFuncs XSourceFuncs = { |
37 XSourcePrepare, | 40 XSourcePrepare, |
38 XSourceCheck, | 41 XSourceCheck, |
39 XSourceDispatch, | 42 XSourceDispatch, |
40 NULL | 43 NULL |
41 }; | 44 }; |
42 | 45 |
43 // A flag to disable GTK's message pump. This is intermediate step | |
44 // to remove gtk and will be removed once migration is complete. | |
45 bool use_gtk_message_pump = true; | |
46 | |
47 // The opcode used for checking events. | 46 // The opcode used for checking events. |
48 int xiopcode = -1; | 47 int xiopcode = -1; |
49 | 48 |
50 // When the GTK/GDK event processing is disabled, the message-pump opens a | 49 // When the GTK/GDK event processing is disabled, the message-pump opens a |
51 // connection to the display and owns it. | 50 // connection to the display and owns it. |
52 Display* g_xdisplay = NULL; | 51 Display* g_xdisplay = NULL; |
53 | 52 |
| 53 #if defined(TOOLKIT_USES_GTK) |
| 54 // A flag to disable GTK's message pump. This is intermediate step |
| 55 // to remove gtk and will be removed once migration is complete. |
| 56 bool use_gtk_message_pump = true; |
| 57 |
54 gboolean PlaceholderDispatch(GSource* source, | 58 gboolean PlaceholderDispatch(GSource* source, |
55 GSourceFunc cb, | 59 GSourceFunc cb, |
56 gpointer data) { | 60 gpointer data) { |
57 return TRUE; | 61 return TRUE; |
58 } | 62 } |
| 63 #endif // defined(TOOLKIT_USES_GTK) |
59 | 64 |
60 void InitializeXInput2(void) { | 65 void InitializeXInput2(void) { |
61 Display* display = base::MessagePumpX::GetDefaultXDisplay(); | 66 Display* display = base::MessagePumpX::GetDefaultXDisplay(); |
62 if (!display) | 67 if (!display) |
63 return; | 68 return; |
64 | 69 |
65 int event, err; | 70 int event, err; |
66 | 71 |
67 if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) { | 72 if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) { |
68 VLOG(1) << "X Input extension not available."; | 73 VLOG(1) << "X Input extension not available."; |
69 xiopcode = -1; | 74 xiopcode = -1; |
70 return; | 75 return; |
71 } | 76 } |
72 | 77 |
73 int major = 2, minor = 0; | 78 int major = 2, minor = 0; |
74 if (XIQueryVersion(display, &major, &minor) == BadRequest) { | 79 if (XIQueryVersion(display, &major, &minor) == BadRequest) { |
75 VLOG(1) << "XInput2 not supported in the server."; | 80 VLOG(1) << "XInput2 not supported in the server."; |
76 xiopcode = -1; | 81 xiopcode = -1; |
77 return; | 82 return; |
78 } | 83 } |
79 } | 84 } |
80 | 85 |
81 } // namespace | 86 } // namespace |
82 | 87 |
83 namespace base { | 88 namespace base { |
84 | 89 |
85 MessagePumpX::MessagePumpX() : MessagePumpGlib(), | 90 MessagePumpX::MessagePumpX() : MessagePumpGlib(), |
86 x_source_(NULL), | 91 #if defined(TOOLKIT_USES_GTK) |
87 gdksource_(NULL), | 92 gdksource_(NULL), |
88 dispatching_event_(false), | 93 dispatching_event_(false), |
89 capture_x_events_(0), | 94 capture_x_events_(0), |
90 capture_gdk_events_(0) { | 95 capture_gdk_events_(0), |
| 96 #endif |
| 97 x_source_(NULL) { |
| 98 InitializeXInput2(); |
| 99 #if defined(TOOLKIT_USES_GTK) |
91 if (use_gtk_message_pump) { | 100 if (use_gtk_message_pump) { |
92 gdk_window_add_filter(NULL, &GdkEventFilter, this); | 101 gdk_window_add_filter(NULL, &GdkEventFilter, this); |
93 gdk_event_handler_set(&EventDispatcherX, this, NULL); | 102 gdk_event_handler_set(&EventDispatcherX, this, NULL); |
94 } else { | 103 } else { |
95 GPollFD* x_poll = new GPollFD(); | 104 GPollFD* x_poll = new GPollFD(); |
96 x_poll->fd = ConnectionNumber(g_xdisplay); | 105 x_poll->fd = ConnectionNumber(g_xdisplay); |
97 x_poll->events = G_IO_IN; | 106 x_poll->events = G_IO_IN; |
98 | 107 |
99 x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource)); | 108 x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource)); |
100 g_source_add_poll(x_source_, x_poll); | 109 g_source_add_poll(x_source_, x_poll); |
101 g_source_set_can_recurse(x_source_, FALSE); | 110 g_source_set_can_recurse(x_source_, FALSE); |
102 g_source_attach(x_source_, g_main_context_default()); | 111 g_source_attach(x_source_, g_main_context_default()); |
103 } | 112 } |
104 | |
105 InitializeXInput2(); | |
106 if (use_gtk_message_pump) | 113 if (use_gtk_message_pump) |
107 InitializeEventsToCapture(); | 114 InitializeEventsToCapture(); |
| 115 #endif |
108 } | 116 } |
109 | 117 |
110 MessagePumpX::~MessagePumpX() { | 118 MessagePumpX::~MessagePumpX() { |
| 119 #if defined(TOOLKIT_USES_GTK) |
111 if (use_gtk_message_pump) { | 120 if (use_gtk_message_pump) { |
112 gdk_window_remove_filter(NULL, &GdkEventFilter, this); | 121 gdk_window_remove_filter(NULL, &GdkEventFilter, this); |
113 gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event), | 122 gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event), |
114 this, NULL); | 123 this, NULL); |
115 } else { | 124 return; |
116 g_source_destroy(x_source_); | |
117 g_source_unref(x_source_); | |
118 XCloseDisplay(g_xdisplay); | |
119 g_xdisplay = NULL; | |
120 } | 125 } |
| 126 #endif |
| 127 |
| 128 g_source_destroy(x_source_); |
| 129 g_source_unref(x_source_); |
| 130 XCloseDisplay(g_xdisplay); |
| 131 g_xdisplay = NULL; |
| 132 } |
| 133 |
| 134 #if defined(TOOLKIT_USES_GTK) |
| 135 // static |
| 136 void MessagePumpX::DisableGtkMessagePump() { |
| 137 use_gtk_message_pump = false; |
| 138 } |
| 139 #endif |
| 140 |
| 141 // static |
| 142 Display* MessagePumpX::GetDefaultXDisplay() { |
| 143 #if defined(TOOLKIT_USES_GTK) |
| 144 if (use_gtk_message_pump) { |
| 145 static GdkDisplay* display = gdk_display_get_default(); |
| 146 return display ? GDK_DISPLAY_XDISPLAY(display) : NULL; |
| 147 } |
| 148 #endif |
| 149 if (!g_xdisplay) |
| 150 g_xdisplay = XOpenDisplay(NULL); |
| 151 return g_xdisplay; |
121 } | 152 } |
122 | 153 |
123 // static | 154 // static |
124 void MessagePumpX::DisableGtkMessagePump() { | |
125 use_gtk_message_pump = false; | |
126 g_xdisplay = XOpenDisplay(NULL); | |
127 } | |
128 | |
129 // static | |
130 Display* MessagePumpX::GetDefaultXDisplay() { | |
131 if (use_gtk_message_pump) { | |
132 static GdkDisplay* display = gdk_display_get_default(); | |
133 return display ? GDK_DISPLAY_XDISPLAY(display) : NULL; | |
134 } else { | |
135 return g_xdisplay; | |
136 } | |
137 } | |
138 | |
139 // static | |
140 bool MessagePumpX::HasXInput2() { | 155 bool MessagePumpX::HasXInput2() { |
141 return xiopcode != -1; | 156 return xiopcode != -1; |
142 } | 157 } |
143 | 158 |
144 bool MessagePumpX::ShouldCaptureXEvent(XEvent* xev) { | 159 bool MessagePumpX::ShouldCaptureXEvent(XEvent* xev) { |
145 return (!use_gtk_message_pump || capture_x_events_[xev->type]) | 160 return |
146 && (xev->type != GenericEvent || xev->xcookie.extension == xiopcode); | 161 #if defined(TOOLKIT_USES_GTK) |
| 162 (!use_gtk_message_pump || capture_x_events_[xev->type]) && |
| 163 #endif |
| 164 (xev->type != GenericEvent || xev->xcookie.extension == xiopcode); |
147 } | 165 } |
148 | 166 |
149 bool MessagePumpX::ProcessXEvent(XEvent* xev) { | 167 bool MessagePumpX::ProcessXEvent(XEvent* xev) { |
150 bool should_quit = false; | 168 bool should_quit = false; |
151 | 169 |
152 bool have_cookie = false; | 170 bool have_cookie = false; |
153 if (xev->type == GenericEvent && | 171 if (xev->type == GenericEvent && |
154 XGetEventData(xev->xgeneric.display, &xev->xcookie)) { | 172 XGetEventData(xev->xgeneric.display, &xev->xcookie)) { |
155 have_cookie = true; | 173 have_cookie = true; |
156 } | 174 } |
(...skipping 23 matching lines...) Expand all Loading... |
180 return g_main_context_iteration(context, block); | 198 return g_main_context_iteration(context, block); |
181 | 199 |
182 if (XPending(display)) { | 200 if (XPending(display)) { |
183 XEvent xev; | 201 XEvent xev; |
184 XPeekEvent(display, &xev); | 202 XPeekEvent(display, &xev); |
185 | 203 |
186 if (ShouldCaptureXEvent(&xev)) { | 204 if (ShouldCaptureXEvent(&xev)) { |
187 XNextEvent(display, &xev); | 205 XNextEvent(display, &xev); |
188 if (ProcessXEvent(&xev)) | 206 if (ProcessXEvent(&xev)) |
189 return true; | 207 return true; |
| 208 #if defined(TOOLKIT_USES_GTK) |
190 } else if (use_gtk_message_pump && gdksource_) { | 209 } else if (use_gtk_message_pump && gdksource_) { |
191 // TODO(sad): A couple of extra events can still sneak in during this. | 210 // TODO(sad): A couple of extra events can still sneak in during this. |
192 // Those should be sent back to the X queue from the dispatcher | 211 // Those should be sent back to the X queue from the dispatcher |
193 // EventDispatcherX. | 212 // EventDispatcherX. |
194 gdksource_->source_funcs->dispatch = gdkdispatcher_; | 213 gdksource_->source_funcs->dispatch = gdkdispatcher_; |
195 g_main_context_iteration(context, FALSE); | 214 g_main_context_iteration(context, FALSE); |
| 215 #endif |
196 } | 216 } |
197 } | 217 } |
198 | 218 |
199 bool retvalue; | 219 bool retvalue; |
| 220 #if defined(TOOLKIT_USES_GTK) |
200 if (gdksource_ && use_gtk_message_pump) { | 221 if (gdksource_ && use_gtk_message_pump) { |
201 // Replace the dispatch callback of the GDK event source temporarily so that | 222 // Replace the dispatch callback of the GDK event source temporarily so that |
202 // it doesn't read events from X. | 223 // it doesn't read events from X. |
203 gboolean (*cb)(GSource*, GSourceFunc, void*) = | 224 gboolean (*cb)(GSource*, GSourceFunc, void*) = |
204 gdksource_->source_funcs->dispatch; | 225 gdksource_->source_funcs->dispatch; |
205 gdksource_->source_funcs->dispatch = PlaceholderDispatch; | 226 gdksource_->source_funcs->dispatch = PlaceholderDispatch; |
206 | 227 |
207 dispatching_event_ = true; | 228 dispatching_event_ = true; |
208 retvalue = g_main_context_iteration(context, block); | 229 retvalue = g_main_context_iteration(context, block); |
209 dispatching_event_ = false; | 230 dispatching_event_ = false; |
210 | 231 |
211 gdksource_->source_funcs->dispatch = cb; | 232 gdksource_->source_funcs->dispatch = cb; |
212 } else { | 233 } else { |
213 retvalue = g_main_context_iteration(context, block); | 234 retvalue = g_main_context_iteration(context, block); |
214 } | 235 } |
| 236 #else |
| 237 retvalue = g_main_context_iteration(context, block); |
| 238 #endif |
215 | 239 |
216 return retvalue; | 240 return retvalue; |
217 } | 241 } |
218 | 242 |
| 243 #if defined(TOOLKIT_USES_GTK) |
219 GdkFilterReturn MessagePumpX::GdkEventFilter(GdkXEvent* gxevent, | 244 GdkFilterReturn MessagePumpX::GdkEventFilter(GdkXEvent* gxevent, |
220 GdkEvent* gevent, | 245 GdkEvent* gevent, |
221 gpointer data) { | 246 gpointer data) { |
222 MessagePumpX* pump = static_cast<MessagePumpX*>(data); | 247 MessagePumpX* pump = static_cast<MessagePumpX*>(data); |
223 XEvent* xev = static_cast<XEvent*>(gxevent); | 248 XEvent* xev = static_cast<XEvent*>(gxevent); |
224 | 249 |
225 if (pump->ShouldCaptureXEvent(xev) && pump->GetDispatcher()) { | 250 if (pump->ShouldCaptureXEvent(xev) && pump->GetDispatcher()) { |
226 pump->ProcessXEvent(xev); | 251 pump->ProcessXEvent(xev); |
227 return GDK_FILTER_REMOVE; | 252 return GDK_FILTER_REMOVE; |
228 } | 253 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 297 |
273 capture_x_events_[ButtonRelease] = true; | 298 capture_x_events_[ButtonRelease] = true; |
274 capture_gdk_events_[GDK_BUTTON_RELEASE] = true; | 299 capture_gdk_events_[GDK_BUTTON_RELEASE] = true; |
275 | 300 |
276 capture_x_events_[MotionNotify] = true; | 301 capture_x_events_[MotionNotify] = true; |
277 capture_gdk_events_[GDK_MOTION_NOTIFY] = true; | 302 capture_gdk_events_[GDK_MOTION_NOTIFY] = true; |
278 | 303 |
279 capture_x_events_[GenericEvent] = true; | 304 capture_x_events_[GenericEvent] = true; |
280 } | 305 } |
281 | 306 |
| 307 COMPILE_ASSERT(XLASTEvent >= LASTEvent, XLASTEvent_too_small); |
| 308 |
| 309 #endif // defined(TOOLKIT_USES_GTK) |
| 310 |
282 MessagePumpObserver::EventStatus | 311 MessagePumpObserver::EventStatus |
283 MessagePumpObserver::WillProcessXEvent(XEvent* xev) { | 312 MessagePumpObserver::WillProcessXEvent(XEvent* xev) { |
284 return EVENT_CONTINUE; | 313 return EVENT_CONTINUE; |
285 } | 314 } |
286 | 315 |
287 COMPILE_ASSERT(XLASTEvent >= LASTEvent, XLASTEvent_too_small); | |
288 | |
289 } // namespace base | 316 } // namespace base |
OLD | NEW |