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