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_shade_set_mask
;
46 pixmap_mask
*ob_s_shade_unset_mask
;
47 pixmap_mask
*ob_s_close_mask
;
49 /* global appearances */
50 Appearance
*ob_a_focused_unpressed_max
;
51 Appearance
*ob_a_focused_pressed_max
;
52 Appearance
*ob_a_focused_pressed_set_max
;
53 Appearance
*ob_a_unfocused_unpressed_max
;
54 Appearance
*ob_a_unfocused_pressed_max
;
55 Appearance
*ob_a_unfocused_pressed_set_max
;
56 Appearance
*ob_a_focused_unpressed_close
;
57 Appearance
*ob_a_focused_pressed_close
;
58 Appearance
*ob_a_unfocused_unpressed_close
;
59 Appearance
*ob_a_unfocused_pressed_close
;
60 Appearance
*ob_a_focused_unpressed_desk
;
61 Appearance
*ob_a_focused_pressed_desk
;
62 Appearance
*ob_a_focused_pressed_set_desk
;
63 Appearance
*ob_a_unfocused_unpressed_desk
;
64 Appearance
*ob_a_unfocused_pressed_desk
;
65 Appearance
*ob_a_unfocused_pressed_set_desk
;
66 Appearance
*ob_a_focused_unpressed_shade
;
67 Appearance
*ob_a_focused_pressed_shade
;
68 Appearance
*ob_a_focused_pressed_set_shade
;
69 Appearance
*ob_a_unfocused_unpressed_shade
;
70 Appearance
*ob_a_unfocused_pressed_shade
;
71 Appearance
*ob_a_unfocused_pressed_set_shade
;
72 Appearance
*ob_a_focused_unpressed_iconify
;
73 Appearance
*ob_a_focused_pressed_iconify
;
74 Appearance
*ob_a_unfocused_unpressed_iconify
;
75 Appearance
*ob_a_unfocused_pressed_iconify
;
76 Appearance
*ob_a_focused_grip
;
77 Appearance
*ob_a_unfocused_grip
;
78 Appearance
*ob_a_focused_title
;
79 Appearance
*ob_a_unfocused_title
;
80 Appearance
*ob_a_focused_label
;
81 Appearance
*ob_a_unfocused_label
;
82 Appearance
*ob_a_icon
; /* always parentrelative, so no focused/unfocused */
83 Appearance
*ob_a_focused_handle
;
84 Appearance
*ob_a_unfocused_handle
;
86 static void layout_title(ObFrame
*self
);
87 static void mouse_event(const ObEvent
*e
, ObFrame
*self
);
93 g_quark_from_string("none");
94 g_quark_from_string("root");
95 g_quark_from_string("client");
96 g_quark_from_string("titlebar");
97 g_quark_from_string("handle");
98 g_quark_from_string("frame");
99 g_quark_from_string("blcorner");
100 g_quark_from_string("brcorner");
101 g_quark_from_string("maximize");
102 g_quark_from_string("alldesktops");
103 g_quark_from_string("shade");
104 g_quark_from_string("iconify");
105 g_quark_from_string("icon");
106 g_quark_from_string("close");
108 /* create the ~/.openbox/themes/openbox dir */
109 path
= g_build_filename(g_get_home_dir(), ".openbox", "themes", "openbox",
111 mkdir(path
, (S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
|
112 S_IROTH
| S_IWOTH
| S_IXOTH
));
115 ob_s_b_color
= ob_s_cb_unfocused_color
= ob_s_cb_focused_color
=
116 ob_s_title_unfocused_color
= ob_s_title_focused_color
=
117 ob_s_titlebut_unfocused_color
= ob_s_titlebut_focused_color
= NULL
;
119 ob_s_max_set_mask
= ob_s_max_unset_mask
= NULL
;
120 ob_s_desk_set_mask
= ob_s_desk_unset_mask
= NULL
;
121 ob_s_shade_set_mask
= ob_s_shade_unset_mask
= NULL
;
122 ob_s_iconify_mask
= ob_s_close_mask
= NULL
;
124 ob_a_focused_unpressed_max
= appearance_new(Surface_Planar
, 1);
125 ob_a_focused_pressed_max
= appearance_new(Surface_Planar
, 1);
126 ob_a_focused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
127 ob_a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 1);
128 ob_a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 1);
129 ob_a_unfocused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
130 ob_a_focused_unpressed_close
= NULL
;
131 ob_a_focused_pressed_close
= NULL
;
132 ob_a_unfocused_unpressed_close
= NULL
;
133 ob_a_unfocused_pressed_close
= NULL
;
134 ob_a_focused_unpressed_desk
= NULL
;
135 ob_a_focused_pressed_desk
= NULL
;
136 ob_a_focused_pressed_set_desk
= NULL
;
137 ob_a_unfocused_unpressed_desk
= NULL
;
138 ob_a_unfocused_pressed_desk
= NULL
;
139 ob_a_unfocused_pressed_set_desk
= NULL
;
140 ob_a_focused_unpressed_shade
= NULL
;
141 ob_a_focused_pressed_shade
= NULL
;
142 ob_a_focused_pressed_set_shade
= NULL
;
143 ob_a_unfocused_unpressed_shade
= NULL
;
144 ob_a_unfocused_pressed_shade
= NULL
;
145 ob_a_unfocused_pressed_set_shade
= NULL
;
146 ob_a_focused_unpressed_iconify
= NULL
;
147 ob_a_focused_pressed_iconify
= NULL
;
148 ob_a_unfocused_unpressed_iconify
= NULL
;
149 ob_a_unfocused_pressed_iconify
= NULL
;
150 ob_a_focused_grip
= appearance_new(Surface_Planar
, 0);
151 ob_a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
152 ob_a_focused_title
= appearance_new(Surface_Planar
, 0);
153 ob_a_unfocused_title
= appearance_new(Surface_Planar
, 0);
154 ob_a_focused_label
= appearance_new(Surface_Planar
, 1);
155 ob_a_unfocused_label
= appearance_new(Surface_Planar
, 1);
156 ob_a_icon
= appearance_new(Surface_Planar
, 1);
157 ob_a_focused_handle
= appearance_new(Surface_Planar
, 0);
158 ob_a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
160 if (obtheme_load()) {
161 RECT_SET(ob_a_focused_pressed_desk
->area
, 0, 0,
162 BUTTON_SIZE
, BUTTON_SIZE
);
163 RECT_SET(ob_a_focused_pressed_set_desk
->area
, 0, 0,
164 BUTTON_SIZE
, BUTTON_SIZE
);
165 RECT_SET(ob_a_focused_unpressed_desk
->area
, 0, 0,
166 BUTTON_SIZE
, BUTTON_SIZE
);
167 RECT_SET(ob_a_unfocused_pressed_desk
->area
, 0, 0,
168 BUTTON_SIZE
, BUTTON_SIZE
);
169 RECT_SET(ob_a_unfocused_pressed_set_desk
->area
, 0, 0,
170 BUTTON_SIZE
, BUTTON_SIZE
);
171 RECT_SET(ob_a_unfocused_unpressed_desk
->area
, 0, 0,
172 BUTTON_SIZE
, BUTTON_SIZE
);
173 RECT_SET(ob_a_focused_pressed_shade
->area
, 0, 0,
174 BUTTON_SIZE
, BUTTON_SIZE
);
175 RECT_SET(ob_a_focused_pressed_set_shade
->area
, 0, 0,
176 BUTTON_SIZE
, BUTTON_SIZE
);
177 RECT_SET(ob_a_focused_unpressed_shade
->area
, 0, 0,
178 BUTTON_SIZE
, BUTTON_SIZE
);
179 RECT_SET(ob_a_unfocused_pressed_shade
->area
, 0, 0,
180 BUTTON_SIZE
, BUTTON_SIZE
);
181 RECT_SET(ob_a_unfocused_pressed_set_shade
->area
, 0, 0,
182 BUTTON_SIZE
, BUTTON_SIZE
);
183 RECT_SET(ob_a_unfocused_unpressed_shade
->area
, 0, 0,
184 BUTTON_SIZE
, BUTTON_SIZE
);
185 RECT_SET(ob_a_focused_pressed_iconify
->area
, 0, 0,
186 BUTTON_SIZE
, BUTTON_SIZE
);
187 RECT_SET(ob_a_focused_unpressed_iconify
->area
, 0, 0,
188 BUTTON_SIZE
, BUTTON_SIZE
);
189 RECT_SET(ob_a_unfocused_pressed_iconify
->area
, 0, 0,
190 BUTTON_SIZE
, BUTTON_SIZE
);
191 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
192 BUTTON_SIZE
, BUTTON_SIZE
);
193 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
194 BUTTON_SIZE
, BUTTON_SIZE
);
195 RECT_SET(ob_a_focused_pressed_max
->area
, 0, 0,
196 BUTTON_SIZE
, BUTTON_SIZE
);
197 RECT_SET(ob_a_focused_pressed_set_max
->area
, 0, 0,
198 BUTTON_SIZE
, BUTTON_SIZE
);
199 RECT_SET(ob_a_focused_unpressed_max
->area
, 0, 0,
200 BUTTON_SIZE
, BUTTON_SIZE
);
201 RECT_SET(ob_a_unfocused_pressed_max
->area
, 0, 0,
202 BUTTON_SIZE
, BUTTON_SIZE
);
203 RECT_SET(ob_a_unfocused_pressed_set_max
->area
, 0, 0,
204 BUTTON_SIZE
, BUTTON_SIZE
);
205 RECT_SET(ob_a_unfocused_unpressed_max
->area
, 0, 0,
206 BUTTON_SIZE
, BUTTON_SIZE
);
207 RECT_SET(ob_a_focused_pressed_close
->area
, 0, 0,
208 BUTTON_SIZE
, BUTTON_SIZE
);
209 RECT_SET(ob_a_focused_unpressed_close
->area
, 0, 0,
210 BUTTON_SIZE
, BUTTON_SIZE
);
211 RECT_SET(ob_a_unfocused_pressed_close
->area
, 0, 0,
212 BUTTON_SIZE
, BUTTON_SIZE
);
213 RECT_SET(ob_a_unfocused_unpressed_close
->area
, 0, 0,
214 BUTTON_SIZE
, BUTTON_SIZE
);
216 RECT_SET(ob_a_focused_grip
->area
, 0, 0,
217 GRIP_WIDTH
, ob_s_handle_height
);
218 RECT_SET(ob_a_unfocused_grip
->area
, 0, 0,
219 GRIP_WIDTH
, ob_s_handle_height
);
227 if (ob_s_b_color
!= NULL
) color_free(ob_s_b_color
);
228 if (ob_s_cb_unfocused_color
!= NULL
) color_free(ob_s_cb_unfocused_color
);
229 if (ob_s_cb_focused_color
!= NULL
) color_free(ob_s_cb_focused_color
);
230 if (ob_s_title_unfocused_color
!= NULL
) color_free(ob_s_title_unfocused_color
);
231 if (ob_s_title_focused_color
!= NULL
) color_free(ob_s_title_focused_color
);
232 if (ob_s_titlebut_unfocused_color
!= NULL
)
233 color_free(ob_s_titlebut_unfocused_color
);
234 if (ob_s_titlebut_focused_color
!= NULL
)
235 color_free(ob_s_titlebut_focused_color
);
237 if (ob_s_max_set_mask
!= NULL
)
238 pixmap_mask_free(ob_s_max_set_mask
);
239 if (ob_s_max_unset_mask
!= NULL
)
240 pixmap_mask_free(ob_s_max_unset_mask
);
241 if (ob_s_desk_set_mask
!= NULL
)
242 pixmap_mask_free(ob_s_desk_set_mask
);
243 if (ob_s_desk_unset_mask
!= NULL
)
244 pixmap_mask_free(ob_s_desk_unset_mask
);
245 if (ob_s_shade_set_mask
!= NULL
)
246 pixmap_mask_free(ob_s_shade_set_mask
);
247 if (ob_s_shade_unset_mask
!= NULL
)
248 pixmap_mask_free(ob_s_shade_unset_mask
);
249 if (ob_s_iconify_mask
!= NULL
)
250 pixmap_mask_free(ob_s_iconify_mask
);
251 if (ob_s_close_mask
!= NULL
)
252 pixmap_mask_free(ob_s_close_mask
);
254 if (ob_s_winfont
!= NULL
) font_close(ob_s_winfont
);
256 appearance_free(ob_a_focused_unpressed_max
);
257 appearance_free(ob_a_focused_pressed_max
);
258 appearance_free(ob_a_focused_pressed_set_max
);
259 appearance_free(ob_a_unfocused_unpressed_max
);
260 appearance_free(ob_a_unfocused_pressed_max
);
261 appearance_free(ob_a_unfocused_pressed_set_max
);
262 if (ob_a_focused_unpressed_close
!= NULL
)
263 appearance_free(ob_a_focused_unpressed_close
);
264 if (ob_a_focused_pressed_close
!= NULL
)
265 appearance_free(ob_a_focused_pressed_close
);
266 if (ob_a_unfocused_unpressed_close
!= NULL
)
267 appearance_free(ob_a_unfocused_unpressed_close
);
268 if (ob_a_unfocused_pressed_close
!= NULL
)
269 appearance_free(ob_a_unfocused_pressed_close
);
270 if (ob_a_focused_unpressed_desk
!= NULL
)
271 appearance_free(ob_a_focused_unpressed_desk
);
272 if (ob_a_focused_pressed_desk
!= NULL
)
273 appearance_free(ob_a_focused_pressed_desk
);
274 if (ob_a_unfocused_unpressed_desk
!= NULL
)
275 appearance_free(ob_a_unfocused_unpressed_desk
);
276 if (ob_a_unfocused_pressed_desk
!= NULL
)
277 appearance_free(ob_a_unfocused_pressed_desk
);
278 if (ob_a_focused_unpressed_shade
!= NULL
)
279 appearance_free(ob_a_focused_unpressed_shade
);
280 if (ob_a_focused_pressed_shade
!= NULL
)
281 appearance_free(ob_a_focused_pressed_shade
);
282 if (ob_a_unfocused_unpressed_shade
!= NULL
)
283 appearance_free(ob_a_unfocused_unpressed_shade
);
284 if (ob_a_unfocused_pressed_shade
!= NULL
)
285 appearance_free(ob_a_unfocused_pressed_shade
);
286 if (ob_a_focused_unpressed_iconify
!= NULL
)
287 appearance_free(ob_a_focused_unpressed_iconify
);
288 if (ob_a_focused_pressed_iconify
!= NULL
)
289 appearance_free(ob_a_focused_pressed_iconify
);
290 if (ob_a_unfocused_unpressed_iconify
!= NULL
)
291 appearance_free(ob_a_unfocused_unpressed_iconify
);
292 if (ob_a_unfocused_pressed_iconify
!= NULL
)
293 appearance_free(ob_a_unfocused_pressed_iconify
);
294 appearance_free(ob_a_focused_grip
);
295 appearance_free(ob_a_unfocused_grip
);
296 appearance_free(ob_a_focused_title
);
297 appearance_free(ob_a_unfocused_title
);
298 appearance_free(ob_a_focused_label
);
299 appearance_free(ob_a_unfocused_label
);
300 appearance_free(ob_a_icon
);
301 appearance_free(ob_a_focused_handle
);
302 appearance_free(ob_a_unfocused_handle
);
305 static Window
createWindow(Window parent
, unsigned long mask
,
306 XSetWindowAttributes
*attrib
)
308 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
309 render_depth
, InputOutput
, render_visual
,
316 XSetWindowAttributes attrib
;
320 self
= g_new(ObFrame
, 1);
322 self
->frame
.visible
= FALSE
;
324 /* create all of the decor windows */
325 mask
= CWOverrideRedirect
| CWEventMask
;
326 attrib
.event_mask
= FRAME_EVENTMASK
;
327 attrib
.override_redirect
= TRUE
;
328 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
331 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
334 attrib
.event_mask
= ELEMENT_EVENTMASK
;
335 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
336 self
->label
= createWindow(self
->title
, mask
, &attrib
);
337 self
->max
= createWindow(self
->title
, mask
, &attrib
);
338 self
->close
= createWindow(self
->title
, mask
, &attrib
);
339 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
340 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
341 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
342 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
343 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
345 attrib
.cursor
= ob_cursors
.ll_angle
;
346 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
347 attrib
.cursor
= ob_cursors
.lr_angle
;
348 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
350 /* the other stuff is shown based on decor settings */
351 XMapWindow(ob_display
, self
->frame
.plate
);
352 XMapWindow(ob_display
, self
->lgrip
);
353 XMapWindow(ob_display
, self
->rgrip
);
354 XMapWindow(ob_display
, self
->label
);
356 /* set colors/appearance/sizes for stuff that doesn't change */
357 XSetWindowBorder(ob_display
, self
->frame
.window
, ob_s_b_color
->pixel
);
358 XSetWindowBorder(ob_display
, self
->label
, ob_s_b_color
->pixel
);
359 XSetWindowBorder(ob_display
, self
->rgrip
, ob_s_b_color
->pixel
);
360 XSetWindowBorder(ob_display
, self
->lgrip
, ob_s_b_color
->pixel
);
362 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
363 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
364 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
365 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
366 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
367 XResizeWindow(ob_display
, self
->shade
, BUTTON_SIZE
, BUTTON_SIZE
);
368 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, ob_s_handle_height
);
369 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, ob_s_handle_height
);
371 /* set up the dynamic appearances */
372 self
->a_unfocused_title
= appearance_copy(ob_a_unfocused_title
);
373 self
->a_focused_title
= appearance_copy(ob_a_focused_title
);
374 self
->a_unfocused_label
= appearance_copy(ob_a_unfocused_label
);
375 self
->a_focused_label
= appearance_copy(ob_a_focused_label
);
376 self
->a_unfocused_handle
= appearance_copy(ob_a_unfocused_handle
);
377 self
->a_focused_handle
= appearance_copy(ob_a_focused_handle
);
378 self
->a_icon
= appearance_copy(ob_a_icon
);
380 self
->max_press
= self
->close_press
= self
->desk_press
=
381 self
->iconify_press
= self
->shade_press
= FALSE
;
383 dispatch_register(Event_X_ButtonPress
| Event_X_ButtonRelease
,
384 (EventHandler
)mouse_event
, self
);
389 static void frame_free(ObFrame
*self
)
391 appearance_free(self
->a_unfocused_title
);
392 appearance_free(self
->a_focused_title
);
393 appearance_free(self
->a_unfocused_label
);
394 appearance_free(self
->a_focused_label
);
395 appearance_free(self
->a_unfocused_handle
);
396 appearance_free(self
->a_focused_handle
);
397 appearance_free(self
->a_icon
);
399 XDestroyWindow(ob_display
, self
->frame
.window
);
401 dispatch_register(0, (EventHandler
)mouse_event
, self
);
406 void frame_show(ObFrame
*self
)
408 if (!self
->frame
.visible
) {
409 self
->frame
.visible
= TRUE
;
410 XMapWindow(ob_display
, self
->frame
.window
);
414 void frame_hide(ObFrame
*self
)
416 if (self
->frame
.visible
) {
417 self
->frame
.visible
= FALSE
;
418 self
->frame
.client
->ignore_unmaps
++;
419 XUnmapWindow(ob_display
, self
->frame
.window
);
423 void frame_adjust_shape(ObFrame
*self
)
429 if (!self
->frame
.client
->shaped
) {
430 /* clear the shape on the frame window */
431 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
432 self
->innersize
.left
,
436 /* make the frame's shape match the clients */
437 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
438 self
->innersize
.left
,
440 self
->frame
.client
->window
,
441 ShapeBounding
, ShapeSet
);
444 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
445 xrect
[0].x
= -ob_s_bevel
;
446 xrect
[0].y
= -ob_s_bevel
;
447 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
448 xrect
[0].height
= TITLE_HEIGHT
+
453 if (self
->frame
.client
->decorations
& Decor_Handle
) {
454 xrect
[1].x
= -ob_s_bevel
;
455 xrect
[1].y
= HANDLE_Y(self
);
456 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
457 xrect
[1].height
= ob_s_handle_height
+
462 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
463 ShapeBounding
, 0, 0, xrect
, num
,
464 ShapeUnion
, Unsorted
);
469 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
472 if (self
->frame
.client
->decorations
& Decor_Border
) {
473 self
->bwidth
= ob_s_bwidth
;
474 self
->cbwidth
= ob_s_cbwidth
;
476 self
->bwidth
= self
->cbwidth
= 0;
478 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
479 self
->cbwidth
, self
->cbwidth
);
480 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
481 g_assert(self
->width
> 0);
483 /* set border widths */
484 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
485 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
486 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
487 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
488 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
489 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
491 /* position/size and map/unmap all the windows */
493 /* they all default off, they're turned on in layout_title */
502 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
503 XMoveResizeWindow(ob_display
, self
->title
,
504 -self
->bwidth
, -self
->bwidth
,
505 self
->width
, TITLE_HEIGHT
);
506 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
507 XMapWindow(ob_display
, self
->title
);
509 RECT_SET(self
->a_focused_title
->area
, 0, 0,
510 self
->width
, TITLE_HEIGHT
);
511 RECT_SET(self
->a_unfocused_title
->area
, 0, 0,
512 self
->width
, TITLE_HEIGHT
);
514 /* layout the title bar elements */
517 XUnmapWindow(ob_display
, self
->title
);
519 if (self
->frame
.client
->decorations
& Decor_Handle
) {
520 XMoveResizeWindow(ob_display
, self
->handle
,
521 -self
->bwidth
, HANDLE_Y(self
),
522 self
->width
, ob_s_handle_height
);
523 XMoveWindow(ob_display
, self
->lgrip
,
524 -self
->bwidth
, -self
->bwidth
);
525 XMoveWindow(ob_display
, self
->rgrip
,
526 -self
->bwidth
+ self
->width
-
527 GRIP_WIDTH
, -self
->bwidth
);
528 self
->innersize
.bottom
+= ob_s_handle_height
+
530 XMapWindow(ob_display
, self
->handle
);
532 if (self
->a_focused_handle
->surface
.data
.planar
.grad
==
533 Background_ParentRelative
)
534 RECT_SET(self
->a_focused_handle
->area
, 0, 0,
535 self
->width
, ob_s_handle_height
);
537 RECT_SET(self
->a_focused_handle
->area
,
538 GRIP_WIDTH
+ self
->bwidth
, 0,
539 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
541 if (self
->a_unfocused_handle
->surface
.data
.planar
.grad
==
542 Background_ParentRelative
)
543 RECT_SET(self
->a_unfocused_handle
->area
, 0, 0,
544 self
->width
, ob_s_handle_height
);
546 RECT_SET(self
->a_unfocused_handle
->area
,
547 GRIP_WIDTH
+ self
->bwidth
, 0,
548 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
552 XUnmapWindow(ob_display
, self
->handle
);
556 /* move and resize the plate */
557 XMoveResizeWindow(ob_display
, self
->frame
.plate
,
558 self
->innersize
.left
- self
->cbwidth
,
559 self
->innersize
.top
- self
->cbwidth
,
560 self
->frame
.client
->area
.width
,
561 self
->frame
.client
->area
.height
);
562 /* when the client has StaticGravity, it likes to move around. */
563 XMoveWindow(ob_display
, self
->frame
.client
->window
, 0, 0);
567 STRUT_SET(self
->frame
.size
,
568 self
->innersize
.left
+ self
->bwidth
,
569 self
->innersize
.top
+ self
->bwidth
,
570 self
->innersize
.right
+ self
->bwidth
,
571 self
->innersize
.bottom
+ self
->bwidth
);
574 /* shading can change without being moved or resized */
575 RECT_SET_SIZE(self
->frame
.area
,
576 self
->frame
.client
->area
.width
+
577 self
->frame
.size
.left
+ self
->frame
.size
.right
,
578 (self
->frame
.client
->shaded
? TITLE_HEIGHT
+ self
->bwidth
*2:
579 self
->frame
.client
->area
.height
+
580 self
->frame
.size
.top
+ self
->frame
.size
.bottom
));
583 /* find the new coordinates, done after setting the frame.size, for
584 frame_client_gravity. */
585 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
586 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
587 frame_client_gravity((Frame
*)self
,
588 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
591 /* move and resize the top level frame.
592 shading can change without being moved or resized */
593 XMoveResizeWindow(ob_display
, self
->frame
.window
,
594 self
->frame
.area
.x
, self
->frame
.area
.y
,
596 self
->frame
.area
.height
- self
->bwidth
* 2);
599 obrender_frame(self
);
601 frame_adjust_shape(self
);
605 void frame_adjust_state(ObFrame
*self
)
607 obrender_frame(self
);
610 void frame_adjust_focus(ObFrame
*self
)
612 obrender_frame(self
);
615 void frame_adjust_title(ObFrame
*self
)
617 obrender_frame(self
);
620 void frame_adjust_icon(ObFrame
*self
)
622 obrender_frame(self
);
625 void frame_grab_client(ObFrame
*self
, Client
*client
)
627 self
->frame
.client
= client
;
629 /* reparent the client to the frame */
630 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
632 When reparenting the client window, it is usually not mapped yet, since
633 this occurs from a MapRequest. However, in the case where Openbox is
634 starting up, the window is already mapped, so we'll see unmap events for
635 it. There are 2 unmap events generated that we see, one with the 'event'
636 member set the root window, and one set to the client, but both get
637 handled and need to be ignored.
639 if (ob_state
== State_Starting
)
640 client
->ignore_unmaps
+= 2;
642 /* select the event mask on the client's parent (to receive config/map
643 req's) the ButtonPress is to catch clicks on the client border */
644 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
646 /* map the client so it maps when the frame does */
647 XMapWindow(ob_display
, client
->window
);
649 frame_adjust_area(self
, TRUE
, TRUE
);
651 /* set all the windows for the frame in the client_map */
652 g_hash_table_insert(client_map
, &self
->frame
.window
, client
);
653 g_hash_table_insert(client_map
, &self
->frame
.plate
, client
);
654 g_hash_table_insert(client_map
, &self
->title
, client
);
655 g_hash_table_insert(client_map
, &self
->label
, client
);
656 g_hash_table_insert(client_map
, &self
->max
, client
);
657 g_hash_table_insert(client_map
, &self
->close
, client
);
658 g_hash_table_insert(client_map
, &self
->desk
, client
);
659 g_hash_table_insert(client_map
, &self
->shade
, client
);
660 g_hash_table_insert(client_map
, &self
->icon
, client
);
661 g_hash_table_insert(client_map
, &self
->iconify
, client
);
662 g_hash_table_insert(client_map
, &self
->handle
, client
);
663 g_hash_table_insert(client_map
, &self
->lgrip
, client
);
664 g_hash_table_insert(client_map
, &self
->rgrip
, client
);
667 void frame_release_client(ObFrame
*self
, Client
*client
)
671 g_assert(self
->frame
.client
== client
);
673 /* check if the app has already reparented its window away */
674 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
675 ReparentNotify
, &ev
)) {
676 XPutBackEvent(ob_display
, &ev
);
677 /* re-map the window since the unmanaging process unmaps it */
678 XMapWindow(ob_display
, client
->window
);
680 /* according to the ICCCM - if the client doesn't reparent itself,
681 then we will reparent the window to root for them */
682 XReparentWindow(ob_display
, client
->window
, ob_root
,
687 /* remove all the windows for the frame from the client_map */
688 g_hash_table_remove(client_map
, &self
->frame
.window
);
689 g_hash_table_remove(client_map
, &self
->frame
.plate
);
690 g_hash_table_remove(client_map
, &self
->title
);
691 g_hash_table_remove(client_map
, &self
->label
);
692 g_hash_table_remove(client_map
, &self
->max
);
693 g_hash_table_remove(client_map
, &self
->close
);
694 g_hash_table_remove(client_map
, &self
->desk
);
695 g_hash_table_remove(client_map
, &self
->shade
);
696 g_hash_table_remove(client_map
, &self
->icon
);
697 g_hash_table_remove(client_map
, &self
->iconify
);
698 g_hash_table_remove(client_map
, &self
->handle
);
699 g_hash_table_remove(client_map
, &self
->lgrip
);
700 g_hash_table_remove(client_map
, &self
->rgrip
);
705 static void layout_title(ObFrame
*self
)
709 gboolean n
, d
, i
, l
, m
, c
, s
;
712 n
= d
= i
= l
= m
= c
= s
= FALSE
;
714 if (!config_get("titlebar.layout", Config_String
, &layout
)) {
715 layout
.string
= "NDLIMC";
716 config_set("titlebar.layout", Config_String
, layout
);
719 /* figure out whats being shown, and the width of the label */
720 self
->label_width
= self
->width
- (ob_s_bevel
+ 1) * 2;
721 for (lc
= layout
.string
; *lc
!= '\0'; ++lc
) {
724 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
725 if (n
) { *lc
= ' '; break; } /* rm duplicates */
727 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
730 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
731 if (d
) { *lc
= ' '; break; } /* rm duplicates */
733 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
736 if (!(self
->frame
.client
->decorations
& Decor_Shade
)) break;
737 if (s
) { *lc
= ' '; break; } /* rm duplicates */
739 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
742 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
743 if (i
) { *lc
= ' '; break; } /* rm duplicates */
745 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
748 if (l
) { *lc
= ' '; break; } /* rm duplicates */
752 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
753 if (m
) { *lc
= ' '; break; } /* rm duplicates */
755 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
758 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
759 if (c
) { *lc
= ' '; break; } /* rm duplicates */
761 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
765 if (self
->label_width
< 1) self
->label_width
= 1;
767 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
770 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
771 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
772 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
773 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
774 if (!l
) XUnmapWindow(ob_display
, self
->label
);
775 if (!m
) XUnmapWindow(ob_display
, self
->max
);
776 if (!c
) XUnmapWindow(ob_display
, self
->close
);
779 for (lc
= layout
.string
; *lc
!= '\0'; ++lc
) {
784 RECT_SET(self
->a_icon
->area
, 0, 0, BUTTON_SIZE
, BUTTON_SIZE
);
785 XMapWindow(ob_display
, self
->icon
);
786 XMoveWindow(ob_display
, self
->icon
, x
, ob_s_bevel
+ 1);
787 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
792 XMapWindow(ob_display
, self
->desk
);
793 XMoveWindow(ob_display
, self
->desk
, x
, ob_s_bevel
+ 1);
794 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
799 XMapWindow(ob_display
, self
->shade
);
800 XMoveWindow(ob_display
, self
->shade
, x
, ob_s_bevel
+ 1);
801 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
806 XMapWindow(ob_display
, self
->iconify
);
807 XMoveWindow(ob_display
, self
->iconify
, x
, ob_s_bevel
+ 1);
808 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
813 XMapWindow(ob_display
, self
->label
);
814 XMoveWindow(ob_display
, self
->label
, x
, ob_s_bevel
);
815 x
+= self
->label_width
+ ob_s_bevel
+ 1;
820 XMapWindow(ob_display
, self
->max
);
821 XMoveWindow(ob_display
, self
->max
, x
, ob_s_bevel
+ 1);
822 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
827 XMapWindow(ob_display
, self
->close
);
828 XMoveWindow(ob_display
, self
->close
, x
, ob_s_bevel
+ 1);
829 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
834 RECT_SET(self
->a_focused_label
->area
, 0, 0,
835 self
->label_width
, LABEL_HEIGHT
);
836 RECT_SET(self
->a_unfocused_label
->area
, 0, 0,
837 self
->label_width
, LABEL_HEIGHT
);
840 static void mouse_event(const ObEvent
*e
, ObFrame
*self
)
843 gboolean press
= e
->type
== Event_X_ButtonPress
;
845 win
= e
->data
.x
.e
->xbutton
.window
;
846 if (win
== self
->max
) {
847 self
->max_press
= press
;
848 obrender_frame(self
);
849 } else if (win
== self
->close
) {
850 self
->close_press
= press
;
851 obrender_frame(self
);
852 } else if (win
== self
->iconify
) {
853 self
->iconify_press
= press
;
854 obrender_frame(self
);
855 } else if (win
== self
->desk
) {
856 self
->desk_press
= press
;
857 obrender_frame(self
);
858 } else if (win
== self
->shade
) {
859 self
->shade_press
= press
;
860 obrender_frame(self
);
864 GQuark
get_context(Client
*client
, Window win
)
868 if (win
== ob_root
) return g_quark_try_string("root");
869 if (client
== NULL
) return g_quark_try_string("none");
870 if (win
== client
->window
) return g_quark_try_string("client");
872 self
= (ObFrame
*) client
->frame
;
873 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
874 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
875 if (win
== self
->title
) return g_quark_try_string("titlebar");
876 if (win
== self
->label
) return g_quark_try_string("titlebar");
877 if (win
== self
->handle
) return g_quark_try_string("handle");
878 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
879 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
880 if (win
== self
->max
) return g_quark_try_string("maximize");
881 if (win
== self
->iconify
) return g_quark_try_string("iconify");
882 if (win
== self
->close
) return g_quark_try_string("close");
883 if (win
== self
->icon
) return g_quark_try_string("icon");
884 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
885 if (win
== self
->shade
) return g_quark_try_string("shade");
887 return g_quark_try_string("none");