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 extern awesome_t globalconf
;
32 /** Get a client by its titlebar.
33 * \param titlebar The titlebar.
37 client_getbytitlebar(wibox_t
*titlebar
)
41 for(c
= globalconf
.clients
; c
; c
= c
->next
)
42 if(c
->titlebar
== titlebar
)
48 /** Get a client by its titlebar window.
49 * \param win The window.
53 client_getbytitlebarwin(xcb_window_t win
)
57 for(c
= globalconf
.clients
; c
; c
= c
->next
)
58 if(c
->titlebar
&& c
->titlebar
->sw
.window
== win
)
64 /** Move a titlebar out of the viewport.
65 * \param titlebar The titlebar.
68 titlebar_ban(wibox_t
*titlebar
)
70 /* Do it manually because client geometry remains unchanged. */
73 simple_window_t
*sw
= &titlebar
->sw
;
77 uint32_t request
[] = { - sw
->geometry
.width
, - sw
->geometry
.height
};
78 /* Move the titlebar to the same place as the window. */
79 xcb_configure_window(globalconf
.connection
, sw
->window
,
80 XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
,
86 /** Get titlebar area.
88 * \param geometry The client geometry including borders, excluding titlebars.
89 * \param res Pointer to area of titlebar, must be allocated already.
92 titlebar_geometry_compute(client_t
*c
, area_t geometry
, area_t
*res
)
94 int height
, width
, x_offset
= 0, y_offset
= 0;
96 switch(c
->titlebar
->position
)
101 width
= MAX(1, geometry
.width
);
102 switch(c
->titlebar
->align
)
107 x_offset
= geometry
.width
- width
;
110 x_offset
= (geometry
.width
- width
) / 2;
113 res
->x
= geometry
.x
+ x_offset
;
114 res
->y
= geometry
.y
- c
->titlebar
->sw
.geometry
.height
;
116 res
->height
= c
->titlebar
->sw
.geometry
.height
;
119 width
= MAX(1, geometry
.width
);
120 switch(c
->titlebar
->align
)
125 x_offset
= geometry
.width
- width
;
128 x_offset
= (geometry
.width
- width
) / 2;
131 res
->x
= geometry
.x
+ x_offset
;
132 res
->y
= geometry
.y
+ geometry
.height
;
134 res
->height
= c
->titlebar
->sw
.geometry
.height
;
137 height
= MAX(1, geometry
.height
);
138 switch(c
->titlebar
->align
)
143 y_offset
= geometry
.height
- height
;
146 y_offset
= (geometry
.height
- height
) / 2;
149 res
->x
= geometry
.x
- c
->titlebar
->sw
.geometry
.width
;
150 res
->y
= geometry
.y
+ y_offset
;
151 res
->width
= c
->titlebar
->sw
.geometry
.width
;
152 res
->height
= height
;
155 height
= MAX(1, geometry
.height
);
156 switch(c
->titlebar
->align
)
161 y_offset
= geometry
.height
- height
;
164 y_offset
= (geometry
.height
- height
) / 2;
167 res
->x
= geometry
.x
+ geometry
.width
;
168 res
->y
= geometry
.y
+ y_offset
;
169 res
->width
= c
->titlebar
->sw
.geometry
.width
;
170 res
->height
= height
;
175 /** Detach a wibox titlebar from its client.
176 * \param c The client.
179 titlebar_client_detach(client_t
*c
)
181 /* If client has a titlebar, kick it out. */
184 simplewindow_wipe(&c
->titlebar
->sw
);
185 c
->titlebar
->type
= WIBOX_TYPE_NORMAL
;
186 c
->titlebar
->screen
= SCREEN_UNDEF
;
187 wibox_unref(&c
->titlebar
);
189 client_need_arrange(c
);
194 /** Attach a wibox to a client as its titlebar.
195 * \param c The client.
196 * \param t The wibox/titlebar.
199 titlebar_client_attach(client_t
*c
, wibox_t
*t
)
201 titlebar_client_detach(c
);
206 /* Get geometry prior to any titlebar changes. */
207 area_t curgeom
= titlebar_geometry_remove(c
->titlebar
, 0, c
->geometry
);
209 /* check if titlebar is already on a client */
210 titlebar_client_detach(client_getbytitlebar(t
));
212 c
->titlebar
= wibox_ref(&t
);
213 t
->type
= WIBOX_TYPE_TITLEBAR
;
214 t
->screen
= c
->screen
;
222 if(!t
->sw
.geometry
.height
)
223 t
->sw
.geometry
.height
= 1.5 * globalconf
.font
->height
;
227 if(!t
->sw
.geometry
.width
)
228 t
->sw
.geometry
.width
= 1.5 * globalconf
.font
->height
;
232 /* Client geometry without titlebar, but including borders, since that is always consistent. */
233 titlebar_geometry_compute(c
, curgeom
, &wingeom
);
235 simplewindow_init(&t
->sw
, c
->phys_screen
,
236 wingeom
, 0, t
->sw
.orientation
,
237 &t
->sw
.ctx
.fg
, &t
->sw
.ctx
.bg
);
238 simplewindow_border_color_set(&t
->sw
, &t
->sw
.border
.color
);
240 t
->need_update
= true;
242 /* Call update geometry. This will move the wibox to the right place,
243 * which might be the same as `wingeom', but then it will ban the
244 * titlebar if needed. */
245 titlebar_update_geometry(c
);
248 xcb_map_window(globalconf
.connection
, t
->sw
.window
);
250 client_need_arrange(c
);
255 /** Map or unmap a titlebar wibox.
256 * \param t The wibox/titlebar.
257 * \param visible The new state of the titlebar.
260 titlebar_set_visible(wibox_t
*t
, bool visible
)
262 if (visible
!= t
->isvisible
)
264 /* The price of (un)mapping something small like a titlebar is pretty cheap.
265 * It would complicate matters if this rare case was treated like clients.
266 * Clients are moved out of the viewport when banned.
268 if ((t
->isvisible
= visible
))
269 xcb_map_window(globalconf
.connection
, t
->sw
.window
);
271 xcb_unmap_window(globalconf
.connection
, t
->sw
.window
);
273 globalconf
.screens
[t
->screen
].need_arrange
= true;
278 /** Titlebar newindex.
279 * \param L The Lua VM state.
280 * \param titlebar The wibox titlebar.
281 * \param tok The attribute token.
282 * \return The number of elements pushed on stack.
285 luaA_titlebar_newindex(lua_State
*L
, wibox_t
*titlebar
, awesome_token_t tok
)
297 if((buf
= luaL_checklstring(L
, 3, &len
)))
298 titlebar
->align
= draw_align_fromstr(buf
, len
);
302 case A_TK_BORDER_WIDTH
:
303 if((i
= luaL_checknumber(L
, 3)) >= 0)
304 simplewindow_border_width_set(&titlebar
->sw
, i
);
308 case A_TK_BORDER_COLOR
:
309 if((buf
= luaL_checklstring(L
, 3, &len
)))
310 if(xcolor_init_reply(xcolor_init_unchecked(&titlebar
->sw
.border
.color
, buf
, len
)))
311 simplewindow_border_color_set(&titlebar
->sw
, &titlebar
->sw
.border
.color
);
314 buf
= luaL_checklstring(L
, 3, &len
);
315 position
= position_fromstr(buf
, len
);
316 if(position
!= titlebar
->position
)
321 switch(titlebar
->position
)
330 tmp
= titlebar
->sw
.geometry
.width
;
331 titlebar
->sw
.geometry
.width
= titlebar
->sw
.geometry
.height
;
332 titlebar
->sw
.geometry
.height
= tmp
;
335 simplewindow_orientation_set(&titlebar
->sw
, North
);
338 switch(titlebar
->position
)
347 tmp
= titlebar
->sw
.geometry
.width
;
348 titlebar
->sw
.geometry
.width
= titlebar
->sw
.geometry
.height
;
349 titlebar
->sw
.geometry
.height
= tmp
;
352 simplewindow_orientation_set(&titlebar
->sw
, South
);
357 switch(titlebar
->position
)
362 tmp
= titlebar
->sw
.geometry
.width
;
363 titlebar
->sw
.geometry
.width
= titlebar
->sw
.geometry
.height
;
364 titlebar
->sw
.geometry
.height
= tmp
;
371 simplewindow_orientation_set(&titlebar
->sw
, East
);
374 titlebar
->position
= position
;
375 if((c
= client_getbytitlebar(titlebar
)))
377 titlebar_update_geometry(c
);
378 /* call geometry hook for client because some like to
379 * set titlebar width in that hook, which make sense */
380 hooks_property(c
, "geometry");
388 if((c
|| (c
= client_getbytitlebar(titlebar
))))
389 client_need_arrange(c
);
394 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80