From 3922a54915d163db29212285274d54a56f06f33d Mon Sep 17 00:00:00 2001 From: "erg@chromium.org" Date: Thu, 31 May 2012 00:22:12 +0000 Subject: aura desktop: Listen for _NET_ACTIVE_WINDOW changes. We now react to normal window focus changes. (TODO: This doesn't dismiss bubbles correctly. That's what's next.) BUG=125106 TEST=none Review URL: https://chromiumcodereview.appspot.com/10445044 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139703 0039d316-1c4b-4281-b951-d872f2087c98 --- .../widget/desktop_native_widget_helper_aura.cc | 3 +- ui/views/widget/x11_window_event_filter.cc | 70 ++++++++++++++++++++-- ui/views/widget/x11_window_event_filter.h | 20 ++++++- 3 files changed, 84 insertions(+), 9 deletions(-) (limited to 'ui/views/widget') diff --git a/ui/views/widget/desktop_native_widget_helper_aura.cc b/ui/views/widget/desktop_native_widget_helper_aura.cc index ef90cd7..d29b9b7 100644 --- a/ui/views/widget/desktop_native_widget_helper_aura.cc +++ b/ui/views/widget/desktop_native_widget_helper_aura.cc @@ -120,7 +120,8 @@ void DesktopNativeWidgetHelperAura::PreInitialize( root_window_event_filter_->AddFilter(input_method_filter_.get()); #if defined(USE_X11) - x11_window_event_filter_.reset(new X11WindowEventFilter(root_window_.get())); + x11_window_event_filter_.reset( + new X11WindowEventFilter(root_window_.get(), widget_)); x11_window_event_filter_->SetUseHostWindowBorders(false); root_window_event_filter_->AddFilter(x11_window_event_filter_.get()); #endif diff --git a/ui/views/widget/x11_window_event_filter.cc b/ui/views/widget/x11_window_event_filter.cc index 5553f95..4fc2ea7 100644 --- a/ui/views/widget/x11_window_event_filter.cc +++ b/ui/views/widget/x11_window_event_filter.cc @@ -4,14 +4,19 @@ #include "ui/views/widget/x11_window_event_filter.h" +#include +#include #include #include #include "base/message_pump_aurax11.h" +#include "ui/aura/dispatcher_linux.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/window_delegate.h" #include "ui/base/hit_test.h" +#include "ui/base/x/x11_util.h" +#include "ui/views/widget/native_widget_aura.h" namespace { @@ -45,6 +50,7 @@ const unsigned long kHintsDecorations = (1L << 1); const char* kAtomsToCache[] = { "_MOTIF_WM_HINTS", + "_NET_ACTIVE_WINDOW", "_NET_WM_MOVERESIZE", NULL }; @@ -53,15 +59,30 @@ const char* kAtomsToCache[] = { namespace views { -X11WindowEventFilter::X11WindowEventFilter(aura::RootWindow* root_window) - : root_window_(root_window), +X11WindowEventFilter::X11WindowEventFilter(aura::RootWindow* root_window, + NativeWidgetAura* widget) + : widget_(widget), xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), - xwindow_(root_window_->GetAcceleratedWidget()), + xwindow_(root_window->GetAcceleratedWidget()), x_root_window_(DefaultRootWindow(xdisplay_)), - atom_cache_(xdisplay_, kAtomsToCache) { + atom_cache_(xdisplay_, kAtomsToCache), + is_active_(false) { + static_cast( + aura::Env::GetInstance()->GetDispatcher())-> + AddDispatcherForRootWindow(this); + + XWindowAttributes attr; + XGetWindowAttributes(xdisplay_, x_root_window_, &attr); + XSelectInput(xdisplay_, x_root_window_, + attr.your_event_mask | PropertyChangeMask | + StructureNotifyMask | SubstructureNotifyMask); } -X11WindowEventFilter::~X11WindowEventFilter() {} +X11WindowEventFilter::~X11WindowEventFilter() { + static_cast( + aura::Env::GetInstance()->GetDispatcher())-> + RemoveDispatcherForRootWindow(this); +} void X11WindowEventFilter::SetUseHostWindowBorders(bool use_os_border) { MotifWmHints motif_hints; @@ -131,6 +152,25 @@ ui::GestureStatus X11WindowEventFilter::PreHandleGestureEvent( return ui::GESTURE_STATUS_UNKNOWN; } +bool X11WindowEventFilter::Dispatch(const base::NativeEvent& event) { + // Check for a change to the active window. + 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)) + OnActiveWindowChanged(static_cast< ::Window>(window)); + } + break; + } + } + + return false; +} + bool X11WindowEventFilter::DispatchHostWindowDragMovement( int hittest, const gfx::Point& screen_location) { @@ -193,5 +233,25 @@ bool X11WindowEventFilter::DispatchHostWindowDragMovement( return true; } +void X11WindowEventFilter::OnActiveWindowChanged(::Window window) { + if (xwindow_ == window) { + if (!is_active_) { + is_active_ = true; + + widget_->Activate(); + } + } else if (is_active_) { + is_active_ = false; + + widget_->Deactivate(); + // TODO(erg): Also tell the activation delegate of |window_| now that + // we've deactivated the widget_. This fixes the bubble case, but breaks + // menus. Figure out why. + + // Force a redraw to show our inactive state. + widget_->GetWidget()->GetRootView()->SchedulePaint(); + } +} + } // namespace views diff --git a/ui/views/widget/x11_window_event_filter.h b/ui/views/widget/x11_window_event_filter.h index 9bc38db..65375c0 100644 --- a/ui/views/widget/x11_window_event_filter.h +++ b/ui/views/widget/x11_window_event_filter.h @@ -11,6 +11,7 @@ #undef RootWindow #include "base/compiler_specific.h" +#include "base/message_loop.h" #include "ui/aura/event.h" #include "ui/aura/event_filter.h" #include "ui/aura/x11_atom_cache.h" @@ -18,14 +19,18 @@ namespace aura { class RootWindow; +class Window; } namespace views { +class NativeWidgetAura; // An EventFilter that sets properties on X11 windows. -class VIEWS_EXPORT X11WindowEventFilter : public aura::EventFilter { +class VIEWS_EXPORT X11WindowEventFilter : public aura::EventFilter, + public MessageLoop::Dispatcher { public: - explicit X11WindowEventFilter(aura::RootWindow* root_window); + explicit X11WindowEventFilter(aura::RootWindow* root_window, + NativeWidgetAura* widget); virtual ~X11WindowEventFilter(); // Changes whether borders are shown on this |root_window|. @@ -42,13 +47,19 @@ class VIEWS_EXPORT X11WindowEventFilter : public aura::EventFilter { aura::Window* target, aura::GestureEvent* event) OVERRIDE; + // Overridden from MessageLoop::Dispatcher: + virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; + private: // Dispatches a _NET_WM_MOVERESIZE message to the window manager to tell it // to act as if a border or titlebar drag occurred. bool DispatchHostWindowDragMovement(int hittest, const gfx::Point& screen_location); - aura::RootWindow* root_window_; + // Handles changes in activation. + void OnActiveWindowChanged(::Window window); + + NativeWidgetAura* widget_; // The display and the native X window hosting the root window. Display* xdisplay_; @@ -59,6 +70,9 @@ class VIEWS_EXPORT X11WindowEventFilter : public aura::EventFilter { aura::X11AtomCache atom_cache_; + // True if |xwindow_| is the current _NET_ACTIVE_WINDOW. + bool is_active_; + DISALLOW_COPY_AND_ASSIGN(X11WindowEventFilter); }; -- cgit v1.1