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 ButtonPressMask | ButtonReleaseMask)
19 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
20 ButtonMotionMask | ExposureMask)
22 /* style settings - geometry */
24 int ob_s_handle_height
;
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
;
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
;
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
;
88 static void layout_title(ObFrame
*self
);
89 static void mouse_event(const ObEvent
*e
, ObFrame
*self
);
95 g_quark_from_string("none");
96 g_quark_from_string("root");
97 g_quark_from_string("client");
98 g_quark_from_string("titlebar");
99 g_quark_from_string("handle");
100 g_quark_from_string("frame");
101 g_quark_from_string("blcorner");
102 g_quark_from_string("brcorner");
103 g_quark_from_string("maximize");
104 g_quark_from_string("alldesktops");
105 g_quark_from_string("shade");
106 g_quark_from_string("iconify");
107 g_quark_from_string("icon");
108 g_quark_from_string("close");
110 /* create the ~/.openbox/themes/openbox dir */
111 path
= g_build_filename(g_get_home_dir(), ".openbox", "themes", "openbox",
113 mkdir(path
, (S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
|
114 S_IROTH
| S_IWOTH
| S_IXOTH
));
117 ob_s_b_color
= ob_s_cb_unfocused_color
= ob_s_cb_focused_color
=
118 ob_s_title_unfocused_color
= ob_s_title_focused_color
=
119 ob_s_titlebut_unfocused_color
= ob_s_titlebut_focused_color
= NULL
;
121 ob_s_max_set_mask
= ob_s_max_unset_mask
= NULL
;
122 ob_s_desk_set_mask
= ob_s_desk_unset_mask
= NULL
;
123 ob_s_shade_set_mask
= ob_s_shade_unset_mask
= NULL
;
124 ob_s_iconify_mask
= ob_s_close_mask
= NULL
;
126 ob_a_focused_unpressed_max
= appearance_new(Surface_Planar
, 1);
127 ob_a_focused_pressed_max
= appearance_new(Surface_Planar
, 1);
128 ob_a_focused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
129 ob_a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 1);
130 ob_a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 1);
131 ob_a_unfocused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
132 ob_a_focused_unpressed_close
= NULL
;
133 ob_a_focused_pressed_close
= NULL
;
134 ob_a_unfocused_unpressed_close
= NULL
;
135 ob_a_unfocused_pressed_close
= NULL
;
136 ob_a_focused_unpressed_desk
= NULL
;
137 ob_a_focused_pressed_desk
= NULL
;
138 ob_a_focused_pressed_set_desk
= NULL
;
139 ob_a_unfocused_unpressed_desk
= NULL
;
140 ob_a_unfocused_pressed_desk
= NULL
;
141 ob_a_unfocused_pressed_set_desk
= NULL
;
142 ob_a_focused_unpressed_shade
= NULL
;
143 ob_a_focused_pressed_shade
= NULL
;
144 ob_a_focused_pressed_set_shade
= NULL
;
145 ob_a_unfocused_unpressed_shade
= NULL
;
146 ob_a_unfocused_pressed_shade
= NULL
;
147 ob_a_unfocused_pressed_set_shade
= NULL
;
148 ob_a_focused_unpressed_iconify
= NULL
;
149 ob_a_focused_pressed_iconify
= NULL
;
150 ob_a_unfocused_unpressed_iconify
= NULL
;
151 ob_a_unfocused_pressed_iconify
= NULL
;
152 ob_a_focused_grip
= appearance_new(Surface_Planar
, 0);
153 ob_a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
154 ob_a_focused_title
= appearance_new(Surface_Planar
, 0);
155 ob_a_unfocused_title
= appearance_new(Surface_Planar
, 0);
156 ob_a_focused_label
= appearance_new(Surface_Planar
, 1);
157 ob_a_unfocused_label
= appearance_new(Surface_Planar
, 1);
158 ob_a_icon
= appearance_new(Surface_Planar
, 1);
159 ob_a_focused_handle
= appearance_new(Surface_Planar
, 0);
160 ob_a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
162 if (obtheme_load()) {
163 RECT_SET(ob_a_focused_pressed_desk
->area
, 0, 0,
164 BUTTON_SIZE
, BUTTON_SIZE
);
165 RECT_SET(ob_a_focused_pressed_set_desk
->area
, 0, 0,
166 BUTTON_SIZE
, BUTTON_SIZE
);
167 RECT_SET(ob_a_focused_unpressed_desk
->area
, 0, 0,
168 BUTTON_SIZE
, BUTTON_SIZE
);
169 RECT_SET(ob_a_unfocused_pressed_desk
->area
, 0, 0,
170 BUTTON_SIZE
, BUTTON_SIZE
);
171 RECT_SET(ob_a_unfocused_pressed_set_desk
->area
, 0, 0,
172 BUTTON_SIZE
, BUTTON_SIZE
);
173 RECT_SET(ob_a_unfocused_unpressed_desk
->area
, 0, 0,
174 BUTTON_SIZE
, BUTTON_SIZE
);
175 RECT_SET(ob_a_focused_pressed_shade
->area
, 0, 0,
176 BUTTON_SIZE
, BUTTON_SIZE
);
177 RECT_SET(ob_a_focused_pressed_set_shade
->area
, 0, 0,
178 BUTTON_SIZE
, BUTTON_SIZE
);
179 RECT_SET(ob_a_focused_unpressed_shade
->area
, 0, 0,
180 BUTTON_SIZE
, BUTTON_SIZE
);
181 RECT_SET(ob_a_unfocused_pressed_shade
->area
, 0, 0,
182 BUTTON_SIZE
, BUTTON_SIZE
);
183 RECT_SET(ob_a_unfocused_pressed_set_shade
->area
, 0, 0,
184 BUTTON_SIZE
, BUTTON_SIZE
);
185 RECT_SET(ob_a_unfocused_unpressed_shade
->area
, 0, 0,
186 BUTTON_SIZE
, BUTTON_SIZE
);
187 RECT_SET(ob_a_focused_pressed_iconify
->area
, 0, 0,
188 BUTTON_SIZE
, BUTTON_SIZE
);
189 RECT_SET(ob_a_focused_unpressed_iconify
->area
, 0, 0,
190 BUTTON_SIZE
, BUTTON_SIZE
);
191 RECT_SET(ob_a_unfocused_pressed_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_unfocused_unpressed_iconify
->area
, 0, 0,
196 BUTTON_SIZE
, BUTTON_SIZE
);
197 RECT_SET(ob_a_focused_pressed_max
->area
, 0, 0,
198 BUTTON_SIZE
, BUTTON_SIZE
);
199 RECT_SET(ob_a_focused_pressed_set_max
->area
, 0, 0,
200 BUTTON_SIZE
, BUTTON_SIZE
);
201 RECT_SET(ob_a_focused_unpressed_max
->area
, 0, 0,
202 BUTTON_SIZE
, BUTTON_SIZE
);
203 RECT_SET(ob_a_unfocused_pressed_max
->area
, 0, 0,
204 BUTTON_SIZE
, BUTTON_SIZE
);
205 RECT_SET(ob_a_unfocused_pressed_set_max
->area
, 0, 0,
206 BUTTON_SIZE
, BUTTON_SIZE
);
207 RECT_SET(ob_a_unfocused_unpressed_max
->area
, 0, 0,
208 BUTTON_SIZE
, BUTTON_SIZE
);
209 RECT_SET(ob_a_focused_pressed_close
->area
, 0, 0,
210 BUTTON_SIZE
, BUTTON_SIZE
);
211 RECT_SET(ob_a_focused_unpressed_close
->area
, 0, 0,
212 BUTTON_SIZE
, BUTTON_SIZE
);
213 RECT_SET(ob_a_unfocused_pressed_close
->area
, 0, 0,
214 BUTTON_SIZE
, BUTTON_SIZE
);
215 RECT_SET(ob_a_unfocused_unpressed_close
->area
, 0, 0,
216 BUTTON_SIZE
, BUTTON_SIZE
);
218 RECT_SET(ob_a_focused_grip
->area
, 0, 0,
219 GRIP_WIDTH
, ob_s_handle_height
);
220 RECT_SET(ob_a_unfocused_grip
->area
, 0, 0,
221 GRIP_WIDTH
, ob_s_handle_height
);
229 if (ob_s_b_color
!= NULL
) color_free(ob_s_b_color
);
230 if (ob_s_cb_unfocused_color
!= NULL
) color_free(ob_s_cb_unfocused_color
);
231 if (ob_s_cb_focused_color
!= NULL
) color_free(ob_s_cb_focused_color
);
232 if (ob_s_title_unfocused_color
!= NULL
) color_free(ob_s_title_unfocused_color
);
233 if (ob_s_title_focused_color
!= NULL
) color_free(ob_s_title_focused_color
);
234 if (ob_s_titlebut_unfocused_color
!= NULL
)
235 color_free(ob_s_titlebut_unfocused_color
);
236 if (ob_s_titlebut_focused_color
!= NULL
)
237 color_free(ob_s_titlebut_focused_color
);
239 if (ob_s_max_set_mask
!= NULL
)
240 pixmap_mask_free(ob_s_max_set_mask
);
241 if (ob_s_max_unset_mask
!= NULL
)
242 pixmap_mask_free(ob_s_max_unset_mask
);
243 if (ob_s_desk_set_mask
!= NULL
)
244 pixmap_mask_free(ob_s_desk_set_mask
);
245 if (ob_s_desk_unset_mask
!= NULL
)
246 pixmap_mask_free(ob_s_desk_unset_mask
);
247 if (ob_s_shade_set_mask
!= NULL
)
248 pixmap_mask_free(ob_s_shade_set_mask
);
249 if (ob_s_shade_unset_mask
!= NULL
)
250 pixmap_mask_free(ob_s_shade_unset_mask
);
251 if (ob_s_iconify_mask
!= NULL
)
252 pixmap_mask_free(ob_s_iconify_mask
);
253 if (ob_s_close_mask
!= NULL
)
254 pixmap_mask_free(ob_s_close_mask
);
256 if (ob_s_winfont
!= NULL
) font_close(ob_s_winfont
);
258 appearance_free(ob_a_focused_unpressed_max
);
259 appearance_free(ob_a_focused_pressed_max
);
260 appearance_free(ob_a_focused_pressed_set_max
);
261 appearance_free(ob_a_unfocused_unpressed_max
);
262 appearance_free(ob_a_unfocused_pressed_max
);
263 appearance_free(ob_a_unfocused_pressed_set_max
);
264 if (ob_a_focused_unpressed_close
!= NULL
)
265 appearance_free(ob_a_focused_unpressed_close
);
266 if (ob_a_focused_pressed_close
!= NULL
)
267 appearance_free(ob_a_focused_pressed_close
);
268 if (ob_a_unfocused_unpressed_close
!= NULL
)
269 appearance_free(ob_a_unfocused_unpressed_close
);
270 if (ob_a_unfocused_pressed_close
!= NULL
)
271 appearance_free(ob_a_unfocused_pressed_close
);
272 if (ob_a_focused_unpressed_desk
!= NULL
)
273 appearance_free(ob_a_focused_unpressed_desk
);
274 if (ob_a_focused_pressed_desk
!= NULL
)
275 appearance_free(ob_a_focused_pressed_desk
);
276 if (ob_a_unfocused_unpressed_desk
!= NULL
)
277 appearance_free(ob_a_unfocused_unpressed_desk
);
278 if (ob_a_unfocused_pressed_desk
!= NULL
)
279 appearance_free(ob_a_unfocused_pressed_desk
);
280 if (ob_a_focused_unpressed_shade
!= NULL
)
281 appearance_free(ob_a_focused_unpressed_shade
);
282 if (ob_a_focused_pressed_shade
!= NULL
)
283 appearance_free(ob_a_focused_pressed_shade
);
284 if (ob_a_unfocused_unpressed_shade
!= NULL
)
285 appearance_free(ob_a_unfocused_unpressed_shade
);
286 if (ob_a_unfocused_pressed_shade
!= NULL
)
287 appearance_free(ob_a_unfocused_pressed_shade
);
288 if (ob_a_focused_unpressed_iconify
!= NULL
)
289 appearance_free(ob_a_focused_unpressed_iconify
);
290 if (ob_a_focused_pressed_iconify
!= NULL
)
291 appearance_free(ob_a_focused_pressed_iconify
);
292 if (ob_a_unfocused_unpressed_iconify
!= NULL
)
293 appearance_free(ob_a_unfocused_unpressed_iconify
);
294 if (ob_a_unfocused_pressed_iconify
!= NULL
)
295 appearance_free(ob_a_unfocused_pressed_iconify
);
296 appearance_free(ob_a_focused_grip
);
297 appearance_free(ob_a_unfocused_grip
);
298 appearance_free(ob_a_focused_title
);
299 appearance_free(ob_a_unfocused_title
);
300 appearance_free(ob_a_focused_label
);
301 appearance_free(ob_a_unfocused_label
);
302 appearance_free(ob_a_icon
);
303 appearance_free(ob_a_focused_handle
);
304 appearance_free(ob_a_unfocused_handle
);
307 static Window
createWindow(Window parent
, unsigned long mask
,
308 XSetWindowAttributes
*attrib
)
310 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
311 render_depth
, InputOutput
, render_visual
,
318 XSetWindowAttributes attrib
;
322 self
= g_new(ObFrame
, 1);
324 self
->frame
.visible
= FALSE
;
326 /* create all of the decor windows */
327 mask
= CWOverrideRedirect
| CWEventMask
;
328 attrib
.event_mask
= FRAME_EVENTMASK
;
329 attrib
.override_redirect
= TRUE
;
330 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
333 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
336 attrib
.event_mask
= ELEMENT_EVENTMASK
;
337 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
338 self
->label
= createWindow(self
->title
, mask
, &attrib
);
339 self
->max
= createWindow(self
->title
, mask
, &attrib
);
340 self
->close
= createWindow(self
->title
, mask
, &attrib
);
341 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
342 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
343 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
344 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
345 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
347 attrib
.cursor
= ob_cursors
.ll_angle
;
348 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
349 attrib
.cursor
= ob_cursors
.lr_angle
;
350 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
352 /* the other stuff is shown based on decor settings */
353 XMapWindow(ob_display
, self
->frame
.plate
);
354 XMapWindow(ob_display
, self
->lgrip
);
355 XMapWindow(ob_display
, self
->rgrip
);
356 XMapWindow(ob_display
, self
->label
);
358 /* set colors/appearance/sizes for stuff that doesn't change */
359 XSetWindowBorder(ob_display
, self
->frame
.window
, ob_s_b_color
->pixel
);
360 XSetWindowBorder(ob_display
, self
->label
, ob_s_b_color
->pixel
);
361 XSetWindowBorder(ob_display
, self
->rgrip
, ob_s_b_color
->pixel
);
362 XSetWindowBorder(ob_display
, self
->lgrip
, ob_s_b_color
->pixel
);
364 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
365 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
366 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
367 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
368 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
369 XResizeWindow(ob_display
, self
->shade
, BUTTON_SIZE
, BUTTON_SIZE
);
370 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, ob_s_handle_height
);
371 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, ob_s_handle_height
);
373 /* set up the dynamic appearances */
374 self
->a_unfocused_title
= appearance_copy(ob_a_unfocused_title
);
375 self
->a_focused_title
= appearance_copy(ob_a_focused_title
);
376 self
->a_unfocused_label
= appearance_copy(ob_a_unfocused_label
);
377 self
->a_focused_label
= appearance_copy(ob_a_focused_label
);
378 self
->a_unfocused_handle
= appearance_copy(ob_a_unfocused_handle
);
379 self
->a_focused_handle
= appearance_copy(ob_a_focused_handle
);
380 self
->a_icon
= appearance_copy(ob_a_icon
);
382 self
->max_press
= self
->close_press
= self
->desk_press
=
383 self
->iconify_press
= self
->shade_press
= FALSE
;
385 dispatch_register(Event_X_ButtonPress
| Event_X_ButtonRelease
,
386 (EventHandler
)mouse_event
, self
);
391 static void frame_free(ObFrame
*self
)
393 appearance_free(self
->a_unfocused_title
);
394 appearance_free(self
->a_focused_title
);
395 appearance_free(self
->a_unfocused_label
);
396 appearance_free(self
->a_focused_label
);
397 appearance_free(self
->a_unfocused_handle
);
398 appearance_free(self
->a_focused_handle
);
399 appearance_free(self
->a_icon
);
401 XDestroyWindow(ob_display
, self
->frame
.window
);
403 dispatch_register(0, (EventHandler
)mouse_event
, self
);
408 void frame_show(ObFrame
*self
)
410 if (!self
->frame
.visible
) {
411 self
->frame
.visible
= TRUE
;
412 XMapWindow(ob_display
, self
->frame
.window
);
416 void frame_hide(ObFrame
*self
)
418 if (self
->frame
.visible
) {
419 self
->frame
.visible
= FALSE
;
420 self
->frame
.client
->ignore_unmaps
++;
421 XUnmapWindow(ob_display
, self
->frame
.window
);
425 void frame_adjust_shape(ObFrame
*self
)
431 if (!self
->frame
.client
->shaped
) {
432 /* clear the shape on the frame window */
433 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
434 self
->innersize
.left
,
438 /* make the frame's shape match the clients */
439 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
440 self
->innersize
.left
,
442 self
->frame
.client
->window
,
443 ShapeBounding
, ShapeSet
);
446 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
447 xrect
[0].x
= -ob_s_bevel
;
448 xrect
[0].y
= -ob_s_bevel
;
449 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
450 xrect
[0].height
= TITLE_HEIGHT
+
455 if (self
->frame
.client
->decorations
& Decor_Handle
) {
456 xrect
[1].x
= -ob_s_bevel
;
457 xrect
[1].y
= HANDLE_Y(self
);
458 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
459 xrect
[1].height
= ob_s_handle_height
+
464 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
465 ShapeBounding
, 0, 0, xrect
, num
,
466 ShapeUnion
, Unsorted
);
471 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
474 if (self
->frame
.client
->decorations
& Decor_Border
) {
475 self
->bwidth
= ob_s_bwidth
;
476 self
->cbwidth
= ob_s_cbwidth
;
478 self
->bwidth
= self
->cbwidth
= 0;
480 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
481 self
->cbwidth
, self
->cbwidth
);
482 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
483 g_assert(self
->width
> 0);
485 /* set border widths */
486 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
487 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
488 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
489 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
490 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
491 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
493 /* position/size and map/unmap all the windows */
495 /* they all default off, they're turned on in layout_title */
499 self
->iconify_x
= -1;
504 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
505 XMoveResizeWindow(ob_display
, self
->title
,
506 -self
->bwidth
, -self
->bwidth
,
507 self
->width
, TITLE_HEIGHT
);
508 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
509 XMapWindow(ob_display
, self
->title
);
511 RECT_SET(self
->a_focused_title
->area
, 0, 0,
512 self
->width
, TITLE_HEIGHT
);
513 RECT_SET(self
->a_unfocused_title
->area
, 0, 0,
514 self
->width
, TITLE_HEIGHT
);
516 /* layout the title bar elements */
519 XUnmapWindow(ob_display
, self
->title
);
521 if (self
->frame
.client
->decorations
& Decor_Handle
) {
522 XMoveResizeWindow(ob_display
, self
->handle
,
523 -self
->bwidth
, HANDLE_Y(self
),
524 self
->width
, ob_s_handle_height
);
525 XMoveWindow(ob_display
, self
->lgrip
,
526 -self
->bwidth
, -self
->bwidth
);
527 XMoveWindow(ob_display
, self
->rgrip
,
528 -self
->bwidth
+ self
->width
-
529 GRIP_WIDTH
, -self
->bwidth
);
530 self
->innersize
.bottom
+= ob_s_handle_height
+
532 XMapWindow(ob_display
, self
->handle
);
534 if (ob_a_focused_grip
->surface
.data
.planar
.grad
==
535 Background_ParentRelative
)
536 RECT_SET(self
->a_focused_handle
->area
, 0, 0,
537 self
->width
, ob_s_handle_height
);
539 RECT_SET(self
->a_focused_handle
->area
,
540 GRIP_WIDTH
+ self
->bwidth
, 0,
541 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
543 if (ob_a_unfocused_grip
->surface
.data
.planar
.grad
==
544 Background_ParentRelative
)
545 RECT_SET(self
->a_unfocused_handle
->area
, 0, 0,
546 self
->width
, ob_s_handle_height
);
548 RECT_SET(self
->a_unfocused_handle
->area
,
549 GRIP_WIDTH
+ self
->bwidth
, 0,
550 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
554 XUnmapWindow(ob_display
, self
->handle
);
558 /* move and resize the plate */
559 XMoveResizeWindow(ob_display
, self
->frame
.plate
,
560 self
->innersize
.left
- self
->cbwidth
,
561 self
->innersize
.top
- self
->cbwidth
,
562 self
->frame
.client
->area
.width
,
563 self
->frame
.client
->area
.height
);
564 /* when the client has StaticGravity, it likes to move around. */
565 XMoveWindow(ob_display
, self
->frame
.client
->window
, 0, 0);
569 STRUT_SET(self
->frame
.size
,
570 self
->innersize
.left
+ self
->bwidth
,
571 self
->innersize
.top
+ self
->bwidth
,
572 self
->innersize
.right
+ self
->bwidth
,
573 self
->innersize
.bottom
+ self
->bwidth
);
576 /* shading can change without being moved or resized */
577 RECT_SET_SIZE(self
->frame
.area
,
578 self
->frame
.client
->area
.width
+
579 self
->frame
.size
.left
+ self
->frame
.size
.right
,
580 (self
->frame
.client
->shaded
? TITLE_HEIGHT
+ self
->bwidth
*2:
581 self
->frame
.client
->area
.height
+
582 self
->frame
.size
.top
+ self
->frame
.size
.bottom
));
585 /* find the new coordinates, done after setting the frame.size, for
586 frame_client_gravity. */
587 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
588 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
589 frame_client_gravity((Frame
*)self
,
590 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
593 /* move and resize the top level frame.
594 shading can change without being moved or resized */
595 XMoveResizeWindow(ob_display
, self
->frame
.window
,
596 self
->frame
.area
.x
, self
->frame
.area
.y
,
598 self
->frame
.area
.height
- self
->bwidth
* 2);
601 obrender_frame(self
);
603 frame_adjust_shape(self
);
607 void frame_adjust_state(ObFrame
*self
)
609 obrender_frame(self
);
612 void frame_adjust_focus(ObFrame
*self
)
614 obrender_frame(self
);
617 void frame_adjust_title(ObFrame
*self
)
619 obrender_frame(self
);
622 void frame_adjust_icon(ObFrame
*self
)
624 obrender_frame(self
);
627 void frame_grab_client(ObFrame
*self
, Client
*client
)
629 self
->frame
.client
= client
;
631 /* reparent the client to the frame */
632 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
634 When reparenting the client window, it is usually not mapped yet, since
635 this occurs from a MapRequest. However, in the case where Openbox is
636 starting up, the window is already mapped, so we'll see unmap events for
637 it. There are 2 unmap events generated that we see, one with the 'event'
638 member set the root window, and one set to the client, but both get
639 handled and need to be ignored.
641 if (ob_state
== State_Starting
)
642 client
->ignore_unmaps
+= 2;
644 /* select the event mask on the client's parent (to receive config/map
645 req's) the ButtonPress is to catch clicks on the client border */
646 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
648 /* map the client so it maps when the frame does */
649 XMapWindow(ob_display
, client
->window
);
651 frame_adjust_area(self
, TRUE
, TRUE
);
653 /* set all the windows for the frame in the client_map */
654 g_hash_table_insert(client_map
, &self
->frame
.window
, client
);
655 g_hash_table_insert(client_map
, &self
->frame
.plate
, client
);
656 g_hash_table_insert(client_map
, &self
->title
, client
);
657 g_hash_table_insert(client_map
, &self
->label
, client
);
658 g_hash_table_insert(client_map
, &self
->max
, client
);
659 g_hash_table_insert(client_map
, &self
->close
, client
);
660 g_hash_table_insert(client_map
, &self
->desk
, client
);
661 g_hash_table_insert(client_map
, &self
->shade
, client
);
662 g_hash_table_insert(client_map
, &self
->icon
, client
);
663 g_hash_table_insert(client_map
, &self
->iconify
, client
);
664 g_hash_table_insert(client_map
, &self
->handle
, client
);
665 g_hash_table_insert(client_map
, &self
->lgrip
, client
);
666 g_hash_table_insert(client_map
, &self
->rgrip
, client
);
669 void frame_release_client(ObFrame
*self
, Client
*client
)
673 g_assert(self
->frame
.client
== client
);
675 /* check if the app has already reparented its window away */
676 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
677 ReparentNotify
, &ev
)) {
678 XPutBackEvent(ob_display
, &ev
);
679 /* re-map the window since the unmanaging process unmaps it */
680 XMapWindow(ob_display
, client
->window
);
682 /* according to the ICCCM - if the client doesn't reparent itself,
683 then we will reparent the window to root for them */
684 XReparentWindow(ob_display
, client
->window
, ob_root
,
689 /* remove all the windows for the frame from the client_map */
690 g_hash_table_remove(client_map
, &self
->frame
.window
);
691 g_hash_table_remove(client_map
, &self
->frame
.plate
);
692 g_hash_table_remove(client_map
, &self
->title
);
693 g_hash_table_remove(client_map
, &self
->label
);
694 g_hash_table_remove(client_map
, &self
->max
);
695 g_hash_table_remove(client_map
, &self
->close
);
696 g_hash_table_remove(client_map
, &self
->desk
);
697 g_hash_table_remove(client_map
, &self
->shade
);
698 g_hash_table_remove(client_map
, &self
->icon
);
699 g_hash_table_remove(client_map
, &self
->iconify
);
700 g_hash_table_remove(client_map
, &self
->handle
);
701 g_hash_table_remove(client_map
, &self
->lgrip
);
702 g_hash_table_remove(client_map
, &self
->rgrip
);
707 static void layout_title(ObFrame
*self
)
711 gboolean n
, d
, i
, l
, m
, c
, s
;
714 n
= d
= i
= l
= m
= c
= s
= FALSE
;
716 if (!config_get("titlebar.layout", Config_String
, &layout
))
717 g_assert_not_reached();
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");