]> Dogcows Code - chaz/openbox/blob - engines/openbox/openbox.c
added justification to textureText
[chaz/openbox] / engines / openbox / openbox.c
1 #include "theme.h"
2 #include "../../kernel/openbox.h"
3 #include "../../kernel/screen.h"
4 #include "../../kernel/extensions.h"
5 #include "../../kernel/themerc.h"
6 #include "../../kernel/frame.h"
7 #include "../../render/render.h"
8 #include "../../render/color.h"
9 #include "../../render/font.h"
10 #include "../../render/mask.h"
11
12 #include <X11/Xlib.h>
13 #include <glib.h>
14
15 #define TITLE_HEIGHT (s_winfont_height + s_bevel * 2)
16 #define LABEL_HEIGHT (s_winfont_height)
17 #define HANDLE_Y(f) (f->innersize.top + f->frame.client->area.height + \
18 f->cbwidth)
19 #define BUTTON_SIZE (LABEL_HEIGHT - 2)
20 #define GRIP_WIDTH (BUTTON_SIZE * 2)
21 #define HANDLE_WIDTH(f) (f->width - (GRIP_WIDTH + f->bwidth) * 2)
22
23 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
24 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
25
26 /* style settings - geometry */
27 int s_bevel;
28 int s_handle_height;
29 int s_bwidth;
30 int s_cbwidth;
31 /* style settings - colors */
32 color_rgb *s_b_color;
33 color_rgb *s_cb_focused_color;
34 color_rgb *s_cb_unfocused_color;
35 color_rgb *s_title_focused_color;
36 color_rgb *s_title_unfocused_color;
37 color_rgb *s_titlebut_focused_color;
38 color_rgb *s_titlebut_unfocused_color;
39 /* style settings - fonts */
40 int s_winfont_height;
41 int s_winfont_shadow;
42 int s_winfont_shadow_offset;
43 ObFont *s_winfont;
44 /* style settings - masks */
45 pixmap_mask *s_max_mask;
46 pixmap_mask *s_icon_mask;
47 pixmap_mask *s_desk_mask;
48 pixmap_mask *s_close_mask;
49
50 /* global appearances */
51 Appearance *a_focused_unpressed_max;
52 Appearance *a_focused_pressed_max;
53 Appearance *a_unfocused_unpressed_max;
54 Appearance *a_unfocused_pressed_max;
55 Appearance *a_focused_unpressed_close;
56 Appearance *a_focused_pressed_close;
57 Appearance *a_unfocused_unpressed_close;
58 Appearance *a_unfocused_pressed_close;
59 Appearance *a_focused_unpressed_desk;
60 Appearance *a_focused_pressed_desk;
61 Appearance *a_unfocused_unpressed_desk;
62 Appearance *a_unfocused_pressed_desk;
63 Appearance *a_focused_unpressed_iconify;
64 Appearance *a_focused_pressed_iconify;
65 Appearance *a_unfocused_unpressed_iconify;
66 Appearance *a_unfocused_pressed_iconify;
67 Appearance *a_focused_grip;
68 Appearance *a_unfocused_grip;
69 Appearance *a_focused_title;
70 Appearance *a_unfocused_title;
71 Appearance *a_focused_label;
72 Appearance *a_unfocused_label;
73 Appearance *a_icon; /* always parentrelative, so no focused/unfocused */
74 Appearance *a_focused_handle;
75 Appearance *a_unfocused_handle;
76
77 typedef struct ObFrame {
78 Frame frame;
79
80 Window title;
81 Window label;
82 Window max;
83 Window close;
84 Window desk;
85 Window icon;
86 Window iconify;
87 Window handle;
88 Window lgrip;
89 Window rgrip;
90
91 Appearance *a_unfocused_title;
92 Appearance *a_focused_title;
93 Appearance *a_unfocused_label;
94 Appearance *a_focused_label;
95 Appearance *a_icon;
96 Appearance *a_unfocused_handle;
97 Appearance *a_focused_handle;
98
99 Strut innersize;
100
101 GSList *clients;
102
103 int width; /* title and handle */
104 int label_width;
105 int icon_x; /* x-position of the window icon button */
106 int label_x; /* x-position of the window title */
107 int iconify_x; /* x-position of the window iconify button */
108 int desk_x; /* x-position of the window all-desktops button */
109 int max_x; /* x-position of the window maximize button */
110 int close_x; /* x-position of the window close button */
111 int bwidth; /* border width */
112 int cbwidth; /* client border width */
113
114 gboolean max_press;
115 gboolean close_press;
116 gboolean desk_press;
117 gboolean iconify_press;
118 } ObFrame;
119
120 static void layout_title(ObFrame *self);
121 static void render(ObFrame *self);
122 static void render_label(ObFrame *self);
123 static void render_max(ObFrame *self);
124 static void render_icon(ObFrame *self);
125 static void render_iconify(ObFrame *self);
126 static void render_desk(ObFrame *self);
127 static void render_close(ObFrame *self);
128
129 gboolean startup()
130 {
131 g_quark_from_string("none");
132 g_quark_from_string("root");
133 g_quark_from_string("client");
134 g_quark_from_string("titlebar");
135 g_quark_from_string("handle");
136 g_quark_from_string("frame");
137 g_quark_from_string("blcorner");
138 g_quark_from_string("brcorner");
139 g_quark_from_string("maximize");
140 g_quark_from_string("alldesktops");
141 g_quark_from_string("iconify");
142 g_quark_from_string("icon");
143 g_quark_from_string("close");
144
145 s_b_color = s_cb_unfocused_color = s_cb_focused_color =
146 s_title_unfocused_color = s_title_focused_color =
147 s_titlebut_unfocused_color = s_titlebut_focused_color = NULL;
148 s_winfont = NULL;
149 s_max_mask = s_icon_mask = s_desk_mask = s_close_mask = NULL;
150
151 a_focused_unpressed_max = appearance_new(Surface_Planar, 1);
152 a_focused_pressed_max = appearance_new(Surface_Planar, 1);
153 a_unfocused_unpressed_max = appearance_new(Surface_Planar, 1);
154 a_unfocused_pressed_max = appearance_new(Surface_Planar, 1);
155 a_focused_unpressed_close = NULL;
156 a_focused_pressed_close = NULL;
157 a_unfocused_unpressed_close = NULL;
158 a_unfocused_pressed_close = NULL;
159 a_focused_unpressed_desk = NULL;
160 a_focused_pressed_desk = NULL;
161 a_unfocused_unpressed_desk = NULL;
162 a_unfocused_pressed_desk = NULL;
163 a_focused_unpressed_iconify = NULL;
164 a_focused_pressed_iconify = NULL;
165 a_unfocused_unpressed_iconify = NULL;
166 a_unfocused_pressed_iconify = NULL;
167 a_focused_grip = appearance_new(Surface_Planar, 0);
168 a_unfocused_grip = appearance_new(Surface_Planar, 0);
169 a_focused_title = appearance_new(Surface_Planar, 0);
170 a_unfocused_title = appearance_new(Surface_Planar, 0);
171 a_focused_label = appearance_new(Surface_Planar, 1);
172 a_unfocused_label = appearance_new(Surface_Planar, 1);
173 a_icon = appearance_new(Surface_Planar, 0);//1);
174 a_focused_handle = appearance_new(Surface_Planar, 0);
175 a_unfocused_handle = appearance_new(Surface_Planar, 0);
176
177 return load();
178 }
179
180 void shutdown()
181 {
182 if (s_b_color != NULL) color_free(s_b_color);
183 if (s_cb_unfocused_color != NULL) color_free(s_cb_unfocused_color);
184 if (s_cb_focused_color != NULL) color_free(s_cb_focused_color);
185 if (s_title_unfocused_color != NULL) color_free(s_title_unfocused_color);
186 if (s_title_focused_color != NULL) color_free(s_title_focused_color);
187 if (s_titlebut_unfocused_color != NULL)
188 color_free(s_titlebut_unfocused_color);
189 if (s_titlebut_focused_color != NULL)
190 color_free(s_titlebut_focused_color);
191
192 if (s_max_mask != NULL) pixmap_mask_free(s_max_mask);
193 if (s_desk_mask != NULL) pixmap_mask_free(s_desk_mask);
194 if (s_icon_mask != NULL) pixmap_mask_free(s_icon_mask);
195 if (s_close_mask != NULL) pixmap_mask_free(s_close_mask);
196
197 if (s_winfont != NULL) font_close(s_winfont);
198
199 appearance_free(a_focused_unpressed_max);
200 appearance_free(a_focused_pressed_max);
201 appearance_free(a_unfocused_unpressed_max);
202 appearance_free(a_unfocused_pressed_max);
203 if (a_focused_unpressed_close != NULL)
204 appearance_free(a_focused_unpressed_close);
205 if (a_focused_pressed_close != NULL)
206 appearance_free(a_focused_pressed_close);
207 if (a_unfocused_unpressed_close != NULL)
208 appearance_free(a_unfocused_unpressed_close);
209 if (a_unfocused_pressed_close != NULL)
210 appearance_free(a_unfocused_pressed_close);
211 if (a_focused_unpressed_desk != NULL)
212 appearance_free(a_focused_unpressed_desk);
213 if (a_focused_pressed_desk != NULL)
214 appearance_free(a_focused_pressed_desk);
215 if (a_unfocused_unpressed_desk != NULL)
216 appearance_free(a_unfocused_unpressed_desk);
217 if (a_unfocused_pressed_desk != NULL)
218 appearance_free(a_unfocused_pressed_desk);
219 if (a_focused_unpressed_iconify != NULL)
220 appearance_free(a_focused_unpressed_iconify);
221 if (a_focused_pressed_iconify != NULL)
222 appearance_free(a_focused_pressed_iconify);
223 if (a_unfocused_unpressed_iconify != NULL)
224 appearance_free(a_unfocused_unpressed_iconify);
225 if (a_unfocused_pressed_iconify != NULL)
226 appearance_free(a_unfocused_pressed_iconify);
227 appearance_free(a_focused_grip);
228 appearance_free(a_unfocused_grip);
229 appearance_free(a_focused_title);
230 appearance_free(a_unfocused_title);
231 appearance_free(a_focused_label);
232 appearance_free(a_unfocused_label);
233 appearance_free(a_icon);
234 appearance_free(a_focused_handle);
235 appearance_free(a_unfocused_handle);
236 }
237
238 static Window createWindow(Window parent, unsigned long mask,
239 XSetWindowAttributes *attrib)
240 {
241 /* XXX DONT USE THE DEFAULT SHIT */
242 return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
243 DefaultDepth(ob_display, ob_screen), InputOutput,
244 DefaultVisual(ob_display, ob_screen),
245 mask, attrib);
246
247 }
248
249 Frame *frame_new()
250 {
251 XSetWindowAttributes attrib;
252 unsigned long mask;
253 ObFrame *self;
254
255 self = g_new(ObFrame, 1);
256
257 self->frame.visible = FALSE;
258
259 /* create all of the decor windows */
260 mask = CWOverrideRedirect | CWEventMask;
261 attrib.event_mask = FRAME_EVENTMASK;
262 attrib.override_redirect = TRUE;
263 self->frame.window = createWindow(ob_root, mask, &attrib);
264
265 mask = 0;
266 self->frame.plate = createWindow(self->frame.window, mask, &attrib);
267
268 mask = CWEventMask;
269 attrib.event_mask = (ButtonPressMask | ButtonReleaseMask |
270 ButtonMotionMask | ExposureMask);
271 self->title = createWindow(self->frame.window, mask, &attrib);
272 self->label = createWindow(self->title, mask, &attrib);
273 self->max = createWindow(self->title, mask, &attrib);
274 self->close = createWindow(self->title, mask, &attrib);
275 self->desk = createWindow(self->title, mask, &attrib);
276 self->icon = createWindow(self->title, mask, &attrib);
277 self->iconify = createWindow(self->title, mask, &attrib);
278 self->handle = createWindow(self->frame.window, mask, &attrib);
279 mask |= CWCursor;
280 attrib.cursor = ob_cursors.ll_angle;
281 self->lgrip = createWindow(self->handle, mask, &attrib);
282 attrib.cursor = ob_cursors.lr_angle;
283 self->rgrip = createWindow(self->handle, mask, &attrib);
284
285 /* the other stuff is shown based on decor settings */
286 XMapWindow(ob_display, self->frame.plate);
287 XMapWindow(ob_display, self->lgrip);
288 XMapWindow(ob_display, self->rgrip);
289 XMapWindow(ob_display, self->label);
290
291 /* set colors/appearance/sizes for stuff that doesn't change */
292 XSetWindowBorder(ob_display, self->frame.window, s_b_color->pixel);
293 XSetWindowBorder(ob_display, self->label, s_b_color->pixel);
294 XSetWindowBorder(ob_display, self->rgrip, s_b_color->pixel);
295 XSetWindowBorder(ob_display, self->lgrip, s_b_color->pixel);
296
297 XResizeWindow(ob_display, self->max, BUTTON_SIZE, BUTTON_SIZE);
298 XResizeWindow(ob_display, self->iconify, BUTTON_SIZE, BUTTON_SIZE);
299 XResizeWindow(ob_display, self->icon, BUTTON_SIZE, BUTTON_SIZE);
300 XResizeWindow(ob_display, self->close, BUTTON_SIZE, BUTTON_SIZE);
301 XResizeWindow(ob_display, self->desk, BUTTON_SIZE, BUTTON_SIZE);
302 XResizeWindow(ob_display, self->lgrip, GRIP_WIDTH, s_handle_height);
303 XResizeWindow(ob_display, self->rgrip, GRIP_WIDTH, s_handle_height);
304
305 /* set up the dynamic appearances */
306 self->a_unfocused_title = appearance_copy(a_unfocused_title);
307 self->a_focused_title = appearance_copy(a_focused_title);
308 self->a_unfocused_label = appearance_copy(a_unfocused_label);
309 self->a_focused_label = appearance_copy(a_focused_label);
310 self->a_unfocused_handle = appearance_copy(a_unfocused_handle);
311 self->a_focused_handle = appearance_copy(a_focused_handle);
312 self->a_icon = appearance_copy(a_icon);
313
314 self->max_press = self->close_press = self->desk_press =
315 self->iconify_press = FALSE;
316
317 return (Frame*)self;
318 }
319
320 static void frame_free(ObFrame *self)
321 {
322 appearance_free(self->a_unfocused_title);
323 appearance_free(self->a_focused_title);
324 appearance_free(self->a_unfocused_label);
325 appearance_free(self->a_focused_label);
326 appearance_free(self->a_unfocused_handle);
327 appearance_free(self->a_focused_handle);
328 appearance_free(self->a_icon);
329
330 XDestroyWindow(ob_display, self->frame.window);
331
332 g_free(self);
333 }
334
335 void frame_show(ObFrame *self)
336 {
337 if (!self->frame.visible) {
338 self->frame.visible = TRUE;
339 XMapWindow(ob_display, self->frame.window);
340 }
341 }
342
343 void frame_hide(ObFrame *self)
344 {
345 if (self->frame.visible) {
346 self->frame.visible = FALSE;
347 self->frame.client->ignore_unmaps++;
348 XUnmapWindow(ob_display, self->frame.window);
349 }
350 }
351
352 void frame_adjust_shape(ObFrame *self)
353 {
354 #ifdef SHAPE
355 int num;
356 XRectangle xrect[2];
357
358 if (!self->frame.client->shaped) {
359 /* clear the shape on the frame window */
360 XShapeCombineMask(ob_display, self->frame.window, ShapeBounding,
361 self->innersize.left,
362 self->innersize.top,
363 None, ShapeSet);
364 } else {
365 /* make the frame's shape match the clients */
366 XShapeCombineShape(ob_display, self->frame.window, ShapeBounding,
367 self->innersize.left,
368 self->innersize.top,
369 self->frame.client->window,
370 ShapeBounding, ShapeSet);
371
372 num = 0;
373 if (self->frame.client->decorations & Decor_Titlebar) {
374 xrect[0].x = -s_bevel;
375 xrect[0].y = -s_bevel;
376 xrect[0].width = self->width + self->bwidth * 2;
377 xrect[0].height = TITLE_HEIGHT +
378 self->bwidth * 2;
379 ++num;
380 }
381
382 if (self->frame.client->decorations & Decor_Handle) {
383 xrect[1].x = -s_bevel;
384 xrect[1].y = HANDLE_Y(self);
385 xrect[1].width = self->width + self->bwidth * 2;
386 xrect[1].height = s_handle_height +
387 self->bwidth * 2;
388 ++num;
389 }
390
391 XShapeCombineRectangles(ob_display, self->frame.window,
392 ShapeBounding, 0, 0, xrect, num,
393 ShapeUnion, Unsorted);
394 }
395 #endif
396 }
397
398 void frame_adjust_size(ObFrame *self)
399 {
400 if (self->frame.client->decorations & Decor_Border) {
401 self->bwidth = s_bwidth;
402 self->cbwidth = s_cbwidth;
403 } else {
404 self->bwidth = self->cbwidth = 0;
405 }
406 STRUT_SET(self->innersize, self->cbwidth, self->cbwidth,
407 self->cbwidth, self->cbwidth);
408 self->width = self->frame.client->area.width + self->cbwidth * 2;
409 g_assert(self->width > 0);
410
411 /* set border widths */
412 XSetWindowBorderWidth(ob_display, self->frame.plate, self->cbwidth);
413 XSetWindowBorderWidth(ob_display, self->frame.window, self->bwidth);
414 XSetWindowBorderWidth(ob_display, self->title, self->bwidth);
415 XSetWindowBorderWidth(ob_display, self->handle, self->bwidth);
416 XSetWindowBorderWidth(ob_display, self->lgrip, self->bwidth);
417 XSetWindowBorderWidth(ob_display, self->rgrip, self->bwidth);
418
419 /* position/size and map/unmap all the windows */
420
421 if (self->frame.client->decorations & Decor_Titlebar) {
422 XMoveResizeWindow(ob_display, self->title,
423 -self->bwidth, -self->bwidth,
424 self->width, TITLE_HEIGHT);
425 self->innersize.top += TITLE_HEIGHT + self->bwidth;
426 XMapWindow(ob_display, self->title);
427
428 /* layout the title bar elements */
429 layout_title(self);
430 } else {
431 XUnmapWindow(ob_display, self->title);
432 /* make all the titlebar stuff not render */
433 self->frame.client->decorations &= ~(Decor_Icon | Decor_Iconify |
434 Decor_Maximize | Decor_Close |
435 Decor_AllDesktops);
436 }
437
438 if (self->frame.client->decorations & Decor_Handle) {
439 XMoveResizeWindow(ob_display, self->handle,
440 -self->bwidth, HANDLE_Y(self),
441 self->width, s_handle_height);
442 XMoveWindow(ob_display, self->lgrip,
443 -self->bwidth, -self->bwidth);
444 XMoveWindow(ob_display, self->rgrip,
445 -self->bwidth + self->width -
446 GRIP_WIDTH, -self->bwidth);
447 self->innersize.bottom += s_handle_height +
448 self->bwidth;
449 XMapWindow(ob_display, self->handle);
450 } else
451 XUnmapWindow(ob_display, self->handle);
452
453 XResizeWindow(ob_display, self->frame.window, self->width,
454 (self->frame.client->shaded ? TITLE_HEIGHT :
455 self->innersize.top + self->innersize.bottom +
456 self->frame.client->area.height));
457
458 /* do this in two steps because clients whose gravity is set to
459 'Static' don't end up getting moved at all with an XMoveResizeWindow */
460 XMoveWindow(ob_display, self->frame.plate,
461 self->innersize.left - self->cbwidth,
462 self->innersize.top - self->cbwidth);
463 XResizeWindow(ob_display, self->frame.plate,
464 self->frame.client->area.width,
465 self->frame.client->area.height);
466
467 STRUT_SET(self->frame.size,
468 self->innersize.left + self->bwidth,
469 self->innersize.top + self->bwidth,
470 self->innersize.right + self->bwidth,
471 self->innersize.bottom + self->bwidth);
472
473 RECT_SET_SIZE(self->frame.area,
474 self->frame.client->area.width +
475 self->frame.size.left + self->frame.size.right,
476 self->frame.client->area.height +
477 self->frame.size.top + self->frame.size.bottom);
478
479 render(self);
480
481 frame_adjust_shape(self);
482 }
483
484 void frame_adjust_position(ObFrame *self)
485 {
486 self->frame.area.x = self->frame.client->area.x;
487 self->frame.area.y = self->frame.client->area.y;
488 frame_client_gravity((Frame*)self,
489 &self->frame.area.x, &self->frame.area.y);
490 XMoveWindow(ob_display, self->frame.window,
491 self->frame.area.x, self->frame.area.y);
492 }
493
494 void frame_adjust_state(ObFrame *self)
495 {
496 render_max(self);
497 render_desk(self);
498 }
499
500 void frame_adjust_focus(ObFrame *self)
501 {
502 render(self);
503 }
504
505 void frame_adjust_title(ObFrame *self)
506 {
507 render_label(self);
508 }
509
510 void frame_adjust_icon(ObFrame *self)
511 {
512 render_icon(self);
513 }
514
515 void frame_grab_client(ObFrame *self, Client *client)
516 {
517 self->frame.client = client;
518
519 /* reparent the client to the frame */
520 XReparentWindow(ob_display, client->window, self->frame.plate, 0, 0);
521 /*
522 When reparenting the client window, it is usually not mapped yet, since
523 this occurs from a MapRequest. However, in the case where Openbox is
524 starting up, the window is already mapped, so we'll see unmap events for
525 it. There are 2 unmap events generated that we see, one with the 'event'
526 member set the root window, and one set to the client, but both get
527 handled and need to be ignored.
528 */
529 if (ob_state == State_Starting)
530 client->ignore_unmaps += 2;
531
532 /* select the event mask on the client's parent (to receive config/map
533 req's) the ButtonPress is to catch clicks on the client border */
534 XSelectInput(ob_display, self->frame.plate, PLATE_EVENTMASK);
535
536 /* map the client so it maps when the frame does */
537 XMapWindow(ob_display, client->window);
538
539 frame_adjust_size(self);
540 frame_adjust_position(self);
541
542 /* set all the windows for the frame in the client_map */
543 g_hash_table_insert(client_map, (gpointer)self->frame.window, client);
544 g_hash_table_insert(client_map, (gpointer)self->frame.plate, client);
545 g_hash_table_insert(client_map, (gpointer)self->title, client);
546 g_hash_table_insert(client_map, (gpointer)self->label, client);
547 g_hash_table_insert(client_map, (gpointer)self->max, client);
548 g_hash_table_insert(client_map, (gpointer)self->close, client);
549 g_hash_table_insert(client_map, (gpointer)self->desk, client);
550 g_hash_table_insert(client_map, (gpointer)self->icon, client);
551 g_hash_table_insert(client_map, (gpointer)self->iconify, client);
552 g_hash_table_insert(client_map, (gpointer)self->handle, client);
553 g_hash_table_insert(client_map, (gpointer)self->lgrip, client);
554 g_hash_table_insert(client_map, (gpointer)self->rgrip, client);
555 }
556
557 void frame_release_client(ObFrame *self, Client *client)
558 {
559 XEvent ev;
560
561 g_assert(self->frame.client == client);
562
563 /* check if the app has already reparented its window away */
564 if (XCheckTypedWindowEvent(ob_display, client->window,
565 ReparentNotify, &ev)) {
566 XPutBackEvent(ob_display, &ev);
567 /* re-map the window since the unmanaging process unmaps it */
568 XMapWindow(ob_display, client->window);
569 } else {
570 /* according to the ICCCM - if the client doesn't reparent itself,
571 then we will reparent the window to root for them */
572 XReparentWindow(ob_display, client->window, ob_root,
573 client->area.x,
574 client->area.y);
575 }
576
577 /* remove all the windows for the frame from the client_map */
578 g_hash_table_remove(client_map, (gpointer)self->frame.window);
579 g_hash_table_remove(client_map, (gpointer)self->frame.plate);
580 g_hash_table_remove(client_map, (gpointer)self->title);
581 g_hash_table_remove(client_map, (gpointer)self->label);
582 g_hash_table_remove(client_map, (gpointer)self->max);
583 g_hash_table_remove(client_map, (gpointer)self->close);
584 g_hash_table_remove(client_map, (gpointer)self->desk);
585 g_hash_table_remove(client_map, (gpointer)self->icon);
586 g_hash_table_remove(client_map, (gpointer)self->iconify);
587 g_hash_table_remove(client_map, (gpointer)self->handle);
588 g_hash_table_remove(client_map, (gpointer)self->lgrip);
589 g_hash_table_remove(client_map, (gpointer)self->rgrip);
590
591 frame_free(self);
592 }
593
594 static void layout_title(ObFrame *self)
595 {
596 const char *lc;
597 int x;
598 gboolean n, d, i, l, m ,c;
599 n = d = i = l = m = c = FALSE;
600
601 /* figure out whats being shown, and the width of the label */
602 self->label_width = self->width - s_bevel * 2;
603 for (lc = themerc_titlebar_layout; *lc != '\0'; ++lc) {
604 switch (*lc) {
605 case 'N':
606 if (!(self->frame.client->decorations & Decor_Icon)) break;
607 n = TRUE;
608 self->label_width -= BUTTON_SIZE + s_bevel;
609 break;
610 case 'D':
611 if (!(self->frame.client->decorations & Decor_AllDesktops)) break;
612 d = TRUE;
613 self->label_width -= BUTTON_SIZE + s_bevel;
614 break;
615 case 'I':
616 if (!(self->frame.client->decorations & Decor_Iconify)) break;
617 i = TRUE;
618 self->label_width -= BUTTON_SIZE + s_bevel;
619 break;
620 case 'L':
621 l = TRUE;
622 break;
623 case 'M':
624 if (!(self->frame.client->decorations & Decor_Maximize)) break;
625 m = TRUE;
626 self->label_width -= BUTTON_SIZE + s_bevel;
627 break;
628 case 'C':
629 if (!(self->frame.client->decorations & Decor_Close)) break;
630 c = TRUE;
631 self->label_width -= BUTTON_SIZE + s_bevel;
632 break;
633 }
634 }
635 if (self->label_width < 1) self->label_width = 1;
636
637 XResizeWindow(ob_display, self->label, self->label_width,
638 s_winfont_height);
639
640 if (!n) {
641 self->frame.client->decorations &= ~Decor_Icon;
642 XUnmapWindow(ob_display, self->icon);
643 self->icon_x = -1;
644 }
645 if (!d) {
646 self->frame.client->decorations &= ~Decor_AllDesktops;
647 XUnmapWindow(ob_display, self->desk);
648 self->desk_x = -1;
649 }
650 if (!i) {
651 self->frame.client->decorations &= ~Decor_Iconify;
652 XUnmapWindow(ob_display, self->iconify);
653 self->icon_x = -1;
654 }
655 if (!l) {
656 XUnmapWindow(ob_display, self->label);
657 self->label_x = -1;
658 }
659 if (!m) {
660 self->frame.client->decorations &= ~Decor_Maximize;
661 XUnmapWindow(ob_display, self->max);
662 self->max_x = -1;
663 }
664 if (!c) {
665 self->frame.client->decorations &= ~Decor_Close;
666 XUnmapWindow(ob_display, self->close);
667 self->close_x = -1;
668 }
669
670 x = s_bevel;
671 for (lc = themerc_titlebar_layout; *lc != '\0'; ++lc) {
672 switch (*lc) {
673 case 'N':
674 if (!n) break;
675 self->icon_x = x;
676 XMapWindow(ob_display, self->icon);
677 XMoveWindow(ob_display, self->icon, x, s_bevel + 1);
678 x += BUTTON_SIZE + s_bevel;
679 break;
680 case 'D':
681 if (!d) break;
682 self->desk_x = x;
683 XMapWindow(ob_display, self->desk);
684 XMoveWindow(ob_display, self->desk, x, s_bevel + 1);
685 x += BUTTON_SIZE + s_bevel;
686 break;
687 case 'I':
688 if (!i) break;
689 self->iconify_x = x;
690 XMapWindow(ob_display, self->iconify);
691 XMoveWindow(ob_display, self->iconify, x, s_bevel + 1);
692 x += BUTTON_SIZE + s_bevel;
693 break;
694 case 'L':
695 if (!l) break;
696 self->label_x = x;
697 XMapWindow(ob_display, self->label);
698 XMoveWindow(ob_display, self->label, x, s_bevel);
699 x += self->label_width + s_bevel;
700 break;
701 case 'M':
702 if (!m) break;
703 self->max_x = x;
704 XMapWindow(ob_display, self->max);
705 XMoveWindow(ob_display, self->max, x, s_bevel + 1);
706 x += BUTTON_SIZE + s_bevel;
707 break;
708 case 'C':
709 if (!c) break;
710 self->close_x = x;
711 XMapWindow(ob_display, self->close);
712 XMoveWindow(ob_display, self->close, x, s_bevel + 1);
713 x += BUTTON_SIZE + s_bevel;
714 break;
715 }
716 }
717 }
718
719 static void render(ObFrame *self)
720 {
721 if (self->frame.client->focused) {
722 XSetWindowBorder(ob_display, self->frame.plate,
723 s_cb_focused_color->pixel);
724 } else {
725 XSetWindowBorder(ob_display, self->frame.plate,
726 s_cb_unfocused_color->pixel);
727 }
728
729 if (self->frame.client->decorations & Decor_Titlebar) {
730 paint(self->title, (self->frame.client->focused ?
731 self->a_focused_title :
732 self->a_unfocused_title),
733 self->width, TITLE_HEIGHT);
734 render_label(self);
735 render_max(self);
736 render_icon(self);
737 render_iconify(self);
738 render_desk(self);
739 render_close(self);
740 }
741
742 if (self->frame.client->decorations & Decor_Handle) {
743 paint(self->handle, (self->frame.client->focused ?
744 self->a_focused_handle :
745 self->a_unfocused_handle),
746 HANDLE_WIDTH(self), s_handle_height);
747 paint(self->lgrip, (self->frame.client->focused ?
748 a_focused_grip :
749 a_unfocused_grip),
750 GRIP_WIDTH, s_handle_height);
751 paint(self->rgrip, (self->frame.client->focused ?
752 a_focused_grip :
753 a_unfocused_grip),
754 GRIP_WIDTH, s_handle_height);
755 }
756 }
757
758 static void render_label(ObFrame *self)
759 {
760 Appearance *a;
761
762 if (self->label_x < 0) return;
763
764 a = (self->frame.client->focused ?
765 self->a_focused_label : self->a_focused_label);
766
767 /* set the texture's text! */
768 a->texture[0].data.text.string = self->frame.client->title;
769
770 paint(self->label, a, self->label_width, LABEL_HEIGHT);
771 }
772
773 static void render_icon(ObFrame *self)
774 {
775 if (self->icon_x < 0) return;
776
777 /* XXX set the texture's icon picture! */
778 paint(self->icon, self->a_icon, BUTTON_SIZE, BUTTON_SIZE);
779 }
780
781 static void render_max(ObFrame *self)
782 {
783 gboolean press = self->max_press ||
784 self->frame.client->max_vert || self->frame.client->max_horz;
785
786 if (self->max_x < 0) return;
787
788 paint(self->max, (self->frame.client->focused ?
789 (press ?
790 a_focused_pressed_max :
791 a_focused_unpressed_max) :
792 (press ?
793 a_unfocused_pressed_max :
794 a_unfocused_unpressed_max)),
795 BUTTON_SIZE, BUTTON_SIZE);
796 }
797
798 static void render_iconify(ObFrame *self)
799 {
800 if (self->iconify_x < 0) return;
801
802 paint(self->iconify, (self->frame.client->focused ?
803 (self->iconify_press ?
804 a_focused_pressed_iconify :
805 a_focused_unpressed_iconify) :
806 (self->iconify_press ?
807 a_unfocused_pressed_iconify :
808 a_unfocused_unpressed_iconify)),
809 BUTTON_SIZE, BUTTON_SIZE);
810 }
811
812 static void render_desk(ObFrame *self)
813 {
814 gboolean press = self->desk_press ||
815 self->frame.client->desktop == DESKTOP_ALL;
816
817 if (self->desk_x < 0) return;
818
819 paint(self->desk, (self->frame.client->focused ?
820 (press ?
821 a_focused_pressed_desk :
822 a_focused_unpressed_desk) :
823 (press ?
824 a_unfocused_pressed_desk :
825 a_unfocused_unpressed_desk)),
826 BUTTON_SIZE, BUTTON_SIZE);
827 }
828
829 static void render_close(ObFrame *self)
830 {
831 if (self->close_x < 0) return;
832
833 paint(self->close, (self->frame.client->focused ?
834 (self->close_press ?
835 a_focused_pressed_close :
836 a_focused_unpressed_close) :
837 (self->close_press ?
838 a_unfocused_pressed_close :
839 a_unfocused_unpressed_close)),
840 BUTTON_SIZE, BUTTON_SIZE);
841 }
842
843 GQuark get_context(Client *client, Window win)
844 {
845 ObFrame *self;
846
847 if (win == ob_root) return g_quark_try_string("root");
848 if (client == NULL) return g_quark_try_string("none");
849 if (win == client->window) return g_quark_try_string("client");
850
851 self = (ObFrame*) client->frame;
852 if (win == self->frame.window) return g_quark_try_string("frame");
853 if (win == self->frame.plate) return g_quark_try_string("client");
854 if (win == self->title) return g_quark_try_string("titlebar");
855 if (win == self->label) return g_quark_try_string("titlebar");
856 if (win == self->handle) return g_quark_try_string("handle");
857 if (win == self->lgrip) return g_quark_try_string("blcorner");
858 if (win == self->rgrip) return g_quark_try_string("brcorner");
859 if (win == self->max) return g_quark_try_string("maximize");
860 if (win == self->iconify) return g_quark_try_string("iconify");
861 if (win == self->close) return g_quark_try_string("close");
862 if (win == self->icon) return g_quark_try_string("icon");
863 if (win == self->desk) return g_quark_try_string("alldesktops");
864
865 return g_quark_try_string("none");
866 }
This page took 0.072287 seconds and 4 git commands to generate.