Chromium Code Reviews| Index: base/message_pump_aurax11.cc |
| diff --git a/base/message_pump_aurax11.cc b/base/message_pump_aurax11.cc |
| index 7f47fa675fe6e655c403f6415704aa0d7ccf67a4..660c0315c10b7aec82e627b7e557ef61a0df6746 100644 |
| --- a/base/message_pump_aurax11.cc |
| +++ b/base/message_pump_aurax11.cc |
| @@ -39,13 +39,16 @@ GSourceFuncs XSourceFuncs = { |
| NULL |
| }; |
| -// The message-pump opens a connection to the display and owns it. |
| +// The connection is essentially a global that's accessed through a static |
| +// method and destroyed whenever ~MessagePumpAuraX11() is called. We do this |
| +// for historical reasons so user code can call |
| +// MessagePumpForUI::GetDefaultXDisplay() where MessagePumpForUI is a typedef |
| +// to whatever type in the current build. |
| +// |
| +// TODO(erg): This can be changed to something more sane like |
| +// MessagePumpAuraX11::Current()->display() once GTK goes away. |
|
sadrul
2012/08/29 16:01:25
Perhaps say once 'MessagePumpGtk' goes away (I was
|
| Display* g_xdisplay = NULL; |
| -// The default dispatcher to process native events when no dispatcher |
| -// is specified. |
| -base::MessagePumpDispatcher* g_default_dispatcher = NULL; |
| - |
| bool InitializeXInput2Internal() { |
| Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
| if (!display) |
| @@ -118,6 +121,10 @@ MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(), |
| InitializeXInput2(); |
| InitializeXkb(); |
| InitXSource(); |
| + |
| + // Can't put this in the initializer list because g_xdisplay may not exist |
| + // until after InitXSource(). |
| + x_root_window_ = DefaultRootWindow(g_xdisplay); |
| } |
| // static |
| @@ -133,23 +140,43 @@ bool MessagePumpAuraX11::HasXInput2() { |
| } |
| // static |
| -void MessagePumpAuraX11::SetDefaultDispatcher( |
| - MessagePumpDispatcher* dispatcher) { |
| - DCHECK(!g_default_dispatcher || !dispatcher); |
| - g_default_dispatcher = dispatcher; |
| -} |
| - |
| -// static |
| MessagePumpAuraX11* MessagePumpAuraX11::Current() { |
| MessageLoopForUI* loop = MessageLoopForUI::current(); |
| return static_cast<MessagePumpAuraX11*>(loop->pump_ui()); |
| } |
| +void MessagePumpAuraX11::AddDispatcherForWindow( |
| + MessagePumpDispatcher* dispatcher, |
| + unsigned long x_window) { |
| + dispatchers_.insert(std::make_pair(x_window, dispatcher)); |
| +} |
| + |
| +void MessagePumpAuraX11::RemoveDispatcherForWindow(unsigned long x_window) { |
| + dispatchers_.erase(x_window); |
| +} |
| + |
| +void MessagePumpAuraX11::AddDispatcherForRootWindow( |
| + MessagePumpDispatcher* dispatcher) { |
| + DCHECK(std::find(root_window_dispatchers_.begin(), |
| + root_window_dispatchers_.end(), |
| + dispatcher) == |
| + root_window_dispatchers_.end()); |
| + root_window_dispatchers_.push_back(dispatcher); |
| +} |
| + |
| +void MessagePumpAuraX11::RemoveDispatcherForRootWindow( |
| + MessagePumpDispatcher* dispatcher) { |
| + root_window_dispatchers_.erase( |
| + std::remove(root_window_dispatchers_.begin(), |
| + root_window_dispatchers_.end(), |
| + dispatcher)); |
| +} |
| + |
| bool MessagePumpAuraX11::DispatchXEvents() { |
| Display* display = GetDefaultXDisplay(); |
| DCHECK(display); |
| MessagePumpDispatcher* dispatcher = |
| - GetDispatcher() ? GetDispatcher() : g_default_dispatcher; |
| + GetDispatcher() ? GetDispatcher() : this; |
| // In the general case, we want to handle all pending events before running |
| // the tasks. This is what happens in the message_pump_glib case. |
| @@ -162,19 +189,19 @@ bool MessagePumpAuraX11::DispatchXEvents() { |
| return TRUE; |
| } |
| -void MessagePumpAuraX11::BlockUntilWindowMapped(unsigned long window) { |
| +void MessagePumpAuraX11::BlockUntilWindowMapped(unsigned long x_window) { |
| XEvent event; |
| Display* display = GetDefaultXDisplay(); |
| DCHECK(display); |
| MessagePumpDispatcher* dispatcher = |
| - GetDispatcher() ? GetDispatcher() : g_default_dispatcher; |
| + GetDispatcher() ? GetDispatcher() : this; |
| do { |
| // Block until there's a message of |event_mask| type on |w|. Then remove |
| // it from the queue and stuff it in |event|. |
| - XWindowEvent(display, window, StructureNotifyMask, &event); |
| + XWindowEvent(display, x_window, StructureNotifyMask, &event); |
| ProcessXEvent(dispatcher, &event); |
| } while (event.type != MapNotify); |
| } |
| @@ -244,4 +271,38 @@ void MessagePumpAuraX11::DidProcessXEvent(XEvent* xevent) { |
| FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent)); |
| } |
| +MessagePumpDispatcher* MessagePumpAuraX11::GetDispatcherForXEvent( |
| + const base::NativeEvent& xev) const { |
| + ::Window x_window = xev->xany.window; |
| + if (xev->type == GenericEvent) { |
| + XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| + x_window = xievent->event; |
| + } |
| + DispatchersMap::const_iterator it = dispatchers_.find(x_window); |
| + return it != dispatchers_.end() ? it->second : NULL; |
| +} |
| + |
| +bool MessagePumpAuraX11::Dispatch(const base::NativeEvent& xev) { |
| + // MappingNotify events (meaning that the keyboard or pointer buttons have |
| + // been remapped) aren't associated with a window; send them to all |
| + // dispatchers. |
| + if (xev->type == MappingNotify) { |
| + for (DispatchersMap::const_iterator it = dispatchers_.begin(); |
| + it != dispatchers_.end(); ++it) { |
| + it->second->Dispatch(xev); |
| + } |
| + return true; |
| + } |
| + if (xev->xany.window == x_root_window_) { |
| + for (Dispatchers::const_iterator it = root_window_dispatchers_.begin(); |
| + it != root_window_dispatchers_.end(); |
| + ++it) { |
| + (*it)->Dispatch(xev); |
| + } |
| + return true; |
| + } |
| + MessagePumpDispatcher* dispatcher = GetDispatcherForXEvent(xev); |
| + return dispatcher ? dispatcher->Dispatch(xev) : true; |
| +} |
| + |
| } // namespace base |