2 * titlebar.c - titlebar management
4 * Copyright © 2008 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.
30 /** Get a client by its titlebar.
31 * \param titlebar The titlebar.
35 client_getbytitlebar(wibox_t
*titlebar
)
37 foreach(c
, globalconf
.clients
)
38 if((*c
)->titlebar
== titlebar
)
44 /** Get a client by its titlebar window.
45 * \param win The window.
49 client_getbytitlebarwin(xcb_window_t win
)
51 foreach(c
, globalconf
.clients
)
52 if((*c
)->titlebar
&& (*c
)->titlebar
->sw
.window
== win
)
58 /** Move a titlebar out of the viewport.
59 * \param titlebar The titlebar.
62 titlebar_ban(wibox_t
*titlebar
)
64 /* Do it manually because client geometry remains unchanged. */
65 if(titlebar
&& !titlebar
->isbanned
)
68 simple_window_t
*sw
= &titlebar
->sw
;
71 xcb_unmap_window(globalconf
.connection
, sw
->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 !isvisible titlebars are unmapped and for fullscreen it'll
89 * end up offscreen anyway. */
90 if(titlebar
&& titlebar
->isbanned
)
93 simple_window_t
*sw
= &titlebar
->sw
;
96 xcb_map_window(globalconf
.connection
, sw
->window
);
98 titlebar
->isbanned
= false;
100 /* Add titlebar geometry from client. */
101 if((c
= client_getbytitlebar(titlebar
)))
102 c
->geometry
= titlebar_geometry_add(titlebar
, 0, c
->geometry
);
106 /** Get titlebar area.
107 * \param c The client
108 * \param geometry The client geometry including borders, excluding titlebars.
109 * \param res Pointer to area of titlebar, must be allocated already.
112 titlebar_geometry_compute(client_t
*c
, area_t geometry
, area_t
*res
)
114 int height
, width
, x_offset
= 0, y_offset
= 0;
116 switch(c
->titlebar
->position
)
121 width
= MAX(1, geometry
.width
);
122 switch(c
->titlebar
->align
)
127 x_offset
= geometry
.width
- width
;
130 x_offset
= (geometry
.width
- width
) / 2;
133 res
->x
= geometry
.x
+ x_offset
;
134 res
->y
= geometry
.y
- c
->titlebar
->sw
.geometry
.height
;
136 res
->height
= c
->titlebar
->sw
.geometry
.height
;
139 width
= MAX(1, geometry
.width
);
140 switch(c
->titlebar
->align
)
145 x_offset
= geometry
.width
- width
;
148 x_offset
= (geometry
.width
- width
) / 2;
151 res
->x
= geometry
.x
+ x_offset
;
152 res
->y
= geometry
.y
+ geometry
.height
;
154 res
->height
= c
->titlebar
->sw
.geometry
.height
;
157 height
= MAX(1, geometry
.height
);
158 switch(c
->titlebar
->align
)
163 y_offset
= geometry
.height
- height
;
166 y_offset
= (geometry
.height
- height
) / 2;
169 res
->x
= geometry
.x
- c
->titlebar
->sw
.geometry
.width
;
170 res
->y
= geometry
.y
+ y_offset
;
171 res
->width
= c
->titlebar
->sw
.geometry
.width
;
172 res
->height
= height
;
175 height
= MAX(1, geometry
.height
);
176 switch(c
->titlebar
->align
)
181 y_offset
= geometry
.height
- height
;
184 y_offset
= (geometry
.height
- height
) / 2;
187 res
->x
= geometry
.x
+ geometry
.width
;
188 res
->y
= geometry
.y
+ y_offset
;
189 res
->width
= c
->titlebar
->sw
.geometry
.width
;
190 res
->height
= height
;
195 /** Detach a wibox titlebar from its client.
196 * \param c The client.
199 titlebar_client_detach(client_t
*c
)
201 /* If client has a titlebar, kick it out. */
204 /* Update client geometry to exclude the titlebar. */
205 c
->geometry
= titlebar_geometry_remove(c
->titlebar
, 0, c
->geometry
);
206 simplewindow_wipe(&c
->titlebar
->sw
);
207 c
->titlebar
->type
= WIBOX_TYPE_NORMAL
;
208 c
->titlebar
->screen
= NULL
;
210 wibox_unref(globalconf
.L
, c
->titlebar
);
213 hook_property(client
, c
, "titlebar");
218 /** Attach a wibox to a client as its titlebar.
219 * \param c The client.
220 * \param ud The index of the wibox on the stack.
223 titlebar_client_attach(client_t
*c
)
225 /* check if we can register the object */
226 wibox_t
*t
= wibox_ref(globalconf
.L
, -1);
228 titlebar_client_detach(c
);
230 /* check if titlebar is already on a client */
231 titlebar_client_detach(client_getbytitlebar(t
));
233 /* check if client already has a titlebar. */
234 titlebar_client_detach(c
);
236 /* set the object as new client's titlebar */
239 t
->type
= WIBOX_TYPE_TITLEBAR
;
240 t
->screen
= c
->screen
;
246 if(!t
->sw
.geometry
.height
)
247 t
->sw
.geometry
.height
= 1.5 * globalconf
.font
->height
;
251 if(!t
->sw
.geometry
.width
)
252 t
->sw
.geometry
.width
= 1.5 * globalconf
.font
->height
;
256 /* Update client geometry to include the titlebar. */
257 c
->geometry
= titlebar_geometry_add(c
->titlebar
, 0, c
->geometry
);
259 /* 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
), &wingeom
);
263 simplewindow_init(&t
->sw
, c
->phys_screen
,
264 wingeom
, 0, &t
->sw
.border
.color
,
265 t
->sw
.orientation
, &t
->sw
.ctx
.fg
, &t
->sw
.ctx
.bg
);
267 t
->need_update
= true;
269 /* Call update geometry. This will move the wibox to the right place,
270 * which might be the same as `wingeom', but then it will ban the
271 * titlebar if needed. */
272 titlebar_update_geometry(c
);
274 xcb_map_window(globalconf
.connection
, t
->sw
.window
);
276 hook_property(client
, c
, "titlebar");
280 /** Map or unmap a titlebar wibox.
281 * \param t The wibox/titlebar.
282 * \param visible The new state of the titlebar.
285 titlebar_set_visible(wibox_t
*t
, bool visible
)
287 if(visible
!= t
->isvisible
)
289 if((t
->isvisible
= visible
))
294 hook_property(wibox
, t
, "visible");
299 /** Titlebar newindex.
300 * \param L The Lua VM state.
301 * \param titlebar The wibox titlebar.
302 * \param tok The attribute token.
303 * \return The number of elements pushed on stack.
306 luaA_titlebar_newindex(lua_State
*L
, wibox_t
*titlebar
, awesome_token_t tok
)
318 if((buf
= luaL_checklstring(L
, 3, &len
)))
319 titlebar
->align
= draw_align_fromstr(buf
, len
);
323 case A_TK_BORDER_WIDTH
:
324 if((i
= luaL_checknumber(L
, 3)) >= 0)
325 simplewindow_border_width_set(&titlebar
->sw
, i
);
329 case A_TK_BORDER_COLOR
:
330 if((buf
= luaL_checklstring(L
, 3, &len
)))
331 if(xcolor_init_reply(xcolor_init_unchecked(&titlebar
->sw
.border
.color
, buf
, len
)))
332 simplewindow_border_color_set(&titlebar
->sw
, &titlebar
->sw
.border
.color
);
335 buf
= luaL_checklstring(L
, 3, &len
);
336 position
= position_fromstr(buf
, len
);
337 if(position
!= titlebar
->position
)
342 switch(titlebar
->position
)
350 tmp
= titlebar
->sw
.geometry
.width
;
351 titlebar
->sw
.geometry
.width
= titlebar
->sw
.geometry
.height
;
352 titlebar
->sw
.geometry
.height
= tmp
;
355 simplewindow_orientation_set(&titlebar
->sw
, North
);
358 switch(titlebar
->position
)
366 tmp
= titlebar
->sw
.geometry
.width
;
367 titlebar
->sw
.geometry
.width
= titlebar
->sw
.geometry
.height
;
368 titlebar
->sw
.geometry
.height
= tmp
;
371 simplewindow_orientation_set(&titlebar
->sw
, South
);
375 switch(titlebar
->position
)
380 tmp
= titlebar
->sw
.geometry
.width
;
381 titlebar
->sw
.geometry
.width
= titlebar
->sw
.geometry
.height
;
382 titlebar
->sw
.geometry
.height
= tmp
;
388 simplewindow_orientation_set(&titlebar
->sw
, East
);
391 titlebar
->position
= position
;
392 if((c
= client_getbytitlebar(titlebar
)))
394 titlebar_update_geometry(c
);
395 /* call geometry hook for client because some like to
396 * set titlebar width in that hook, which make sense */
397 hook_property(client
, c
, "geometry");
408 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80