]> Dogcows Code - chaz/openbox/blob - engines/openbox/openbox.c
use the unfocused label when not focused
[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
600 n = d = i = l = m = c = FALSE;
601
602 /* figure out whats being shown, and the width of the label */
603 self->label_width = self->width - (s_bevel + 1) * 2;
604 for (lc = themerc_titlebar_layout; *lc != '\0'; ++lc) {
605 switch (*lc) {
606 case 'N':
607 if (!(self->frame.client->decorations & Decor_Icon)) break;
608 n = TRUE;
609 self->label_width -= BUTTON_SIZE + s_bevel + 1;
610 break;
611 case 'D':
612 if (!(self->frame.client->decorations & Decor_AllDesktops)) break;
613 d = TRUE;
614 self->label_width -= BUTTON_SIZE + s_bevel + 1;
615 break;
616 case 'I':
617 if (!(self->frame.client->decorations & Decor_Iconify)) break;
618 i = TRUE;
619 self->label_width -= BUTTON_SIZE + s_bevel + 1;
620 break;
621 case 'L':
622 l = TRUE;
623 break;
624 case 'M':
625 if (!(self->frame.client->decorations & Decor_Maximize)) break;
626 m = TRUE;
627 self->label_width -= BUTTON_SIZE + s_bevel + 1;
628 break;
629 case 'C':
630 if (!(self->frame.client->decorations & Decor_Close)) break;
631 c = TRUE;
632 self->label_width -= BUTTON_SIZE + s_bevel + 1;
633 break;
634 }
635 }
636 if (self->label_width < 1) self->label_width = 1;
637
638 XResizeWindow(ob_display, self->label, self->label_width,
639 s_winfont_height);
640
641 if (!n) {
642 self->frame.client->decorations &= ~Decor_Icon;
643 XUnmapWindow(ob_display, self->icon);
644 self->icon_x = -1;
645 }
646 if (!d) {
647 self->frame.client->decorations &= ~Decor_AllDesktops;
648 XUnmapWindow(ob_display, self->desk);
649 self->desk_x = -1;
650 }
651 if (!i) {
652 self->frame.client->decorations &= ~Decor_Iconify;
653 XUnmapWindow(ob_display, self->iconify);
654 self->icon_x = -1;
655 }
656 if (!l) {
657 XUnmapWindow(ob_display, self->label);
658 self->label_x = -1;
659 }
660 if (!m) {
661 self->frame.client->decorations &= ~Decor_Maximize;
662 XUnmapWindow(ob_display, self->max);
663 self->max_x = -1;
664 }
665 if (!c) {
666 self->frame.client->decorations &= ~Decor_Close;
667 XUnmapWindow(ob_display, self->close);
668 self->close_x = -1;
669 }
670
671 x = s_bevel + 1;
672 for (lc = themerc_titlebar_layout; *lc != '\0'; ++lc) {
673 switch (*lc) {
674 case 'N':
675 if (!n) break;
676 self->icon_x = x;
677 XMapWindow(ob_display, self->icon);
678 XMoveWindow(ob_display, self->icon, x, s_bevel + 1);
679 x += BUTTON_SIZE + s_bevel + 1;
680 break;
681 case 'D':
682 if (!d) break;
683 self->desk_x = x;
684 XMapWindow(ob_display, self->desk);
685 XMoveWindow(ob_display, self->desk, x, s_bevel + 1);
686 x += BUTTON_SIZE + s_bevel + 1;
687 break;
688 case 'I':
689 if (!i) break;
690 self->iconify_x = x;
691 XMapWindow(ob_display, self->iconify);
692 XMoveWindow(ob_display, self->iconify, x, s_bevel + 1);
693 x += BUTTON_SIZE + s_bevel + 1;
694 break;
695 case 'L':
696 if (!l) break;
697 self->label_x = x;
698 XMapWindow(ob_display, self->label);
699 XMoveWindow(ob_display, self->label, x, s_bevel);
700 x += self->label_width + s_bevel + 1;
701 break;
702 case 'M':
703 if (!m) break;
704 self->max_x = x;
705 XMapWindow(ob_display, self->max);
706 XMoveWindow(ob_display, self->max, x, s_bevel + 1);
707 x += BUTTON_SIZE + s_bevel + 1;
708 break;
709 case 'C':
710 if (!c) break;
711 self->close_x = x;
712 XMapWindow(ob_display, self->close);
713 XMoveWindow(ob_display, self->close, x, s_bevel + 1);
714 x += BUTTON_SIZE + s_bevel + 1;
715 break;
716 }
717 }
718 }
719
720 static void render(ObFrame *self)
721 {
722 if (self->frame.client->focused) {
723 XSetWindowBorder(ob_display, self->frame.plate,
724 s_cb_focused_color->pixel);
725 } else {
726 XSetWindowBorder(ob_display, self->frame.plate,
727 s_cb_unfocused_color->pixel);
728 }
729
730 if (self->frame.client->decorations & Decor_Titlebar) {
731 paint(self->title, (self->frame.client->focused ?
732 self->a_focused_title :
733 self->a_unfocused_title),
734 0, 0, self->width, TITLE_HEIGHT);
735 render_label(self);
736 render_max(self);
737 render_icon(self);
738 render_iconify(self);
739 render_desk(self);
740 render_close(self);
741 }
742
743 if (self->frame.client->decorations & Decor_Handle) {
744 paint(self->handle, (self->frame.client->focused ?
745 self->a_focused_handle :
746 self->a_unfocused_handle),
747 GRIP_WIDTH + self->bwidth, 0,
748 HANDLE_WIDTH(self), s_handle_height);
749 paint(self->lgrip, (self->frame.client->focused ?
750 a_focused_grip :
751 a_unfocused_grip),
752 0, 0, GRIP_WIDTH, s_handle_height);
753 paint(self->rgrip, (self->frame.client->focused ?
754 a_focused_grip :
755 a_unfocused_grip),
756 0, 0, GRIP_WIDTH, s_handle_height);
757 }
758 }
759
760 static void render_label(ObFrame *self)
761 {
762 Appearance *a;
763
764 if (self->label_x < 0) return;
765
766 a = (self->frame.client->focused ?
767 self->a_focused_label : self->a_unfocused_label);
768
769 /* set the texture's text! */
770 a->texture[0].data.text.string = self->frame.client->title;
771
772 paint(self->label, a, 0, 0, self->label_width, LABEL_HEIGHT);
773 }
774
775 static void render_icon(ObFrame *self)
776 {
777 if (self->icon_x < 0) return;
778
779 /* XXX set the texture's icon picture! */
780 paint(self->icon, self->a_icon, 0, 0, BUTTON_SIZE, BUTTON_SIZE);
781 }
782
783 static void render_max(ObFrame *self)
784 {
785 gboolean press = self->max_press ||
786 self->frame.client->max_vert || self->frame.client->max_horz;
787
788 if (self->max_x < 0) return;
789
790 paint(self->max, (self->frame.client->focused ?
791 (press ?
792 a_focused_pressed_max :
793 a_focused_unpressed_max) :
794 (press ?
795 a_unfocused_pressed_max :
796 a_unfocused_unpressed_max)),
797 0, 0, BUTTON_SIZE, BUTTON_SIZE);
798 }
799
800 static void render_iconify(ObFrame *self)
801 {
802 if (self->iconify_x < 0) return;
803
804 paint(self->iconify, (self->frame.client->focused ?
805 (self->iconify_press ?
806 a_focused_pressed_iconify :
807 a_focused_unpressed_iconify) :
808 (self->iconify_press ?
809 a_unfocused_pressed_iconify :
810 a_unfocused_unpressed_iconify)),
811 0, 0, BUTTON_SIZE, BUTTON_SIZE);
812 }
813
814 static void render_desk(ObFrame *self)
815 {
816 gboolean press = self->desk_press ||
817 self->frame.client->desktop == DESKTOP_ALL;
818
819 if (self->desk_x < 0) return;
820
821 paint(self->desk, (self->frame.client->focused ?
822 (press ?
823 a_focused_pressed_desk :
824 a_focused_unpressed_desk) :
825 (press ?
826 a_unfocused_pressed_desk :
827 a_unfocused_unpressed_desk)),
828 0, 0, BUTTON_SIZE, BUTTON_SIZE);
829 }
830
831 static void render_close(ObFrame *self)
832 {
833 if (self->close_x < 0) return;
834
835 paint(self->close, (self->frame.client->focused ?
836 (self->close_press ?
837 a_focused_pressed_close :
838 a_focused_unpressed_close) :
839 (self->close_press ?
840 a_unfocused_pressed_close :
841 a_unfocused_unpressed_close)),
842 0, 0, BUTTON_SIZE, BUTTON_SIZE);
843 }
844
845 GQuark get_context(Client *client, Window win)
846 {
847 ObFrame *self;
848
849 if (win == ob_root) return g_quark_try_string("root");
850 if (client == NULL) return g_quark_try_string("none");
851 if (win == client->window) return g_quark_try_string("client");
852
853 self = (ObFrame*) client->frame;
854 if (win == self->frame.window) return g_quark_try_string("frame");
855 if (win == self->frame.plate) return g_quark_try_string("client");
856 if (win == self->title) return g_quark_try_string("titlebar");
857 if (win == self->label) return g_quark_try_string("titlebar");
858 if (win == self->handle) return g_quark_try_string("handle");
859 if (win == self->lgrip) return g_quark_try_string("blcorner");
860 if (win == self->rgrip) return g_quark_try_string("brcorner");
861 if (win == self->max) return g_quark_try_string("maximize");
862 if (win == self->iconify) return g_quark_try_string("iconify");
863 if (win == self->close) return g_quark_try_string("close");
864 if (win == self->icon) return g_quark_try_string("icon");
865 if (win == self->desk) return g_quark_try_string("alldesktops");
866
867 return g_quark_try_string("none");
868 }
869
870 void frame_mouse_enter(ObFrame *self, Window win)
871 {
872 }
873
874 void frame_mouse_leave(ObFrame *self, Window win)
875 {
876 }
877
878 void frame_mouse_press(ObFrame *self, Window win, int x, int y)
879 {
880 if (win == self->max) {
881 self->max_press = TRUE;
882 render_max(self);
883 }
884 else if (win == self->close) {
885 self->close_press = TRUE;
886 render_close(self);
887 }
888 else if (win == self->iconify) {
889 self->iconify_press = TRUE;
890 render_iconify(self);
891 }
892 else if (win == self->desk) {
893 self->desk_press = TRUE;
894 render_desk(self);
895 }
896 }
897
898 void frame_mouse_release(ObFrame *self, Window win, int x, int y)
899 {
900 if (win == self->max) {
901 self->max_press = FALSE;
902 render_max(self);
903 }
904 else if (win == self->close) {
905 self->close_press = FALSE;
906 render_close(self);
907 }
908 else if (win == self->iconify) {
909 self->iconify_press = FALSE;
910 render_iconify(self);
911 }
912 else if (win == self->desk) {
913 self->desk_press = FALSE;
914 render_desk(self);
915 }
916 }
This page took 0.075802 seconds and 5 git commands to generate.