message_pump_glib_x.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/message_pump_glib_x.h" 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <gdk/gdkx.h> 8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <X11/Xlib.h> 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/message_pump_glib_x_dispatch.h" 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace { 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdochgboolean PlaceholderDispatch(GSource* source, 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GSourceFunc cb, 16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gpointer data) { 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return TRUE; 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace base { 23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 24513209b27ff55e2841eac0e4120199c23acce758Ben MurdochMessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gdksource_(NULL), 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch dispatching_event_(false), 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_x_events_(0), 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_gdk_events_(0) { 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gdk_event_handler_set(&EventDispatcherX, this, NULL); 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch InitializeEventsToCapture(); 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 34513209b27ff55e2841eac0e4120199c23acce758Ben MurdochMessagePumpGlibX::~MessagePumpGlibX() { 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GdkDisplay* gdisp = gdk_display_get_default(); 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Display* display = GDK_DISPLAY_XDISPLAY(gdisp); 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (XPending(display)) { 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch XEvent xev; 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch XPeekEvent(display, &xev); 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (capture_x_events_[xev.type]) { 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch XNextEvent(display, &xev); 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool processed = static_cast<MessagePumpGlibXDispatcher*> 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (GetDispatcher())->Dispatch(&xev); 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!processed) { 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DLOG(WARNING) << "Event (" << xev.type << ") not handled."; 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(sad): A couple of extra events can still sneak in during this. 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Those should be sent back to the X queue from the dispatcher 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // EventDispatcherX. 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch g_main_context_iteration(context, FALSE); 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool retvalue; 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (gdksource_) { 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Replace the dispatch callback of the GDK event source temporarily so that 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // it doesn't read events from X. 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gboolean (*cb)(GSource*, GSourceFunc, void*) = 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gdksource_->source_funcs->dispatch; 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gdksource_->source_funcs->dispatch = PlaceholderDispatch; 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch dispatching_event_ = true; 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch retvalue = g_main_context_iteration(context, block); 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch dispatching_event_ = false; 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gdksource_->source_funcs->dispatch = cb; 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch retvalue = g_main_context_iteration(context, block); 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return retvalue; 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid MessagePumpGlibX::InitializeEventsToCapture(void) { 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(sad): Decide which events we want to capture and update the tables 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // accordingly. 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_x_events_[KeyPress] = true; 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_gdk_events_[GDK_KEY_PRESS] = true; 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_x_events_[KeyRelease] = true; 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_gdk_events_[GDK_KEY_RELEASE] = true; 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_x_events_[ButtonPress] = true; 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_gdk_events_[GDK_BUTTON_PRESS] = true; 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_x_events_[ButtonRelease] = true; 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_gdk_events_[GDK_BUTTON_RELEASE] = true; 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_x_events_[MotionNotify] = true; 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch capture_gdk_events_[GDK_MOTION_NOTIFY] = true; 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) { 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data); 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!pump_x->gdksource_) { 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch pump_x->gdksource_ = g_main_current_source(); 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (!pump_x->IsDispatchingEvent()) { 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (event->type != GDK_NOTHING && 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch pump_x->capture_gdk_events_[event->type]) { 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(sad): An X event is caught by the GDK handler. Put it back in the 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // X queue so that we catch it in the next iteration. When done, the 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // following DLOG statement will be removed. 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DLOG(WARNING) << "GDK received an event it shouldn't have"; 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch pump_x->DispatchEvents(event); 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace base 118