4 #include "../../kernel/openbox.h"
5 #include "../../kernel/extensions.h"
6 #include "../../kernel/dispatch.h"
7 #include "../../kernel/config.h"
10 # include <sys/stat.h>
11 # include <sys/types.h>
16 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
17 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
18 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
19 ButtonMotionMask | ExposureMask)
21 /* style settings - geometry */
23 int ob_s_handle_height
;
26 /* style settings - colors */
27 color_rgb
*ob_s_b_color
;
28 color_rgb
*ob_s_cb_focused_color
;
29 color_rgb
*ob_s_cb_unfocused_color
;
30 color_rgb
*ob_s_title_focused_color
;
31 color_rgb
*ob_s_title_unfocused_color
;
32 color_rgb
*ob_s_titlebut_focused_color
;
33 color_rgb
*ob_s_titlebut_unfocused_color
;
34 /* style settings - fonts */
35 int ob_s_winfont_height
;
36 int ob_s_winfont_shadow
;
37 int ob_s_winfont_shadow_offset
;
39 /* style settings - masks */
40 pixmap_mask
*ob_s_max_set_mask
;
41 pixmap_mask
*ob_s_max_unset_mask
;
42 pixmap_mask
*ob_s_iconify_mask
;
43 pixmap_mask
*ob_s_desk_set_mask
;
44 pixmap_mask
*ob_s_desk_unset_mask
;
45 pixmap_mask
*ob_s_close_mask
;
47 /* global appearances */
48 Appearance
*ob_a_focused_unpressed_max
;
49 Appearance
*ob_a_focused_pressed_max
;
50 Appearance
*ob_a_focused_pressed_set_max
;
51 Appearance
*ob_a_unfocused_unpressed_max
;
52 Appearance
*ob_a_unfocused_pressed_max
;
53 Appearance
*ob_a_unfocused_pressed_set_max
;
54 Appearance
*ob_a_focused_unpressed_close
;
55 Appearance
*ob_a_focused_pressed_close
;
56 Appearance
*ob_a_unfocused_unpressed_close
;
57 Appearance
*ob_a_unfocused_pressed_close
;
58 Appearance
*ob_a_focused_unpressed_desk
;
59 Appearance
*ob_a_focused_pressed_desk
;
60 Appearance
*ob_a_focused_pressed_set_desk
;
61 Appearance
*ob_a_unfocused_unpressed_desk
;
62 Appearance
*ob_a_unfocused_pressed_desk
;
63 Appearance
*ob_a_unfocused_pressed_set_desk
;
64 Appearance
*ob_a_focused_unpressed_iconify
;
65 Appearance
*ob_a_focused_pressed_iconify
;
66 Appearance
*ob_a_unfocused_unpressed_iconify
;
67 Appearance
*ob_a_unfocused_pressed_iconify
;
68 Appearance
*ob_a_focused_grip
;
69 Appearance
*ob_a_unfocused_grip
;
70 Appearance
*ob_a_focused_title
;
71 Appearance
*ob_a_unfocused_title
;
72 Appearance
*ob_a_focused_label
;
73 Appearance
*ob_a_unfocused_label
;
74 Appearance
*ob_a_icon
; /* always parentrelative, so no focused/unfocused */
75 Appearance
*ob_a_focused_handle
;
76 Appearance
*ob_a_unfocused_handle
;
78 static void layout_title(ObFrame
*self
);
79 static void mouse_event(const ObEvent
*e
, ObFrame
*self
);
85 g_quark_from_string("none");
86 g_quark_from_string("root");
87 g_quark_from_string("client");
88 g_quark_from_string("titlebar");
89 g_quark_from_string("handle");
90 g_quark_from_string("frame");
91 g_quark_from_string("blcorner");
92 g_quark_from_string("brcorner");
93 g_quark_from_string("maximize");
94 g_quark_from_string("alldesktops");
95 g_quark_from_string("iconify");
96 g_quark_from_string("icon");
97 g_quark_from_string("close");
99 /* create the ~/.openbox/themes/openbox dir */
100 path
= g_build_filename(g_get_home_dir(), ".openbox", "themes", "openbox",
102 mkdir(path
, (S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
|
103 S_IROTH
| S_IWOTH
| S_IXOTH
));
106 ob_s_b_color
= ob_s_cb_unfocused_color
= ob_s_cb_focused_color
=
107 ob_s_title_unfocused_color
= ob_s_title_focused_color
=
108 ob_s_titlebut_unfocused_color
= ob_s_titlebut_focused_color
= NULL
;
110 ob_s_max_set_mask
= ob_s_max_unset_mask
= NULL
;
111 ob_s_desk_set_mask
= ob_s_desk_unset_mask
= NULL
;
112 ob_s_iconify_mask
= ob_s_close_mask
= NULL
;
114 ob_a_focused_unpressed_max
= appearance_new(Surface_Planar
, 1);
115 ob_a_focused_pressed_max
= appearance_new(Surface_Planar
, 1);
116 ob_a_focused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
117 ob_a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 1);
118 ob_a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 1);
119 ob_a_unfocused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
120 ob_a_focused_unpressed_close
= NULL
;
121 ob_a_focused_pressed_close
= NULL
;
122 ob_a_unfocused_unpressed_close
= NULL
;
123 ob_a_unfocused_pressed_close
= NULL
;
124 ob_a_focused_unpressed_desk
= NULL
;
125 ob_a_focused_pressed_desk
= NULL
;
126 ob_a_focused_pressed_set_desk
= NULL
;
127 ob_a_unfocused_unpressed_desk
= NULL
;
128 ob_a_unfocused_pressed_desk
= NULL
;
129 ob_a_unfocused_pressed_set_desk
= 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);
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_iconify
->area
, 0, 0,
158 BUTTON_SIZE
, BUTTON_SIZE
);
159 RECT_SET(ob_a_focused_unpressed_iconify
->area
, 0, 0,
160 BUTTON_SIZE
, BUTTON_SIZE
);
161 RECT_SET(ob_a_unfocused_pressed_iconify
->area
, 0, 0,
162 BUTTON_SIZE
, BUTTON_SIZE
);
163 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
164 BUTTON_SIZE
, BUTTON_SIZE
);
165 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
166 BUTTON_SIZE
, BUTTON_SIZE
);
167 RECT_SET(ob_a_focused_pressed_max
->area
, 0, 0,
168 BUTTON_SIZE
, BUTTON_SIZE
);
169 RECT_SET(ob_a_focused_pressed_set_max
->area
, 0, 0,
170 BUTTON_SIZE
, BUTTON_SIZE
);
171 RECT_SET(ob_a_focused_unpressed_max
->area
, 0, 0,
172 BUTTON_SIZE
, BUTTON_SIZE
);
173 RECT_SET(ob_a_unfocused_pressed_max
->area
, 0, 0,
174 BUTTON_SIZE
, BUTTON_SIZE
);
175 RECT_SET(ob_a_unfocused_pressed_set_max
->area
, 0, 0,
176 BUTTON_SIZE
, BUTTON_SIZE
);
177 RECT_SET(ob_a_unfocused_unpressed_max
->area
, 0, 0,
178 BUTTON_SIZE
, BUTTON_SIZE
);
179 RECT_SET(ob_a_focused_pressed_close
->area
, 0, 0,
180 BUTTON_SIZE
, BUTTON_SIZE
);
181 RECT_SET(ob_a_focused_unpressed_close
->area
, 0, 0,
182 BUTTON_SIZE
, BUTTON_SIZE
);
183 RECT_SET(ob_a_unfocused_pressed_close
->area
, 0, 0,
184 BUTTON_SIZE
, BUTTON_SIZE
);
185 RECT_SET(ob_a_unfocused_unpressed_close
->area
, 0, 0,
186 BUTTON_SIZE
, BUTTON_SIZE
);
188 RECT_SET(ob_a_focused_grip
->area
, 0, 0,
189 GRIP_WIDTH
, ob_s_handle_height
);
190 RECT_SET(ob_a_unfocused_grip
->area
, 0, 0,
191 GRIP_WIDTH
, ob_s_handle_height
);
199 if (ob_s_b_color
!= NULL
) color_free(ob_s_b_color
);
200 if (ob_s_cb_unfocused_color
!= NULL
) color_free(ob_s_cb_unfocused_color
);
201 if (ob_s_cb_focused_color
!= NULL
) color_free(ob_s_cb_focused_color
);
202 if (ob_s_title_unfocused_color
!= NULL
) color_free(ob_s_title_unfocused_color
);
203 if (ob_s_title_focused_color
!= NULL
) color_free(ob_s_title_focused_color
);
204 if (ob_s_titlebut_unfocused_color
!= NULL
)
205 color_free(ob_s_titlebut_unfocused_color
);
206 if (ob_s_titlebut_focused_color
!= NULL
)
207 color_free(ob_s_titlebut_focused_color
);
209 if (ob_s_max_set_mask
!= NULL
)
210 pixmap_mask_free(ob_s_max_set_mask
);
211 if (ob_s_max_unset_mask
!= NULL
)
212 pixmap_mask_free(ob_s_max_unset_mask
);
213 if (ob_s_desk_set_mask
!= NULL
)
214 pixmap_mask_free(ob_s_desk_set_mask
);
215 if (ob_s_desk_unset_mask
!= NULL
)
216 pixmap_mask_free(ob_s_desk_unset_mask
);
217 if (ob_s_iconify_mask
!= NULL
)
218 pixmap_mask_free(ob_s_iconify_mask
);
219 if (ob_s_close_mask
!= NULL
)
220 pixmap_mask_free(ob_s_close_mask
);
222 if (ob_s_winfont
!= NULL
) font_close(ob_s_winfont
);
224 appearance_free(ob_a_focused_unpressed_max
);
225 appearance_free(ob_a_focused_pressed_max
);
226 appearance_free(ob_a_focused_pressed_set_max
);
227 appearance_free(ob_a_unfocused_unpressed_max
);
228 appearance_free(ob_a_unfocused_pressed_max
);
229 appearance_free(ob_a_unfocused_pressed_set_max
);
230 if (ob_a_focused_unpressed_close
!= NULL
)
231 appearance_free(ob_a_focused_unpressed_close
);
232 if (ob_a_focused_pressed_close
!= NULL
)
233 appearance_free(ob_a_focused_pressed_close
);
234 if (ob_a_unfocused_unpressed_close
!= NULL
)
235 appearance_free(ob_a_unfocused_unpressed_close
);
236 if (ob_a_unfocused_pressed_close
!= NULL
)
237 appearance_free(ob_a_unfocused_pressed_close
);
238 if (ob_a_focused_unpressed_desk
!= NULL
)
239 appearance_free(ob_a_focused_unpressed_desk
);
240 if (ob_a_focused_pressed_desk
!= NULL
)
241 appearance_free(ob_a_focused_pressed_desk
);
242 if (ob_a_unfocused_unpressed_desk
!= NULL
)
243 appearance_free(ob_a_unfocused_unpressed_desk
);
244 if (ob_a_unfocused_pressed_desk
!= NULL
)
245 appearance_free(ob_a_unfocused_pressed_desk
);
246 if (ob_a_focused_unpressed_iconify
!= NULL
)
247 appearance_free(ob_a_focused_unpressed_iconify
);
248 if (ob_a_focused_pressed_iconify
!= NULL
)
249 appearance_free(ob_a_focused_pressed_iconify
);
250 if (ob_a_unfocused_unpressed_iconify
!= NULL
)
251 appearance_free(ob_a_unfocused_unpressed_iconify
);
252 if (ob_a_unfocused_pressed_iconify
!= NULL
)
253 appearance_free(ob_a_unfocused_pressed_iconify
);
254 appearance_free(ob_a_focused_grip
);
255 appearance_free(ob_a_unfocused_grip
);
256 appearance_free(ob_a_focused_title
);
257 appearance_free(ob_a_unfocused_title
);
258 appearance_free(ob_a_focused_label
);
259 appearance_free(ob_a_unfocused_label
);
260 appearance_free(ob_a_icon
);
261 appearance_free(ob_a_focused_handle
);
262 appearance_free(ob_a_unfocused_handle
);
265 static Window
createWindow(Window parent
, unsigned long mask
,
266 XSetWindowAttributes
*attrib
)
268 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
269 render_depth
, InputOutput
, render_visual
,
276 XSetWindowAttributes attrib
;
280 self
= g_new(ObFrame
, 1);
282 self
->frame
.visible
= FALSE
;
284 /* create all of the decor windows */
285 mask
= CWOverrideRedirect
| CWEventMask
;
286 attrib
.event_mask
= FRAME_EVENTMASK
;
287 attrib
.override_redirect
= TRUE
;
288 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
291 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
294 attrib
.event_mask
= ELEMENT_EVENTMASK
;
295 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
296 self
->label
= createWindow(self
->title
, mask
, &attrib
);
297 self
->max
= createWindow(self
->title
, mask
, &attrib
);
298 self
->close
= createWindow(self
->title
, mask
, &attrib
);
299 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
300 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
301 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
302 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
304 attrib
.cursor
= ob_cursors
.ll_angle
;
305 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
306 attrib
.cursor
= ob_cursors
.lr_angle
;
307 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
309 /* the other stuff is shown based on decor settings */
310 XMapWindow(ob_display
, self
->frame
.plate
);
311 XMapWindow(ob_display
, self
->lgrip
);
312 XMapWindow(ob_display
, self
->rgrip
);
313 XMapWindow(ob_display
, self
->label
);
315 /* set colors/appearance/sizes for stuff that doesn't change */
316 XSetWindowBorder(ob_display
, self
->frame
.window
, ob_s_b_color
->pixel
);
317 XSetWindowBorder(ob_display
, self
->label
, ob_s_b_color
->pixel
);
318 XSetWindowBorder(ob_display
, self
->rgrip
, ob_s_b_color
->pixel
);
319 XSetWindowBorder(ob_display
, self
->lgrip
, ob_s_b_color
->pixel
);
321 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
322 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
323 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
324 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
325 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
326 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, ob_s_handle_height
);
327 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, ob_s_handle_height
);
329 /* set up the dynamic appearances */
330 self
->a_unfocused_title
= appearance_copy(ob_a_unfocused_title
);
331 self
->a_focused_title
= appearance_copy(ob_a_focused_title
);
332 self
->a_unfocused_label
= appearance_copy(ob_a_unfocused_label
);
333 self
->a_focused_label
= appearance_copy(ob_a_focused_label
);
334 self
->a_unfocused_handle
= appearance_copy(ob_a_unfocused_handle
);
335 self
->a_focused_handle
= appearance_copy(ob_a_focused_handle
);
336 self
->a_icon
= appearance_copy(ob_a_icon
);
338 self
->max_press
= self
->close_press
= self
->desk_press
=
339 self
->iconify_press
= FALSE
;
341 dispatch_register(Event_X_ButtonPress
| Event_X_ButtonRelease
,
342 (EventHandler
)mouse_event
, self
);
347 static void frame_free(ObFrame
*self
)
349 appearance_free(self
->a_unfocused_title
);
350 appearance_free(self
->a_focused_title
);
351 appearance_free(self
->a_unfocused_label
);
352 appearance_free(self
->a_focused_label
);
353 appearance_free(self
->a_unfocused_handle
);
354 appearance_free(self
->a_focused_handle
);
355 appearance_free(self
->a_icon
);
357 XDestroyWindow(ob_display
, self
->frame
.window
);
359 dispatch_register(0, (EventHandler
)mouse_event
, self
);
364 void frame_show(ObFrame
*self
)
366 if (!self
->frame
.visible
) {
367 self
->frame
.visible
= TRUE
;
368 XMapWindow(ob_display
, self
->frame
.window
);
372 void frame_hide(ObFrame
*self
)
374 if (self
->frame
.visible
) {
375 self
->frame
.visible
= FALSE
;
376 self
->frame
.client
->ignore_unmaps
++;
377 XUnmapWindow(ob_display
, self
->frame
.window
);
381 void frame_adjust_shape(ObFrame
*self
)
387 if (!self
->frame
.client
->shaped
) {
388 /* clear the shape on the frame window */
389 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
390 self
->innersize
.left
,
394 /* make the frame's shape match the clients */
395 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
396 self
->innersize
.left
,
398 self
->frame
.client
->window
,
399 ShapeBounding
, ShapeSet
);
402 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
403 xrect
[0].x
= -ob_s_bevel
;
404 xrect
[0].y
= -ob_s_bevel
;
405 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
406 xrect
[0].height
= TITLE_HEIGHT
+
411 if (self
->frame
.client
->decorations
& Decor_Handle
) {
412 xrect
[1].x
= -ob_s_bevel
;
413 xrect
[1].y
= HANDLE_Y(self
);
414 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
415 xrect
[1].height
= ob_s_handle_height
+
420 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
421 ShapeBounding
, 0, 0, xrect
, num
,
422 ShapeUnion
, Unsorted
);
427 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
430 if (self
->frame
.client
->decorations
& Decor_Border
) {
431 self
->bwidth
= ob_s_bwidth
;
432 self
->cbwidth
= ob_s_cbwidth
;
434 self
->bwidth
= self
->cbwidth
= 0;
436 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
437 self
->cbwidth
, self
->cbwidth
);
438 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
439 g_assert(self
->width
> 0);
441 /* set border widths */
442 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
443 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
444 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
445 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
446 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
447 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
449 /* position/size and map/unmap all the windows */
451 /* they all default off, they're turned on in layout_title */
459 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
460 XMoveResizeWindow(ob_display
, self
->title
,
461 -self
->bwidth
, -self
->bwidth
,
462 self
->width
, TITLE_HEIGHT
);
463 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
464 XMapWindow(ob_display
, self
->title
);
466 RECT_SET(self
->a_focused_title
->area
, 0, 0,
467 self
->width
, TITLE_HEIGHT
);
468 RECT_SET(self
->a_unfocused_title
->area
, 0, 0,
469 self
->width
, TITLE_HEIGHT
);
471 /* layout the title bar elements */
474 XUnmapWindow(ob_display
, self
->title
);
475 /* make all the titlebar stuff not render */
476 self
->frame
.client
->decorations
&= ~(Decor_Icon
| Decor_Iconify
|
477 Decor_Maximize
| Decor_Close
|
481 if (self
->frame
.client
->decorations
& Decor_Handle
) {
482 XMoveResizeWindow(ob_display
, self
->handle
,
483 -self
->bwidth
, HANDLE_Y(self
),
484 self
->width
, ob_s_handle_height
);
485 XMoveWindow(ob_display
, self
->lgrip
,
486 -self
->bwidth
, -self
->bwidth
);
487 XMoveWindow(ob_display
, self
->rgrip
,
488 -self
->bwidth
+ self
->width
-
489 GRIP_WIDTH
, -self
->bwidth
);
490 self
->innersize
.bottom
+= ob_s_handle_height
+
492 XMapWindow(ob_display
, self
->handle
);
494 if (self
->a_focused_handle
->surface
.data
.planar
.grad
==
495 Background_ParentRelative
)
496 RECT_SET(self
->a_focused_handle
->area
, 0, 0,
497 self
->width
, ob_s_handle_height
);
499 RECT_SET(self
->a_focused_handle
->area
,
500 GRIP_WIDTH
+ self
->bwidth
, 0,
501 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
503 if (self
->a_unfocused_handle
->surface
.data
.planar
.grad
==
504 Background_ParentRelative
)
505 RECT_SET(self
->a_unfocused_handle
->area
, 0, 0,
506 self
->width
, ob_s_handle_height
);
508 RECT_SET(self
->a_unfocused_handle
->area
,
509 GRIP_WIDTH
+ self
->bwidth
, 0,
510 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
514 XUnmapWindow(ob_display
, self
->handle
);
518 /* move and resize the plate */
519 XMoveResizeWindow(ob_display
, self
->frame
.plate
,
520 self
->innersize
.left
- self
->cbwidth
,
521 self
->innersize
.top
- self
->cbwidth
,
522 self
->frame
.client
->area
.width
,
523 self
->frame
.client
->area
.height
);
524 /* when the client has StaticGravity, it likes to move around. */
525 XMoveWindow(ob_display
, self
->frame
.client
->window
, 0, 0);
529 STRUT_SET(self
->frame
.size
,
530 self
->innersize
.left
+ self
->bwidth
,
531 self
->innersize
.top
+ self
->bwidth
,
532 self
->innersize
.right
+ self
->bwidth
,
533 self
->innersize
.bottom
+ self
->bwidth
);
536 /* shading can change without being moved or resized */
537 RECT_SET_SIZE(self
->frame
.area
,
538 self
->frame
.client
->area
.width
+
539 self
->frame
.size
.left
+ self
->frame
.size
.right
,
540 (self
->frame
.client
->shaded
? TITLE_HEIGHT
+ self
->bwidth
*2:
541 self
->frame
.client
->area
.height
+
542 self
->frame
.size
.top
+ self
->frame
.size
.bottom
));
545 /* find the new coordinates, done after setting the frame.size, for
546 frame_client_gravity. */
547 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
548 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
549 frame_client_gravity((Frame
*)self
,
550 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
553 /* move and resize the top level frame.
554 shading can change without being moved or resized */
555 XMoveResizeWindow(ob_display
, self
->frame
.window
,
556 self
->frame
.area
.x
, self
->frame
.area
.y
,
558 self
->frame
.area
.height
- self
->bwidth
* 2);
561 obrender_frame(self
);
563 frame_adjust_shape(self
);
567 void frame_adjust_state(ObFrame
*self
)
569 obrender_frame(self
);
572 void frame_adjust_focus(ObFrame
*self
)
574 obrender_frame(self
);
577 void frame_adjust_title(ObFrame
*self
)
579 obrender_frame(self
);
582 void frame_adjust_icon(ObFrame
*self
)
584 obrender_frame(self
);
587 void frame_grab_client(ObFrame
*self
, Client
*client
)
589 self
->frame
.client
= client
;
591 /* reparent the client to the frame */
592 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
594 When reparenting the client window, it is usually not mapped yet, since
595 this occurs from a MapRequest. However, in the case where Openbox is
596 starting up, the window is already mapped, so we'll see unmap events for
597 it. There are 2 unmap events generated that we see, one with the 'event'
598 member set the root window, and one set to the client, but both get
599 handled and need to be ignored.
601 if (ob_state
== State_Starting
)
602 client
->ignore_unmaps
+= 2;
604 /* select the event mask on the client's parent (to receive config/map
605 req's) the ButtonPress is to catch clicks on the client border */
606 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
608 /* map the client so it maps when the frame does */
609 XMapWindow(ob_display
, client
->window
);
611 frame_adjust_area(self
, TRUE
, TRUE
);
613 /* set all the windows for the frame in the client_map */
614 g_hash_table_insert(client_map
, &self
->frame
.window
, client
);
615 g_hash_table_insert(client_map
, &self
->frame
.plate
, client
);
616 g_hash_table_insert(client_map
, &self
->title
, client
);
617 g_hash_table_insert(client_map
, &self
->label
, client
);
618 g_hash_table_insert(client_map
, &self
->max
, client
);
619 g_hash_table_insert(client_map
, &self
->close
, client
);
620 g_hash_table_insert(client_map
, &self
->desk
, client
);
621 g_hash_table_insert(client_map
, &self
->icon
, client
);
622 g_hash_table_insert(client_map
, &self
->iconify
, client
);
623 g_hash_table_insert(client_map
, &self
->handle
, client
);
624 g_hash_table_insert(client_map
, &self
->lgrip
, client
);
625 g_hash_table_insert(client_map
, &self
->rgrip
, client
);
628 void frame_release_client(ObFrame
*self
, Client
*client
)
632 g_assert(self
->frame
.client
== client
);
634 /* check if the app has already reparented its window away */
635 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
636 ReparentNotify
, &ev
)) {
637 XPutBackEvent(ob_display
, &ev
);
638 /* re-map the window since the unmanaging process unmaps it */
639 XMapWindow(ob_display
, client
->window
);
641 /* according to the ICCCM - if the client doesn't reparent itself,
642 then we will reparent the window to root for them */
643 XReparentWindow(ob_display
, client
->window
, ob_root
,
648 /* remove all the windows for the frame from the client_map */
649 g_hash_table_remove(client_map
, &self
->frame
.window
);
650 g_hash_table_remove(client_map
, &self
->frame
.plate
);
651 g_hash_table_remove(client_map
, &self
->title
);
652 g_hash_table_remove(client_map
, &self
->label
);
653 g_hash_table_remove(client_map
, &self
->max
);
654 g_hash_table_remove(client_map
, &self
->close
);
655 g_hash_table_remove(client_map
, &self
->desk
);
656 g_hash_table_remove(client_map
, &self
->icon
);
657 g_hash_table_remove(client_map
, &self
->iconify
);
658 g_hash_table_remove(client_map
, &self
->handle
);
659 g_hash_table_remove(client_map
, &self
->lgrip
);
660 g_hash_table_remove(client_map
, &self
->rgrip
);
665 static void layout_title(ObFrame
*self
)
669 gboolean n
, d
, i
, l
, m
,c
;
672 n
= d
= i
= l
= m
= c
= FALSE
;
674 if (!config_get("titlebar.layout", Config_String
, &layout
)) {
675 layout
.string
= "NDLIMC";
676 config_set("titlebar.layout", Config_String
, layout
);
679 /* figure out whats being shown, and the width of the label */
680 self
->label_width
= self
->width
- (ob_s_bevel
+ 1) * 2;
681 for (lc
= layout
.string
; *lc
!= '\0'; ++lc
) {
684 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
685 if (n
) { *lc
= ' '; break; } /* rm duplicates */
687 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
690 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
691 if (d
) { *lc
= ' '; break; } /* rm duplicates */
693 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
696 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
697 if (i
) { *lc
= ' '; break; } /* rm duplicates */
699 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
702 if (l
) { *lc
= ' '; break; } /* rm duplicates */
706 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
707 if (m
) { *lc
= ' '; break; } /* rm duplicates */
709 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
712 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
713 if (c
) { *lc
= ' '; break; } /* rm duplicates */
715 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
719 if (self
->label_width
< 1) self
->label_width
= 1;
721 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
724 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
725 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
726 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
727 if (!l
) XUnmapWindow(ob_display
, self
->label
);
728 if (!m
) XUnmapWindow(ob_display
, self
->max
);
729 if (!c
) XUnmapWindow(ob_display
, self
->close
);
732 for (lc
= layout
.string
; *lc
!= '\0'; ++lc
) {
737 RECT_SET(self
->a_icon
->area
, 0, 0, BUTTON_SIZE
, BUTTON_SIZE
);
738 XMapWindow(ob_display
, self
->icon
);
739 XMoveWindow(ob_display
, self
->icon
, x
, ob_s_bevel
+ 1);
740 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
745 XMapWindow(ob_display
, self
->desk
);
746 XMoveWindow(ob_display
, self
->desk
, x
, ob_s_bevel
+ 1);
747 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
752 XMapWindow(ob_display
, self
->iconify
);
753 XMoveWindow(ob_display
, self
->iconify
, x
, ob_s_bevel
+ 1);
754 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
759 XMapWindow(ob_display
, self
->label
);
760 XMoveWindow(ob_display
, self
->label
, x
, ob_s_bevel
);
761 x
+= self
->label_width
+ ob_s_bevel
+ 1;
766 XMapWindow(ob_display
, self
->max
);
767 XMoveWindow(ob_display
, self
->max
, x
, ob_s_bevel
+ 1);
768 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
773 XMapWindow(ob_display
, self
->close
);
774 XMoveWindow(ob_display
, self
->close
, x
, ob_s_bevel
+ 1);
775 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
780 RECT_SET(self
->a_focused_label
->area
, 0, 0,
781 self
->label_width
, LABEL_HEIGHT
);
782 RECT_SET(self
->a_unfocused_label
->area
, 0, 0,
783 self
->label_width
, LABEL_HEIGHT
);
786 static void mouse_event(const ObEvent
*e
, ObFrame
*self
)
789 gboolean press
= e
->type
== Event_X_ButtonPress
;
791 win
= e
->data
.x
.e
->xbutton
.window
;
792 if (win
== self
->max
) {
793 self
->max_press
= press
;
794 obrender_frame(self
);
795 } else if (win
== self
->close
) {
796 self
->close_press
= press
;
797 obrender_frame(self
);
798 } else if (win
== self
->iconify
) {
799 self
->iconify_press
= press
;
800 obrender_frame(self
);
801 } else if (win
== self
->desk
) {
802 self
->desk_press
= press
;
803 obrender_frame(self
);
807 GQuark
get_context(Client
*client
, Window win
)
811 if (win
== ob_root
) return g_quark_try_string("root");
812 if (client
== NULL
) return g_quark_try_string("none");
813 if (win
== client
->window
) return g_quark_try_string("client");
815 self
= (ObFrame
*) client
->frame
;
816 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
817 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
818 if (win
== self
->title
) return g_quark_try_string("titlebar");
819 if (win
== self
->label
) return g_quark_try_string("titlebar");
820 if (win
== self
->handle
) return g_quark_try_string("handle");
821 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
822 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
823 if (win
== self
->max
) return g_quark_try_string("maximize");
824 if (win
== self
->iconify
) return g_quark_try_string("iconify");
825 if (win
== self
->close
) return g_quark_try_string("close");
826 if (win
== self
->icon
) return g_quark_try_string("icon");
827 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
829 return g_quark_try_string("none");