Prefix xutil functions properly
[awesome.git] / titlebar.c
blobf670c5852ee7c662744afb7c2636d38031a387f3
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 <xcb/xcb.h>
23 #include <xcb/xcb_aux.h>
25 #include <math.h>
27 #include "titlebar.h"
28 #include "screen.h"
29 #include "layouts/floating.h"
31 extern AwesomeConf globalconf;
33 /** Initialize a titlebar: create the SimpleWindow.
34 * We still need to update its geometry to have it placed correctly.
35 * \param c the client
37 void
38 titlebar_init(Client *c)
40 int width;
42 if(!c->titlebar.height)
43 c->titlebar.height = 1.5 * MAX(c->titlebar.styles.normal.font->height,
44 MAX(c->titlebar.styles.focus.font->height,
45 c->titlebar.styles.urgent.font->height));
47 switch(c->titlebar.position)
49 case Off:
50 return;
51 case Auto:
52 c->titlebar.position = Off;
53 return;
54 case Top:
55 case Bottom:
56 if(!c->titlebar.width)
57 width = c->geometry.width + 2 * c->border;
58 else
59 width = MIN(c->titlebar.width, c->geometry.width);
60 c->titlebar.sw = simplewindow_new(globalconf.connection,
61 c->phys_screen, 0, 0,
62 width, c->titlebar.height, 0);
63 break;
64 case Left:
65 case Right:
66 if(!c->titlebar.width)
67 width = c->geometry.height + 2 * c->border;
68 else
69 width = MIN(c->titlebar.width, c->geometry.height);
70 c->titlebar.sw = simplewindow_new(globalconf.connection,
71 c->phys_screen, 0, 0,
72 c->titlebar.height, width, 0);
73 break;
74 default:
75 break;
77 xcb_map_window(globalconf.connection, c->titlebar.sw->window);
80 /** Add the titlebar geometry to a geometry.
81 * \param t the titlebar
82 * \param geometry the geometry
83 * \return a new geometry bigger if the titlebar is visible
85 area_t
86 titlebar_geometry_add(Titlebar *t, area_t geometry)
88 if(!t->sw)
89 return geometry;
91 switch(t->position)
93 case Top:
94 geometry.y -= t->sw->geometry.height;
95 geometry.height += t->sw->geometry.height;
96 break;
97 case Bottom:
98 geometry.height += t->sw->geometry.height;
99 break;
100 case Left:
101 geometry.x -= t->sw->geometry.width;
102 geometry.width += t->sw->geometry.width;
103 break;
104 case Right:
105 geometry.width += t->sw->geometry.width;
106 break;
107 default:
108 break;
111 return geometry;
114 /** Remove the titlebar geometry to a geometry.
115 * \param t the titlebar
116 * \param geometry the geometry
117 * \return a new geometry smaller if the titlebar is visible
119 area_t
120 titlebar_geometry_remove(Titlebar *t, area_t geometry)
122 if(!t->sw)
123 return geometry;
125 switch(t->position)
127 case Top:
128 geometry.y += t->sw->geometry.height;
129 geometry.height -= t->sw->geometry.height;
130 break;
131 case Bottom:
132 geometry.height -= t->sw->geometry.height;
133 break;
134 case Left:
135 geometry.x += t->sw->geometry.width;
136 geometry.width -= t->sw->geometry.width;
137 break;
138 case Right:
139 geometry.width -= t->sw->geometry.width;
140 break;
141 default:
142 break;
145 return geometry;
148 /** Draw the titlebar content.
149 * \param c the client
151 void
152 titlebar_draw(Client *c)
154 xcb_drawable_t dw = 0;
155 DrawCtx *ctx;
156 style_t style;
157 area_t geometry;
158 xcb_screen_t *s;
160 if(!c->titlebar.sw)
161 return;
163 s = xcb_aux_get_screen(globalconf.connection,
164 c->titlebar.sw->phys_screen);
166 switch(c->titlebar.position)
168 case Off:
169 return;
170 case Right:
171 case Left:
172 dw = xcb_generate_id(globalconf.connection);
173 xcb_create_pixmap(globalconf.connection, s->root_depth,
175 xutil_root_window(globalconf.connection, c->titlebar.sw->phys_screen),
176 c->titlebar.sw->geometry.height,
177 c->titlebar.sw->geometry.width);
178 ctx = draw_context_new(globalconf.connection, c->titlebar.sw->phys_screen,
179 c->titlebar.sw->geometry.height,
180 c->titlebar.sw->geometry.width,
181 dw);
182 geometry.width = c->titlebar.sw->geometry.height;
183 geometry.height = c->titlebar.sw->geometry.width;
184 break;
185 default:
186 ctx = draw_context_new(globalconf.connection, c->titlebar.sw->phys_screen,
187 c->titlebar.sw->geometry.width,
188 c->titlebar.sw->geometry.height,
189 c->titlebar.sw->drawable);
190 geometry = c->titlebar.sw->geometry;
191 break;
194 /* Check if the client is focused/urgent/normal */
195 if(globalconf.focus->client == c)
196 style = c->titlebar.styles.focus;
197 else if(c->isurgent)
198 style = c->titlebar.styles.urgent;
199 else
200 style = c->titlebar.styles.normal;
202 geometry.x = geometry.y = 0;
204 draw_text(ctx, geometry, c->titlebar.text_align, style.font->height / 2,
205 c->name, style);
207 switch(c->titlebar.position)
209 case Left:
210 draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width,
211 - M_PI_2, 0, c->titlebar.sw->geometry.height);
212 xcb_free_pixmap(globalconf.connection, dw);
213 break;
214 case Right:
215 draw_rotate(ctx, c->titlebar.sw->drawable, ctx->height, ctx->width,
216 M_PI_2, c->titlebar.sw->geometry.width, 0);
217 xcb_free_pixmap(globalconf.connection, dw);
218 default:
219 break;
222 simplewindow_refresh_drawable(c->titlebar.sw, c->titlebar.sw->phys_screen);
224 draw_context_delete(&ctx);
227 /** Update the titlebar geometry for a floating client.
228 * \param c the client
230 void
231 titlebar_update_geometry_floating(Client *c)
233 int width, x_offset = 0, y_offset = 0;
235 if(!c->titlebar.sw)
236 return;
238 switch(c->titlebar.position)
240 default:
241 return;
242 case Off:
243 return;
244 case Top:
245 if(!c->titlebar.width)
246 width = c->geometry.width + 2 * c->border;
247 else
248 width = MIN(c->titlebar.width, c->geometry.width);
249 switch(c->titlebar.align)
251 default:
252 break;
253 case AlignRight:
254 x_offset = 2 * c->border + c->geometry.width - width;
255 break;
256 case AlignCenter:
257 x_offset = (c->geometry.width - width) / 2;
258 break;
260 simplewindow_move_resize(c->titlebar.sw,
261 c->geometry.x + x_offset,
262 c->geometry.y - c->titlebar.sw->geometry.height,
263 width,
264 c->titlebar.sw->geometry.height);
265 break;
266 case Bottom:
267 if(!c->titlebar.width)
268 width = c->geometry.width + 2 * c->border;
269 else
270 width = MIN(c->titlebar.width, c->geometry.width);
271 switch(c->titlebar.align)
273 default:
274 break;
275 case AlignRight:
276 x_offset = 2 * c->border + c->geometry.width - width;
277 break;
278 case AlignCenter:
279 x_offset = (c->geometry.width - width) / 2;
280 break;
282 simplewindow_move_resize(c->titlebar.sw,
283 c->geometry.x + x_offset,
284 c->geometry.y + c->geometry.height + 2 * c->border,
285 width,
286 c->titlebar.sw->geometry.height);
287 break;
288 case Left:
289 if(!c->titlebar.width)
290 width = c->geometry.height + 2 * c->border;
291 else
292 width = MIN(c->titlebar.width, c->geometry.height);
293 switch(c->titlebar.align)
295 default:
296 break;
297 case AlignRight:
298 y_offset = 2 * c->border + c->geometry.height - width;
299 break;
300 case AlignCenter:
301 y_offset = (c->geometry.height - width) / 2;
302 break;
304 simplewindow_move_resize(c->titlebar.sw,
305 c->geometry.x - c->titlebar.sw->geometry.width,
306 c->geometry.y + y_offset,
307 c->titlebar.sw->geometry.width,
308 width);
309 break;
310 case Right:
311 if(!c->titlebar.width)
312 width = c->geometry.height + 2 * c->border;
313 else
314 width = MIN(c->titlebar.width, c->geometry.height);
315 switch(c->titlebar.align)
317 default:
318 break;
319 case AlignRight:
320 y_offset = 2 * c->border + c->geometry.height - width;
321 break;
322 case AlignCenter:
323 y_offset = (c->geometry.height - width) / 2;
324 break;
326 simplewindow_move_resize(c->titlebar.sw,
327 c->geometry.x + c->geometry.width + 2 * c->border,
328 c->geometry.y + y_offset,
329 c->titlebar.sw->geometry.width,
330 width);
331 break;
334 titlebar_draw(c);
338 /** Update the titlebar geometry for a tiled client.
339 * \param c the client
340 * \param geometry the geometry the client will receive
342 void
343 titlebar_update_geometry(Client *c, area_t geometry)
345 int width, x_offset = 0 , y_offset = 0;
347 if(!c->titlebar.sw)
348 return;
350 switch(c->titlebar.position)
352 default:
353 return;
354 case Off:
355 return;
356 case Top:
357 if(!c->titlebar.width)
358 width = geometry.width + 2 * c->border;
359 else
360 width = MIN(c->titlebar.width, geometry.width);
361 switch(c->titlebar.align)
363 default:
364 break;
365 case AlignRight:
366 x_offset = 2 * c->border + geometry.width - width;
367 break;
368 case AlignCenter:
369 x_offset = (geometry.width - width) / 2;
370 break;
372 simplewindow_move_resize(c->titlebar.sw,
373 geometry.x + x_offset,
374 geometry.y,
375 width,
376 c->titlebar.sw->geometry.height);
377 break;
378 case Bottom:
379 if(!c->titlebar.width)
380 width = geometry.width + 2 * c->border;
381 else
382 width = MIN(c->titlebar.width, geometry.width);
383 switch(c->titlebar.align)
385 default:
386 break;
387 case AlignRight:
388 x_offset = 2 * c->border + geometry.width - width;
389 break;
390 case AlignCenter:
391 x_offset = (geometry.width - width) / 2;
392 break;
394 simplewindow_move_resize(c->titlebar.sw,
395 geometry.x + x_offset,
396 geometry.y + geometry.height
397 - c->titlebar.sw->geometry.height + 2 * c->border,
398 width,
399 c->titlebar.sw->geometry.height);
400 break;
401 case Left:
402 if(!c->titlebar.width)
403 width = geometry.height + 2 * c->border;
404 else
405 width = MIN(c->titlebar.width, geometry.height);
406 switch(c->titlebar.align)
408 default:
409 break;
410 case AlignRight:
411 y_offset = 2 * c->border + geometry.height - width;
412 break;
413 case AlignCenter:
414 y_offset = (geometry.height - width) / 2;
415 break;
417 simplewindow_move_resize(c->titlebar.sw,
418 geometry.x,
419 geometry.y + y_offset,
420 c->titlebar.sw->geometry.width,
421 width);
422 break;
423 case Right:
424 if(!c->titlebar.width)
425 width = geometry.height + 2 * c->border;
426 else
427 width = MIN(c->titlebar.width, geometry.height);
428 switch(c->titlebar.align)
430 default:
431 break;
432 case AlignRight:
433 y_offset = 2 * c->border + geometry.height - width;
434 break;
435 case AlignCenter:
436 y_offset = (geometry.height - width) / 2;
437 break;
439 simplewindow_move_resize(c->titlebar.sw,
440 geometry.x + geometry.width
441 - c->titlebar.sw->geometry.width + 2 * c->border,
442 geometry.y + y_offset,
443 c->titlebar.sw->geometry.width,
444 width);
445 break;
448 titlebar_draw(c);
451 void
452 titlebar_position_set(Titlebar *t, Position p)
454 if(!t->sw)
455 return;
457 if((t->position = p))
458 xcb_map_window(globalconf.connection, t->sw->window);
459 else
460 xcb_unmap_window(globalconf.connection, t->sw->window);
463 /** Toggle the visibility of the focused window's titlebar.
464 * \param screen screen number (unused)
465 * \param arg unused argument
466 * \ingroup ui_callback
468 void
469 uicb_client_toggletitlebar(int screen __attribute__ ((unused)), char *arg __attribute__ ((unused)))
471 Client *c = globalconf.focus->client;
473 if(!c || !c->titlebar.sw)
474 return;
476 if(!c->titlebar.position)
477 titlebar_position_set(&c->titlebar, c->titlebar.dposition);
478 else
479 titlebar_position_set(&c->titlebar, Off);
481 if(c->isfloating || layout_get_current(screen)->arrange == layout_floating)
482 titlebar_update_geometry_floating(c);
483 else
484 globalconf.screens[c->screen].need_arrange = true;
487 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80