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