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.
25 #include "objects/client.h"
26 #include "objects/drawin.h"
29 stack_client_remove(client_t
*c
)
31 foreach(client
, globalconf
.stack
)
34 client_array_remove(&globalconf
.stack
, client
);
37 ewmh_update_net_client_list_stacking();
41 /** Push the client at the beginning of the client stack.
42 * \param c The client to push.
45 stack_client_push(client_t
*c
)
47 stack_client_remove(c
);
48 client_array_push(&globalconf
.stack
, c
);
49 ewmh_update_net_client_list_stacking();
53 /** Push the client at the end of the client stack.
54 * \param c The client to push.
57 stack_client_append(client_t
*c
)
59 stack_client_remove(c
);
60 client_array_append(&globalconf
.stack
, c
);
61 ewmh_update_net_client_list_stacking();
65 static bool need_stack_refresh
= false;
70 need_stack_refresh
= true;
73 /** Stack a window above another window, without causing errors.
74 * \param w The window.
75 * \param previous The window which should be below this window.
78 stack_window_above(xcb_window_t w
, xcb_window_t previous
)
80 if (previous
== XCB_NONE
)
81 /* This would cause an error from the X server. Also, if we really
82 * changed the stacking order of all windows, they'd all have to redraw
83 * themselves. Doing it like this is better. */
86 xcb_configure_window(globalconf
.connection
, w
,
87 XCB_CONFIG_WINDOW_SIBLING
| XCB_CONFIG_WINDOW_STACK_MODE
,
88 (uint32_t[]) { previous
, XCB_STACK_MODE_ABOVE
});
91 /** Stack a client above.
92 * \param client The client.
93 * \param previous The previous client on the stack.
94 * \return The next-previous!
97 stack_client_above(client_t
*c
, xcb_window_t previous
)
99 stack_window_above(c
->frame_window
, previous
);
101 previous
= c
->frame_window
;
103 /* stack transient window on top of their parents */
104 foreach(node
, globalconf
.stack
)
105 if((*node
)->transient_for
== c
)
106 previous
= stack_client_above(*node
, previous
);
111 /** Stacking layout layers */
114 /** This one is a special layer */
116 WINDOW_LAYER_DESKTOP
,
120 WINDOW_LAYER_FULLSCREEN
,
122 /** This one only used for counting and is not a real layer */
126 /** Get the real layer of a client according to its attribute (fullscreen, …)
127 * \param c The client.
128 * \return The real layer.
130 static window_layer_t
131 client_layer_translator(client_t
*c
)
133 /* first deal with user set attributes */
135 return WINDOW_LAYER_ONTOP
;
136 /* Fullscreen windows only get their own layer when they have the focus */
137 else if(c
->fullscreen
&& globalconf
.focus
.client
== c
)
138 return WINDOW_LAYER_FULLSCREEN
;
140 return WINDOW_LAYER_ABOVE
;
142 return WINDOW_LAYER_BELOW
;
143 /* check for transient attr */
144 else if(c
->transient_for
)
145 return WINDOW_LAYER_IGNORE
;
147 /* then deal with windows type */
150 case WINDOW_TYPE_DESKTOP
:
151 return WINDOW_LAYER_DESKTOP
;
156 return WINDOW_LAYER_NORMAL
;
160 * \todo It might be worth stopping to restack everyone and only stack `c'
161 * relatively to the first matching in the list.
166 if(!need_stack_refresh
)
169 xcb_window_t next
= XCB_NONE
;
171 /* stack desktop windows */
172 for(window_layer_t layer
= WINDOW_LAYER_DESKTOP
; layer
< WINDOW_LAYER_BELOW
; layer
++)
173 foreach(node
, globalconf
.stack
)
174 if(client_layer_translator(*node
) == layer
)
175 next
= stack_client_above(*node
, next
);
177 /* first stack not ontop drawin window */
178 foreach(drawin
, globalconf
.drawins
)
179 if(!(*drawin
)->ontop
)
181 stack_window_above((*drawin
)->window
, next
);
182 next
= (*drawin
)->window
;
185 /* then stack clients */
186 for(window_layer_t layer
= WINDOW_LAYER_BELOW
; layer
< WINDOW_LAYER_COUNT
; layer
++)
187 foreach(node
, globalconf
.stack
)
188 if(client_layer_translator(*node
) == layer
)
189 next
= stack_client_above(*node
, next
);
191 /* then stack ontop drawin window */
192 foreach(drawin
, globalconf
.drawins
)
195 stack_window_above((*drawin
)->window
, next
);
196 next
= (*drawin
)->window
;
199 need_stack_refresh
= false;
203 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80