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
;
40 /* style settings - masks */
41 pixmap_mask
*ob_s_max_set_mask
;
42 pixmap_mask
*ob_s_max_unset_mask
;
43 pixmap_mask
*ob_s_iconify_mask
;
44 pixmap_mask
*ob_s_desk_set_mask
;
45 pixmap_mask
*ob_s_desk_unset_mask
;
46 pixmap_mask
*ob_s_shade_set_mask
;
47 pixmap_mask
*ob_s_shade_unset_mask
;
48 pixmap_mask
*ob_s_close_mask
;
50 /* global appearances */
51 Appearance
*ob_a_focused_unpressed_max
;
52 Appearance
*ob_a_focused_pressed_max
;
53 Appearance
*ob_a_focused_pressed_set_max
;
54 Appearance
*ob_a_unfocused_unpressed_max
;
55 Appearance
*ob_a_unfocused_pressed_max
;
56 Appearance
*ob_a_unfocused_pressed_set_max
;
57 Appearance
*ob_a_focused_unpressed_close
;
58 Appearance
*ob_a_focused_pressed_close
;
59 Appearance
*ob_a_unfocused_unpressed_close
;
60 Appearance
*ob_a_unfocused_pressed_close
;
61 Appearance
*ob_a_focused_unpressed_desk
;
62 Appearance
*ob_a_focused_pressed_desk
;
63 Appearance
*ob_a_focused_pressed_set_desk
;
64 Appearance
*ob_a_unfocused_unpressed_desk
;
65 Appearance
*ob_a_unfocused_pressed_desk
;
66 Appearance
*ob_a_unfocused_pressed_set_desk
;
67 Appearance
*ob_a_focused_unpressed_shade
;
68 Appearance
*ob_a_focused_pressed_shade
;
69 Appearance
*ob_a_focused_pressed_set_shade
;
70 Appearance
*ob_a_unfocused_unpressed_shade
;
71 Appearance
*ob_a_unfocused_pressed_shade
;
72 Appearance
*ob_a_unfocused_pressed_set_shade
;
73 Appearance
*ob_a_focused_unpressed_iconify
;
74 Appearance
*ob_a_focused_pressed_iconify
;
75 Appearance
*ob_a_unfocused_unpressed_iconify
;
76 Appearance
*ob_a_unfocused_pressed_iconify
;
77 Appearance
*ob_a_focused_grip
;
78 Appearance
*ob_a_unfocused_grip
;
79 Appearance
*ob_a_focused_title
;
80 Appearance
*ob_a_unfocused_title
;
81 Appearance
*ob_a_focused_label
;
82 Appearance
*ob_a_unfocused_label
;
83 Appearance
*ob_a_icon
; /* always parentrelative, so no focused/unfocused */
84 Appearance
*ob_a_focused_handle
;
85 Appearance
*ob_a_unfocused_handle
;
87 static void layout_title(ObFrame
*self
);
88 static void mouse_event(const ObEvent
*e
, ObFrame
*self
);
94 g_quark_from_string("none");
95 g_quark_from_string("root");
96 g_quark_from_string("client");
97 g_quark_from_string("titlebar");
98 g_quark_from_string("handle");
99 g_quark_from_string("frame");
100 g_quark_from_string("blcorner");
101 g_quark_from_string("brcorner");
102 g_quark_from_string("maximize");
103 g_quark_from_string("alldesktops");
104 g_quark_from_string("shade");
105 g_quark_from_string("iconify");
106 g_quark_from_string("icon");
107 g_quark_from_string("close");
109 /* create the ~/.openbox/themes/openbox dir */
110 path
= g_build_filename(g_get_home_dir(), ".openbox", "themes", "openbox",
112 mkdir(path
, (S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
|
113 S_IROTH
| S_IWOTH
| S_IXOTH
));
116 ob_s_b_color
= ob_s_cb_unfocused_color
= ob_s_cb_focused_color
=
117 ob_s_title_unfocused_color
= ob_s_title_focused_color
=
118 ob_s_titlebut_unfocused_color
= ob_s_titlebut_focused_color
= NULL
;
120 ob_s_max_set_mask
= ob_s_max_unset_mask
= NULL
;
121 ob_s_desk_set_mask
= ob_s_desk_unset_mask
= NULL
;
122 ob_s_shade_set_mask
= ob_s_shade_unset_mask
= NULL
;
123 ob_s_iconify_mask
= ob_s_close_mask
= NULL
;
125 ob_a_focused_unpressed_max
= appearance_new(Surface_Planar
, 1);
126 ob_a_focused_pressed_max
= appearance_new(Surface_Planar
, 1);
127 ob_a_focused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
128 ob_a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 1);
129 ob_a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 1);
130 ob_a_unfocused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
131 ob_a_focused_unpressed_close
= NULL
;
132 ob_a_focused_pressed_close
= NULL
;
133 ob_a_unfocused_unpressed_close
= NULL
;
134 ob_a_unfocused_pressed_close
= NULL
;
135 ob_a_focused_unpressed_desk
= NULL
;
136 ob_a_focused_pressed_desk
= NULL
;
137 ob_a_focused_pressed_set_desk
= NULL
;
138 ob_a_unfocused_unpressed_desk
= NULL
;
139 ob_a_unfocused_pressed_desk
= NULL
;
140 ob_a_unfocused_pressed_set_desk
= NULL
;
141 ob_a_focused_unpressed_shade
= NULL
;
142 ob_a_focused_pressed_shade
= NULL
;
143 ob_a_focused_pressed_set_shade
= NULL
;
144 ob_a_unfocused_unpressed_shade
= NULL
;
145 ob_a_unfocused_pressed_shade
= NULL
;
146 ob_a_unfocused_pressed_set_shade
= NULL
;
147 ob_a_focused_unpressed_iconify
= NULL
;
148 ob_a_focused_pressed_iconify
= NULL
;
149 ob_a_unfocused_unpressed_iconify
= NULL
;
150 ob_a_unfocused_pressed_iconify
= NULL
;
151 ob_a_focused_grip
= appearance_new(Surface_Planar
, 0);
152 ob_a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
153 ob_a_focused_title
= appearance_new(Surface_Planar
, 0);
154 ob_a_unfocused_title
= appearance_new(Surface_Planar
, 0);
155 ob_a_focused_label
= appearance_new(Surface_Planar
, 1);
156 ob_a_unfocused_label
= appearance_new(Surface_Planar
, 1);
157 ob_a_icon
= appearance_new(Surface_Planar
, 1);
158 ob_a_focused_handle
= appearance_new(Surface_Planar
, 0);
159 ob_a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
161 if (obtheme_load()) {
162 RECT_SET(ob_a_focused_pressed_desk
->area
, 0, 0,
163 BUTTON_SIZE
, BUTTON_SIZE
);
164 RECT_SET(ob_a_focused_pressed_set_desk
->area
, 0, 0,
165 BUTTON_SIZE
, BUTTON_SIZE
);
166 RECT_SET(ob_a_focused_unpressed_desk
->area
, 0, 0,
167 BUTTON_SIZE
, BUTTON_SIZE
);
168 RECT_SET(ob_a_unfocused_pressed_desk
->area
, 0, 0,
169 BUTTON_SIZE
, BUTTON_SIZE
);
170 RECT_SET(ob_a_unfocused_pressed_set_desk
->area
, 0, 0,
171 BUTTON_SIZE
, BUTTON_SIZE
);
172 RECT_SET(ob_a_unfocused_unpressed_desk
->area
, 0, 0,
173 BUTTON_SIZE
, BUTTON_SIZE
);
174 RECT_SET(ob_a_focused_pressed_shade
->area
, 0, 0,
175 BUTTON_SIZE
, BUTTON_SIZE
);
176 RECT_SET(ob_a_focused_pressed_set_shade
->area
, 0, 0,
177 BUTTON_SIZE
, BUTTON_SIZE
);
178 RECT_SET(ob_a_focused_unpressed_shade
->area
, 0, 0,
179 BUTTON_SIZE
, BUTTON_SIZE
);
180 RECT_SET(ob_a_unfocused_pressed_shade
->area
, 0, 0,
181 BUTTON_SIZE
, BUTTON_SIZE
);
182 RECT_SET(ob_a_unfocused_pressed_set_shade
->area
, 0, 0,
183 BUTTON_SIZE
, BUTTON_SIZE
);
184 RECT_SET(ob_a_unfocused_unpressed_shade
->area
, 0, 0,
185 BUTTON_SIZE
, BUTTON_SIZE
);
186 RECT_SET(ob_a_focused_pressed_iconify
->area
, 0, 0,
187 BUTTON_SIZE
, BUTTON_SIZE
);
188 RECT_SET(ob_a_focused_unpressed_iconify
->area
, 0, 0,
189 BUTTON_SIZE
, BUTTON_SIZE
);
190 RECT_SET(ob_a_unfocused_pressed_iconify
->area
, 0, 0,
191 BUTTON_SIZE
, BUTTON_SIZE
);
192 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
193 BUTTON_SIZE
, BUTTON_SIZE
);
194 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
195 BUTTON_SIZE
, BUTTON_SIZE
);
196 RECT_SET(ob_a_focused_pressed_max
->area
, 0, 0,
197 BUTTON_SIZE
, BUTTON_SIZE
);
198 RECT_SET(ob_a_focused_pressed_set_max
->area
, 0, 0,
199 BUTTON_SIZE
, BUTTON_SIZE
);
200 RECT_SET(ob_a_focused_unpressed_max
->area
, 0, 0,
201 BUTTON_SIZE
, BUTTON_SIZE
);
202 RECT_SET(ob_a_unfocused_pressed_max
->area
, 0, 0,
203 BUTTON_SIZE
, BUTTON_SIZE
);
204 RECT_SET(ob_a_unfocused_pressed_set_max
->area
, 0, 0,
205 BUTTON_SIZE
, BUTTON_SIZE
);
206 RECT_SET(ob_a_unfocused_unpressed_max
->area
, 0, 0,
207 BUTTON_SIZE
, BUTTON_SIZE
);
208 RECT_SET(ob_a_focused_pressed_close
->area
, 0, 0,
209 BUTTON_SIZE
, BUTTON_SIZE
);
210 RECT_SET(ob_a_focused_unpressed_close
->area
, 0, 0,
211 BUTTON_SIZE
, BUTTON_SIZE
);
212 RECT_SET(ob_a_unfocused_pressed_close
->area
, 0, 0,
213 BUTTON_SIZE
, BUTTON_SIZE
);
214 RECT_SET(ob_a_unfocused_unpressed_close
->area
, 0, 0,
215 BUTTON_SIZE
, BUTTON_SIZE
);
217 RECT_SET(ob_a_focused_grip
->area
, 0, 0,
218 GRIP_WIDTH
, ob_s_handle_height
);
219 RECT_SET(ob_a_unfocused_grip
->area
, 0, 0,
220 GRIP_WIDTH
, ob_s_handle_height
);
228 if (ob_s_b_color
!= NULL
) color_free(ob_s_b_color
);
229 if (ob_s_cb_unfocused_color
!= NULL
) color_free(ob_s_cb_unfocused_color
);
230 if (ob_s_cb_focused_color
!= NULL
) color_free(ob_s_cb_focused_color
);
231 if (ob_s_title_unfocused_color
!= NULL
) color_free(ob_s_title_unfocused_color
);
232 if (ob_s_title_focused_color
!= NULL
) color_free(ob_s_title_focused_color
);
233 if (ob_s_titlebut_unfocused_color
!= NULL
)
234 color_free(ob_s_titlebut_unfocused_color
);
235 if (ob_s_titlebut_focused_color
!= NULL
)
236 color_free(ob_s_titlebut_focused_color
);
238 if (ob_s_max_set_mask
!= NULL
)
239 pixmap_mask_free(ob_s_max_set_mask
);
240 if (ob_s_max_unset_mask
!= NULL
)
241 pixmap_mask_free(ob_s_max_unset_mask
);
242 if (ob_s_desk_set_mask
!= NULL
)
243 pixmap_mask_free(ob_s_desk_set_mask
);
244 if (ob_s_desk_unset_mask
!= NULL
)
245 pixmap_mask_free(ob_s_desk_unset_mask
);
246 if (ob_s_shade_set_mask
!= NULL
)
247 pixmap_mask_free(ob_s_shade_set_mask
);
248 if (ob_s_shade_unset_mask
!= NULL
)
249 pixmap_mask_free(ob_s_shade_unset_mask
);
250 if (ob_s_iconify_mask
!= NULL
)
251 pixmap_mask_free(ob_s_iconify_mask
);
252 if (ob_s_close_mask
!= NULL
)
253 pixmap_mask_free(ob_s_close_mask
);
255 if (ob_s_winfont
!= NULL
) font_close(ob_s_winfont
);
257 appearance_free(ob_a_focused_unpressed_max
);
258 appearance_free(ob_a_focused_pressed_max
);
259 appearance_free(ob_a_focused_pressed_set_max
);
260 appearance_free(ob_a_unfocused_unpressed_max
);
261 appearance_free(ob_a_unfocused_pressed_max
);
262 appearance_free(ob_a_unfocused_pressed_set_max
);
263 if (ob_a_focused_unpressed_close
!= NULL
)
264 appearance_free(ob_a_focused_unpressed_close
);
265 if (ob_a_focused_pressed_close
!= NULL
)
266 appearance_free(ob_a_focused_pressed_close
);
267 if (ob_a_unfocused_unpressed_close
!= NULL
)
268 appearance_free(ob_a_unfocused_unpressed_close
);
269 if (ob_a_unfocused_pressed_close
!= NULL
)
270 appearance_free(ob_a_unfocused_pressed_close
);
271 if (ob_a_focused_unpressed_desk
!= NULL
)
272 appearance_free(ob_a_focused_unpressed_desk
);
273 if (ob_a_focused_pressed_desk
!= NULL
)
274 appearance_free(ob_a_focused_pressed_desk
);
275 if (ob_a_unfocused_unpressed_desk
!= NULL
)
276 appearance_free(ob_a_unfocused_unpressed_desk
);
277 if (ob_a_unfocused_pressed_desk
!= NULL
)
278 appearance_free(ob_a_unfocused_pressed_desk
);
279 if (ob_a_focused_unpressed_shade
!= NULL
)
280 appearance_free(ob_a_focused_unpressed_shade
);
281 if (ob_a_focused_pressed_shade
!= NULL
)
282 appearance_free(ob_a_focused_pressed_shade
);
283 if (ob_a_unfocused_unpressed_shade
!= NULL
)
284 appearance_free(ob_a_unfocused_unpressed_shade
);
285 if (ob_a_unfocused_pressed_shade
!= NULL
)
286 appearance_free(ob_a_unfocused_pressed_shade
);
287 if (ob_a_focused_unpressed_iconify
!= NULL
)
288 appearance_free(ob_a_focused_unpressed_iconify
);
289 if (ob_a_focused_pressed_iconify
!= NULL
)
290 appearance_free(ob_a_focused_pressed_iconify
);
291 if (ob_a_unfocused_unpressed_iconify
!= NULL
)
292 appearance_free(ob_a_unfocused_unpressed_iconify
);
293 if (ob_a_unfocused_pressed_iconify
!= NULL
)
294 appearance_free(ob_a_unfocused_pressed_iconify
);
295 appearance_free(ob_a_focused_grip
);
296 appearance_free(ob_a_unfocused_grip
);
297 appearance_free(ob_a_focused_title
);
298 appearance_free(ob_a_unfocused_title
);
299 appearance_free(ob_a_focused_label
);
300 appearance_free(ob_a_unfocused_label
);
301 appearance_free(ob_a_icon
);
302 appearance_free(ob_a_focused_handle
);
303 appearance_free(ob_a_unfocused_handle
);
306 static Window
createWindow(Window parent
, unsigned long mask
,
307 XSetWindowAttributes
*attrib
)
309 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
310 render_depth
, InputOutput
, render_visual
,
317 XSetWindowAttributes attrib
;
321 self
= g_new(ObFrame
, 1);
323 self
->frame
.visible
= FALSE
;
325 /* create all of the decor windows */
326 mask
= CWOverrideRedirect
| CWEventMask
;
327 attrib
.event_mask
= FRAME_EVENTMASK
;
328 attrib
.override_redirect
= TRUE
;
329 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
332 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
335 attrib
.event_mask
= ELEMENT_EVENTMASK
;
336 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
337 self
->label
= createWindow(self
->title
, mask
, &attrib
);
338 self
->max
= createWindow(self
->title
, mask
, &attrib
);
339 self
->close
= createWindow(self
->title
, mask
, &attrib
);
340 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
341 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
342 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
343 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
344 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
346 attrib
.cursor
= ob_cursors
.ll_angle
;
347 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
348 attrib
.cursor
= ob_cursors
.lr_angle
;
349 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
351 /* the other stuff is shown based on decor settings */
352 XMapWindow(ob_display
, self
->frame
.plate
);
353 XMapWindow(ob_display
, self
->lgrip
);
354 XMapWindow(ob_display
, self
->rgrip
);
355 XMapWindow(ob_display
, self
->label
);
357 /* set colors/appearance/sizes for stuff that doesn't change */
358 XSetWindowBorder(ob_display
, self
->frame
.window
, ob_s_b_color
->pixel
);
359 XSetWindowBorder(ob_display
, self
->label
, ob_s_b_color
->pixel
);
360 XSetWindowBorder(ob_display
, self
->rgrip
, ob_s_b_color
->pixel
);
361 XSetWindowBorder(ob_display
, self
->lgrip
, ob_s_b_color
->pixel
);
363 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
364 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
365 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
366 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
367 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
368 XResizeWindow(ob_display
, self
->shade
, BUTTON_SIZE
, BUTTON_SIZE
);
369 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, ob_s_handle_height
);
370 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, ob_s_handle_height
);
372 /* set up the dynamic appearances */
373 self
->a_unfocused_title
= appearance_copy(ob_a_unfocused_title
);
374 self
->a_focused_title
= appearance_copy(ob_a_focused_title
);
375 self
->a_unfocused_label
= appearance_copy(ob_a_unfocused_label
);
376 self
->a_focused_label
= appearance_copy(ob_a_focused_label
);
377 self
->a_unfocused_handle
= appearance_copy(ob_a_unfocused_handle
);
378 self
->a_focused_handle
= appearance_copy(ob_a_focused_handle
);
379 self
->a_icon
= appearance_copy(ob_a_icon
);
381 self
->max_press
= self
->close_press
= self
->desk_press
=
382 self
->iconify_press
= self
->shade_press
= FALSE
;
384 dispatch_register(Event_X_ButtonPress
| Event_X_ButtonRelease
,
385 (EventHandler
)mouse_event
, self
);
390 static void frame_free(ObFrame
*self
)
392 appearance_free(self
->a_unfocused_title
);
393 appearance_free(self
->a_focused_title
);
394 appearance_free(self
->a_unfocused_label
);
395 appearance_free(self
->a_focused_label
);
396 appearance_free(self
->a_unfocused_handle
);
397 appearance_free(self
->a_focused_handle
);
398 appearance_free(self
->a_icon
);
400 XDestroyWindow(ob_display
, self
->frame
.window
);
402 dispatch_register(0, (EventHandler
)mouse_event
, self
);
407 void frame_show(ObFrame
*self
)
409 if (!self
->frame
.visible
) {
410 self
->frame
.visible
= TRUE
;
411 XMapWindow(ob_display
, self
->frame
.window
);
415 void frame_hide(ObFrame
*self
)
417 if (self
->frame
.visible
) {
418 self
->frame
.visible
= FALSE
;
419 self
->frame
.client
->ignore_unmaps
++;
420 XUnmapWindow(ob_display
, self
->frame
.window
);
424 void frame_adjust_shape(ObFrame
*self
)
430 if (!self
->frame
.client
->shaped
) {
431 /* clear the shape on the frame window */
432 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
433 self
->innersize
.left
,
437 /* make the frame's shape match the clients */
438 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
439 self
->innersize
.left
,
441 self
->frame
.client
->window
,
442 ShapeBounding
, ShapeSet
);
445 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
446 xrect
[0].x
= -ob_s_bevel
;
447 xrect
[0].y
= -ob_s_bevel
;
448 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
449 xrect
[0].height
= TITLE_HEIGHT
+
454 if (self
->frame
.client
->decorations
& Decor_Handle
) {
455 xrect
[1].x
= -ob_s_bevel
;
456 xrect
[1].y
= HANDLE_Y(self
);
457 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
458 xrect
[1].height
= ob_s_handle_height
+
463 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
464 ShapeBounding
, 0, 0, xrect
, num
,
465 ShapeUnion
, Unsorted
);
470 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
473 if (self
->frame
.client
->decorations
& Decor_Border
) {
474 self
->bwidth
= ob_s_bwidth
;
475 self
->cbwidth
= ob_s_cbwidth
;
477 self
->bwidth
= self
->cbwidth
= 0;
479 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
480 self
->cbwidth
, self
->cbwidth
);
481 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
482 g_assert(self
->width
> 0);
484 /* set border widths */
485 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
486 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
487 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
488 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
489 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
490 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
492 /* position/size and map/unmap all the windows */
494 /* they all default off, they're turned on in layout_title */
503 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
504 XMoveResizeWindow(ob_display
, self
->title
,
505 -self
->bwidth
, -self
->bwidth
,
506 self
->width
, TITLE_HEIGHT
);
507 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
508 XMapWindow(ob_display
, self
->title
);
510 RECT_SET(self
->a_focused_title
->area
, 0, 0,
511 self
->width
, TITLE_HEIGHT
);
512 RECT_SET(self
->a_unfocused_title
->area
, 0, 0,
513 self
->width
, TITLE_HEIGHT
);
515 /* layout the title bar elements */
518 XUnmapWindow(ob_display
, self
->title
);
520 if (self
->frame
.client
->decorations
& Decor_Handle
) {
521 XMoveResizeWindow(ob_display
, self
->handle
,
522 -self
->bwidth
, HANDLE_Y(self
),
523 self
->width
, ob_s_handle_height
);
524 XMoveWindow(ob_display
, self
->lgrip
,
525 -self
->bwidth
, -self
->bwidth
);
526 XMoveWindow(ob_display
, self
->rgrip
,
527 -self
->bwidth
+ self
->width
-
528 GRIP_WIDTH
, -self
->bwidth
);
529 self
->innersize
.bottom
+= ob_s_handle_height
+
531 XMapWindow(ob_display
, self
->handle
);
533 if (self
->a_focused_handle
->surface
.data
.planar
.grad
==
534 Background_ParentRelative
)
535 RECT_SET(self
->a_focused_handle
->area
, 0, 0,
536 self
->width
, ob_s_handle_height
);
538 RECT_SET(self
->a_focused_handle
->area
,
539 GRIP_WIDTH
+ self
->bwidth
, 0,
540 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
542 if (self
->a_unfocused_handle
->surface
.data
.planar
.grad
==
543 Background_ParentRelative
)
544 RECT_SET(self
->a_unfocused_handle
->area
, 0, 0,
545 self
->width
, ob_s_handle_height
);
547 RECT_SET(self
->a_unfocused_handle
->area
,
548 GRIP_WIDTH
+ self
->bwidth
, 0,
549 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
553 XUnmapWindow(ob_display
, self
->handle
);
557 /* move and resize the plate */
558 XMoveResizeWindow(ob_display
, self
->frame
.plate
,
559 self
->innersize
.left
- self
->cbwidth
,
560 self
->innersize
.top
- self
->cbwidth
,
561 self
->frame
.client
->area
.width
,
562 self
->frame
.client
->area
.height
);
563 /* when the client has StaticGravity, it likes to move around. */
564 XMoveWindow(ob_display
, self
->frame
.client
->window
, 0, 0);
568 STRUT_SET(self
->frame
.size
,
569 self
->innersize
.left
+ self
->bwidth
,
570 self
->innersize
.top
+ self
->bwidth
,
571 self
->innersize
.right
+ self
->bwidth
,
572 self
->innersize
.bottom
+ self
->bwidth
);
575 /* shading can change without being moved or resized */
576 RECT_SET_SIZE(self
->frame
.area
,
577 self
->frame
.client
->area
.width
+
578 self
->frame
.size
.left
+ self
->frame
.size
.right
,
579 (self
->frame
.client
->shaded
? TITLE_HEIGHT
+ self
->bwidth
*2:
580 self
->frame
.client
->area
.height
+
581 self
->frame
.size
.top
+ self
->frame
.size
.bottom
));
584 /* find the new coordinates, done after setting the frame.size, for
585 frame_client_gravity. */
586 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
587 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
588 frame_client_gravity((Frame
*)self
,
589 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
592 /* move and resize the top level frame.
593 shading can change without being moved or resized */
594 XMoveResizeWindow(ob_display
, self
->frame
.window
,
595 self
->frame
.area
.x
, self
->frame
.area
.y
,
597 self
->frame
.area
.height
- self
->bwidth
* 2);
600 obrender_frame(self
);
602 frame_adjust_shape(self
);
606 void frame_adjust_state(ObFrame
*self
)
608 obrender_frame(self
);
611 void frame_adjust_focus(ObFrame
*self
)
613 obrender_frame(self
);
616 void frame_adjust_title(ObFrame
*self
)
618 obrender_frame(self
);
621 void frame_adjust_icon(ObFrame
*self
)
623 obrender_frame(self
);
626 void frame_grab_client(ObFrame
*self
, Client
*client
)
628 self
->frame
.client
= client
;
630 /* reparent the client to the frame */
631 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
633 When reparenting the client window, it is usually not mapped yet, since
634 this occurs from a MapRequest. However, in the case where Openbox is
635 starting up, the window is already mapped, so we'll see unmap events for
636 it. There are 2 unmap events generated that we see, one with the 'event'
637 member set the root window, and one set to the client, but both get
638 handled and need to be ignored.
640 if (ob_state
== State_Starting
)
641 client
->ignore_unmaps
+= 2;
643 /* select the event mask on the client's parent (to receive config/map
644 req's) the ButtonPress is to catch clicks on the client border */
645 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
647 /* map the client so it maps when the frame does */
648 XMapWindow(ob_display
, client
->window
);
650 frame_adjust_area(self
, TRUE
, TRUE
);
652 /* set all the windows for the frame in the client_map */
653 g_hash_table_insert(client_map
, &self
->frame
.window
, client
);
654 g_hash_table_insert(client_map
, &self
->frame
.plate
, client
);
655 g_hash_table_insert(client_map
, &self
->title
, client
);
656 g_hash_table_insert(client_map
, &self
->label
, client
);
657 g_hash_table_insert(client_map
, &self
->max
, client
);
658 g_hash_table_insert(client_map
, &self
->close
, client
);
659 g_hash_table_insert(client_map
, &self
->desk
, client
);
660 g_hash_table_insert(client_map
, &self
->shade
, client
);
661 g_hash_table_insert(client_map
, &self
->icon
, client
);
662 g_hash_table_insert(client_map
, &self
->iconify
, client
);
663 g_hash_table_insert(client_map
, &self
->handle
, client
);
664 g_hash_table_insert(client_map
, &self
->lgrip
, client
);
665 g_hash_table_insert(client_map
, &self
->rgrip
, client
);
668 void frame_release_client(ObFrame
*self
, Client
*client
)
672 g_assert(self
->frame
.client
== client
);
674 /* check if the app has already reparented its window away */
675 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
676 ReparentNotify
, &ev
)) {
677 XPutBackEvent(ob_display
, &ev
);
678 /* re-map the window since the unmanaging process unmaps it */
679 XMapWindow(ob_display
, client
->window
);
681 /* according to the ICCCM - if the client doesn't reparent itself,
682 then we will reparent the window to root for them */
683 XReparentWindow(ob_display
, client
->window
, ob_root
,
688 /* remove all the windows for the frame from the client_map */
689 g_hash_table_remove(client_map
, &self
->frame
.window
);
690 g_hash_table_remove(client_map
, &self
->frame
.plate
);
691 g_hash_table_remove(client_map
, &self
->title
);
692 g_hash_table_remove(client_map
, &self
->label
);
693 g_hash_table_remove(client_map
, &self
->max
);
694 g_hash_table_remove(client_map
, &self
->close
);
695 g_hash_table_remove(client_map
, &self
->desk
);
696 g_hash_table_remove(client_map
, &self
->shade
);
697 g_hash_table_remove(client_map
, &self
->icon
);
698 g_hash_table_remove(client_map
, &self
->iconify
);
699 g_hash_table_remove(client_map
, &self
->handle
);
700 g_hash_table_remove(client_map
, &self
->lgrip
);
701 g_hash_table_remove(client_map
, &self
->rgrip
);
706 static void layout_title(ObFrame
*self
)
710 gboolean n
, d
, i
, l
, m
, c
, s
;
713 n
= d
= i
= l
= m
= c
= s
= FALSE
;
715 if (!config_get("titlebar.layout", Config_String
, &layout
)) {
716 layout
.string
= "NDSLIMC";
717 config_set("titlebar.layout", Config_String
, layout
);
720 /* figure out whats being shown, and the width of the label */
721 self
->label_width
= self
->width
- (ob_s_bevel
+ 1) * 2;
722 for (lc
= layout
.string
; *lc
!= '\0'; ++lc
) {
725 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
726 if (n
) { *lc
= ' '; break; } /* rm duplicates */
728 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
731 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
732 if (d
) { *lc
= ' '; break; } /* rm duplicates */
734 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
737 if (!(self
->frame
.client
->decorations
& Decor_Shade
)) break;
738 if (s
) { *lc
= ' '; break; } /* rm duplicates */
740 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
743 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
744 if (i
) { *lc
= ' '; break; } /* rm duplicates */
746 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
749 if (l
) { *lc
= ' '; break; } /* rm duplicates */
753 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
754 if (m
) { *lc
= ' '; break; } /* rm duplicates */
756 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
759 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
760 if (c
) { *lc
= ' '; break; } /* rm duplicates */
762 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
766 if (self
->label_width
< 1) self
->label_width
= 1;
768 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
771 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
772 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
773 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
774 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
775 if (!l
) XUnmapWindow(ob_display
, self
->label
);
776 if (!m
) XUnmapWindow(ob_display
, self
->max
);
777 if (!c
) XUnmapWindow(ob_display
, self
->close
);
780 for (lc
= layout
.string
; *lc
!= '\0'; ++lc
) {
785 RECT_SET(self
->a_icon
->area
, 0, 0, BUTTON_SIZE
, BUTTON_SIZE
);
786 XMapWindow(ob_display
, self
->icon
);
787 XMoveWindow(ob_display
, self
->icon
, x
, ob_s_bevel
+ 1);
788 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
793 XMapWindow(ob_display
, self
->desk
);
794 XMoveWindow(ob_display
, self
->desk
, x
, ob_s_bevel
+ 1);
795 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
800 XMapWindow(ob_display
, self
->shade
);
801 XMoveWindow(ob_display
, self
->shade
, x
, ob_s_bevel
+ 1);
802 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
807 XMapWindow(ob_display
, self
->iconify
);
808 XMoveWindow(ob_display
, self
->iconify
, x
, ob_s_bevel
+ 1);
809 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
814 XMapWindow(ob_display
, self
->label
);
815 XMoveWindow(ob_display
, self
->label
, x
, ob_s_bevel
);
816 x
+= self
->label_width
+ ob_s_bevel
+ 1;
821 XMapWindow(ob_display
, self
->max
);
822 XMoveWindow(ob_display
, self
->max
, x
, ob_s_bevel
+ 1);
823 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
828 XMapWindow(ob_display
, self
->close
);
829 XMoveWindow(ob_display
, self
->close
, x
, ob_s_bevel
+ 1);
830 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
835 RECT_SET(self
->a_focused_label
->area
, 0, 0,
836 self
->label_width
, LABEL_HEIGHT
);
837 RECT_SET(self
->a_unfocused_label
->area
, 0, 0,
838 self
->label_width
, LABEL_HEIGHT
);
841 static void mouse_event(const ObEvent
*e
, ObFrame
*self
)
844 gboolean press
= e
->type
== Event_X_ButtonPress
;
846 win
= e
->data
.x
.e
->xbutton
.window
;
847 if (win
== self
->max
) {
848 self
->max_press
= press
;
849 obrender_frame(self
);
850 } else if (win
== self
->close
) {
851 self
->close_press
= press
;
852 obrender_frame(self
);
853 } else if (win
== self
->iconify
) {
854 self
->iconify_press
= press
;
855 obrender_frame(self
);
856 } else if (win
== self
->desk
) {
857 self
->desk_press
= press
;
858 obrender_frame(self
);
859 } else if (win
== self
->shade
) {
860 self
->shade_press
= press
;
861 obrender_frame(self
);
865 GQuark
get_context(Client
*client
, Window win
)
869 if (win
== ob_root
) return g_quark_try_string("root");
870 if (client
== NULL
) return g_quark_try_string("none");
871 if (win
== client
->window
) return g_quark_try_string("client");
873 self
= (ObFrame
*) client
->frame
;
874 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
875 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
876 if (win
== self
->title
) return g_quark_try_string("titlebar");
877 if (win
== self
->label
) return g_quark_try_string("titlebar");
878 if (win
== self
->handle
) return g_quark_try_string("handle");
879 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
880 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
881 if (win
== self
->max
) return g_quark_try_string("maximize");
882 if (win
== self
->iconify
) return g_quark_try_string("iconify");
883 if (win
== self
->close
) return g_quark_try_string("close");
884 if (win
== self
->icon
) return g_quark_try_string("icon");
885 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
886 if (win
== self
->shade
) return g_quark_try_string("shade");
888 return g_quark_try_string("none");