From 95648fd1942651ea1ca9aab9b7aa79df6f843f40 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Fri, 28 Oct 2011 23:29:01 +0100 Subject: [PATCH] x11: Implement GDK_WINDOW_STATE_FOCUSED on top of _NET_WM_STATE_FOCUSED _NET_WM_STATE_FOCUSED is a new _NET_WM_STATE hint which allows us to implement a meaningful GDK_WINDOW_STATE_FOCUSED under X11. If the window manager doesn't support this hint we keep GDK_WINDOW_STATE_FOCUSED set since that is what gtk+ implicitly assumed historically. https://bugzilla.gnome.org/show_bug.cgi?id=661428 --- gdk/x11/gdkdisplay-x11.c | 27 ++++++++++++++++++++++++++- gdk/x11/gdkwindow-x11.h | 4 ++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index d71e8caefd..ecf9f09e1e 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -155,7 +155,8 @@ static const char *const precache_atoms[] = { "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_USER_TIME", "_NET_VIRTUAL_ROOTS", - "GDK_SELECTION" + "GDK_SELECTION", + "_NET_WM_STATE_FOCUSED" }; static char *gdk_sm_client_id; @@ -240,6 +241,21 @@ do_net_wm_state_changes (GdkWindow *window) 0, GDK_WINDOW_STATE_MAXIMIZED); } + + if (old_state & GDK_WINDOW_STATE_FOCUSED) + { + if (!toplevel->have_focused) + gdk_synthesize_window_state (window, + GDK_WINDOW_STATE_FOCUSED, + 0); + } + else + { + if (toplevel->have_focused) + gdk_synthesize_window_state (window, + 0, + GDK_WINDOW_STATE_FOCUSED); + } } static void @@ -282,6 +298,7 @@ gdk_check_wm_state_changed (GdkWindow *window) { GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + GdkScreen *screen = GDK_WINDOW_SCREEN (window); Atom type; gint format; @@ -297,6 +314,7 @@ gdk_check_wm_state_changed (GdkWindow *window) toplevel->have_maxvert = FALSE; toplevel->have_maxhorz = FALSE; toplevel->have_fullscreen = FALSE; + toplevel->have_focused = FALSE; type = None; gdk_x11_display_error_trap_push (display); @@ -312,6 +330,7 @@ gdk_check_wm_state_changed (GdkWindow *window) Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT"); Atom maxhorz_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ"); Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN"); + Atom focused_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FOCUSED"); atoms = (Atom *)data; @@ -326,6 +345,8 @@ gdk_check_wm_state_changed (GdkWindow *window) toplevel->have_maxhorz = TRUE; else if (atoms[i] == fullscreen_atom) toplevel->have_fullscreen = TRUE; + else if (atoms[i] == focused_atom) + toplevel->have_focused = TRUE; ++i; } @@ -333,6 +354,10 @@ gdk_check_wm_state_changed (GdkWindow *window) XFree (atoms); } + if (!gdk_x11_screen_supports_net_wm_hint (screen, + gdk_atom_intern_static_string ("_NET_WM_STATE_FOCUSED"))) + toplevel->have_focused = TRUE; + /* When have_sticky is turned on, we have to check the DESKTOP property * as well. */ diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index b58a31b001..740fb08b76 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -123,6 +123,10 @@ struct _GdkToplevelX11 guint have_fullscreen : 1; /* _NET_WM_STATE_FULLSCREEN */ guint is_leader : 1; + + /* Set if the WM is presenting us as focused, i.e. with active decorations + */ + guint have_focused : 1; gulong map_serial; /* Serial of last transition from unmapped */