diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/active_window_watcher_x.cc | 63 | ||||
-rw-r--r-- | app/active_window_watcher_x.h | 48 | ||||
-rw-r--r-- | app/app.gyp | 2 |
3 files changed, 113 insertions, 0 deletions
diff --git a/app/active_window_watcher_x.cc b/app/active_window_watcher_x.cc new file mode 100644 index 0000000..d834a5c --- /dev/null +++ b/app/active_window_watcher_x.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <X11/Xlib.h> +#include <gdk/gdk.h> +#include <gdk/gdkx.h> + +#include "app/active_window_watcher_x.h" + +// static +void ActiveWindowWatcherX::AddObserver(Observer* observer) { + Singleton<ActiveWindowWatcherX>::get()->observers_.AddObserver(observer); +} + +// static +void ActiveWindowWatcherX::RemoveObserver(Observer* observer) { + Singleton<ActiveWindowWatcherX>::get()->observers_.RemoveObserver(observer); +} + +ActiveWindowWatcherX::ActiveWindowWatcherX() { + Init(); +} + +void ActiveWindowWatcherX::Init() { + // Set up X Event filter to listen for PropertyChange X events. These events + // tell us when the active window changes. + GdkWindow* root = gdk_screen_get_root_window(gdk_screen_get_default()); + gdk_window_add_filter(root, &ActiveWindowWatcherX::OnWindowXEvent, this); + XSelectInput(GDK_WINDOW_XDISPLAY(root), GDK_WINDOW_XID(root), + PropertyChangeMask); +} + +void ActiveWindowWatcherX::NotifyActiveWindowChanged() { + GdkWindow* active_window = gdk_screen_get_active_window( + gdk_screen_get_default()); + + // If the window manager doesn't support _NET_ACTIVE_WINDOW, we don't know + // which window is active and just give up. + if (!active_window) + return; + + FOR_EACH_OBSERVER(Observer, observers_, ActiveWindowChanged(active_window)); +} + +GdkFilterReturn ActiveWindowWatcherX::OnWindowXEvent(GdkXEvent* xevent, + GdkEvent* event, gpointer window_watcher) { + static const GdkAtom kNetActiveWindow = gdk_atom_intern( + "_NET_ACTIVE_WINDOW", FALSE); + static const Atom kNetActiveWindowAtom = gdk_x11_atom_to_xatom_for_display( + gdk_screen_get_display(gdk_screen_get_default()), kNetActiveWindow); + + ActiveWindowWatcherX* watcher = reinterpret_cast<ActiveWindowWatcherX*>( + window_watcher); + XEvent* xev = static_cast<XEvent*>(xevent); + + if (xev->xany.type == PropertyNotify && + xev->xproperty.atom == kNetActiveWindowAtom) { + watcher->NotifyActiveWindowChanged(); + } + + return GDK_FILTER_CONTINUE; +} diff --git a/app/active_window_watcher_x.h b/app/active_window_watcher_x.h new file mode 100644 index 0000000..2ea524e --- /dev/null +++ b/app/active_window_watcher_x.h @@ -0,0 +1,48 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef APP_ACTIVE_WINDOW_WATCHER_X_H_ +#define APP_ACTIVE_WINDOW_WATCHER_X_H_ + +#include <gdk/gdk.h> + +#include "base/basictypes.h" +#include "base/observer_list.h" +#include "base/singleton.h" + +// This is a helper class that is used to keep track of which window the X +// window manager thinks is active. Add an Observer to listener for changes to +// the active window. +class ActiveWindowWatcherX { + public: + class Observer { + public: + virtual void ActiveWindowChanged(GdkWindow* active_window) = 0; + }; + + static void AddObserver(Observer* observer); + static void RemoveObserver(Observer* observer); + + private: + friend struct DefaultSingletonTraits<ActiveWindowWatcherX>; + + ActiveWindowWatcherX(); + + void Init(); + + // Sends a notification out through the NotificationService that the active + // window has changed. + void NotifyActiveWindowChanged(); + + // Callback for PropertyChange XEvents. + static GdkFilterReturn OnWindowXEvent(GdkXEvent* xevent, + GdkEvent* event, + gpointer window_watcher); + + ObserverList<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(ActiveWindowWatcherX); +}; + +#endif // APP_ACTIVE_WINDOW_WATCHER_X_H_ diff --git a/app/app.gyp b/app/app.gyp index 7c61d17..73d65ba 100644 --- a/app/app.gyp +++ b/app/app.gyp @@ -59,6 +59,8 @@ # All .cc, .h, and .mm files under app/ except for tests. 'animation.cc', 'animation.h', + 'active_window_watcher_x.cc', + 'active_window_watcher_x.h', 'app_paths.h', 'app_paths.cc', 'app_switches.h', |