awful.mouse: load finder
[awesome.git] / titlebar.c
blob9d73efe3bc37c1b84471259bb2641c9a61b333ba
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 luaA_object_push(globalconf.L, c);
214 luaA_object_emit_signal(globalconf.L, -1, "property::titlebar", 0);
215 lua_pop(globalconf.L, 1);
216 client_stack();
220 /** Attach a wibox to a client as its titlebar.
221 * \param c The client.
223 void
224 titlebar_client_attach(client_t *c)
226 /* check if we can register the object */
227 wibox_t *t = luaA_object_ref_class(globalconf.L, -1, &wibox_class);
229 titlebar_client_detach(c);
231 /* check if titlebar is already on a client */
232 titlebar_client_detach(client_getbytitlebar(t));
234 /* check if client already has a titlebar. */
235 titlebar_client_detach(c);
237 /* set the object as new client's titlebar */
238 c->titlebar = t;
240 t->type = WIBOX_TYPE_TITLEBAR;
241 t->screen = c->screen;
243 switch(t->position)
245 case Top:
246 case Bottom:
247 if(!t->geometry.height)
248 t->geometry.height = 1.5 * globalconf.font->height;
249 break;
250 case Left:
251 case Right:
252 if(!t->geometry.width)
253 t->geometry.width = 1.5 * globalconf.font->height;
254 break;
257 /* Update client geometry to include the titlebar. */
258 c->geometry = titlebar_geometry_add(c->titlebar, 0, c->geometry);
260 /* Client geometry without titlebar, but including borders, since that is always consistent. */
261 titlebar_geometry_compute(c, titlebar_geometry_remove(c->titlebar, 0, c->geometry), &t->geometry);
263 wibox_init(t, c->phys_screen);
265 t->need_update = true;
267 /* Call update geometry. This will move the wibox to the right place,
268 * which might be the same as `wingeom', but then it will ban the
269 * titlebar if needed. */
270 titlebar_update_geometry(c);
272 xcb_map_window(globalconf.connection, t->window);
274 hook_property(c, "titlebar");
276 luaA_object_push(globalconf.L, c);
277 luaA_object_emit_signal(globalconf.L, -1, "property::titlebar", 0);
278 lua_pop(globalconf.L, 1);
279 client_stack();
282 /** Map or unmap a titlebar wibox.
283 * \param t The wibox/titlebar.
284 * \param visible The new state of the titlebar.
286 void
287 titlebar_set_visible(wibox_t *t, bool visible)
289 if(visible != t->visible)
291 if((t->visible = visible))
292 titlebar_unban(t);
293 else
294 titlebar_ban(t);
296 hook_property(t, "visible");
297 client_stack();
302 luaA_titlebar_set_position(lua_State *L, int udx)
304 wibox_t *titlebar = luaA_checkudata(L, udx, &wibox_class);
305 size_t len;
306 const char *buf = luaL_checklstring(L, -1, &len);
307 position_t position = position_fromstr(buf, len);
308 if(position != titlebar->position)
310 switch(position)
312 case Left:
313 switch(titlebar->position)
315 int tmp;
316 case Left:
317 case Right:
318 break;
319 case Top:
320 case Bottom:
321 tmp = titlebar->geometry.width;
322 titlebar->geometry.width = titlebar->geometry.height;
323 titlebar->geometry.height = tmp;
324 break;
326 wibox_set_orientation(L, udx, North);
327 break;
328 case Right:
329 switch(titlebar->position)
331 int tmp;
332 case Left:
333 case Right:
334 break;
335 case Top:
336 case Bottom:
337 tmp = titlebar->geometry.width;
338 titlebar->geometry.width = titlebar->geometry.height;
339 titlebar->geometry.height = tmp;
340 break;
342 wibox_set_orientation(L, udx, South);
343 break;
344 case Top:
345 case Bottom:
346 switch(titlebar->position)
348 int tmp;
349 case Left:
350 case Right:
351 tmp = titlebar->geometry.width;
352 titlebar->geometry.width = titlebar->geometry.height;
353 titlebar->geometry.height = tmp;
354 break;
355 case Top:
356 case Bottom:
357 break;
359 wibox_set_orientation(L, udx, East);
360 break;
362 titlebar->position = position;
363 client_t *c;
364 if((c = client_getbytitlebar(titlebar)))
366 titlebar_update_geometry(c);
367 /* call geometry hook for client because some like to
368 * set titlebar width in that hook, which make sense */
369 hook_property(c, "geometry");
372 return 0;
375 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80