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