| 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 InitXSource(); |
| 96 x_poll->fd = ConnectionNumber(g_xdisplay); | |
| 97 x_poll->events = G_IO_IN; | |
| 98 | |
| 99 x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource)); | |
| 100 g_source_add_poll(x_source_, x_poll); | |
| 101 g_source_set_can_recurse(x_source_, FALSE); | |
| 102 g_source_attach(x_source_, g_main_context_default()); | |
| 103 } | 105 } |
| 104 | |
| 105 InitializeXInput2(); | |
| 106 if (use_gtk_message_pump) | 106 if (use_gtk_message_pump) |
| 107 InitializeEventsToCapture(); | 107 InitializeEventsToCapture(); |
| 108 #else |
| 109 InitXSource(); |
| 110 #endif |
| 108 } | 111 } |
| 109 | 112 |
| 110 MessagePumpX::~MessagePumpX() { | 113 MessagePumpX::~MessagePumpX() { |
| 114 #if defined(TOOLKIT_USES_GTK) |
| 111 if (use_gtk_message_pump) { | 115 if (use_gtk_message_pump) { |
| 112 gdk_window_remove_filter(NULL, &GdkEventFilter, this); | 116 gdk_window_remove_filter(NULL, &GdkEventFilter, this); |
| 113 gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event), | 117 gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event), |
| 114 this, NULL); | 118 this, NULL); |
| 115 } else { | 119 return; |
| 116 g_source_destroy(x_source_); | |
| 117 g_source_unref(x_source_); | |
| 118 XCloseDisplay(g_xdisplay); | |
| 119 g_xdisplay = NULL; | |
| 120 } | 120 } |
| 121 #endif |
| 122 |
| 123 g_source_destroy(x_source_); |
| 124 g_source_unref(x_source_); |
| 125 XCloseDisplay(g_xdisplay); |
| 126 g_xdisplay = NULL; |
| 127 } |
| 128 |
| 129 #if defined(TOOLKIT_USES_GTK) |
| 130 // static |
| 131 void MessagePumpX::DisableGtkMessagePump() { |
| 132 use_gtk_message_pump = false; |
| 133 } |
| 134 #endif |
| 135 |
| 136 // static |
| 137 Display* MessagePumpX::GetDefaultXDisplay() { |
| 138 #if defined(TOOLKIT_USES_GTK) |
| 139 if (use_gtk_message_pump) { |
| 140 static GdkDisplay* display = gdk_display_get_default(); |
| 141 return display ? GDK_DISPLAY_XDISPLAY(display) : NULL; |
| 142 } |
| 143 #endif |
| 144 if (!g_xdisplay) |
| 145 g_xdisplay = XOpenDisplay(NULL); |
| 146 return g_xdisplay; |
| 121 } | 147 } |
| 122 | 148 |
| 123 // static | 149 // 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() { | 150 bool MessagePumpX::HasXInput2() { |
| 141 return xiopcode != -1; | 151 return xiopcode != -1; |
| 142 } | 152 } |
| 143 | 153 |
| 154 void MessagePumpX::InitXSource() { |
| 155 DCHECK(!x_source_); |
| 156 GPollFD* x_poll = new GPollFD(); |
| 157 x_poll->fd = ConnectionNumber(g_xdisplay); |
| 158 x_poll->events = G_IO_IN; |
| 159 |
| 160 x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource)); |
| 161 g_source_add_poll(x_source_, x_poll); |
| 162 g_source_set_can_recurse(x_source_, FALSE); |
| 163 g_source_attach(x_source_, g_main_context_default()); |
| 164 } |
| 165 |
| 144 bool MessagePumpX::ShouldCaptureXEvent(XEvent* xev) { | 166 bool MessagePumpX::ShouldCaptureXEvent(XEvent* xev) { |
| 145 return (!use_gtk_message_pump || capture_x_events_[xev->type]) | 167 return |
| 146 && (xev->type != GenericEvent || xev->xcookie.extension == xiopcode); | 168 #if defined(TOOLKIT_USES_GTK) |
| 169 (!use_gtk_message_pump || capture_x_events_[xev->type]) && |
| 170 #endif |
| 171 (xev->type != GenericEvent || xev->xcookie.extension == xiopcode); |
| 147 } | 172 } |
| 148 | 173 |
| 149 bool MessagePumpX::ProcessXEvent(XEvent* xev) { | 174 bool MessagePumpX::ProcessXEvent(XEvent* xev) { |
| 150 bool should_quit = false; | 175 bool should_quit = false; |
| 151 | 176 |
| 152 bool have_cookie = false; | 177 bool have_cookie = false; |
| 153 if (xev->type == GenericEvent && | 178 if (xev->type == GenericEvent && |
| 154 XGetEventData(xev->xgeneric.display, &xev->xcookie)) { | 179 XGetEventData(xev->xgeneric.display, &xev->xcookie)) { |
| 155 have_cookie = true; | 180 have_cookie = true; |
| 156 } | 181 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 180 return g_main_context_iteration(context, block); | 205 return g_main_context_iteration(context, block); |
| 181 | 206 |
| 182 if (XPending(display)) { | 207 if (XPending(display)) { |
| 183 XEvent xev; | 208 XEvent xev; |
| 184 XPeekEvent(display, &xev); | 209 XPeekEvent(display, &xev); |
| 185 | 210 |
| 186 if (ShouldCaptureXEvent(&xev)) { | 211 if (ShouldCaptureXEvent(&xev)) { |
| 187 XNextEvent(display, &xev); | 212 XNextEvent(display, &xev); |
| 188 if (ProcessXEvent(&xev)) | 213 if (ProcessXEvent(&xev)) |
| 189 return true; | 214 return true; |
| 215 #if defined(TOOLKIT_USES_GTK) |
| 190 } else if (use_gtk_message_pump && gdksource_) { | 216 } else if (use_gtk_message_pump && gdksource_) { |
| 191 // TODO(sad): A couple of extra events can still sneak in during this. | 217 // 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 | 218 // Those should be sent back to the X queue from the dispatcher |
| 193 // EventDispatcherX. | 219 // EventDispatcherX. |
| 194 gdksource_->source_funcs->dispatch = gdkdispatcher_; | 220 gdksource_->source_funcs->dispatch = gdkdispatcher_; |
| 195 g_main_context_iteration(context, FALSE); | 221 g_main_context_iteration(context, FALSE); |
| 222 #endif |
| 196 } | 223 } |
| 197 } | 224 } |
| 198 | 225 |
| 199 bool retvalue; | 226 bool retvalue; |
| 227 #if defined(TOOLKIT_USES_GTK) |
| 200 if (gdksource_ && use_gtk_message_pump) { | 228 if (gdksource_ && use_gtk_message_pump) { |
| 201 // Replace the dispatch callback of the GDK event source temporarily so that | 229 // Replace the dispatch callback of the GDK event source temporarily so that |
| 202 // it doesn't read events from X. | 230 // it doesn't read events from X. |
| 203 gboolean (*cb)(GSource*, GSourceFunc, void*) = | 231 gboolean (*cb)(GSource*, GSourceFunc, void*) = |
| 204 gdksource_->source_funcs->dispatch; | 232 gdksource_->source_funcs->dispatch; |
| 205 gdksource_->source_funcs->dispatch = PlaceholderDispatch; | 233 gdksource_->source_funcs->dispatch = PlaceholderDispatch; |
| 206 | 234 |
| 207 dispatching_event_ = true; | 235 dispatching_event_ = true; |
| 208 retvalue = g_main_context_iteration(context, block); | 236 retvalue = g_main_context_iteration(context, block); |
| 209 dispatching_event_ = false; | 237 dispatching_event_ = false; |
| 210 | 238 |
| 211 gdksource_->source_funcs->dispatch = cb; | 239 gdksource_->source_funcs->dispatch = cb; |
| 212 } else { | 240 } else { |
| 213 retvalue = g_main_context_iteration(context, block); | 241 retvalue = g_main_context_iteration(context, block); |
| 214 } | 242 } |
| 243 #else |
| 244 retvalue = g_main_context_iteration(context, block); |
| 245 #endif |
| 215 | 246 |
| 216 return retvalue; | 247 return retvalue; |
| 217 } | 248 } |
| 218 | 249 |
| 250 #if defined(TOOLKIT_USES_GTK) |
| 219 GdkFilterReturn MessagePumpX::GdkEventFilter(GdkXEvent* gxevent, | 251 GdkFilterReturn MessagePumpX::GdkEventFilter(GdkXEvent* gxevent, |
| 220 GdkEvent* gevent, | 252 GdkEvent* gevent, |
| 221 gpointer data) { | 253 gpointer data) { |
| 222 MessagePumpX* pump = static_cast<MessagePumpX*>(data); | 254 MessagePumpX* pump = static_cast<MessagePumpX*>(data); |
| 223 XEvent* xev = static_cast<XEvent*>(gxevent); | 255 XEvent* xev = static_cast<XEvent*>(gxevent); |
| 224 | 256 |
| 225 if (pump->ShouldCaptureXEvent(xev) && pump->GetDispatcher()) { | 257 if (pump->ShouldCaptureXEvent(xev) && pump->GetDispatcher()) { |
| 226 pump->ProcessXEvent(xev); | 258 pump->ProcessXEvent(xev); |
| 227 return GDK_FILTER_REMOVE; | 259 return GDK_FILTER_REMOVE; |
| 228 } | 260 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 | 304 |
| 273 capture_x_events_[ButtonRelease] = true; | 305 capture_x_events_[ButtonRelease] = true; |
| 274 capture_gdk_events_[GDK_BUTTON_RELEASE] = true; | 306 capture_gdk_events_[GDK_BUTTON_RELEASE] = true; |
| 275 | 307 |
| 276 capture_x_events_[MotionNotify] = true; | 308 capture_x_events_[MotionNotify] = true; |
| 277 capture_gdk_events_[GDK_MOTION_NOTIFY] = true; | 309 capture_gdk_events_[GDK_MOTION_NOTIFY] = true; |
| 278 | 310 |
| 279 capture_x_events_[GenericEvent] = true; | 311 capture_x_events_[GenericEvent] = true; |
| 280 } | 312 } |
| 281 | 313 |
| 314 COMPILE_ASSERT(XLASTEvent >= LASTEvent, XLASTEvent_too_small); |
| 315 |
| 316 #endif // defined(TOOLKIT_USES_GTK) |
| 317 |
| 282 MessagePumpObserver::EventStatus | 318 MessagePumpObserver::EventStatus |
| 283 MessagePumpObserver::WillProcessXEvent(XEvent* xev) { | 319 MessagePumpObserver::WillProcessXEvent(XEvent* xev) { |
| 284 return EVENT_CONTINUE; | 320 return EVENT_CONTINUE; |
| 285 } | 321 } |
| 286 | 322 |
| 287 COMPILE_ASSERT(XLASTEvent >= LASTEvent, XLASTEvent_too_small); | |
| 288 | |
| 289 } // namespace base | 323 } // namespace base |
| OLD | NEW |