2 * stack.c - client stack management
4 * Copyright © 2008-2009 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "objects/client.h"
25 #include "objects/drawin.h"
28 stack_client_remove(client_t
*c
)
30 foreach(client
, globalconf
.stack
)
33 client_array_remove(&globalconf
.stack
, client
);
36 ewmh_update_net_client_list_stacking();
40 /** Push the client at the beginning of the client stack.
41 * \param c The client to push.
44 stack_client_push(client_t
*c
)
46 stack_client_remove(c
);
47 client_array_push(&globalconf
.stack
, c
);
48 ewmh_update_net_client_list_stacking();
52 /** Push the client at the end of the client stack.
53 * \param c The client to push.
56 stack_client_append(client_t
*c
)
58 stack_client_remove(c
);
59 client_array_append(&globalconf
.stack
, c
);
60 ewmh_update_net_client_list_stacking();
64 static bool need_stack_refresh
= false;
69 need_stack_refresh
= true;
72 /** Stack a window above another window, without causing errors.
73 * \param w The window.
74 * \param previous The window which should be below this window.
77 stack_window_above(xcb_window_t w
, xcb_window_t previous
)
79 if (previous
== XCB_NONE
)
80 /* This would cause an error from the X server. Also, if we really
81 * changed the stacking order of all windows, they'd all have to redraw
82 * themselves. Doing it like this is better. */
85 xcb_configure_window(globalconf
.connection
, w
,
86 XCB_CONFIG_WINDOW_SIBLING
| XCB_CONFIG_WINDOW_STACK_MODE
,
87 (uint32_t[]) { previous
, XCB_STACK_MODE_ABOVE
});
90 /** Stack a client above.
91 * \param client The client.
92 * \param previous The previous client on the stack.
93 * \return The next-previous!
96 stack_client_above(client_t
*c
, xcb_window_t previous
)
98 stack_window_above(c
->frame_window
, previous
);
100 previous
= c
->frame_window
;
102 /* stack transient window on top of their parents */
103 foreach(node
, globalconf
.stack
)
104 if((*node
)->transient_for
== c
)
105 previous
= stack_client_above(*node
, previous
);
110 /** Stacking layout layers */
113 /** This one is a special layer */
115 WINDOW_LAYER_DESKTOP
,
119 WINDOW_LAYER_FULLSCREEN
,
121 /** This one only used for counting and is not a real layer */
125 /** Get the real layer of a client according to its attribute (fullscreen, …)
126 * \param c The client.
127 * \return The real layer.
129 static window_layer_t
130 client_layer_translator(client_t
*c
)
132 /* first deal with user set attributes */
134 return WINDOW_LAYER_ONTOP
;
135 /* Fullscreen windows only get their own layer when they have the focus */
136 else if(c
->fullscreen
&& globalconf
.focus
.client
== c
)
137 return WINDOW_LAYER_FULLSCREEN
;
139 return WINDOW_LAYER_ABOVE
;
141 return WINDOW_LAYER_BELOW
;
142 /* check for transient attr */
143 else if(c
->transient_for
)
144 return WINDOW_LAYER_IGNORE
;
146 /* then deal with windows type */
149 case WINDOW_TYPE_DESKTOP
:
150 return WINDOW_LAYER_DESKTOP
;
155 return WINDOW_LAYER_NORMAL
;
159 * \todo It might be worth stopping to restack everyone and only stack `c'
160 * relatively to the first matching in the list.
165 if(!need_stack_refresh
)
168 xcb_window_t next
= XCB_NONE
;
170 /* stack desktop windows */
171 for(window_layer_t layer
= WINDOW_LAYER_DESKTOP
; layer
< WINDOW_LAYER_BELOW
; layer
++)
172 foreach(node
, globalconf
.stack
)
173 if(client_layer_translator(*node
) == layer
)
174 next
= stack_client_above(*node
, next
);
176 /* first stack not ontop drawin window */
177 foreach(drawin
, globalconf
.drawins
)
178 if(!(*drawin
)->ontop
)
180 stack_window_above((*drawin
)->window
, next
);
181 next
= (*drawin
)->window
;
184 /* then stack clients */
185 for(window_layer_t layer
= WINDOW_LAYER_BELOW
; layer
< WINDOW_LAYER_COUNT
; layer
++)
186 foreach(node
, globalconf
.stack
)
187 if(client_layer_translator(*node
) == layer
)
188 next
= stack_client_above(*node
, next
);
190 /* then stack ontop drawin window */
191 foreach(drawin
, globalconf
.drawins
)
194 stack_window_above((*drawin
)->window
, next
);
195 next
= (*drawin
)->window
;
198 need_stack_refresh
= false;
202 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80