[titlebar] Fix unmap/map handling
[awesome.git] / titlebar.c
blob1be0e4a616ad18dd3a42fc064ba8922a154a26b5
1 /*
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.
22 #include <math.h>
24 #include "titlebar.h"
25 #include "screen.h"
26 #include "layouts/floating.h"
28 extern AwesomeConf globalconf;
30 /** Initialize a titlebar: create the SimpleWindow.
31 * We still need to update its geometry to have it placed correctly.
32 * \param c the client
34 void
35 titlebar_init(Client *c)
37 int width;
39 if(!c->titlebar.height)
40 c->titlebar.height = 1.5 * MAX(c->titlebar.styles.normal.font->height,
41 MAX(c->titlebar.styles.focus.font->height,
42 c->titlebar.styles.urgent.font->height));
44 switch(c->titlebar.position)
46 case Off:
47 return;
48 case Auto:
49 c->titlebar.position = Off;
50 return;
51 case Top:
52 case Bottom:
53 if(!c->titlebar.width)
54 width = c->geometry.width + 2 * c->border;
55 else
56 width = MIN(c->titlebar.width, c->geometry.width);
57 c->titlebar.sw = simplewindow_new(globalconf.display,
58 c->phys_screen, 0, 0,
59 width, c->titlebar.height, 0);
60 break;
61 case Left:
62 case Right:
63 if(!c->titlebar.width)
64 width = c->geometry.height + 2 * c->border;
65 else
66 width = MIN(c->titlebar.width, c->geometry.height);
67 c->titlebar.sw = simplewindow_new(globalconf.display,
68 c->phys_screen, 0, 0,
69 c->titlebar.height, width, 0);
70 break;
71 default:
72 break;
74 XMapWindow(globalconf.display, c->titlebar.sw->window);
77 /** Add the titlebar geometry to a geometry.
78 * \param t the titlebar
79 * \param geometry the geometry
80 * \return a new geometry bigger if the titlebar is visible
82 area_t
83 titlebar_geometry_add(Titlebar *t, area_t geometry)
85 if(!t->sw)
86 return geometry;
88 switch(t->position)
90 case Top:
91 geometry.y -= t->sw->geometry.height;
92 geometry.height += t->sw->geometry.height;
93 break;
94 case Bottom:
95 geometry.height += t->sw->geometry.height;
96 break;
97 case Left:
98 geometry.x -= t->sw->geometry.width;
99 geometry.width += t->sw->geometry.width;
100 break;
101 case Right:
102 geometry.width += t->sw->geometry.width;
103 break;
104 default:
105 break;
108 return geometry;
111 /** Remove the titlebar geometry to a geometry.
112 * \param t the titlebar
113 * \param geometry the geometry
114 * \return a new geometry smaller if the titlebar is visible
116 area_t
117 titlebar_geometry_remove(Titlebar *t, area_t geometry)
119 if(!t->sw)
120 return geometry;
122 switch(t->position)
124 case Top:
125 geometry.y += t->sw->geometry.height;
126 geometry.height -= t->sw->geometry.height;
127 break;
128 case Bottom:
129 geometry.height -= t->sw->geometry.height;
130 break;
131 case Left:
132 geometry.x += t->sw->geometry.width;
133 geometry.width -= t->sw->geometry.width;
134 break;
135 case Right:
136 geometry.width -= t->sw->geometry.width;
137 break;
138 default:
139 break;
142 return geometry;
145 /** Draw the titlebar content.
146 * \param c the client
148 void
149 titlebar_draw(Client *c)
151 Drawable dw = 0;
152 DrawCtx *ctx;
153 style_t style;
154 area_t geometry;
156 if(!c->titlebar.sw)
157 return;
159 switch(c->titlebar.position)
161 case Off:
162 return;
163 case Right:
164 case Left:
165 dw = XCreatePixmap(globalconf.display,
166 RootWindow(globalconf.display, c->titlebar.sw->phys_screen),
167 c->titlebar.sw->geometry.height,
168 c->titlebar.sw->geometry.width,
169 DefaultDepth(globalconf.display, c->titlebar.sw->phys_screen));
170 ctx = draw_context_new(globalconf.display, c->titlebar.sw->phys_screen,
171 c->titlebar.sw->geometry.height,
172 c->titlebar.sw->geometry.width,
173 dw);
174 geometry.width = c->titlebar.sw->geometry.height;
175 geometry.height = c->titlebar.sw->geometry.width;
176 break;
177 default:
178 ctx = draw_context_new(globalconf.display, c->titlebar.sw->phys_screen,
179 c->titlebar.sw->geometry.width,
180 c->titlebar.sw->geometry.height,
181 c->titlebar.sw->drawable);
182 geometry = c->titlebar.sw->geometry;
183 break;
186 /* Check if the client is focused/urgent/normal */
187 if(globalconf.focus->client == c)
188 style = c->titlebar.styles.focus;
189 else if(c->isurgent)
190 style = c->titlebar.styles.urgent;
191 else
192 style = c->titlebar.styles.normal;
194 geometry.x = geometry.y = 0;
196 draw_text(ctx, geometry, c->titlebar.text_align, style.font->height / 2,
197 c->name, style);
199 switch(c->titlebar.position)
201 case Left:
202 draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width,
203 - M_PI_2, 0, c->titlebar.sw->geometry.height);
204 XFreePixmap(globalconf.display, dw);
205 break;
206 case Right:
207 draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width,
208 M_PI_2, c->titlebar.sw->geometry.width, 0);
209 XFreePixmap(globalconf.display, dw);
210 default:
211 break;
214 simplewindow_refresh_drawable(c->titlebar.sw, c->titlebar.sw->phys_screen);
216 draw_context_delete(&ctx);
219 /** Update the titlebar geometry for a floating client.
220 * \param c the client
222 void
223 titlebar_update_geometry_floating(Client *c)
225 int width, x_offset = 0, y_offset = 0;
227 if(!c->titlebar.sw)
228 return;
230 switch(c->titlebar.position)
232 default:
233 return;
234 case Off:
235 return;
236 case Top:
237 if(!c->titlebar.width)
238 width = c->geometry.width + 2 * c->border;
239 else
240 width = MIN(c->titlebar.width, c->geometry.width);
241 switch(c->titlebar.align)
243 default:
244 break;
245 case AlignRight:
246 x_offset = 2 * c->border + c->geometry.width - width;
247 break;
248 case AlignCenter:
249 x_offset = (c->geometry.width - width) / 2;
250 break;
252 simplewindow_move_resize(c->titlebar.sw,
253 c->geometry.x + x_offset,
254 c->geometry.y - c->titlebar.sw->geometry.height,
255 width,
256 c->titlebar.sw->geometry.height);
257 break;
258 case Bottom:
259 if(!c->titlebar.width)
260 width = c->geometry.width + 2 * c->border;
261 else
262 width = MIN(c->titlebar.width, c->geometry.width);
263 switch(c->titlebar.align)
265 default:
266 break;
267 case AlignRight:
268 x_offset = 2 * c->border + c->geometry.width - width;
269 break;
270 case AlignCenter:
271 x_offset = (c->geometry.width - width) / 2;
272 break;
274 simplewindow_move_resize(c->titlebar.sw,
275 c->geometry.x + x_offset,
276 c->geometry.y + c->geometry.height + 2 * c->border,
277 width,
278 c->titlebar.sw->geometry.height);
279 break;
280 case Left:
281 if(!c->titlebar.width)
282 width = c->geometry.height + 2 * c->border;
283 else
284 width = MIN(c->titlebar.width, c->geometry.height);
285 switch(c->titlebar.align)
287 default:
288 break;
289 case AlignRight:
290 y_offset = 2 * c->border + c->geometry.height - width;
291 break;
292 case AlignCenter:
293 y_offset = (c->geometry.height - width) / 2;
294 break;
296 simplewindow_move_resize(c->titlebar.sw,
297 c->geometry.x - c->titlebar.sw->geometry.width,
298 c->geometry.y + y_offset,
299 c->titlebar.sw->geometry.width,
300 width);
301 break;
302 case Right:
303 if(!c->titlebar.width)
304 width = c->geometry.height + 2 * c->border;
305 else
306 width = MIN(c->titlebar.width, c->geometry.height);
307 switch(c->titlebar.align)
309 default:
310 break;
311 case AlignRight:
312 y_offset = 2 * c->border + c->geometry.height - width;
313 break;
314 case AlignCenter:
315 y_offset = (c->geometry.height - width) / 2;
316 break;
318 simplewindow_move_resize(c->titlebar.sw,
319 c->geometry.x + c->geometry.width + 2 * c->border,
320 c->geometry.y + y_offset,
321 c->titlebar.sw->geometry.width,
322 width);
323 break;
326 titlebar_draw(c);
330 /** Update the titlebar geometry for a tiled client.
331 * \param c the client
332 * \param geometry the geometry the client will receive
334 void
335 titlebar_update_geometry(Client *c, area_t geometry)
337 int width, x_offset = 0 , y_offset = 0;
339 if(!c->titlebar.sw)
340 return;
342 switch(c->titlebar.position)
344 default:
345 return;
346 case Off:
347 return;
348 case Top:
349 if(!c->titlebar.width)
350 width = geometry.width + 2 * c->border;
351 else
352 width = MIN(c->titlebar.width, geometry.width);
353 switch(c->titlebar.align)
355 default:
356 break;
357 case AlignRight:
358 x_offset = 2 * c->border + geometry.width - width;
359 break;
360 case AlignCenter:
361 x_offset = (geometry.width - width) / 2;
362 break;
364 simplewindow_move_resize(c->titlebar.sw,
365 geometry.x + x_offset,
366 geometry.y,
367 width,
368 c->titlebar.sw->geometry.height);
369 break;
370 case Bottom:
371 if(!c->titlebar.width)
372 width = geometry.width + 2 * c->border;
373 else
374 width = MIN(c->titlebar.width, geometry.width);
375 switch(c->titlebar.align)
377 default:
378 break;
379 case AlignRight:
380 x_offset = 2 * c->border + geometry.width - width;
381 break;
382 case AlignCenter:
383 x_offset = (geometry.width - width) / 2;
384 break;
386 simplewindow_move_resize(c->titlebar.sw,
387 geometry.x + x_offset,
388 geometry.y + geometry.height
389 - c->titlebar.sw->geometry.height + 2 * c->border,
390 width,
391 c->titlebar.sw->geometry.height);
392 break;
393 case Left:
394 if(!c->titlebar.width)
395 width = geometry.height + 2 * c->border;
396 else
397 width = MIN(c->titlebar.width, geometry.height);
398 switch(c->titlebar.align)
400 default:
401 break;
402 case AlignRight:
403 y_offset = 2 * c->border + geometry.height - width;
404 break;
405 case AlignCenter:
406 y_offset = (geometry.height - width) / 2;
407 break;
409 simplewindow_move_resize(c->titlebar.sw,
410 geometry.x,
411 geometry.y + y_offset,
412 c->titlebar.sw->geometry.width,
413 width);
414 break;
415 case Right:
416 if(!c->titlebar.width)
417 width = geometry.height + 2 * c->border;
418 else
419 width = MIN(c->titlebar.width, geometry.height);
420 switch(c->titlebar.align)
422 default:
423 break;
424 case AlignRight:
425 y_offset = 2 * c->border + geometry.height - width;
426 break;
427 case AlignCenter:
428 y_offset = (geometry.height - width) / 2;
429 break;
431 simplewindow_move_resize(c->titlebar.sw,
432 geometry.x + geometry.width
433 - c->titlebar.sw->geometry.width + 2 * c->border,
434 geometry.y + y_offset,
435 c->titlebar.sw->geometry.width,
436 width);
437 break;
440 titlebar_draw(c);
443 /** Toggle the visibility of the focused window's titlebar.
444 * \param screen screen number (unused)
445 * \param arg unused argument
446 * \ingroup ui_callback
448 void
449 uicb_client_toggletitlebar(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused)))
451 Client *c = globalconf.focus->client;
453 if(!c || !c->titlebar.sw)
454 return;
456 if(!c->titlebar.position)
458 if((c->titlebar.position = c->titlebar.dposition))
459 XMapWindow(globalconf.display, c->titlebar.sw->window);
461 else
463 c->titlebar.position = Off;
464 XUnmapWindow(globalconf.display, c->titlebar.sw->window);
467 if(c->isfloating || layout_get_current(screen)->arrange == layout_floating)
468 titlebar_update_geometry_floating(c);
469 else
470 globalconf.screens[c->screen].need_arrange = True;
473 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80