Skip to content

Commit

Permalink
vmside: Implement the WM_STATE property.
Browse files Browse the repository at this point in the history
The WM_STATE property is defined by ICCCM, and should be set by the
window manager to indicate the current state of a client window.  It
is used for two primary purposes:

- A client can examine the property to determine whether the client's
  own window is conceptually "visible" (NormalState) or "hidden"
  (IconicState).

- A client can look for this property on other clients' windows, in
  order to distinguish application windows (which have the WM_STATE
  property) from windows created by the window manager.

One notable program that makes use of the latter feature is Mozilla
Firefox, which allows WebRTC sites to perform "screen sharing" - but
in order to share a single window rather than the whole screen, that
other window must have the WM_STATE property.

We want to set this property when a client window is mapped, and unset
it when the window is unmapped (withdrawn).  In Qubes, we pretend that
the window is always in normal state, regardless of whether it's
currently minimized/iconified/shaded in dom0.

Note that this property shouldn't be set for override-redirect
windows, since those are beyond the window manager's purview.
  • Loading branch information
Benjamin Moody committed Dec 11, 2020
1 parent ea4931e commit 585fa45
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions gui-agent/vmside.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct _global_handles {
Atom tray_opcode; /* Atom: _NET_SYSTEM_TRAY_MESSAGE_OPCODE */
Atom xembed_info; /* Atom: _XEMBED_INFO */
Atom utf8_string_atom; /* Atom: UTF8_STRING */
Atom wm_state; /* Atom: WM_STATE */
Atom net_wm_state; /* Atom: _NET_WM_STATE */
Atom wm_state_fullscreen; /* Atom: _NET_WM_STATE_FULLSCREEN */
Atom wm_state_demands_attention; /* Atom: _NET_WM_STATE_DEMANDS_ATTENTION */
Expand Down Expand Up @@ -802,6 +803,7 @@ static void send_window_state(Ghandles * g, XID window)
static void process_xevent_map(Ghandles * g, XID window)
{
XWindowAttributes attr;
long new_wm_state[2];
struct msg_hdr hdr;
struct msg_map_info map_info;
Window transient;
Expand All @@ -825,6 +827,13 @@ static void process_xevent_map(Ghandles * g, XID window)
write_message(g->vchan, hdr, map_info);
send_wmname(g, window);
// process_xevent_damage(g, window, 0, 0, attr.width, attr.height);

if (!attr.override_redirect) {
/* WM_STATE is always set to normal */
new_wm_state[0] = NormalState; /* state */
new_wm_state[1] = None; /* icon */
XChangeProperty(g->display, window, g->wm_state, g->wm_state, 32, PropModeReplace, (unsigned char *)new_wm_state, 2);
}
}

static void process_xevent_unmap(Ghandles * g, XID window)
Expand All @@ -838,6 +847,7 @@ static void process_xevent_unmap(Ghandles * g, XID window)
hdr.window = window;
hdr.untrusted_len = 0;
write_struct(g->vchan, hdr);
XDeleteProperty(g->display, window, g->wm_state);
XDeleteProperty(g->display, window, g->net_wm_state);
}

Expand Down Expand Up @@ -1552,6 +1562,7 @@ static void mkghandles(Ghandles * g)
g->tray_opcode =
XInternAtom(g->display, "_NET_SYSTEM_TRAY_OPCODE", False);
g->xembed_info = XInternAtom(g->display, "_XEMBED_INFO", False);
g->wm_state = XInternAtom(g->display, "WM_STATE", False);
g->net_wm_state = XInternAtom(g->display, "_NET_WM_STATE", False);
g->wm_state_fullscreen = XInternAtom(g->display, "_NET_WM_STATE_FULLSCREEN", False);
g->wm_state_demands_attention = XInternAtom(g->display, "_NET_WM_STATE_DEMANDS_ATTENTION", False);
Expand Down

0 comments on commit 585fa45

Please sign in to comment.