@@ -130,6 +130,7 @@ struct _global_handles {
130130 Atom wm_state ; /* Atom: _NET_WM_STATE */
131131 Atom wm_state_fullscreen ; /* Atom: _NET_WM_STATE_FULLSCREEN */
132132 Atom wm_state_demands_attention ; /* Atom: _NET_WM_STATE_DEMANDS_ATTENTION */
133+ Atom wm_state_hidden ; /* Atom: _NET_WM_STATE_HIDDEN */
133134 Atom frame_extents ; /* Atom: _NET_FRAME_EXTENTS */
134135 /* shared memory handling */
135136 struct shm_cmd * shmcmd ; /* shared memory with Xorg */
@@ -468,6 +469,7 @@ static void mkghandles(Ghandles * g)
468469 g -> wm_state = XInternAtom (g -> display , "_NET_WM_STATE" , False );
469470 g -> wm_state_fullscreen = XInternAtom (g -> display , "_NET_WM_STATE_FULLSCREEN" , False );
470471 g -> wm_state_demands_attention = XInternAtom (g -> display , "_NET_WM_STATE_DEMANDS_ATTENTION" , False );
472+ g -> wm_state_hidden = XInternAtom (g -> display , "_NET_WM_STATE_HIDDEN" , False );
471473 g -> frame_extents = XInternAtom (g -> display , "_NET_FRAME_EXTENTS" , False );
472474 /* create graphical contexts */
473475 get_frame_gc (g , g -> cmdline_color ? : "red" );
@@ -1517,6 +1519,8 @@ static inline uint32_t flags_from_atom(Ghandles * g, Atom a) {
15171519 return WINDOW_FLAG_FULLSCREEN ;
15181520 else if (a == g -> wm_state_demands_attention )
15191521 return WINDOW_FLAG_DEMANDS_ATTENTION ;
1522+ else if (a == g -> wm_state_hidden )
1523+ return WINDOW_FLAG_MINIMIZE ;
15201524 else {
15211525 /* ignore unsupported states */
15221526 }
@@ -2062,8 +2066,13 @@ static void handle_wmflags(Ghandles * g, struct windowdata *vm_window)
20622066
20632067 /* sanitize start */
20642068 VERIFY ((untrusted_msg .flags_set & untrusted_msg .flags_unset ) == 0 );
2065- msg .flags_set = untrusted_msg .flags_set & (WINDOW_FLAG_FULLSCREEN | WINDOW_FLAG_DEMANDS_ATTENTION );
2066- msg .flags_unset = untrusted_msg .flags_unset & (WINDOW_FLAG_FULLSCREEN | WINDOW_FLAG_DEMANDS_ATTENTION );
2069+ msg .flags_set = untrusted_msg .flags_set & (
2070+ WINDOW_FLAG_FULLSCREEN |
2071+ WINDOW_FLAG_DEMANDS_ATTENTION |
2072+ WINDOW_FLAG_MINIMIZE );
2073+ msg .flags_unset = untrusted_msg .flags_unset & (
2074+ WINDOW_FLAG_FULLSCREEN |
2075+ WINDOW_FLAG_DEMANDS_ATTENTION );
20672076 /* sanitize end */
20682077
20692078 if (!vm_window -> is_mapped ) {
@@ -2072,7 +2081,7 @@ static void handle_wmflags(Ghandles * g, struct windowdata *vm_window)
20722081 Atom state_list [10 ];
20732082 int i = 0 ;
20742083
2075- vm_window -> flags_set = 0 ;
2084+ vm_window -> flags_set &= ~( WINDOW_FLAG_FULLSCREEN | WINDOW_FLAG_DEMANDS_ATTENTION ) ;
20762085 if (msg .flags_set & WINDOW_FLAG_FULLSCREEN ) {
20772086 if (g -> allow_fullscreen ) {
20782087 vm_window -> flags_set |= WINDOW_FLAG_FULLSCREEN ;
@@ -2095,6 +2104,10 @@ static void handle_wmflags(Ghandles * g, struct windowdata *vm_window)
20952104 } else
20962105 /* just in case */
20972106 XDeleteProperty (g -> display , vm_window -> local_winid , g -> wm_state );
2107+
2108+ /* Regarding WINDOW_FLAG_MINIMIZE:
2109+ * Restoring window from minimize state is exactly the same as MSG_MAP,
2110+ * so to not risk some regressions do not duplicate the code. */
20982111 } else {
20992112 /* for mapped windows, send message to window manager (via root window) */
21002113 XClientMessageEvent ev ;
@@ -2104,6 +2117,10 @@ static void handle_wmflags(Ghandles * g, struct windowdata *vm_window)
21042117 /* no change requested */
21052118 return ;
21062119
2120+ // WINDOW_FLAG_FULLSCREEN and WINDOW_FLAG_MINIMIZE are mutually exclusive
2121+ if (msg .flags_set & WINDOW_FLAG_MINIMIZE )
2122+ msg .flags_set &= ~WINDOW_FLAG_FULLSCREEN ;
2123+
21072124 memset (& ev , 0 , sizeof (ev ));
21082125 ev .type = ClientMessage ;
21092126 ev .display = g -> display ;
@@ -2134,6 +2151,9 @@ static void handle_wmflags(Ghandles * g, struct windowdata *vm_window)
21342151 (SubstructureNotifyMask |SubstructureRedirectMask ),
21352152 (XEvent * ) & ev );
21362153 }
2154+ if (msg .flags_set & WINDOW_FLAG_MINIMIZE ) {
2155+ XIconifyWindow (g -> display , vm_window -> local_winid , g -> screen );
2156+ }
21372157 }
21382158}
21392159
0 commit comments