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