diff options
Diffstat (limited to 'app/active_window_watcher_x.cc')
-rw-r--r-- | app/active_window_watcher_x.cc | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/app/active_window_watcher_x.cc b/app/active_window_watcher_x.cc index d834a5c..8b8b72c 100644 --- a/app/active_window_watcher_x.cc +++ b/app/active_window_watcher_x.cc @@ -8,6 +8,8 @@ #include "app/active_window_watcher_x.h" +static Atom kNetActiveWindowAtom = None; + // static void ActiveWindowWatcherX::AddObserver(Observer* observer) { Singleton<ActiveWindowWatcherX>::get()->observers_.AddObserver(observer); @@ -23,33 +25,58 @@ ActiveWindowWatcherX::ActiveWindowWatcherX() { } void ActiveWindowWatcherX::Init() { + GdkAtom kNetActiveWindow = gdk_atom_intern("_NET_ACTIVE_WINDOW", FALSE); + kNetActiveWindowAtom = gdk_x11_atom_to_xatom_for_display( + gdk_screen_get_display(gdk_screen_get_default()), kNetActiveWindow); + + GdkWindow* root = gdk_get_default_root_window(); // 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); + 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()); + // We don't use gdk_screen_get_active_window() because it caches + // whether or not the window manager supports _NET_ACTIVE_WINDOW. + // This causes problems at startup for chromiumos. + Atom type = None; + int format = 0; // size in bits of each item in 'property' + long unsigned int num_items = 0, remaining_bytes = 0; + unsigned char* property = NULL; + + XGetWindowProperty(gdk_x11_get_default_xdisplay(), + GDK_WINDOW_XID(gdk_get_default_root_window()), + kNetActiveWindowAtom, + 0, // offset into property data to read + 1, // length to get in 32-bit quantities + False, // deleted + AnyPropertyType, + &type, + &format, + &num_items, + &remaining_bytes, + &property); - // 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; + // Check that the property was set and contained a single 32-bit item. + if (format == 32 && num_items == 1 && remaining_bytes == 0) { + int xid = *reinterpret_cast<int*>(property); + GdkWindow* active_window = gdk_window_lookup(xid); - FOR_EACH_OBSERVER(Observer, observers_, ActiveWindowChanged(active_window)); + if (active_window) { + FOR_EACH_OBSERVER( + Observer, + observers_, + ActiveWindowChanged(active_window)); + } + } + if (property) + XFree(property); } 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); |