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