From 3f6592f60fd15fb353fc84600caefba3054dc892 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 21 Feb 2012 17:14:16 +0100 Subject: [PATCH] Iconification using _NET_WM_STATE_HIDDEN hint if supported by WM If the Window Manager supports the _NET_WM_STATE_HIDDEN, we use it to use the _NET_WM_STATE protocol when de-iconifying windows (iconification is unchanged, via XIconifyWindow). Additionally, we no longer interpret all UnmapNotify events for our window as the result of iconification. (Based on patch by Tomas Frydrych ) --- gdk/x11/gdkevents-x11.c | 53 +++++++++++++++++++++++++++++++---------- gdk/x11/gdkwindow-x11.c | 17 +++++++++++++ gdk/x11/gdkwindow-x11.h | 1 + 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 3d56c9650..7cc1000d6 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -477,6 +477,21 @@ do_net_wm_state_changes (GdkWindow *window) 0, GDK_WINDOW_STATE_MAXIMIZED); } + + if (old_state & GDK_WINDOW_STATE_ICONIFIED) + { + if (!toplevel->have_hidden) + gdk_synthesize_window_state (window, + GDK_WINDOW_STATE_ICONIFIED, + 0); + } + else + { + if (toplevel->have_hidden) + gdk_synthesize_window_state (window, + 0, + GDK_WINDOW_STATE_ICONIFIED); + } } static void @@ -534,6 +549,7 @@ gdk_check_wm_state_changed (GdkWindow *window) toplevel->have_maxvert = FALSE; toplevel->have_maxhorz = FALSE; toplevel->have_fullscreen = FALSE; + toplevel->have_hidden = FALSE; type = None; gdk_error_trap_push (); @@ -549,6 +565,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 hidden_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_HIDDEN"); atoms = (Atom *)data; @@ -563,6 +580,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] == hidden_atom) + toplevel->have_hidden = TRUE; ++i; } @@ -1767,21 +1786,29 @@ gdk_event_translate (GdkDisplay *display, event->any.type = GDK_UNMAP; event->any.window = window; - /* If we are shown (not withdrawn) and get an unmap, it means we - * were iconified in the X sense. If we are withdrawn, and get - * an unmap, it means we hid the window ourselves, so we - * will have already flipped the iconified bit off. + /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to + * interpret UnmapNotify events as implying iconic state. + * http://bugzilla.gnome.org/show_bug.cgi?id=590726. */ - if (window) - { - if (GDK_WINDOW_IS_MAPPED (window)) - gdk_synthesize_window_state (window, - 0, - GDK_WINDOW_STATE_ICONIFIED); + if (screen && + !gdk_x11_screen_supports_net_wm_hint (screen, + gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"))) + { + /* If we are shown (not withdrawn) and get an unmap, it means we were + * iconified in the X sense. If we are withdrawn, and get an unmap, it + * means we hid the window ourselves, so we will have already flipped + * the iconified bit off. + */ + if (window) + { + if (GDK_WINDOW_IS_MAPPED (window)) + gdk_synthesize_window_state (window, + 0, + GDK_WINDOW_STATE_ICONIFIED); - _gdk_xgrab_check_unmap (window, xevent->xany.serial); - } - + _gdk_xgrab_check_unmap (window, xevent->xany.serial); + } + } break; case MapNotify: diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index f32246ec9..59a15069c 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -1321,6 +1321,14 @@ set_initial_hints (GdkWindow *window) ++i; } + if (private->state & GDK_WINDOW_STATE_ICONIFIED) + { + atoms[i] = gdk_x11_get_xatom_by_name_for_display (display, + "_NET_WM_STATE_HIDDEN"); + ++i; + toplevel->have_hidden = TRUE; + } + if (i > 0) { XChangeProperty (xdisplay, @@ -4023,6 +4031,9 @@ gdk_window_iconify (GdkWindow *window) gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_ICONIFIED); + gdk_wmspec_change_state (TRUE, window, + gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"), + GDK_NONE); } } @@ -4047,6 +4058,9 @@ gdk_window_deiconify (GdkWindow *window) if (GDK_WINDOW_IS_MAPPED (window)) { gdk_window_show (window); + gdk_wmspec_change_state (FALSE, window, + gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"), + GDK_NONE); } else { @@ -4054,6 +4068,9 @@ gdk_window_deiconify (GdkWindow *window) gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0); + gdk_wmspec_change_state (FALSE, window, + gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"), + GDK_NONE); } } diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 9a7f2aed3..90f734b2c 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -109,6 +109,7 @@ struct _GdkToplevelX11 guint have_maxvert : 1; /* _NET_WM_STATE_MAXIMIZED_VERT */ guint have_maxhorz : 1; /* _NET_WM_STATE_MAXIMIZED_HORZ */ guint have_fullscreen : 1; /* _NET_WM_STATE_FULLSCREEN */ + guint have_hidden : 1; /* _NET_WM_STATE_HIDDEN */ guint is_leader : 1;