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