| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/message_pump_aurax11.h" | 5 #include "base/message_loop/message_pump_aurax11.h" |
| 6 | 6 |
| 7 #include <glib.h> | 7 #include <glib.h> |
| 8 #include <X11/X.h> | 8 #include <X11/X.h> |
| 9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
| 10 #include <X11/XKBlib.h> | 10 #include <X11/XKBlib.h> |
| 11 | 11 |
| 12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 | 14 |
| 15 namespace base { |
| 16 |
| 15 namespace { | 17 namespace { |
| 16 | 18 |
| 17 gboolean XSourcePrepare(GSource* source, gint* timeout_ms) { | 19 gboolean XSourcePrepare(GSource* source, gint* timeout_ms) { |
| 18 if (XPending(base::MessagePumpAuraX11::GetDefaultXDisplay())) | 20 if (XPending(MessagePumpAuraX11::GetDefaultXDisplay())) |
| 19 *timeout_ms = 0; | 21 *timeout_ms = 0; |
| 20 else | 22 else |
| 21 *timeout_ms = -1; | 23 *timeout_ms = -1; |
| 22 return FALSE; | 24 return FALSE; |
| 23 } | 25 } |
| 24 | 26 |
| 25 gboolean XSourceCheck(GSource* source) { | 27 gboolean XSourceCheck(GSource* source) { |
| 26 return XPending(base::MessagePumpAuraX11::GetDefaultXDisplay()); | 28 return XPending(MessagePumpAuraX11::GetDefaultXDisplay()); |
| 27 } | 29 } |
| 28 | 30 |
| 29 gboolean XSourceDispatch(GSource* source, | 31 gboolean XSourceDispatch(GSource* source, |
| 30 GSourceFunc unused_func, | 32 GSourceFunc unused_func, |
| 31 gpointer data) { | 33 gpointer data) { |
| 32 base::MessagePumpAuraX11* pump = static_cast<base::MessagePumpAuraX11*>(data); | 34 MessagePumpAuraX11* pump = static_cast<MessagePumpAuraX11*>(data); |
| 33 return pump->DispatchXEvents(); | 35 return pump->DispatchXEvents(); |
| 34 } | 36 } |
| 35 | 37 |
| 36 GSourceFuncs XSourceFuncs = { | 38 GSourceFuncs XSourceFuncs = { |
| 37 XSourcePrepare, | 39 XSourcePrepare, |
| 38 XSourceCheck, | 40 XSourceCheck, |
| 39 XSourceDispatch, | 41 XSourceDispatch, |
| 40 NULL | 42 NULL |
| 41 }; | 43 }; |
| 42 | 44 |
| 43 // The connection is essentially a global that's accessed through a static | 45 // The connection is essentially a global that's accessed through a static |
| 44 // method and destroyed whenever ~MessagePumpAuraX11() is called. We do this | 46 // method and destroyed whenever ~MessagePumpAuraX11() is called. We do this |
| 45 // for historical reasons so user code can call | 47 // for historical reasons so user code can call |
| 46 // MessagePumpForUI::GetDefaultXDisplay() where MessagePumpForUI is a typedef | 48 // MessagePumpForUI::GetDefaultXDisplay() where MessagePumpForUI is a typedef |
| 47 // to whatever type in the current build. | 49 // to whatever type in the current build. |
| 48 // | 50 // |
| 49 // TODO(erg): This can be changed to something more sane like | 51 // TODO(erg): This can be changed to something more sane like |
| 50 // MessagePumpAuraX11::Current()->display() once MessagePumpGtk goes away. | 52 // MessagePumpAuraX11::Current()->display() once MessagePumpGtk goes away. |
| 51 Display* g_xdisplay = NULL; | 53 Display* g_xdisplay = NULL; |
| 52 int g_xinput_opcode = -1; | 54 int g_xinput_opcode = -1; |
| 53 | 55 |
| 54 bool InitializeXInput2Internal() { | 56 bool InitializeXInput2Internal() { |
| 55 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 57 Display* display = MessagePumpAuraX11::GetDefaultXDisplay(); |
| 56 if (!display) | 58 if (!display) |
| 57 return false; | 59 return false; |
| 58 | 60 |
| 59 int event, err; | 61 int event, err; |
| 60 | 62 |
| 61 int xiopcode; | 63 int xiopcode; |
| 62 if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) { | 64 if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) { |
| 63 DVLOG(1) << "X Input extension not available."; | 65 DVLOG(1) << "X Input extension not available."; |
| 64 return false; | 66 return false; |
| 65 } | 67 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 79 if (major < 2 || (major == 2 && minor < USE_XI2_MT)) { | 81 if (major < 2 || (major == 2 && minor < USE_XI2_MT)) { |
| 80 DVLOG(1) << "XI version on server is " << major << "." << minor << ". " | 82 DVLOG(1) << "XI version on server is " << major << "." << minor << ". " |
| 81 << "But 2." << USE_XI2_MT << " is required."; | 83 << "But 2." << USE_XI2_MT << " is required."; |
| 82 return false; | 84 return false; |
| 83 } | 85 } |
| 84 #endif | 86 #endif |
| 85 | 87 |
| 86 return true; | 88 return true; |
| 87 } | 89 } |
| 88 | 90 |
| 89 Window FindEventTarget(const base::NativeEvent& xev) { | 91 Window FindEventTarget(const NativeEvent& xev) { |
| 90 Window target = xev->xany.window; | 92 Window target = xev->xany.window; |
| 91 if (xev->type == GenericEvent && | 93 if (xev->type == GenericEvent && |
| 92 static_cast<XIEvent*>(xev->xcookie.data)->extension == g_xinput_opcode) { | 94 static_cast<XIEvent*>(xev->xcookie.data)->extension == g_xinput_opcode) { |
| 93 target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event; | 95 target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event; |
| 94 } | 96 } |
| 95 return target; | 97 return target; |
| 96 } | 98 } |
| 97 | 99 |
| 98 bool InitializeXInput2() { | 100 bool InitializeXInput2() { |
| 99 static bool xinput2_supported = InitializeXInput2Internal(); | 101 static bool xinput2_supported = InitializeXInput2Internal(); |
| 100 return xinput2_supported; | 102 return xinput2_supported; |
| 101 } | 103 } |
| 102 | 104 |
| 103 bool InitializeXkb() { | 105 bool InitializeXkb() { |
| 104 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 106 Display* display = MessagePumpAuraX11::GetDefaultXDisplay(); |
| 105 if (!display) | 107 if (!display) |
| 106 return false; | 108 return false; |
| 107 | 109 |
| 108 int opcode, event, error; | 110 int opcode, event, error; |
| 109 int major = XkbMajorVersion; | 111 int major = XkbMajorVersion; |
| 110 int minor = XkbMinorVersion; | 112 int minor = XkbMinorVersion; |
| 111 if (!XkbQueryExtension(display, &opcode, &event, &error, &major, &minor)) { | 113 if (!XkbQueryExtension(display, &opcode, &event, &error, &major, &minor)) { |
| 112 DVLOG(1) << "Xkb extension not available."; | 114 DVLOG(1) << "Xkb extension not available."; |
| 113 return false; | 115 return false; |
| 114 } | 116 } |
| 115 | 117 |
| 116 // Ask the server not to send KeyRelease event when the user holds down a key. | 118 // Ask the server not to send KeyRelease event when the user holds down a key. |
| 117 // crbug.com/138092 | 119 // crbug.com/138092 |
| 118 Bool supported_return; | 120 Bool supported_return; |
| 119 if (!XkbSetDetectableAutoRepeat(display, True, &supported_return)) { | 121 if (!XkbSetDetectableAutoRepeat(display, True, &supported_return)) { |
| 120 DVLOG(1) << "XKB not supported in the server."; | 122 DVLOG(1) << "XKB not supported in the server."; |
| 121 return false; | 123 return false; |
| 122 } | 124 } |
| 123 | 125 |
| 124 return true; | 126 return true; |
| 125 } | 127 } |
| 126 | 128 |
| 127 } // namespace | 129 } // namespace |
| 128 | 130 |
| 129 namespace base { | |
| 130 | |
| 131 MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(), | 131 MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(), |
| 132 x_source_(NULL) { | 132 x_source_(NULL) { |
| 133 InitializeXInput2(); | 133 InitializeXInput2(); |
| 134 InitializeXkb(); | 134 InitializeXkb(); |
| 135 InitXSource(); | 135 InitXSource(); |
| 136 | 136 |
| 137 // Can't put this in the initializer list because g_xdisplay may not exist | 137 // Can't put this in the initializer list because g_xdisplay may not exist |
| 138 // until after InitXSource(). | 138 // until after InitXSource(). |
| 139 x_root_window_ = DefaultRootWindow(g_xdisplay); | 139 x_root_window_ = DefaultRootWindow(g_xdisplay); |
| 140 } | 140 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 return true; | 270 return true; |
| 271 } | 271 } |
| 272 return false; | 272 return false; |
| 273 } | 273 } |
| 274 | 274 |
| 275 void MessagePumpAuraX11::DidProcessXEvent(XEvent* xevent) { | 275 void MessagePumpAuraX11::DidProcessXEvent(XEvent* xevent) { |
| 276 FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent)); | 276 FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent)); |
| 277 } | 277 } |
| 278 | 278 |
| 279 MessagePumpDispatcher* MessagePumpAuraX11::GetDispatcherForXEvent( | 279 MessagePumpDispatcher* MessagePumpAuraX11::GetDispatcherForXEvent( |
| 280 const base::NativeEvent& xev) const { | 280 const NativeEvent& xev) const { |
| 281 ::Window x_window = FindEventTarget(xev); | 281 ::Window x_window = FindEventTarget(xev); |
| 282 DispatchersMap::const_iterator it = dispatchers_.find(x_window); | 282 DispatchersMap::const_iterator it = dispatchers_.find(x_window); |
| 283 return it != dispatchers_.end() ? it->second : NULL; | 283 return it != dispatchers_.end() ? it->second : NULL; |
| 284 } | 284 } |
| 285 | 285 |
| 286 bool MessagePumpAuraX11::Dispatch(const base::NativeEvent& xev) { | 286 bool MessagePumpAuraX11::Dispatch(const NativeEvent& xev) { |
| 287 // MappingNotify events (meaning that the keyboard or pointer buttons have | 287 // MappingNotify events (meaning that the keyboard or pointer buttons have |
| 288 // been remapped) aren't associated with a window; send them to all | 288 // been remapped) aren't associated with a window; send them to all |
| 289 // dispatchers. | 289 // dispatchers. |
| 290 if (xev->type == MappingNotify) { | 290 if (xev->type == MappingNotify) { |
| 291 for (DispatchersMap::const_iterator it = dispatchers_.begin(); | 291 for (DispatchersMap::const_iterator it = dispatchers_.begin(); |
| 292 it != dispatchers_.end(); ++it) { | 292 it != dispatchers_.end(); ++it) { |
| 293 it->second->Dispatch(xev); | 293 it->second->Dispatch(xev); |
| 294 } | 294 } |
| 295 return true; | 295 return true; |
| 296 } | 296 } |
| 297 | 297 |
| 298 if (FindEventTarget(xev) == x_root_window_) { | 298 if (FindEventTarget(xev) == x_root_window_) { |
| 299 FOR_EACH_OBSERVER(MessagePumpDispatcher, root_window_dispatchers_, | 299 FOR_EACH_OBSERVER(MessagePumpDispatcher, root_window_dispatchers_, |
| 300 Dispatch(xev)); | 300 Dispatch(xev)); |
| 301 return true; | 301 return true; |
| 302 } | 302 } |
| 303 MessagePumpDispatcher* dispatcher = GetDispatcherForXEvent(xev); | 303 MessagePumpDispatcher* dispatcher = GetDispatcherForXEvent(xev); |
| 304 return dispatcher ? dispatcher->Dispatch(xev) : true; | 304 return dispatcher ? dispatcher->Dispatch(xev) : true; |
| 305 } | 305 } |
| 306 | 306 |
| 307 } // namespace base | 307 } // namespace base |
| OLD | NEW |