message_pump_glib_x.cc revision 513209b27ff55e2841eac0e4120199c23acce758
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 3// found in the LICENSE file. 4 5#include "base/message_pump_glib_x.h" 6 7#include <gdk/gdkx.h> 8#include <X11/Xlib.h> 9 10#include "base/message_pump_glib_x_dispatch.h" 11 12namespace { 13 14gboolean PlaceholderDispatch(GSource* source, 15 GSourceFunc cb, 16 gpointer data) { 17 return TRUE; 18} 19 20} // namespace 21 22namespace base { 23 24MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), 25 gdksource_(NULL), 26 dispatching_event_(false), 27 capture_x_events_(0), 28 capture_gdk_events_(0) { 29 gdk_event_handler_set(&EventDispatcherX, this, NULL); 30 31 InitializeEventsToCapture(); 32} 33 34MessagePumpGlibX::~MessagePumpGlibX() { 35} 36 37bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { 38 GdkDisplay* gdisp = gdk_display_get_default(); 39 Display* display = GDK_DISPLAY_XDISPLAY(gdisp); 40 if (XPending(display)) { 41 XEvent xev; 42 XPeekEvent(display, &xev); 43 if (capture_x_events_[xev.type]) { 44 XNextEvent(display, &xev); 45 46 bool processed = static_cast<MessagePumpGlibXDispatcher*> 47 (GetDispatcher())->Dispatch(&xev); 48 49 if (!processed) { 50 DLOG(WARNING) << "Event (" << xev.type << ") not handled."; 51 } 52 } else { 53 // TODO(sad): A couple of extra events can still sneak in during this. 54 // Those should be sent back to the X queue from the dispatcher 55 // EventDispatcherX. 56 g_main_context_iteration(context, FALSE); 57 } 58 } 59 60 bool retvalue; 61 if (gdksource_) { 62 // Replace the dispatch callback of the GDK event source temporarily so that 63 // it doesn't read events from X. 64 gboolean (*cb)(GSource*, GSourceFunc, void*) = 65 gdksource_->source_funcs->dispatch; 66 gdksource_->source_funcs->dispatch = PlaceholderDispatch; 67 68 dispatching_event_ = true; 69 retvalue = g_main_context_iteration(context, block); 70 dispatching_event_ = false; 71 72 gdksource_->source_funcs->dispatch = cb; 73 } else { 74 retvalue = g_main_context_iteration(context, block); 75 } 76 77 return retvalue; 78} 79 80void MessagePumpGlibX::InitializeEventsToCapture(void) { 81 // TODO(sad): Decide which events we want to capture and update the tables 82 // accordingly. 83 capture_x_events_[KeyPress] = true; 84 capture_gdk_events_[GDK_KEY_PRESS] = true; 85 86 capture_x_events_[KeyRelease] = true; 87 capture_gdk_events_[GDK_KEY_RELEASE] = true; 88 89 capture_x_events_[ButtonPress] = true; 90 capture_gdk_events_[GDK_BUTTON_PRESS] = true; 91 92 capture_x_events_[ButtonRelease] = true; 93 capture_gdk_events_[GDK_BUTTON_RELEASE] = true; 94 95 capture_x_events_[MotionNotify] = true; 96 capture_gdk_events_[GDK_MOTION_NOTIFY] = true; 97} 98 99void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) { 100 MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data); 101 102 if (!pump_x->gdksource_) { 103 pump_x->gdksource_ = g_main_current_source(); 104 } else if (!pump_x->IsDispatchingEvent()) { 105 if (event->type != GDK_NOTHING && 106 pump_x->capture_gdk_events_[event->type]) { 107 // TODO(sad): An X event is caught by the GDK handler. Put it back in the 108 // X queue so that we catch it in the next iteration. When done, the 109 // following DLOG statement will be removed. 110 DLOG(WARNING) << "GDK received an event it shouldn't have"; 111 } 112 } 113 114 pump_x->DispatchEvents(event); 115} 116 117} // namespace base 118