Set c.screen in ewmh.tag and before tags in rules.execute
[awesome.git] / stack.c
blob42f25abdf71076fbe0ead0f5d26c132b2e36512b
1 /*
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.
22 #include "ewmh.h"
23 #include "screen.h"
24 #include "stack.h"
25 #include "objects/client.h"
26 #include "objects/drawin.h"
28 void
29 stack_client_remove(client_t *c)
31 foreach(client, globalconf.stack)
32 if(*client == c)
34 client_array_remove(&globalconf.stack, client);
35 break;
37 ewmh_update_net_client_list_stacking();
38 stack_windows();
41 /** Push the client at the beginning of the client stack.
42 * \param c The client to push.
44 void
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();
50 stack_windows();
53 /** Push the client at the end of the client stack.
54 * \param c The client to push.
56 void
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();
62 stack_windows();
65 static bool need_stack_refresh = false;
67 void
68 stack_windows(void)
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.
77 static void
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. */
84 return;
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!
96 static xcb_window_t
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);
108 return previous;
111 /** Stacking layout layers */
112 typedef enum
114 /** This one is a special layer */
115 WINDOW_LAYER_IGNORE,
116 WINDOW_LAYER_DESKTOP,
117 WINDOW_LAYER_BELOW,
118 WINDOW_LAYER_NORMAL,
119 WINDOW_LAYER_ABOVE,
120 WINDOW_LAYER_FULLSCREEN,
121 WINDOW_LAYER_ONTOP,
122 /** This one only used for counting and is not a real layer */
123 WINDOW_LAYER_COUNT
124 } window_layer_t;
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 */
134 if(c->ontop)
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;
139 else if(c->above)
140 return WINDOW_LAYER_ABOVE;
141 else if(c->below)
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 */
148 switch(c->type)
150 case WINDOW_TYPE_DESKTOP:
151 return WINDOW_LAYER_DESKTOP;
152 default:
153 break;
156 return WINDOW_LAYER_NORMAL;
159 /** Restack clients.
160 * \todo It might be worth stopping to restack everyone and only stack `c'
161 * relatively to the first matching in the list.
163 void
164 stack_refresh()
166 if(!need_stack_refresh)
167 return;
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)
193 if((*drawin)->ontop)
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