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