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 <tf@linux.intel.com>)
This commit is contained in:
Mikael Magnusson
2012-02-21 17:14:16 +01:00
parent 03b7195e64
commit 3f6592f60f
3 changed files with 58 additions and 13 deletions

View File

@ -477,6 +477,21 @@ do_net_wm_state_changes (GdkWindow *window)
0, 0,
GDK_WINDOW_STATE_MAXIMIZED); 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 static void
@ -534,6 +549,7 @@ gdk_check_wm_state_changed (GdkWindow *window)
toplevel->have_maxvert = FALSE; toplevel->have_maxvert = FALSE;
toplevel->have_maxhorz = FALSE; toplevel->have_maxhorz = FALSE;
toplevel->have_fullscreen = FALSE; toplevel->have_fullscreen = FALSE;
toplevel->have_hidden = FALSE;
type = None; type = None;
gdk_error_trap_push (); 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 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 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 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; atoms = (Atom *)data;
@ -563,6 +580,8 @@ gdk_check_wm_state_changed (GdkWindow *window)
toplevel->have_maxhorz = TRUE; toplevel->have_maxhorz = TRUE;
else if (atoms[i] == fullscreen_atom) else if (atoms[i] == fullscreen_atom)
toplevel->have_fullscreen = TRUE; toplevel->have_fullscreen = TRUE;
else if (atoms[i] == hidden_atom)
toplevel->have_hidden = TRUE;
++i; ++i;
} }
@ -1767,21 +1786,29 @@ gdk_event_translate (GdkDisplay *display,
event->any.type = GDK_UNMAP; event->any.type = GDK_UNMAP;
event->any.window = window; event->any.window = window;
/* If we are shown (not withdrawn) and get an unmap, it means we /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to
* were iconified in the X sense. If we are withdrawn, and get * interpret UnmapNotify events as implying iconic state.
* an unmap, it means we hid the window ourselves, so we * http://bugzilla.gnome.org/show_bug.cgi?id=590726.
* will have already flipped the iconified bit off.
*/ */
if (window) if (screen &&
{ !gdk_x11_screen_supports_net_wm_hint (screen,
if (GDK_WINDOW_IS_MAPPED (window)) gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN")))
gdk_synthesize_window_state (window, {
0, /* If we are shown (not withdrawn) and get an unmap, it means we were
GDK_WINDOW_STATE_ICONIFIED); * 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; break;
case MapNotify: case MapNotify:

View File

@ -1321,6 +1321,14 @@ set_initial_hints (GdkWindow *window)
++i; ++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) if (i > 0)
{ {
XChangeProperty (xdisplay, XChangeProperty (xdisplay,
@ -4023,6 +4031,9 @@ gdk_window_iconify (GdkWindow *window)
gdk_synthesize_window_state (window, gdk_synthesize_window_state (window,
0, 0,
GDK_WINDOW_STATE_ICONIFIED); 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)) if (GDK_WINDOW_IS_MAPPED (window))
{ {
gdk_window_show (window); gdk_window_show (window);
gdk_wmspec_change_state (FALSE, window,
gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
GDK_NONE);
} }
else else
{ {
@ -4054,6 +4068,9 @@ gdk_window_deiconify (GdkWindow *window)
gdk_synthesize_window_state (window, gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_ICONIFIED, GDK_WINDOW_STATE_ICONIFIED,
0); 0);
gdk_wmspec_change_state (FALSE, window,
gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
GDK_NONE);
} }
} }

View File

@ -109,6 +109,7 @@ struct _GdkToplevelX11
guint have_maxvert : 1; /* _NET_WM_STATE_MAXIMIZED_VERT */ guint have_maxvert : 1; /* _NET_WM_STATE_MAXIMIZED_VERT */
guint have_maxhorz : 1; /* _NET_WM_STATE_MAXIMIZED_HORZ */ guint have_maxhorz : 1; /* _NET_WM_STATE_MAXIMIZED_HORZ */
guint have_fullscreen : 1; /* _NET_WM_STATE_FULLSCREEN */ guint have_fullscreen : 1; /* _NET_WM_STATE_FULLSCREEN */
guint have_hidden : 1; /* _NET_WM_STATE_HIDDEN */
guint is_leader : 1; guint is_leader : 1;