From 3af77fd56e1e623623b47a3ba328f4972e55ccdf Mon Sep 17 00:00:00 2001 From: Wolfgang Kroener Date: Tue, 8 Apr 2008 19:52:59 +0200 Subject: [PATCH] add ewmh stacking layers Add layers for ewmh stacking order http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#STACKINGORDER desktop, below, tile, float, above, fullscreen Signed-off-by: Wolfgang Kroener Signed-off-by: Julien Danjou --- client.c | 97 ++++++++++++++++++++++++++++--------------------------- client.h | 2 +- ewmh.c | 42 +++++++++++++++++++++--- structs.h | 14 ++++++++ 4 files changed, 102 insertions(+), 53 deletions(-) diff --git a/client.c b/client.c index 527466b1..8017cc30 100644 --- a/client.c +++ b/client.c @@ -56,11 +56,11 @@ client_loadprops(Client * c, int screen) for(tag = globalconf.screens[screen].tags; tag; tag = tag->next) ntags++; - prop = p_new(char, ntags + 2); + prop = p_new(char, ntags + 3); if(xgettextprop(globalconf.display, c->win, XInternAtom(globalconf.display, "_AWESOME_PROPERTIES", False), - prop, ntags + 2)) + prop, ntags + 3)) { for(i = 0, tag = globalconf.screens[screen].tags; tag && i < ntags && prop[i]; i++, tag = tag->next) if(prop[i] == '1') @@ -71,8 +71,8 @@ client_loadprops(Client * c, int screen) else untag_client(c, tag); - if(i <= ntags && prop[i]) - client_setfloating(c, prop[i] == '1'); + if(prop[i]) + client_setfloating(c, prop[i] == '1', prop[i + 1] ? atoi(&prop[i + 1]) : prop[i] == '1' ? LAYER_FLOAT : LAYER_TILE); } p_delete(&prop); @@ -241,51 +241,40 @@ void client_stack(Client *c) { XWindowChanges wc; - Layout *curlay = layout_get_current(c->screen); + Client *client; + unsigned int layer; + Layer maxlayer = LAYER_FULLSCREEN; - if(c->isfloating || curlay->arrange == layout_floating) + wc.stack_mode = Above; + wc.sibling = None; + + for(layer = 0; layer < maxlayer; layer++) { - XRaiseWindow(globalconf.display, c->win); - if(c->titlebar.position && c->titlebar.sw) - XRaiseWindow(globalconf.display, c->titlebar.sw->window); - } - else - { - Client *client; - wc.stack_mode = Below; - wc.sibling = None; for(client = globalconf.clients; client; client = client->next) - if(client != c && client_isvisible(client, c->screen) && client->isfloating) - { - if(client->titlebar.position && client->titlebar.sw) - { - XConfigureWindow(globalconf.display, client->titlebar.sw->window, - CWSibling | CWStackMode, &wc); - wc.sibling = client->titlebar.sw->window; - } - XConfigureWindow(globalconf.display, client->win, CWSibling | CWStackMode, &wc); - wc.sibling = client->win; - } - if(c->titlebar.position && c->titlebar.sw) { - XConfigureWindow(globalconf.display, c->titlebar.sw->window, - CWSibling | CWStackMode, &wc); - wc.sibling = c->titlebar.sw->window; - } - XConfigureWindow(globalconf.display, c->win, CWSibling | CWStackMode, &wc); - wc.sibling = c->win; - for(client = globalconf.clients; client; client = client->next) - if(client != c && IS_TILED(client, c->screen)) + if(client->layer == layer && client != c && client_isvisible(client, c->screen)) { if(client->titlebar.position && client->titlebar.sw) { XConfigureWindow(globalconf.display, client->titlebar.sw->window, - CWSibling | CWStackMode, &wc); + CWSibling | CWStackMode, &wc); wc.sibling = client->titlebar.sw->window; } XConfigureWindow(globalconf.display, client->win, CWSibling | CWStackMode, &wc); wc.sibling = client->win; } + } + if(c->layer == layer) + { + if(c->titlebar.position && c->titlebar.sw) + { + XConfigureWindow(globalconf.display, c->titlebar.sw->window, + CWSibling | CWStackMode, &wc); + wc.sibling = c->titlebar.sw->window; + } + XConfigureWindow(globalconf.display, c->win, CWSibling | CWStackMode, &wc); + wc.sibling = c->win; + } } } @@ -322,6 +311,7 @@ client_manage(Window w, XWindowAttributes *wa, int screen) c->geometry.height = c->f_geometry.height = c->m_geometry.height = wa->height; c->oldborder = wa->border_width; c->newcomer = True; + c->layer = c->oldlayer = LAYER_TILE; /* Set windows borders */ wc.border_width = c->border = globalconf.screens[screen].borderpx; @@ -362,10 +352,10 @@ client_manage(Window w, XWindowAttributes *wa, int screen) case Maybe: break; case Yes: - client_setfloating(c, True); + client_setfloating(c, True, c->layer != LAYER_TILE ? c->layer : LAYER_FLOAT); break; case No: - client_setfloating(c, False); + client_setfloating(c, False, LAYER_TILE); break; } @@ -384,7 +374,7 @@ client_manage(Window w, XWindowAttributes *wa, int screen) /* should be floating if transsient or fixed */ if(rettrans || c->isfixed) - client_setfloating(c, True); + client_setfloating(c, True, c->layer != LAYER_TILE ? c->layer : LAYER_FLOAT); /* titlebar init */ if(rule && rule->titlebar.position != Auto) @@ -567,14 +557,13 @@ client_resize(Client *c, area_t geometry, Bool hints) } void -client_setfloating(Client *c, Bool floating) +client_setfloating(Client *c, Bool floating, Layer layer) { if(c->isfloating != floating) { if((c->isfloating = floating)) { client_resize(c, c->f_geometry, False); - XRaiseWindow(globalconf.display, c->win); } else if(c->ismax) { @@ -584,6 +573,16 @@ client_setfloating(Client *c, Bool floating) if(client_isvisible(c, c->screen)) globalconf.screens[c->screen].need_arrange = True; widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); + if(floating) + { + c->oldlayer = c->layer; + c->layer = layer; + } + else + { + c->layer = c->oldlayer; + } + client_stack(c); client_saveprops(c); } } @@ -601,13 +600,14 @@ client_saveprops(Client *c) for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next) ntags++; - prop = p_new(char, ntags + 2); + prop = p_new(char, ntags + 3); for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++) prop[i] = is_client_tagged(c, tag) ? '1' : '0'; - if(i <= ntags) - prop[i] = c->isfloating ? '1' : '0'; + prop[i] = c->isfloating ? '1' : '0'; + + sprintf(&prop[++i], "%d", c->layer); prop[++i] = '\0'; @@ -994,14 +994,14 @@ client_maximize(Client *c, area_t geometry) c->wasfloating = c->isfloating; c->m_geometry = c->geometry; if(layout_get_current(c->screen)->arrange != layout_floating) - client_setfloating(c, True); + client_setfloating(c, True, LAYER_FULLSCREEN); client_focus(c, c->screen, True); client_resize(c, geometry, False); } else if(c->wasfloating) { c->titlebar.position = c->titlebar.dposition; - client_setfloating(c, True); + client_setfloating(c, True, LAYER_FULLSCREEN); client_resize(c, c->m_geometry, False); } else if(layout_get_current(c->screen)->arrange == layout_floating) @@ -1012,7 +1012,7 @@ client_maximize(Client *c, area_t geometry) else { c->titlebar.position = c->titlebar.dposition; - client_setfloating(c, False); + client_setfloating(c, False, LAYER_TILE); } widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); } @@ -1145,7 +1145,8 @@ void uicb_client_togglefloating(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused))) { if(globalconf.focus->client) - client_setfloating(globalconf.focus->client, !globalconf.focus->client->isfloating); + client_setfloating(globalconf.focus->client, !globalconf.focus->client->isfloating, + globalconf.focus->client->layer == LAYER_FLOAT ? LAYER_TILE : LAYER_FLOAT); } /** Toggle the scratch client attribute on the focused client. diff --git a/client.h b/client.h index fea076ba..5b82f3e7 100644 --- a/client.h +++ b/client.h @@ -39,7 +39,7 @@ long client_updatesizehints(Client *); void client_updatetitle(Client *); void client_saveprops(Client *); void client_kill(Client *); -void client_setfloating(Client *, Bool); +void client_setfloating(Client *, Bool, Layer); Uicb uicb_client_kill; Uicb uicb_client_moveresize; diff --git a/ewmh.c b/ewmh.c index f06ebbde..75c8e55a 100644 --- a/ewmh.c +++ b/ewmh.c @@ -53,6 +53,8 @@ static Atom net_wm_state; static Atom net_wm_state_sticky; static Atom net_wm_state_skip_taskbar; static Atom net_wm_state_fullscreen; +static Atom net_wm_state_above; +static Atom net_wm_state_below; static Atom utf8_string; @@ -85,6 +87,8 @@ static AtomItem AtomNames[] = { "_NET_WM_STATE_STICKY", &net_wm_state_sticky }, { "_NET_WM_STATE_SKIP_TASKBAR", &net_wm_state_skip_taskbar }, { "_NET_WM_STATE_FULLSCREEN", &net_wm_state_fullscreen }, + { "_NET_WM_STATE_ABOVE", &net_wm_state_above }, + { "_NET_WM_STATE_BELOW", &net_wm_state_below }, { "UTF8_STRING", &utf8_string }, }; @@ -136,6 +140,8 @@ ewmh_set_supported_hints(int phys_screen) atom[i++] = net_wm_state_sticky; atom[i++] = net_wm_state_skip_taskbar; atom[i++] = net_wm_state_fullscreen; + atom[i++] = net_wm_state_above; + atom[i++] = net_wm_state_below; XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen), net_supported, XA_ATOM, 32, @@ -258,7 +264,7 @@ ewmh_process_state_atom(Client *c, Atom state, int set) titlebar_position_set(&c->titlebar, c->titlebar.dposition); c->border = c->oldborder; c->ismax = False; - client_setfloating(c, c->wasfloating); + client_setfloating(c, c->wasfloating, c->oldlayer); } else if(set == _NET_WM_STATE_ADD) { @@ -271,12 +277,37 @@ ewmh_process_state_atom(Client *c, Atom state, int set) c->oldborder = c->border; c->border = 0; c->ismax = True; - client_setfloating(c, True); + client_setfloating(c, True, LAYER_FULLSCREEN); } widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); client_resize(c, geometry, False); XRaiseWindow(globalconf.display, c->win); } + else if(state == net_wm_state_above) + { + if(set == _NET_WM_STATE_REMOVE) + { + c->layer = c->oldlayer; + } + else if(set == _NET_WM_STATE_ADD) + { + c->oldlayer = c->layer; + c->layer = LAYER_ABOVE; + } + } + else if(state == net_wm_state_below) + { + if(set == _NET_WM_STATE_REMOVE) + { + c->layer = c->oldlayer; + } + else if(set == _NET_WM_STATE_ADD) + { + c->oldlayer = c->layer; + c->layer = LAYER_BELOW; + } + } + } static void @@ -293,11 +324,14 @@ ewmh_process_window_type_atom(Client *c, Atom state) c->skip = True; c->isfixed = True; titlebar_position_set(&c->titlebar, Off); - client_setfloating(c, True); + client_setfloating(c, True, LAYER_ABOVE); } else if (state == net_wm_window_type_dialog) - client_setfloating(c, True); + { + client_setfloating(c, True, LAYER_ABOVE); + } } + void ewmh_process_client_message(XClientMessageEvent *ev) { diff --git a/structs.h b/structs.h index 65129415..7039ecbc 100644 --- a/structs.h +++ b/structs.h @@ -28,6 +28,17 @@ #include "common/swindow.h" #include "common/xscreen.h" +/** stacking layout */ +typedef enum +{ + LAYER_DESKTOP, + LAYER_BELOW, + LAYER_TILE, + LAYER_FLOAT, + LAYER_ABOVE, + LAYER_FULLSCREEN +} Layer; + /** Rules for floating rule */ typedef enum { @@ -219,6 +230,9 @@ struct Client Bool newcomer; /** Titlebar */ Titlebar titlebar; + /** layer in the stacking order */ + Layer layer; + Layer oldlayer; }; typedef struct client_node_t client_node_t;