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.
31 /** Get a client by its titlebar.
32 * \param titlebar The titlebar.
36 client_getbytitlebar(wibox_t
*titlebar
)
38 foreach(c
, globalconf
.clients
)
39 if((*c
)->titlebar
== titlebar
)
45 /** Get a client by its titlebar window.
46 * \param win The window.
50 client_getbytitlebarwin(xcb_window_t win
)
52 foreach(c
, globalconf
.clients
)
53 if((*c
)->titlebar
&& (*c
)->titlebar
->window
== win
)
59 /** Move a titlebar out of the viewport.
60 * \param titlebar The titlebar.
63 titlebar_ban(wibox_t
*titlebar
)
65 /* Do it manually because client geometry remains unchanged. */
66 if(titlebar
&& !titlebar
->isbanned
)
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.
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
)
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.
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
)
120 width
= MAX(1, geometry
.width
);
121 switch(c
->titlebar
->align
)
126 x_offset
= geometry
.width
- width
;
129 x_offset
= (geometry
.width
- width
) / 2;
132 res
->x
= geometry
.x
+ x_offset
;
133 res
->y
= geometry
.y
- c
->titlebar
->geometry
.height
;
135 res
->height
= c
->titlebar
->geometry
.height
;
138 width
= MAX(1, geometry
.width
);
139 switch(c
->titlebar
->align
)
144 x_offset
= geometry
.width
- width
;
147 x_offset
= (geometry
.width
- width
) / 2;
150 res
->x
= geometry
.x
+ x_offset
;
151 res
->y
= geometry
.y
+ geometry
.height
;
153 res
->height
= c
->titlebar
->geometry
.height
;
156 height
= MAX(1, geometry
.height
);
157 switch(c
->titlebar
->align
)
162 y_offset
= geometry
.height
- height
;
165 y_offset
= (geometry
.height
- height
) / 2;
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
;
174 height
= MAX(1, geometry
.height
);
175 switch(c
->titlebar
->align
)
180 y_offset
= geometry
.height
- height
;
183 y_offset
= (geometry
.height
- height
) / 2;
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
;
195 workaround_broken_titlebars(client_t
*c
)
197 /* Ugly hack to fix #610 */
198 if(c
->maximized_horizontal
)
200 c
->maximized_horizontal
= false;
201 client_set_maximized_horizontal(globalconf
.L
, -1, true);
203 if(c
->maximized_vertical
)
205 c
->maximized_vertical
= false;
206 client_set_maximized_vertical(globalconf
.L
, -1, true);
210 /** Detach a wibox titlebar from its client.
211 * \param c The client.
214 titlebar_client_detach(client_t
*c
)
216 /* If client has a titlebar, kick it out. */
219 /* Update client geometry to exclude the titlebar. */
220 c
->geometry
= titlebar_geometry_remove(c
->titlebar
, 0, c
->geometry
);
221 wibox_wipe(c
->titlebar
);
222 c
->titlebar
->type
= WIBOX_TYPE_NORMAL
;
223 c
->titlebar
->screen
= NULL
;
225 luaA_object_unref(globalconf
.L
, c
->titlebar
);
228 hook_property(c
, "titlebar");
229 luaA_object_push(globalconf
.L
, c
);
230 luaA_object_emit_signal(globalconf
.L
, -1, "property::titlebar", 0);
232 workaround_broken_titlebars(c
);
234 lua_pop(globalconf
.L
, 1);
239 /** Attach a wibox to a client as its titlebar.
240 * \param c The client.
243 titlebar_client_attach(client_t
*c
)
245 /* check if we can register the object */
246 wibox_t
*t
= luaA_object_ref_class(globalconf
.L
, -1, &wibox_class
);
248 titlebar_client_detach(c
);
250 /* check if titlebar is already on a client */
251 titlebar_client_detach(client_getbytitlebar(t
));
253 /* check if client already has a titlebar. */
254 titlebar_client_detach(c
);
256 /* set the object as new client's titlebar */
259 t
->type
= WIBOX_TYPE_TITLEBAR
;
260 t
->screen
= c
->screen
;
266 if(!t
->geometry
.height
)
267 t
->geometry
.height
= 1.5 * globalconf
.font
->height
;
271 if(!t
->geometry
.width
)
272 t
->geometry
.width
= 1.5 * globalconf
.font
->height
;
276 /* Update client geometry to include the titlebar. */
277 c
->geometry
= titlebar_geometry_add(c
->titlebar
, 0, c
->geometry
);
279 /* Client geometry without titlebar, but including borders, since that is always consistent. */
280 titlebar_geometry_compute(c
, titlebar_geometry_remove(c
->titlebar
, 0, c
->geometry
), &t
->geometry
);
282 wibox_init(t
, c
->phys_screen
);
284 t
->need_update
= true;
286 /* Call update geometry. This will move the wibox to the right place,
287 * which might be the same as `wingeom', but then it will ban the
288 * titlebar if needed. */
289 titlebar_update_geometry(c
);
291 xcb_map_window(globalconf
.connection
, t
->window
);
293 hook_property(c
, "titlebar");
295 luaA_object_push(globalconf
.L
, c
);
296 luaA_object_emit_signal(globalconf
.L
, -1, "property::titlebar", 0);
298 workaround_broken_titlebars(c
);
300 lua_pop(globalconf
.L
, 1);
304 /** Map or unmap a titlebar wibox.
305 * \param t The wibox/titlebar.
306 * \param visible The new state of the titlebar.
309 titlebar_set_visible(wibox_t
*t
, bool visible
)
311 if(visible
!= t
->visible
)
313 if((t
->visible
= visible
))
318 hook_property(t
, "visible");
324 luaA_titlebar_set_position(lua_State
*L
, int udx
)
326 wibox_t
*titlebar
= luaA_checkudata(L
, udx
, &wibox_class
);
328 const char *buf
= luaL_checklstring(L
, -1, &len
);
329 position_t position
= position_fromstr(buf
, len
);
330 if(position
!= titlebar
->position
)
335 switch(titlebar
->position
)
343 tmp
= titlebar
->geometry
.width
;
344 titlebar
->geometry
.width
= titlebar
->geometry
.height
;
345 titlebar
->geometry
.height
= tmp
;
348 wibox_set_orientation(L
, udx
, North
);
351 switch(titlebar
->position
)
359 tmp
= titlebar
->geometry
.width
;
360 titlebar
->geometry
.width
= titlebar
->geometry
.height
;
361 titlebar
->geometry
.height
= tmp
;
364 wibox_set_orientation(L
, udx
, South
);
368 switch(titlebar
->position
)
373 tmp
= titlebar
->geometry
.width
;
374 titlebar
->geometry
.width
= titlebar
->geometry
.height
;
375 titlebar
->geometry
.height
= tmp
;
381 wibox_set_orientation(L
, udx
, East
);
384 titlebar
->position
= position
;
386 if((c
= client_getbytitlebar(titlebar
)))
388 titlebar_update_geometry(c
);
389 /* call geometry hook for client because some like to
390 * set titlebar width in that hook, which make sense */
391 hook_property(c
, "geometry");
397 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80