Chromium Code Reviews| 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_pump_aurax11.h" |
| 6 | 6 |
| 7 #include <glib.h> | 7 #include <glib.h> |
| 8 #include <X11/extensions/XInput2.h> | 8 #include <X11/extensions/XInput2.h> |
| 9 #include <X11/XKBlib.h> | 9 #include <X11/XKBlib.h> |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 return pump->DispatchXEvents(); | 32 return pump->DispatchXEvents(); |
| 33 } | 33 } |
| 34 | 34 |
| 35 GSourceFuncs XSourceFuncs = { | 35 GSourceFuncs XSourceFuncs = { |
| 36 XSourcePrepare, | 36 XSourcePrepare, |
| 37 XSourceCheck, | 37 XSourceCheck, |
| 38 XSourceDispatch, | 38 XSourceDispatch, |
| 39 NULL | 39 NULL |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 // The message-pump opens a connection to the display and owns it. | 42 // The connection is essentially a global that's accessed through a static |
| 43 // method and destroyed whenever ~MessagePumpAuraX11() is called. We do this | |
| 44 // for historical reasons so user code can call | |
| 45 // MessagePumpForUI::GetDefaultXDisplay() where MessagePumpForUI is a typedef | |
| 46 // to whatever type in the current build. | |
| 47 // | |
| 48 // TODO(erg): This can be changed to something more sane like | |
| 49 // MessagePumpAuraX11::Current()->display() once GTK goes away. | |
|
sadrul
2012/08/29 16:01:25
Perhaps say once 'MessagePumpGtk' goes away (I was
| |
| 43 Display* g_xdisplay = NULL; | 50 Display* g_xdisplay = NULL; |
| 44 | 51 |
| 45 // The default dispatcher to process native events when no dispatcher | |
| 46 // is specified. | |
| 47 base::MessagePumpDispatcher* g_default_dispatcher = NULL; | |
| 48 | |
| 49 bool InitializeXInput2Internal() { | 52 bool InitializeXInput2Internal() { |
| 50 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 53 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
| 51 if (!display) | 54 if (!display) |
| 52 return false; | 55 return false; |
| 53 | 56 |
| 54 int event, err; | 57 int event, err; |
| 55 | 58 |
| 56 int xiopcode; | 59 int xiopcode; |
| 57 if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) { | 60 if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) { |
| 58 DVLOG(1) << "X Input extension not available."; | 61 DVLOG(1) << "X Input extension not available."; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 | 114 |
| 112 } // namespace | 115 } // namespace |
| 113 | 116 |
| 114 namespace base { | 117 namespace base { |
| 115 | 118 |
| 116 MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(), | 119 MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(), |
| 117 x_source_(NULL) { | 120 x_source_(NULL) { |
| 118 InitializeXInput2(); | 121 InitializeXInput2(); |
| 119 InitializeXkb(); | 122 InitializeXkb(); |
| 120 InitXSource(); | 123 InitXSource(); |
| 124 | |
| 125 // Can't put this in the initializer list because g_xdisplay may not exist | |
| 126 // until after InitXSource(). | |
| 127 x_root_window_ = DefaultRootWindow(g_xdisplay); | |
| 121 } | 128 } |
| 122 | 129 |
| 123 // static | 130 // static |
| 124 Display* MessagePumpAuraX11::GetDefaultXDisplay() { | 131 Display* MessagePumpAuraX11::GetDefaultXDisplay() { |
| 125 if (!g_xdisplay) | 132 if (!g_xdisplay) |
| 126 g_xdisplay = XOpenDisplay(NULL); | 133 g_xdisplay = XOpenDisplay(NULL); |
| 127 return g_xdisplay; | 134 return g_xdisplay; |
| 128 } | 135 } |
| 129 | 136 |
| 130 // static | 137 // static |
| 131 bool MessagePumpAuraX11::HasXInput2() { | 138 bool MessagePumpAuraX11::HasXInput2() { |
| 132 return InitializeXInput2(); | 139 return InitializeXInput2(); |
| 133 } | 140 } |
| 134 | 141 |
| 135 // static | 142 // static |
| 136 void MessagePumpAuraX11::SetDefaultDispatcher( | |
| 137 MessagePumpDispatcher* dispatcher) { | |
| 138 DCHECK(!g_default_dispatcher || !dispatcher); | |
| 139 g_default_dispatcher = dispatcher; | |
| 140 } | |
| 141 | |
| 142 // static | |
| 143 MessagePumpAuraX11* MessagePumpAuraX11::Current() { | 143 MessagePumpAuraX11* MessagePumpAuraX11::Current() { |
| 144 MessageLoopForUI* loop = MessageLoopForUI::current(); | 144 MessageLoopForUI* loop = MessageLoopForUI::current(); |
| 145 return static_cast<MessagePumpAuraX11*>(loop->pump_ui()); | 145 return static_cast<MessagePumpAuraX11*>(loop->pump_ui()); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void MessagePumpAuraX11::AddDispatcherForWindow( | |
| 149 MessagePumpDispatcher* dispatcher, | |
| 150 unsigned long x_window) { | |
| 151 dispatchers_.insert(std::make_pair(x_window, dispatcher)); | |
| 152 } | |
| 153 | |
| 154 void MessagePumpAuraX11::RemoveDispatcherForWindow(unsigned long x_window) { | |
| 155 dispatchers_.erase(x_window); | |
| 156 } | |
| 157 | |
| 158 void MessagePumpAuraX11::AddDispatcherForRootWindow( | |
| 159 MessagePumpDispatcher* dispatcher) { | |
| 160 DCHECK(std::find(root_window_dispatchers_.begin(), | |
| 161 root_window_dispatchers_.end(), | |
| 162 dispatcher) == | |
| 163 root_window_dispatchers_.end()); | |
| 164 root_window_dispatchers_.push_back(dispatcher); | |
| 165 } | |
| 166 | |
| 167 void MessagePumpAuraX11::RemoveDispatcherForRootWindow( | |
| 168 MessagePumpDispatcher* dispatcher) { | |
| 169 root_window_dispatchers_.erase( | |
| 170 std::remove(root_window_dispatchers_.begin(), | |
| 171 root_window_dispatchers_.end(), | |
| 172 dispatcher)); | |
| 173 } | |
| 174 | |
| 148 bool MessagePumpAuraX11::DispatchXEvents() { | 175 bool MessagePumpAuraX11::DispatchXEvents() { |
| 149 Display* display = GetDefaultXDisplay(); | 176 Display* display = GetDefaultXDisplay(); |
| 150 DCHECK(display); | 177 DCHECK(display); |
| 151 MessagePumpDispatcher* dispatcher = | 178 MessagePumpDispatcher* dispatcher = |
| 152 GetDispatcher() ? GetDispatcher() : g_default_dispatcher; | 179 GetDispatcher() ? GetDispatcher() : this; |
| 153 | 180 |
| 154 // In the general case, we want to handle all pending events before running | 181 // In the general case, we want to handle all pending events before running |
| 155 // the tasks. This is what happens in the message_pump_glib case. | 182 // the tasks. This is what happens in the message_pump_glib case. |
| 156 while (XPending(display)) { | 183 while (XPending(display)) { |
| 157 XEvent xev; | 184 XEvent xev; |
| 158 XNextEvent(display, &xev); | 185 XNextEvent(display, &xev); |
| 159 if (dispatcher && ProcessXEvent(dispatcher, &xev)) | 186 if (dispatcher && ProcessXEvent(dispatcher, &xev)) |
| 160 return TRUE; | 187 return TRUE; |
| 161 } | 188 } |
| 162 return TRUE; | 189 return TRUE; |
| 163 } | 190 } |
| 164 | 191 |
| 165 void MessagePumpAuraX11::BlockUntilWindowMapped(unsigned long window) { | 192 void MessagePumpAuraX11::BlockUntilWindowMapped(unsigned long x_window) { |
| 166 XEvent event; | 193 XEvent event; |
| 167 | 194 |
| 168 Display* display = GetDefaultXDisplay(); | 195 Display* display = GetDefaultXDisplay(); |
| 169 DCHECK(display); | 196 DCHECK(display); |
| 170 | 197 |
| 171 MessagePumpDispatcher* dispatcher = | 198 MessagePumpDispatcher* dispatcher = |
| 172 GetDispatcher() ? GetDispatcher() : g_default_dispatcher; | 199 GetDispatcher() ? GetDispatcher() : this; |
| 173 | 200 |
| 174 do { | 201 do { |
| 175 // Block until there's a message of |event_mask| type on |w|. Then remove | 202 // Block until there's a message of |event_mask| type on |w|. Then remove |
| 176 // it from the queue and stuff it in |event|. | 203 // it from the queue and stuff it in |event|. |
| 177 XWindowEvent(display, window, StructureNotifyMask, &event); | 204 XWindowEvent(display, x_window, StructureNotifyMask, &event); |
| 178 ProcessXEvent(dispatcher, &event); | 205 ProcessXEvent(dispatcher, &event); |
| 179 } while (event.type != MapNotify); | 206 } while (event.type != MapNotify); |
| 180 } | 207 } |
| 181 | 208 |
| 182 MessagePumpAuraX11::~MessagePumpAuraX11() { | 209 MessagePumpAuraX11::~MessagePumpAuraX11() { |
| 183 g_source_destroy(x_source_); | 210 g_source_destroy(x_source_); |
| 184 g_source_unref(x_source_); | 211 g_source_unref(x_source_); |
| 185 XCloseDisplay(g_xdisplay); | 212 XCloseDisplay(g_xdisplay); |
| 186 g_xdisplay = NULL; | 213 g_xdisplay = NULL; |
| 187 } | 214 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 if (obs->WillProcessEvent(xevent)) | 264 if (obs->WillProcessEvent(xevent)) |
| 238 return true; | 265 return true; |
| 239 } | 266 } |
| 240 return false; | 267 return false; |
| 241 } | 268 } |
| 242 | 269 |
| 243 void MessagePumpAuraX11::DidProcessXEvent(XEvent* xevent) { | 270 void MessagePumpAuraX11::DidProcessXEvent(XEvent* xevent) { |
| 244 FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent)); | 271 FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent)); |
| 245 } | 272 } |
| 246 | 273 |
| 274 MessagePumpDispatcher* MessagePumpAuraX11::GetDispatcherForXEvent( | |
| 275 const base::NativeEvent& xev) const { | |
| 276 ::Window x_window = xev->xany.window; | |
| 277 if (xev->type == GenericEvent) { | |
| 278 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 279 x_window = xievent->event; | |
| 280 } | |
| 281 DispatchersMap::const_iterator it = dispatchers_.find(x_window); | |
| 282 return it != dispatchers_.end() ? it->second : NULL; | |
| 283 } | |
| 284 | |
| 285 bool MessagePumpAuraX11::Dispatch(const base::NativeEvent& xev) { | |
| 286 // MappingNotify events (meaning that the keyboard or pointer buttons have | |
| 287 // been remapped) aren't associated with a window; send them to all | |
| 288 // dispatchers. | |
| 289 if (xev->type == MappingNotify) { | |
| 290 for (DispatchersMap::const_iterator it = dispatchers_.begin(); | |
| 291 it != dispatchers_.end(); ++it) { | |
| 292 it->second->Dispatch(xev); | |
| 293 } | |
| 294 return true; | |
| 295 } | |
| 296 if (xev->xany.window == x_root_window_) { | |
| 297 for (Dispatchers::const_iterator it = root_window_dispatchers_.begin(); | |
| 298 it != root_window_dispatchers_.end(); | |
| 299 ++it) { | |
| 300 (*it)->Dispatch(xev); | |
| 301 } | |
| 302 return true; | |
| 303 } | |
| 304 MessagePumpDispatcher* dispatcher = GetDispatcherForXEvent(xev); | |
| 305 return dispatcher ? dispatcher->Dispatch(xev) : true; | |
| 306 } | |
| 307 | |
| 247 } // namespace base | 308 } // namespace base |
| OLD | NEW |