client: update EWMH hints when changing skip_taskbar
[awesome.git] / titlebar.c
blob793b7add300ff6144f1e0367fbca2ff64e235610
1 /*
2 * titlebar.c - titlebar 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 <xcb/xcb.h>
24 #include "titlebar.h"
25 #include "client.h"
26 #include "widget.h"
27 #include "wibox.h"
28 #include "screen.h"
29 #include "luaa.h"
31 /** Get a client by its titlebar.
32 * \param titlebar The titlebar.
33 * \return A client.
35 client_t *
36 client_getbytitlebar(wibox_t *titlebar)
38 foreach(c, globalconf.clients)
39 if((*c)->titlebar == titlebar)
40 return *c;
42 return NULL;
45 /** Get a client by its titlebar window.
46 * \param win The window.
47 * \return A client.
49 client_t *
50 client_getbytitlebarwin(xcb_window_t win)
52 foreach(c, globalconf.clients)
53 if((*c)->titlebar && (*c)->titlebar->window == win)
54 return *c;
56 return NULL;
59 /** Move a titlebar out of the viewport.
60 * \param titlebar The titlebar.
62 void
63 titlebar_ban(wibox_t *titlebar)
65 /* Do it manually because client geometry remains unchanged. */
66 if(titlebar && !titlebar->isbanned)
68 client_t *c;
70 if(titlebar->window)
71 xcb_unmap_window(globalconf.connection, titlebar->window);
73 /* Remove titlebar geometry from client. */
74 if((c = client_getbytitlebar(titlebar)))
75 c->geometry = titlebar_geometry_remove(titlebar, 0, c->geometry);
77 titlebar->isbanned = true;
81 /** Move a titlebar on top of its client.
82 * \param titlebar The titlebar.
84 void
85 titlebar_unban(wibox_t *titlebar)
87 /* Do this manually because the system doesn't know we moved the toolbar.
88 * Note that !visible titlebars are unmapped and for fullscreen it'll
89 * end up offscreen anyway. */
90 if(titlebar && titlebar->isbanned)
92 client_t *c;
94 if(titlebar->window)
95 xcb_map_window(globalconf.connection, titlebar->window);
97 titlebar->isbanned = false;
99 /* Add titlebar geometry from client. */
100 if((c = client_getbytitlebar(titlebar)))
101 c->geometry = titlebar_geometry_add(titlebar, 0, c->geometry);
105 /** Get titlebar area.
106 * \param c The client
107 * \param geometry The client geometry including borders, excluding titlebars.
108 * \param res Pointer to area of titlebar, must be allocated already.
110 void
111 titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res)
113 int height, width, x_offset = 0, y_offset = 0;
115 switch(c->titlebar->position)
117 default:
118 return;
119 case Top:
120 width = MAX(1, geometry.width);
121 switch(c->titlebar->align)
123 default:
124 break;
125 case AlignRight:
126 x_offset = geometry.width - width;
127 break;
128 case AlignCenter:
129 x_offset = (geometry.width - width) / 2;
130 break;
132 res->x = geometry.x + x_offset;
133 res->y = geometry.y - c->titlebar->geometry.height;
134 res->width = width;
135 res->height = c->titlebar->geometry.height;
136 break;
137 case Bottom:
138 width = MAX(1, geometry.width);
139 switch(c->titlebar->align)
141 default:
142 break;
143 case AlignRight:
144 x_offset = geometry.width - width;
145 break;
146 case AlignCenter:
147 x_offset = (geometry.width - width) / 2;
148 break;
150 res->x = geometry.x + x_offset;
151 res->y = geometry.y + geometry.height;
152 res->width = width;
153 res->height = c->titlebar->geometry.height;
154 break;
155 case Left:
156 height = MAX(1, geometry.height);
157 switch(c->titlebar->align)
159 default:
160 break;
161 case AlignRight:
162 y_offset = geometry.height - height;
163 break;
164 case AlignCenter:
165 y_offset = (geometry.height - height) / 2;
166 break;
168 res->x = geometry.x - c->titlebar->geometry.width;
169 res->y = geometry.y + y_offset;
170 res->width = c->titlebar->geometry.width;
171 res->height = height;
172 break;
173 case Right:
174 height = MAX(1, geometry.height);
175 switch(c->titlebar->align)
177 default:
178 break;
179 case AlignRight:
180 y_offset = geometry.height - height;
181 break;
182 case AlignCenter:
183 y_offset = (geometry.height - height) / 2;
184 break;
186 res->x = geometry.x + geometry.width;
187 res->y = geometry.y + y_offset;
188 res->width = c->titlebar->geometry.width;
189 res->height = height;
190 break;
194 /** Detach a wibox titlebar from its client.
195 * \param c The client.
197 void
198 titlebar_client_detach(client_t *c)
200 /* If client has a titlebar, kick it out. */
201 if(c && c->titlebar)
203 /* Update client geometry to exclude the titlebar. */
204 c->geometry = titlebar_geometry_remove(c->titlebar, 0, c->geometry);
205 wibox_wipe(c->titlebar);
206 c->titlebar->type = WIBOX_TYPE_NORMAL;
207 c->titlebar->screen = NULL;
209 luaA_object_unref(globalconf.L, c->titlebar);
210 c->titlebar = NULL;
212 hook_property(c, "titlebar");
213 client_stack();
217 /** Attach a wibox to a client as its titlebar.
218 * \param c The client.
220 void
221 titlebar_client_attach(client_t *c)
223 /* check if we can register the object */
224 wibox_t *t = luaA_object_ref(globalconf.L, -1);
226 titlebar_client_detach(c);
228 /* check if titlebar is already on a client */
229 titlebar_client_detach(client_getbytitlebar(t));
231 /* check if client already has a titlebar. */
232 titlebar_client_detach(c);
234 /* set the object as new client's titlebar */
235 c->titlebar = t;
237 t->type = WIBOX_TYPE_TITLEBAR;
238 t->screen = c->screen;
240 switch(t->position)
242 case Top:
243 case Bottom:
244 if(!t->geometry.height)
245 t->geometry.height = 1.5 * globalconf.font->height;
246 break;
247 case Left:
248 case Right:
249 if(!t->geometry.width)
250 t->geometry.width = 1.5 * globalconf.font->height;
251 break;
254 /* Update client geometry to include the titlebar. */
255 c->geometry = titlebar_geometry_add(c->titlebar, 0, c->geometry);
257 /* Client geometry without titlebar, but including borders, since that is always consistent. */
258 titlebar_geometry_compute(c, titlebar_geometry_remove(c->titlebar, 0, c->geometry), &t->geometry);
260 wibox_init(t, c->phys_screen);
262 t->need_update = true;
264 /* Call update geometry. This will move the wibox to the right place,
265 * which might be the same as `wingeom', but then it will ban the
266 * titlebar if needed. */
267 titlebar_update_geometry(c);
269 xcb_map_window(globalconf.connection, t->window);
271 hook_property(c, "titlebar");
272 client_stack();
275 /** Map or unmap a titlebar wibox.
276 * \param t The wibox/titlebar.
277 * \param visible The new state of the titlebar.
279 void
280 titlebar_set_visible(wibox_t *t, bool visible)
282 if(visible != t->visible)
284 if((t->visible = visible))
285 titlebar_unban(t);
286 else
287 titlebar_ban(t);
289 hook_property(t, "visible");
290 client_stack();
295 luaA_titlebar_set_position(lua_State *L, int udx)
297 wibox_t *titlebar = luaA_checkudata(L, udx, &wibox_class);
298 size_t len;
299 const char *buf = luaL_checklstring(L, -1, &len);
300 position_t position = position_fromstr(buf, len);
301 if(position != titlebar->position)
303 switch(position)
305 case Left:
306 switch(titlebar->position)
308 int tmp;
309 case Left:
310 case Right:
311 break;
312 case Top:
313 case Bottom:
314 tmp = titlebar->geometry.width;
315 titlebar->geometry.width = titlebar->geometry.height;
316 titlebar->geometry.height = tmp;
317 break;
319 wibox_set_orientation(L, udx, North);
320 break;
321 case Right:
322 switch(titlebar->position)
324 int tmp;
325 case Left:
326 case Right:
327 break;
328 case Top:
329 case Bottom:
330 tmp = titlebar->geometry.width;
331 titlebar->geometry.width = titlebar->geometry.height;
332 titlebar->geometry.height = tmp;
333 break;
335 wibox_set_orientation(L, udx, South);
336 break;
337 case Top:
338 case Bottom:
339 switch(titlebar->position)
341 int tmp;
342 case Left:
343 case Right:
344 tmp = titlebar->geometry.width;
345 titlebar->geometry.width = titlebar->geometry.height;
346 titlebar->geometry.height = tmp;
347 break;
348 case Top:
349 case Bottom:
350 break;
352 wibox_set_orientation(L, udx, East);
353 break;
355 titlebar->position = position;
356 client_t *c;
357 if((c = client_getbytitlebar(titlebar)))
359 titlebar_update_geometry(c);
360 /* call geometry hook for client because some like to
361 * set titlebar width in that hook, which make sense */
362 hook_property(c, "geometry");
365 return 0;
368 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80