xwm: set the _NET_WM_DESKTOP property of the windows

Some X clients use the _NET_WM_DESKTOP property to tell if the window
is mapped or not. If set, it should say the virtual desktop the window
is currently in, if unset it means the window is unmapped.
The xwm currently has no way to know how many virtual desktops
the shell plugin has, or if it even implements the metaphor. For now
just set the property to 0, meaning the first desktop, if the window is
mapped, and delete the property when unmapped.

Reviewed-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index 6f1996f..4d3611f 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -863,6 +863,29 @@
 	hash_table_insert(wm->window_hash, window->frame_id, window);
 }
 
+/*
+ * Sets the _NET_WM_DESKTOP property for the window to 'desktop'.
+ * Passing a <0 desktop value deletes the property.
+ */
+static void
+weston_wm_window_set_virtual_desktop(struct weston_wm_window *window,
+                                     int desktop)
+{
+	if (desktop >= 0) {
+		xcb_change_property(window->wm->conn,
+		                    XCB_PROP_MODE_REPLACE,
+		                    window->id,
+		                    window->wm->atom.net_wm_desktop,
+		                    XCB_ATOM_CARDINAL,
+		                    32, /* format */
+		                    1, &desktop);
+	} else {
+		xcb_delete_property(window->wm->conn,
+		                    window->id,
+		                    window->wm->atom.net_wm_desktop);
+	}
+}
+
 static void
 weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event)
 {
@@ -888,6 +911,7 @@
 
 	weston_wm_window_set_wm_state(window, ICCCM_NORMAL_STATE);
 	weston_wm_window_set_net_wm_state(window);
+	weston_wm_window_set_virtual_desktop(window, 0);
 
 	xcb_map_window(wm->conn, map_request->window);
 	xcb_map_window(wm->conn, window->frame_id);
@@ -935,6 +959,10 @@
 	window->surface = NULL;
 	window->shsurf = NULL;
 	window->view = NULL;
+
+	weston_wm_window_set_wm_state(window, ICCCM_WITHDRAWN_STATE);
+	weston_wm_window_set_virtual_desktop(window, -1);
+
 	xcb_unmap_window(wm->conn, window->frame_id);
 }
 
@@ -1123,6 +1151,7 @@
 		xcb_reparent_window(wm->conn, window->id, wm->wm_window, 0, 0);
 		xcb_destroy_window(wm->conn, window->frame_id);
 		weston_wm_window_set_wm_state(window, ICCCM_WITHDRAWN_STATE);
+		weston_wm_window_set_virtual_desktop(window, -1);
 		hash_table_remove(wm->window_hash, window->frame_id);
 		window->frame_id = XCB_WINDOW_NONE;
 	}
@@ -1858,6 +1887,7 @@
 		{ "_NET_WM_STATE_FULLSCREEN", F(atom.net_wm_state_fullscreen) },
 		{ "_NET_WM_USER_TIME", F(atom.net_wm_user_time) },
 		{ "_NET_WM_ICON_NAME", F(atom.net_wm_icon_name) },
+		{ "_NET_WM_DESKTOP", F(atom.net_wm_desktop) },
 		{ "_NET_WM_WINDOW_TYPE", F(atom.net_wm_window_type) },
 
 		{ "_NET_WM_WINDOW_TYPE_DESKTOP", F(atom.net_wm_window_type_desktop) },