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