]> Dogcows Code - chaz/openbox/blob - engines/openbox/obengine.c
4dda711e1cd03c8d50360aea32d72e7be31bde9e
[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 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 int ob_s_winfont_shadow;
38 int ob_s_winfont_shadow_offset;
39 int ob_s_winfont_shadow_tint;
40 ObFont *ob_s_winfont;
41 /* style settings - masks */
42 pixmap_mask *ob_s_max_set_mask;
43 pixmap_mask *ob_s_max_unset_mask;
44 pixmap_mask *ob_s_iconify_mask;
45 pixmap_mask *ob_s_desk_set_mask;
46 pixmap_mask *ob_s_desk_unset_mask;
47 pixmap_mask *ob_s_shade_set_mask;
48 pixmap_mask *ob_s_shade_unset_mask;
49 pixmap_mask *ob_s_close_mask;
50
51 /* global appearances */
52 Appearance *ob_a_focused_unpressed_max;
53 Appearance *ob_a_focused_pressed_max;
54 Appearance *ob_a_focused_pressed_set_max;
55 Appearance *ob_a_unfocused_unpressed_max;
56 Appearance *ob_a_unfocused_pressed_max;
57 Appearance *ob_a_unfocused_pressed_set_max;
58 Appearance *ob_a_focused_unpressed_close;
59 Appearance *ob_a_focused_pressed_close;
60 Appearance *ob_a_unfocused_unpressed_close;
61 Appearance *ob_a_unfocused_pressed_close;
62 Appearance *ob_a_focused_unpressed_desk;
63 Appearance *ob_a_focused_pressed_desk;
64 Appearance *ob_a_focused_pressed_set_desk;
65 Appearance *ob_a_unfocused_unpressed_desk;
66 Appearance *ob_a_unfocused_pressed_desk;
67 Appearance *ob_a_unfocused_pressed_set_desk;
68 Appearance *ob_a_focused_unpressed_shade;
69 Appearance *ob_a_focused_pressed_shade;
70 Appearance *ob_a_focused_pressed_set_shade;
71 Appearance *ob_a_unfocused_unpressed_shade;
72 Appearance *ob_a_unfocused_pressed_shade;
73 Appearance *ob_a_unfocused_pressed_set_shade;
74 Appearance *ob_a_focused_unpressed_iconify;
75 Appearance *ob_a_focused_pressed_iconify;
76 Appearance *ob_a_unfocused_unpressed_iconify;
77 Appearance *ob_a_unfocused_pressed_iconify;
78 Appearance *ob_a_focused_grip;
79 Appearance *ob_a_unfocused_grip;
80 Appearance *ob_a_focused_title;
81 Appearance *ob_a_unfocused_title;
82 Appearance *ob_a_focused_label;
83 Appearance *ob_a_unfocused_label;
84 Appearance *ob_a_icon; /* always parentrelative, so no focused/unfocused */
85 Appearance *ob_a_focused_handle;
86 Appearance *ob_a_unfocused_handle;
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
147 if (obtheme_load()) {
148 RECT_SET(ob_a_focused_pressed_desk->area, 0, 0,
149 BUTTON_SIZE, BUTTON_SIZE);
150 RECT_SET(ob_a_focused_pressed_set_desk->area, 0, 0,
151 BUTTON_SIZE, BUTTON_SIZE);
152 RECT_SET(ob_a_focused_unpressed_desk->area, 0, 0,
153 BUTTON_SIZE, BUTTON_SIZE);
154 RECT_SET(ob_a_unfocused_pressed_desk->area, 0, 0,
155 BUTTON_SIZE, BUTTON_SIZE);
156 RECT_SET(ob_a_unfocused_pressed_set_desk->area, 0, 0,
157 BUTTON_SIZE, BUTTON_SIZE);
158 RECT_SET(ob_a_unfocused_unpressed_desk->area, 0, 0,
159 BUTTON_SIZE, BUTTON_SIZE);
160 RECT_SET(ob_a_focused_pressed_shade->area, 0, 0,
161 BUTTON_SIZE, BUTTON_SIZE);
162 RECT_SET(ob_a_focused_pressed_set_shade->area, 0, 0,
163 BUTTON_SIZE, BUTTON_SIZE);
164 RECT_SET(ob_a_focused_unpressed_shade->area, 0, 0,
165 BUTTON_SIZE, BUTTON_SIZE);
166 RECT_SET(ob_a_unfocused_pressed_shade->area, 0, 0,
167 BUTTON_SIZE, BUTTON_SIZE);
168 RECT_SET(ob_a_unfocused_pressed_set_shade->area, 0, 0,
169 BUTTON_SIZE, BUTTON_SIZE);
170 RECT_SET(ob_a_unfocused_unpressed_shade->area, 0, 0,
171 BUTTON_SIZE, BUTTON_SIZE);
172 RECT_SET(ob_a_focused_pressed_iconify->area, 0, 0,
173 BUTTON_SIZE, BUTTON_SIZE);
174 RECT_SET(ob_a_focused_unpressed_iconify->area, 0, 0,
175 BUTTON_SIZE, BUTTON_SIZE);
176 RECT_SET(ob_a_unfocused_pressed_iconify->area, 0, 0,
177 BUTTON_SIZE, BUTTON_SIZE);
178 RECT_SET(ob_a_unfocused_unpressed_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_focused_pressed_max->area, 0, 0,
183 BUTTON_SIZE, BUTTON_SIZE);
184 RECT_SET(ob_a_focused_pressed_set_max->area, 0, 0,
185 BUTTON_SIZE, BUTTON_SIZE);
186 RECT_SET(ob_a_focused_unpressed_max->area, 0, 0,
187 BUTTON_SIZE, BUTTON_SIZE);
188 RECT_SET(ob_a_unfocused_pressed_max->area, 0, 0,
189 BUTTON_SIZE, BUTTON_SIZE);
190 RECT_SET(ob_a_unfocused_pressed_set_max->area, 0, 0,
191 BUTTON_SIZE, BUTTON_SIZE);
192 RECT_SET(ob_a_unfocused_unpressed_max->area, 0, 0,
193 BUTTON_SIZE, BUTTON_SIZE);
194 RECT_SET(ob_a_focused_pressed_close->area, 0, 0,
195 BUTTON_SIZE, BUTTON_SIZE);
196 RECT_SET(ob_a_focused_unpressed_close->area, 0, 0,
197 BUTTON_SIZE, BUTTON_SIZE);
198 RECT_SET(ob_a_unfocused_pressed_close->area, 0, 0,
199 BUTTON_SIZE, BUTTON_SIZE);
200 RECT_SET(ob_a_unfocused_unpressed_close->area, 0, 0,
201 BUTTON_SIZE, BUTTON_SIZE);
202
203 RECT_SET(ob_a_focused_grip->area, 0, 0,
204 GRIP_WIDTH, ob_s_handle_height);
205 RECT_SET(ob_a_unfocused_grip->area, 0, 0,
206 GRIP_WIDTH, ob_s_handle_height);
207 return TRUE;
208 } else
209 return FALSE;
210 }
211
212 void shutdown()
213 {
214 if (ob_s_b_color != NULL) color_free(ob_s_b_color);
215 if (ob_s_cb_unfocused_color != NULL) color_free(ob_s_cb_unfocused_color);
216 if (ob_s_cb_focused_color != NULL) color_free(ob_s_cb_focused_color);
217 if (ob_s_title_unfocused_color != NULL) color_free(ob_s_title_unfocused_color);
218 if (ob_s_title_focused_color != NULL) color_free(ob_s_title_focused_color);
219 if (ob_s_titlebut_unfocused_color != NULL)
220 color_free(ob_s_titlebut_unfocused_color);
221 if (ob_s_titlebut_focused_color != NULL)
222 color_free(ob_s_titlebut_focused_color);
223
224 if (ob_s_max_set_mask != NULL)
225 pixmap_mask_free(ob_s_max_set_mask);
226 if (ob_s_max_unset_mask != NULL)
227 pixmap_mask_free(ob_s_max_unset_mask);
228 if (ob_s_desk_set_mask != NULL)
229 pixmap_mask_free(ob_s_desk_set_mask);
230 if (ob_s_desk_unset_mask != NULL)
231 pixmap_mask_free(ob_s_desk_unset_mask);
232 if (ob_s_shade_set_mask != NULL)
233 pixmap_mask_free(ob_s_shade_set_mask);
234 if (ob_s_shade_unset_mask != NULL)
235 pixmap_mask_free(ob_s_shade_unset_mask);
236 if (ob_s_iconify_mask != NULL)
237 pixmap_mask_free(ob_s_iconify_mask);
238 if (ob_s_close_mask != NULL)
239 pixmap_mask_free(ob_s_close_mask);
240
241 if (ob_s_winfont != NULL) font_close(ob_s_winfont);
242
243 appearance_free(ob_a_focused_unpressed_max);
244 appearance_free(ob_a_focused_pressed_max);
245 appearance_free(ob_a_focused_pressed_set_max);
246 appearance_free(ob_a_unfocused_unpressed_max);
247 appearance_free(ob_a_unfocused_pressed_max);
248 appearance_free(ob_a_unfocused_pressed_set_max);
249 if (ob_a_focused_unpressed_close != NULL)
250 appearance_free(ob_a_focused_unpressed_close);
251 if (ob_a_focused_pressed_close != NULL)
252 appearance_free(ob_a_focused_pressed_close);
253 if (ob_a_unfocused_unpressed_close != NULL)
254 appearance_free(ob_a_unfocused_unpressed_close);
255 if (ob_a_unfocused_pressed_close != NULL)
256 appearance_free(ob_a_unfocused_pressed_close);
257 if (ob_a_focused_unpressed_desk != NULL)
258 appearance_free(ob_a_focused_unpressed_desk);
259 if (ob_a_focused_pressed_desk != NULL)
260 appearance_free(ob_a_focused_pressed_desk);
261 if (ob_a_unfocused_unpressed_desk != NULL)
262 appearance_free(ob_a_unfocused_unpressed_desk);
263 if (ob_a_unfocused_pressed_desk != NULL)
264 appearance_free(ob_a_unfocused_pressed_desk);
265 if (ob_a_focused_unpressed_shade != NULL)
266 appearance_free(ob_a_focused_unpressed_shade);
267 if (ob_a_focused_pressed_shade != NULL)
268 appearance_free(ob_a_focused_pressed_shade);
269 if (ob_a_unfocused_unpressed_shade != NULL)
270 appearance_free(ob_a_unfocused_unpressed_shade);
271 if (ob_a_unfocused_pressed_shade != NULL)
272 appearance_free(ob_a_unfocused_pressed_shade);
273 if (ob_a_focused_unpressed_iconify != NULL)
274 appearance_free(ob_a_focused_unpressed_iconify);
275 if (ob_a_focused_pressed_iconify != NULL)
276 appearance_free(ob_a_focused_pressed_iconify);
277 if (ob_a_unfocused_unpressed_iconify != NULL)
278 appearance_free(ob_a_unfocused_unpressed_iconify);
279 if (ob_a_unfocused_pressed_iconify != NULL)
280 appearance_free(ob_a_unfocused_pressed_iconify);
281 appearance_free(ob_a_focused_grip);
282 appearance_free(ob_a_unfocused_grip);
283 appearance_free(ob_a_focused_title);
284 appearance_free(ob_a_unfocused_title);
285 appearance_free(ob_a_focused_label);
286 appearance_free(ob_a_unfocused_label);
287 appearance_free(ob_a_icon);
288 appearance_free(ob_a_focused_handle);
289 appearance_free(ob_a_unfocused_handle);
290 }
291
292 static Window createWindow(Window parent, unsigned long mask,
293 XSetWindowAttributes *attrib)
294 {
295 return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
296 render_depth, InputOutput, render_visual,
297 mask, attrib);
298
299 }
300
301 Frame *frame_new()
302 {
303 XSetWindowAttributes attrib;
304 unsigned long mask;
305 ObFrame *self;
306
307 self = g_new(ObFrame, 1);
308
309 self->frame.visible = FALSE;
310
311 /* create all of the decor windows */
312 mask = CWOverrideRedirect | CWEventMask;
313 attrib.event_mask = FRAME_EVENTMASK;
314 attrib.override_redirect = TRUE;
315 self->frame.window = createWindow(ob_root, mask, &attrib);
316
317 mask = 0;
318 self->frame.plate = createWindow(self->frame.window, mask, &attrib);
319
320 mask = CWEventMask;
321 attrib.event_mask = ELEMENT_EVENTMASK;
322 self->title = createWindow(self->frame.window, mask, &attrib);
323 self->label = createWindow(self->title, mask, &attrib);
324 self->max = createWindow(self->title, mask, &attrib);
325 self->close = createWindow(self->title, mask, &attrib);
326 self->desk = createWindow(self->title, mask, &attrib);
327 self->shade = createWindow(self->title, mask, &attrib);
328 self->icon = createWindow(self->title, mask, &attrib);
329 self->iconify = createWindow(self->title, mask, &attrib);
330 self->handle = createWindow(self->frame.window, mask, &attrib);
331 mask |= CWCursor;
332 attrib.cursor = ob_cursors.ll_angle;
333 self->lgrip = createWindow(self->handle, mask, &attrib);
334 attrib.cursor = ob_cursors.lr_angle;
335 self->rgrip = createWindow(self->handle, mask, &attrib);
336
337 /* the other stuff is shown based on decor settings */
338 XMapWindow(ob_display, self->frame.plate);
339 XMapWindow(ob_display, self->lgrip);
340 XMapWindow(ob_display, self->rgrip);
341 XMapWindow(ob_display, self->label);
342
343 /* set colors/appearance/sizes for stuff that doesn't change */
344 XSetWindowBorder(ob_display, self->frame.window, ob_s_b_color->pixel);
345 XSetWindowBorder(ob_display, self->label, ob_s_b_color->pixel);
346 XSetWindowBorder(ob_display, self->rgrip, ob_s_b_color->pixel);
347 XSetWindowBorder(ob_display, self->lgrip, ob_s_b_color->pixel);
348
349 XResizeWindow(ob_display, self->max, BUTTON_SIZE, BUTTON_SIZE);
350 XResizeWindow(ob_display, self->iconify, BUTTON_SIZE, BUTTON_SIZE);
351 XResizeWindow(ob_display, self->icon, BUTTON_SIZE, BUTTON_SIZE);
352 XResizeWindow(ob_display, self->close, BUTTON_SIZE, BUTTON_SIZE);
353 XResizeWindow(ob_display, self->desk, BUTTON_SIZE, BUTTON_SIZE);
354 XResizeWindow(ob_display, self->shade, BUTTON_SIZE, BUTTON_SIZE);
355 XResizeWindow(ob_display, self->lgrip, GRIP_WIDTH, ob_s_handle_height);
356 XResizeWindow(ob_display, self->rgrip, GRIP_WIDTH, ob_s_handle_height);
357
358 /* set up the dynamic appearances */
359 self->a_unfocused_title = appearance_copy(ob_a_unfocused_title);
360 self->a_focused_title = appearance_copy(ob_a_focused_title);
361 self->a_unfocused_label = appearance_copy(ob_a_unfocused_label);
362 self->a_focused_label = appearance_copy(ob_a_focused_label);
363 self->a_unfocused_handle = appearance_copy(ob_a_unfocused_handle);
364 self->a_focused_handle = appearance_copy(ob_a_focused_handle);
365 self->a_icon = appearance_copy(ob_a_icon);
366
367 self->max_press = self->close_press = self->desk_press =
368 self->iconify_press = self->shade_press = FALSE;
369
370 dispatch_register(Event_X_ButtonPress | Event_X_ButtonRelease,
371 (EventHandler)mouse_event, self);
372
373 return (Frame*)self;
374 }
375
376 static void frame_free(ObFrame *self)
377 {
378 appearance_free(self->a_unfocused_title);
379 appearance_free(self->a_focused_title);
380 appearance_free(self->a_unfocused_label);
381 appearance_free(self->a_focused_label);
382 appearance_free(self->a_unfocused_handle);
383 appearance_free(self->a_focused_handle);
384 appearance_free(self->a_icon);
385
386 XDestroyWindow(ob_display, self->frame.window);
387
388 dispatch_register(0, (EventHandler)mouse_event, self);
389
390 g_free(self);
391 }
392
393 void frame_show(ObFrame *self)
394 {
395 if (!self->frame.visible) {
396 self->frame.visible = TRUE;
397 XMapWindow(ob_display, self->frame.window);
398 }
399 }
400
401 void frame_hide(ObFrame *self)
402 {
403 if (self->frame.visible) {
404 self->frame.visible = FALSE;
405 self->frame.client->ignore_unmaps++;
406 XUnmapWindow(ob_display, self->frame.window);
407 }
408 }
409
410 void frame_adjust_shape(ObFrame *self)
411 {
412 #ifdef SHAPE
413 int num;
414 XRectangle xrect[2];
415
416 if (!self->frame.client->shaped) {
417 /* clear the shape on the frame window */
418 XShapeCombineMask(ob_display, self->frame.window, ShapeBounding,
419 self->innersize.left,
420 self->innersize.top,
421 None, ShapeSet);
422 } else {
423 /* make the frame's shape match the clients */
424 XShapeCombineShape(ob_display, self->frame.window, ShapeBounding,
425 self->innersize.left,
426 self->innersize.top,
427 self->frame.client->window,
428 ShapeBounding, ShapeSet);
429
430 num = 0;
431 if (self->frame.client->decorations & Decor_Titlebar) {
432 xrect[0].x = -ob_s_bevel;
433 xrect[0].y = -ob_s_bevel;
434 xrect[0].width = self->width + self->bwidth * 2;
435 xrect[0].height = TITLE_HEIGHT +
436 self->bwidth * 2;
437 ++num;
438 }
439
440 if (self->frame.client->decorations & Decor_Handle) {
441 xrect[1].x = -ob_s_bevel;
442 xrect[1].y = HANDLE_Y(self);
443 xrect[1].width = self->width + self->bwidth * 2;
444 xrect[1].height = ob_s_handle_height +
445 self->bwidth * 2;
446 ++num;
447 }
448
449 XShapeCombineRectangles(ob_display, self->frame.window,
450 ShapeBounding, 0, 0, xrect, num,
451 ShapeUnion, Unsorted);
452 }
453 #endif
454 }
455
456 void frame_adjust_area(ObFrame *self, gboolean moved, gboolean resized)
457 {
458 if (resized) {
459 if (self->frame.client->decorations & Decor_Border) {
460 self->bwidth = ob_s_bwidth;
461 self->cbwidth = ob_s_cbwidth;
462 } else {
463 self->bwidth = self->cbwidth = 0;
464 }
465 STRUT_SET(self->innersize, self->cbwidth, self->cbwidth,
466 self->cbwidth, self->cbwidth);
467 self->width = self->frame.client->area.width + self->cbwidth * 2;
468 g_assert(self->width > 0);
469
470 /* set border widths */
471 XSetWindowBorderWidth(ob_display, self->frame.plate, self->cbwidth);
472 XSetWindowBorderWidth(ob_display, self->frame.window, self->bwidth);
473 XSetWindowBorderWidth(ob_display, self->title, self->bwidth);
474 XSetWindowBorderWidth(ob_display, self->handle, self->bwidth);
475 XSetWindowBorderWidth(ob_display, self->lgrip, self->bwidth);
476 XSetWindowBorderWidth(ob_display, self->rgrip, self->bwidth);
477
478 /* position/size and map/unmap all the windows */
479
480 /* they all default off, they're turned on in layout_title */
481 self->icon_x = -1;
482 self->desk_x = -1;
483 self->shade_x = -1;
484 self->iconify_x = -1;
485 self->label_x = -1;
486 self->max_x = -1;
487 self->close_x = -1;
488
489 if (self->frame.client->decorations & Decor_Titlebar) {
490 XMoveResizeWindow(ob_display, self->title,
491 -self->bwidth, -self->bwidth,
492 self->width, TITLE_HEIGHT);
493 self->innersize.top += TITLE_HEIGHT + self->bwidth;
494 XMapWindow(ob_display, self->title);
495
496 RECT_SET(self->a_focused_title->area, 0, 0,
497 self->width, TITLE_HEIGHT);
498 RECT_SET(self->a_unfocused_title->area, 0, 0,
499 self->width, TITLE_HEIGHT);
500
501 /* layout the title bar elements */
502 layout_title(self);
503 } else
504 XUnmapWindow(ob_display, self->title);
505
506 if (self->frame.client->decorations & Decor_Handle) {
507 XMoveResizeWindow(ob_display, self->handle,
508 -self->bwidth, HANDLE_Y(self),
509 self->width, ob_s_handle_height);
510 XMoveWindow(ob_display, self->lgrip,
511 -self->bwidth, -self->bwidth);
512 XMoveWindow(ob_display, self->rgrip,
513 -self->bwidth + self->width -
514 GRIP_WIDTH, -self->bwidth);
515 self->innersize.bottom += ob_s_handle_height +
516 self->bwidth;
517 XMapWindow(ob_display, self->handle);
518
519 if (ob_a_focused_grip->surface.data.planar.grad ==
520 Background_ParentRelative)
521 RECT_SET(self->a_focused_handle->area, 0, 0,
522 self->width, ob_s_handle_height);
523 else
524 RECT_SET(self->a_focused_handle->area,
525 GRIP_WIDTH + self->bwidth, 0,
526 self->width - (GRIP_WIDTH + self->bwidth) * 2,
527 ob_s_handle_height);
528 if (ob_a_unfocused_grip->surface.data.planar.grad ==
529 Background_ParentRelative)
530 RECT_SET(self->a_unfocused_handle->area, 0, 0,
531 self->width, ob_s_handle_height);
532 else
533 RECT_SET(self->a_unfocused_handle->area,
534 GRIP_WIDTH + self->bwidth, 0,
535 self->width - (GRIP_WIDTH + self->bwidth) * 2,
536 ob_s_handle_height);
537
538 } else
539 XUnmapWindow(ob_display, self->handle);
540 }
541
542 if (resized) {
543 /* move and resize the plate */
544 XMoveResizeWindow(ob_display, self->frame.plate,
545 self->innersize.left - self->cbwidth,
546 self->innersize.top - self->cbwidth,
547 self->frame.client->area.width,
548 self->frame.client->area.height);
549 /* when the client has StaticGravity, it likes to move around. */
550 XMoveWindow(ob_display, self->frame.client->window, 0, 0);
551 }
552
553 if (resized) {
554 STRUT_SET(self->frame.size,
555 self->innersize.left + self->bwidth,
556 self->innersize.top + self->bwidth,
557 self->innersize.right + self->bwidth,
558 self->innersize.bottom + self->bwidth);
559 }
560
561 /* shading can change without being moved or resized */
562 RECT_SET_SIZE(self->frame.area,
563 self->frame.client->area.width +
564 self->frame.size.left + self->frame.size.right,
565 (self->frame.client->shaded ? TITLE_HEIGHT + self->bwidth*2:
566 self->frame.client->area.height +
567 self->frame.size.top + self->frame.size.bottom));
568
569 if (moved) {
570 /* find the new coordinates, done after setting the frame.size, for
571 frame_client_gravity. */
572 self->frame.area.x = self->frame.client->area.x;
573 self->frame.area.y = self->frame.client->area.y;
574 frame_client_gravity((Frame*)self,
575 &self->frame.area.x, &self->frame.area.y);
576 }
577
578 /* move and resize the top level frame.
579 shading can change without being moved or resized */
580 XMoveResizeWindow(ob_display, self->frame.window,
581 self->frame.area.x, self->frame.area.y,
582 self->width,
583 self->frame.area.height - self->bwidth * 2);
584
585 if (resized) {
586 obrender_frame(self);
587
588 frame_adjust_shape(self);
589 }
590 }
591
592 void frame_adjust_state(ObFrame *self)
593 {
594 obrender_frame(self);
595 }
596
597 void frame_adjust_focus(ObFrame *self)
598 {
599 obrender_frame(self);
600 }
601
602 void frame_adjust_title(ObFrame *self)
603 {
604 obrender_frame(self);
605 }
606
607 void frame_adjust_icon(ObFrame *self)
608 {
609 obrender_frame(self);
610 }
611
612 void frame_grab_client(ObFrame *self, Client *client)
613 {
614 self->frame.client = client;
615
616 /* reparent the client to the frame */
617 XReparentWindow(ob_display, client->window, self->frame.plate, 0, 0);
618 /*
619 When reparenting the client window, it is usually not mapped yet, since
620 this occurs from a MapRequest. However, in the case where Openbox is
621 starting up, the window is already mapped, so we'll see unmap events for
622 it. There are 2 unmap events generated that we see, one with the 'event'
623 member set the root window, and one set to the client, but both get
624 handled and need to be ignored.
625 */
626 if (ob_state == State_Starting)
627 client->ignore_unmaps += 2;
628
629 /* select the event mask on the client's parent (to receive config/map
630 req's) the ButtonPress is to catch clicks on the client border */
631 XSelectInput(ob_display, self->frame.plate, PLATE_EVENTMASK);
632
633 /* map the client so it maps when the frame does */
634 XMapWindow(ob_display, client->window);
635
636 frame_adjust_area(self, TRUE, TRUE);
637
638 /* set all the windows for the frame in the client_map */
639 g_hash_table_insert(client_map, &self->frame.window, client);
640 g_hash_table_insert(client_map, &self->frame.plate, client);
641 g_hash_table_insert(client_map, &self->title, client);
642 g_hash_table_insert(client_map, &self->label, client);
643 g_hash_table_insert(client_map, &self->max, client);
644 g_hash_table_insert(client_map, &self->close, client);
645 g_hash_table_insert(client_map, &self->desk, client);
646 g_hash_table_insert(client_map, &self->shade, client);
647 g_hash_table_insert(client_map, &self->icon, client);
648 g_hash_table_insert(client_map, &self->iconify, client);
649 g_hash_table_insert(client_map, &self->handle, client);
650 g_hash_table_insert(client_map, &self->lgrip, client);
651 g_hash_table_insert(client_map, &self->rgrip, client);
652 }
653
654 void frame_release_client(ObFrame *self, Client *client)
655 {
656 XEvent ev;
657
658 g_assert(self->frame.client == client);
659
660 /* check if the app has already reparented its window away */
661 if (XCheckTypedWindowEvent(ob_display, client->window,
662 ReparentNotify, &ev)) {
663 XPutBackEvent(ob_display, &ev);
664 /* re-map the window since the unmanaging process unmaps it */
665 XMapWindow(ob_display, client->window);
666 } else {
667 /* according to the ICCCM - if the client doesn't reparent itself,
668 then we will reparent the window to root for them */
669 XReparentWindow(ob_display, client->window, ob_root,
670 client->area.x,
671 client->area.y);
672 }
673
674 /* remove all the windows for the frame from the client_map */
675 g_hash_table_remove(client_map, &self->frame.window);
676 g_hash_table_remove(client_map, &self->frame.plate);
677 g_hash_table_remove(client_map, &self->title);
678 g_hash_table_remove(client_map, &self->label);
679 g_hash_table_remove(client_map, &self->max);
680 g_hash_table_remove(client_map, &self->close);
681 g_hash_table_remove(client_map, &self->desk);
682 g_hash_table_remove(client_map, &self->shade);
683 g_hash_table_remove(client_map, &self->icon);
684 g_hash_table_remove(client_map, &self->iconify);
685 g_hash_table_remove(client_map, &self->handle);
686 g_hash_table_remove(client_map, &self->lgrip);
687 g_hash_table_remove(client_map, &self->rgrip);
688
689 frame_free(self);
690 }
691
692 static void layout_title(ObFrame *self)
693 {
694 char *lc;
695 int x;
696 gboolean n, d, i, l, m, c, s;
697 ConfigValue layout;
698
699 n = d = i = l = m = c = s = FALSE;
700
701 if (!config_get("titlebar.layout", Config_String, &layout))
702 g_assert_not_reached();
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 = layout.string; *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 = layout.string; *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.070035 seconds and 3 git commands to generate.