message_pump_glib_x.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
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>
84a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <X11/extensions/XInput2.h>
104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <X11/Xlib.h>
124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/message_pump_glib_x_dispatch.h"
15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
16513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace {
17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdochgboolean PlaceholderDispatch(GSource* source,
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                             GSourceFunc cb,
20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                             gpointer data) {
21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return TRUE;
22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Setup XInput2 select for the GtkWidget.
274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochgboolean GtkWidgetRealizeCallback(GSignalInvocationHint* hint, guint nparams,
284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                  const GValue* pvalues, gpointer data) {
294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  GtkWidget* widget = GTK_WIDGET(g_value_get_object(pvalues));
304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  GdkWindow* window = widget->window;
314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  base::MessagePumpGlibX* msgpump = static_cast<base::MessagePumpGlibX*>(data);
324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK(window);  // TODO(sad): Remove once determined if necessary.
344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // TODO(sad): Do we need to set a flag on |window| to make sure we don't
364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // select for the same GdkWindow multiple times? Does it matter?
374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  msgpump->SetupXInput2ForXWindow(GDK_WINDOW_XID(window));
384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// We need to capture all the GDK windows that get created, and start
434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// listening for XInput2 events. So we setup a callback to the 'realize'
444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// signal for GTK+ widgets, so that whenever the signal triggers for any
454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// GtkWidget, which means the GtkWidget should now have a GdkWindow, we can
464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// setup XInput2 events for the GdkWindow.
474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid SetupGtkWidgetRealizeNotifier(base::MessagePumpGlibX* msgpump) {
484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  guint signal_id;
494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  gpointer klass = g_type_class_ref(GTK_TYPE_WIDGET);
504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  g_signal_parse_name("realize", GTK_TYPE_WIDGET, &signal_id, NULL, FALSE);
524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  g_signal_add_emission_hook(signal_id, 0, GtkWidgetRealizeCallback,
534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      static_cast<gpointer>(msgpump), NULL);
544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  g_type_class_unref(klass);
564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif  // HAVE_XINPUT2
594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}  // namespace
61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace base {
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
64513209b27ff55e2841eac0e4120199c23acce758Ben MurdochMessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(),
654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    xiopcode_(-1),
674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    masters_(),
684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    slaves_(),
694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gdksource_(NULL),
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    dispatching_event_(false),
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    capture_x_events_(0),
73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    capture_gdk_events_(0) {
74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  gdk_event_handler_set(&EventDispatcherX, this, NULL);
75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  InitializeXInput2();
784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  InitializeEventsToCapture();
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
82513209b27ff55e2841eac0e4120199c23acce758Ben MurdochMessagePumpGlibX::~MessagePumpGlibX() {
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
85513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GdkDisplay* gdisp = gdk_display_get_default();
87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  Display* display = GDK_DISPLAY_XDISPLAY(gdisp);
88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (XPending(display)) {
89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    XEvent xev;
90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    XPeekEvent(display, &xev);
914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (capture_x_events_[xev.type]
924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        && (xev.type != GenericEvent || xev.xcookie.extension == xiopcode_)
944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        ) {
96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      XNextEvent(display, &xev);
97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      bool processed = static_cast<MessagePumpGlibXDispatcher*>
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          (GetDispatcher())->Dispatch(&xev);
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (!processed) {
102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        DLOG(WARNING) << "Event (" << xev.type << ") not handled.";
1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        // TODO(sad): It is necessary to put back the event so that the default
1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        // GDK events handler can take care of it. Without this, it is
1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        // impossible to use the omnibox at the moment. However, this will
1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        // eventually be removed once the omnibox code is updated for touchui.
1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        XPutBackEvent(display, &xev);
1094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        g_main_context_iteration(context, FALSE);
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      }
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    } else {
112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // TODO(sad): A couple of extra events can still sneak in during this.
113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Those should be sent back to the X queue from the dispatcher
114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // EventDispatcherX.
115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      g_main_context_iteration(context, FALSE);
116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool retvalue;
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (gdksource_) {
121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Replace the dispatch callback of the GDK event source temporarily so that
122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // it doesn't read events from X.
123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gboolean (*cb)(GSource*, GSourceFunc, void*) =
124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        gdksource_->source_funcs->dispatch;
125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gdksource_->source_funcs->dispatch = PlaceholderDispatch;
126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    dispatching_event_ = true;
128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    retvalue = g_main_context_iteration(context, block);
129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    dispatching_event_ = false;
130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gdksource_->source_funcs->dispatch = cb;
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    retvalue = g_main_context_iteration(context, block);
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return retvalue;
137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
139513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid MessagePumpGlibX::InitializeEventsToCapture(void) {
140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // TODO(sad): Decide which events we want to capture and update the tables
141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // accordingly.
142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_x_events_[KeyPress] = true;
143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_gdk_events_[GDK_KEY_PRESS] = true;
144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_x_events_[KeyRelease] = true;
146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_gdk_events_[GDK_KEY_RELEASE] = true;
147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_x_events_[ButtonPress] = true;
149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_gdk_events_[GDK_BUTTON_PRESS] = true;
150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_x_events_[ButtonRelease] = true;
152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_gdk_events_[GDK_BUTTON_RELEASE] = true;
153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_x_events_[MotionNotify] = true;
155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  capture_gdk_events_[GDK_MOTION_NOTIFY] = true;
1564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
1584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  capture_x_events_[GenericEvent] = true;
1594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(HAVE_XINPUT2)
1634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid MessagePumpGlibX::InitializeXInput2(void) {
1644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  GdkDisplay* display = gdk_display_get_default();
1654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  Display* xdisplay = GDK_DISPLAY_XDISPLAY(display);
1664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int event, err;
1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!XQueryExtension(xdisplay, "XInputExtension", &xiopcode_, &event, &err)) {
1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    DLOG(WARNING) << "X Input extension not available.";
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    xiopcode_ = -1;
1714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
1724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int major = 2, minor = 0;
1754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (XIQueryVersion(xdisplay, &major, &minor) == BadRequest) {
1764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    DLOG(WARNING) << "XInput2 not supported in the server.";
1774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    xiopcode_ = -1;
1784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
1794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  SetupGtkWidgetRealizeNotifier(this);
1824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Instead of asking X for the list of devices all the time, let's maintain a
1844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // list of slave (physical) and master (virtual) pointer devices.
1854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int count = 0;
1864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XIDeviceInfo* devices = XIQueryDevice(xdisplay, XIAllDevices, &count);
1874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (int i = 0; i < count; i++) {
1884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    XIDeviceInfo* devinfo = devices + i;
1894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (devinfo->use == XISlavePointer) {
1904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      slaves_.insert(devinfo->deviceid);
1914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    } else if (devinfo->use == XIMasterPointer) {
1924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      masters_.insert(devinfo->deviceid);
1934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
1944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    // We do not need to care about XIFloatingSlave, because the callback for
1954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    // XI_HierarchyChanged event will take care of it.
1964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XIFreeDeviceInfo(devices);
1984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // TODO(sad): Select on root for XI_HierarchyChanged so that slaves_ and
2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // masters_ can be kept up-to-date. This is a relatively rare event, so we can
2014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // put it off for a later time.
2024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Note: It is not necessary to listen for XI_DeviceChanged events.
203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
204513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
2054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) {
2064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
2074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Setup mask for mouse events.
2094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  unsigned char mask[(XI_LASTEVENT + 7)/8];
2104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  memset(mask, 0, sizeof(mask));
2114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XISetMask(mask, XI_ButtonPress);
2134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XISetMask(mask, XI_ButtonRelease);
2144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XISetMask(mask, XI_Motion);
2154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // It is necessary to select only for the master devices. XInput2 provides
2174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // enough information to the event callback to decide which slave device
2184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // triggered the event, thus decide whether the 'pointer event' is a 'mouse
2194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // event' or a 'touch event'. So it is not necessary to select for the slave
2204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // devices here.
2214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XIEventMask evmasks[masters_.size()];
2224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int count = 0;
2234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (std::set<int>::const_iterator iter = masters_.begin();
2244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch       iter != masters_.end();
2254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch       ++iter, ++count) {
2264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    evmasks[count].deviceid = *iter;
2274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    evmasks[count].mask_len = sizeof(mask);
2284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    evmasks[count].mask = mask;
2294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
2304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XISelectEvents(xdisplay, xwindow, evmasks, masters_.size());
2324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // TODO(sad): Setup masks for keyboard events.
2344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  XFlush(xdisplay);
2364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
2374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif  // HAVE_XINPUT2
2394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
240513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
241513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data);
242513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!pump_x->gdksource_) {
244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    pump_x->gdksource_ = g_main_current_source();
245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else if (!pump_x->IsDispatchingEvent()) {
246513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (event->type != GDK_NOTHING &&
247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        pump_x->capture_gdk_events_[event->type]) {
248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // TODO(sad): An X event is caught by the GDK handler. Put it back in the
249513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // X queue so that we catch it in the next iteration. When done, the
250513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // following DLOG statement will be removed.
251513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      DLOG(WARNING) << "GDK received an event it shouldn't have";
252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  pump_x->DispatchEvents(event);
256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}  // namespace base
259