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