diff options
Diffstat (limited to 'chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc')
-rw-r--r-- | chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc | 116 |
1 files changed, 72 insertions, 44 deletions
diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc index 0cfe040cbdf..d43b853093b 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc @@ -9,19 +9,18 @@ #include "base/message_loop/message_loop.h" #include "ui/aura/env.h" -#include "ui/aura/root_window.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/base/x/x11_menu_list.h" #include "ui/base/x/x11_util.h" - -#if !defined(OS_CHROMEOS) +#include "ui/events/platform/platform_event_source.h" +#include "ui/gfx/x/x11_error_tracker.h" #include "ui/views/ime/input_method.h" -#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h" -#endif +#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" namespace { const char* kAtomsToCache[] = { "_NET_ACTIVE_WINDOW", - "_NET_SUPPORTED", NULL }; @@ -43,10 +42,12 @@ X11DesktopHandler* X11DesktopHandler::get() { X11DesktopHandler::X11DesktopHandler() : xdisplay_(gfx::GetXDisplay()), x_root_window_(DefaultRootWindow(xdisplay_)), + wm_user_time_ms_(0), current_window_(None), atom_cache_(xdisplay_, kAtomsToCache), wm_supports_active_window_(false) { - base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this); + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); aura::Env::GetInstance()->AddObserver(this); XWindowAttributes attr; @@ -55,22 +56,16 @@ X11DesktopHandler::X11DesktopHandler() attr.your_event_mask | PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask); - std::vector<Atom> atoms; - if (ui::GetAtomArrayProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &atoms)) { - Atom active_window = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW"); - for (std::vector<Atom>::iterator iter = atoms.begin(); iter != atoms.end(); - ++iter) { - if (*(iter) == active_window) { - wm_supports_active_window_ = true; - break; - } - } - } + ::Window active_window; + wm_supports_active_window_ = + ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &active_window) && + active_window; } X11DesktopHandler::~X11DesktopHandler() { aura::Env::GetInstance()->RemoveObserver(this); - base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this); + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); } void X11DesktopHandler::ActivateWindow(::Window window) { @@ -84,7 +79,7 @@ void X11DesktopHandler::ActivateWindow(::Window window) { xclient.xclient.message_type = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW"); xclient.xclient.format = 32; xclient.xclient.data.l[0] = 1; // Specified we are an app. - xclient.xclient.data.l[1] = CurrentTime; + xclient.xclient.data.l[1] = wm_user_time_ms_; xclient.xclient.data.l[2] = None; xclient.xclient.data.l[3] = 0; xclient.xclient.data.l[4] = 0; @@ -94,6 +89,12 @@ void X11DesktopHandler::ActivateWindow(::Window window) { &xclient); } else { XRaiseWindow(xdisplay_, window); + + // XRaiseWindow will not give input focus to the window. We now need to ask + // the X server to do that. Note that the call will raise an X error if the + // window is not mapped. + XSetInputFocus(xdisplay_, window, RevertToParent, CurrentTime); + OnActiveWindowChanged(window); } } @@ -102,16 +103,14 @@ bool X11DesktopHandler::IsActiveWindow(::Window window) const { return window == current_window_; } -void X11DesktopHandler::ProcessXEvent(const base::NativeEvent& event) { +void X11DesktopHandler::ProcessXEvent(XEvent* event) { switch (event->type) { - case EnterNotify: - if (event->xcrossing.focus == True && - current_window_ != event->xcrossing.window) - OnActiveWindowChanged(event->xcrossing.window); + case FocusIn: + if (current_window_ != event->xfocus.window) + OnActiveWindowChanged(event->xfocus.window); break; - case LeaveNotify: - if (event->xcrossing.focus == False && - current_window_ == event->xcrossing.window) + case FocusOut: + if (current_window_ == event->xfocus.window) OnActiveWindowChanged(None); break; default: @@ -119,25 +118,53 @@ void X11DesktopHandler::ProcessXEvent(const base::NativeEvent& event) { } } -bool X11DesktopHandler::Dispatch(const base::NativeEvent& event) { - // Check for a change to the active window. +bool X11DesktopHandler::CanDispatchEvent(const ui::PlatformEvent& event) { + return event->type == CreateNotify || event->type == DestroyNotify || + (event->type == PropertyNotify && + event->xproperty.window == x_root_window_); +} + +uint32_t X11DesktopHandler::DispatchEvent(const ui::PlatformEvent& event) { switch (event->type) { case PropertyNotify: { - ::Atom active_window = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW"); - - if (event->xproperty.window == x_root_window_ && - event->xproperty.atom == active_window) { - int window; - if (ui::GetIntProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) && + // Check for a change to the active window. + CHECK_EQ(x_root_window_, event->xproperty.window); + ::Atom active_window_atom = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW"); + if (event->xproperty.atom == active_window_atom) { + ::Window window; + if (ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) && window) { - OnActiveWindowChanged(static_cast< ::Window>(window)); + OnActiveWindowChanged(window); } } break; } + + // Menus created by Chrome can be drag and drop targets. Since they are + // direct children of the screen root window and have override_redirect + // we cannot use regular _NET_CLIENT_LIST_STACKING property to find them + // and use a separate cache to keep track of them. + // TODO(varkha): Implement caching of all top level X windows and their + // coordinates and stacking order to eliminate repeated calls to X server + // during mouse movement, drag and shaping events. + case CreateNotify: { + // The window might be destroyed if the message pump haven't gotten a + // chance to run but we can safely ignore the X error. + gfx::X11ErrorTracker error_tracker; + XCreateWindowEvent *xcwe = &event->xcreatewindow; + ui::XMenuList::GetInstance()->MaybeRegisterMenu(xcwe->window); + break; + } + case DestroyNotify: { + XDestroyWindowEvent *xdwe = &event->xdestroywindow; + ui::XMenuList::GetInstance()->MaybeUnregisterMenu(xdwe->window); + break; + } + default: + NOTREACHED(); } - return true; + return ui::POST_DISPATCH_NONE; } void X11DesktopHandler::OnWindowInitialized(aura::Window* window) { @@ -151,17 +178,18 @@ void X11DesktopHandler::OnWillDestroyEnv() { void X11DesktopHandler::OnActiveWindowChanged(::Window xid) { if (current_window_ == xid) return; - DesktopRootWindowHostX11* old_host = - views::DesktopRootWindowHostX11::GetHostForXID(current_window_); + DesktopWindowTreeHostX11* old_host = + views::DesktopWindowTreeHostX11::GetHostForXID(current_window_); if (old_host) old_host->HandleNativeWidgetActivationChanged(false); - DesktopRootWindowHostX11* new_host = - views::DesktopRootWindowHostX11::GetHostForXID(xid); + // Update the current window ID to effectively change the active widget. + current_window_ = xid; + + DesktopWindowTreeHostX11* new_host = + views::DesktopWindowTreeHostX11::GetHostForXID(xid); if (new_host) new_host->HandleNativeWidgetActivationChanged(true); - - current_window_ = xid; } } // namespace views |