diff --git a/ewmhints.c b/ewmhints.c index 260d366..82d1ede 100644 --- a/ewmhints.c +++ b/ewmhints.c @@ -31,7 +31,7 @@ extern Display *g_display; static Atom g_net_wm_state_maximized_vert_atom, g_net_wm_state_maximized_horz_atom, g_net_wm_state_hidden_atom; -Atom g_net_wm_state_atom; +Atom g_net_wm_state_atom, g_net_wm_desktop_atom; /* Get window property value (32 bit format) @@ -174,6 +174,7 @@ ewmh_init() XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); g_net_wm_state_hidden_atom = XInternAtom(g_display, "_NET_WM_STATE_HIDDEN", False); g_net_wm_state_atom = XInternAtom(g_display, "_NET_WM_STATE", False); + g_net_wm_desktop_atom = XInternAtom(g_display, "_NET_WM_DESKTOP", False); } @@ -271,6 +272,52 @@ ewmh_change_state(Window wnd, int state) return 0; } + +int +ewmh_get_window_desktop(Window wnd) +{ + unsigned long nitems_return; + unsigned char *prop_return; + int desktop; + + if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return) < 0) + return (-1); + + if (nitems_return != 1) + { + fprintf(stderr, "_NET_WM_DESKTOP has bad length\n"); + return (-1); + } + + desktop = *prop_return; + XFree(prop_return); + return desktop; +} + + +int +ewmh_move_to_desktop(Window wnd, unsigned int desktop) +{ + Status status; + XEvent xevent; + + xevent.type = ClientMessage; + xevent.xclient.window = wnd; + xevent.xclient.message_type = g_net_wm_desktop_atom; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = desktop; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + status = XSendEvent(g_display, DefaultRootWindow(g_display), False, + SubstructureNotifyMask | SubstructureRedirectMask, &xevent); + if (!status) + return -1; + + return 0; +} + #endif /* MAKE_PROTO */ diff --git a/xproto.h b/xproto.h index 7dc0638..27c772f 100644 --- a/xproto.h +++ b/xproto.h @@ -4,3 +4,5 @@ void xclip_handle_SelectionClear(void); void xclip_handle_PropertyNotify(XPropertyEvent * xev); int ewmh_get_window_state(Window w); int ewmh_change_state(Window wnd, int state); +int ewmh_move_to_desktop(Window wnd, unsigned int desktop); +int ewmh_get_window_desktop(Window wnd); diff --git a/xwin.c b/xwin.c index 6810bfa..84586ab 100644 --- a/xwin.c +++ b/xwin.c @@ -57,6 +57,7 @@ typedef struct _seamless_window int xoffset, yoffset; int width, height; unsigned int state; /* normal/minimized/maximized */ + unsigned int desktop; struct _seamless_window *next; } seamless_window; static seamless_window *g_seamless_windows = NULL; @@ -85,6 +86,7 @@ static Cursor g_current_cursor; static HCURSOR g_null_cursor = NULL; static Atom g_protocol_atom, g_kill_atom; extern Atom g_net_wm_state_atom; +extern Atom g_net_wm_desktop_atom; static BOOL g_focused; static BOOL g_mouse_in_wnd; /* Indicates that: @@ -300,6 +302,24 @@ seamless_remove_window(seamless_window * win) } +/* Move all windows except wnd to new desktop */ +static void +seamless_all_to_desktop(Window wnd, unsigned int desktop) +{ + seamless_window *sw; + for (sw = g_seamless_windows; sw; sw = sw->next) + { + if (sw->wnd == wnd) + continue; + if (sw->desktop != desktop) + { + ewmh_move_to_desktop(sw->wnd, desktop); + sw->desktop = desktop; + } + } +} + + static void mwm_hide_decorations(Window wnd) { @@ -1957,6 +1977,14 @@ xwin_process_events(void) sw->state = ewmh_get_window_state(sw->wnd); seamless_send_state(sw->id, sw->state, 0); } + + if ((xevent.xproperty.atom == g_net_wm_desktop_atom) + && (xevent.xproperty.state == PropertyNewValue)) + { + sw->desktop = ewmh_get_window_desktop(sw->wnd); + seamless_all_to_desktop(sw->wnd, sw->desktop); + } + break; case MapNotify: if (!g_seamless_rdp)