client: better handling of transient windows stacking

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-11-03 11:46:57 +01:00
parent 0df0077a2b
commit 9ce1f986d9
2 changed files with 50 additions and 45 deletions

View File

@ -225,16 +225,17 @@ client_focus(client_t *c)
/** Stack a window below. /** Stack a window below.
* \param c The client. * \param c The client.
* \param mode The mode.
* \param previous The previous window on the stack. * \param previous The previous window on the stack.
* \param return The next-previous! * \param return The next-previous!
*/ */
static xcb_window_t static xcb_window_t
client_stack_below(client_t *c, xcb_window_t previous) client_stack_position(client_t *c, xcb_stack_mode_t mode, xcb_window_t previous)
{ {
uint32_t config_win_vals[2]; uint32_t config_win_vals[2];
config_win_vals[0] = previous; config_win_vals[0] = previous;
config_win_vals[1] = XCB_STACK_MODE_BELOW; config_win_vals[1] = mode;
if(c->titlebar) if(c->titlebar)
{ {
@ -247,21 +248,20 @@ client_stack_below(client_t *c, xcb_window_t previous)
xcb_configure_window(globalconf.connection, c->win, xcb_configure_window(globalconf.connection, c->win,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals); config_win_vals);
config_win_vals[0] = c->win;
return c->win; return c->win;
} }
/** Stacking layout layers */ /** Stacking layout layers */
typedef enum typedef enum
{ {
LAYER_DESKTOP = 1, /** This one is a special layer */
LAYER_TRANSIENT_FOR,
LAYER_DESKTOP,
LAYER_BELOW, LAYER_BELOW,
LAYER_TILE, LAYER_TILE,
LAYER_FLOAT, LAYER_FLOAT,
LAYER_ABOVE, LAYER_ABOVE,
LAYER_FULLSCREEN, LAYER_FULLSCREEN,
LAYER_MODAL,
LAYER_ONTOP, LAYER_ONTOP,
LAYER_OUTOFSPACE LAYER_OUTOFSPACE
} layer_t; } layer_t;
@ -275,22 +275,19 @@ client_layer_translator(client_t *c)
{ {
if(c->isontop) if(c->isontop)
return LAYER_ONTOP; return LAYER_ONTOP;
else if(c->ismodal)
return LAYER_MODAL;
else if(c->isfullscreen) else if(c->isfullscreen)
return LAYER_FULLSCREEN; return LAYER_FULLSCREEN;
else if(c->isabove) else if(c->isabove)
return LAYER_ABOVE; return LAYER_ABOVE;
else if(c->isfloating) else if(c->isfloating)
return LAYER_FLOAT; return LAYER_FLOAT;
else if(c->transient_for)
return LAYER_TRANSIENT_FOR;
switch(c->type) switch(c->type)
{ {
case WINDOW_TYPE_DOCK: case WINDOW_TYPE_DOCK:
return LAYER_ABOVE; return LAYER_ABOVE;
case WINDOW_TYPE_SPLASH:
case WINDOW_TYPE_DIALOG:
return LAYER_MODAL;
case WINDOW_TYPE_DESKTOP: case WINDOW_TYPE_DESKTOP:
return LAYER_DESKTOP; return LAYER_DESKTOP;
default: default:
@ -306,41 +303,14 @@ void
client_stack() client_stack()
{ {
uint32_t config_win_vals[2]; uint32_t config_win_vals[2];
client_node_t *node; client_node_t *node, *last = *client_node_list_last(&globalconf.stack);
layer_t layer; layer_t layer;
int screen; int screen;
config_win_vals[0] = XCB_NONE; config_win_vals[0] = XCB_NONE;
config_win_vals[1] = XCB_STACK_MODE_BELOW; config_win_vals[1] = XCB_STACK_MODE_ABOVE;
/* first stack modal and fullscreen windows */ /* first stack not ontop wibox window */
for(layer = LAYER_OUTOFSPACE - 1; layer >= LAYER_FULLSCREEN; layer--)
for(node = globalconf.stack; node; node = node->next)
if(client_layer_translator(node->client) == layer)
config_win_vals[0] = client_stack_below(node->client, config_win_vals[0]);
/* then stack ontop wibox window */
for(screen = 0; screen < globalconf.nscreen; screen++)
for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
{
wibox_t *sb = globalconf.screens[screen].wiboxes.tab[i];
if(sb->ontop)
{
xcb_configure_window(globalconf.connection,
sb->sw.window,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals);
config_win_vals[0] = sb->sw.window;
}
}
/* finally stack everything else */
for(layer = LAYER_FULLSCREEN - 1; layer >= LAYER_TILE; layer--)
for(node = globalconf.stack; node; node = node->next)
if(client_layer_translator(node->client) == layer)
config_win_vals[0] = client_stack_below(node->client, config_win_vals[0]);
/* then stack not ontop wibox window */
for(screen = 0; screen < globalconf.nscreen; screen++) for(screen = 0; screen < globalconf.nscreen; screen++)
for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++) for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
{ {
@ -355,11 +325,44 @@ client_stack()
} }
} }
/* finally stack everything else */ /* stack bottom layers */
for(layer = LAYER_TILE - 1; layer >= LAYER_DESKTOP; layer--) for(layer = LAYER_DESKTOP; layer < LAYER_FULLSCREEN; layer++)
for(node = globalconf.stack; node; node = node->next) for(node = last; node; node = node->prev)
if(client_layer_translator(node->client) == layer) if(client_layer_translator(node->client) == layer)
config_win_vals[0] = client_stack_below(node->client, config_win_vals[0]); config_win_vals[0] = client_stack_position(node->client,
XCB_STACK_MODE_ABOVE,
config_win_vals[0]);
/* then stack ontop wibox window */
for(screen = 0; screen < globalconf.nscreen; screen++)
for(int i = globalconf.screens[screen].wiboxes.len - 1; i > 0; i--)
{
wibox_t *sb = globalconf.screens[screen].wiboxes.tab[i];
if(sb->ontop)
{
xcb_configure_window(globalconf.connection,
sb->sw.window,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals);
config_win_vals[0] = sb->sw.window;
}
}
/* finally stack ontop and fullscreen windows */
for(layer = LAYER_FULLSCREEN; layer < LAYER_OUTOFSPACE; layer++)
for(node = last; node; node = node->prev)
if(client_layer_translator(node->client) == layer)
config_win_vals[0] = client_stack_position(node->client,
XCB_STACK_MODE_ABOVE,
config_win_vals[0]);
/* stack transient window on top of their parents */
for(node = last; node; node = node->prev)
if(client_layer_translator(node->client) == LAYER_TRANSIENT_FOR)
client_stack_position(node->client,
XCB_STACK_MODE_ABOVE,
node->client->transient_for->win);
} }
/** Manage a new client. /** Manage a new client.

View File

@ -78,6 +78,8 @@ static inline void
client_raise(client_t *c) client_raise(client_t *c)
{ {
/* Push c on top of the stack. */ /* Push c on top of the stack. */
if(c->transient_for)
stack_client_push(c->transient_for);
stack_client_push(c); stack_client_push(c);
client_stack(); client_stack();
} }