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 <wk@azog.de>
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Wolfgang Kroener 2008-04-08 19:52:59 +02:00 committed by Julien Danjou
parent 24d2e200af
commit 3af77fd56e
4 changed files with 102 additions and 53 deletions

View File

@ -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.

View File

@ -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;

42
ewmh.c
View File

@ -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)
{

View File

@ -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;