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