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
;
38 /* style settings - masks */
39 pixmap_mask
*ob_s_max_set_mask
;
40 pixmap_mask
*ob_s_max_unset_mask
;
41 pixmap_mask
*ob_s_iconify_mask
;
42 pixmap_mask
*ob_s_desk_set_mask
;
43 pixmap_mask
*ob_s_desk_unset_mask
;
44 pixmap_mask
*ob_s_shade_set_mask
;
45 pixmap_mask
*ob_s_shade_unset_mask
;
46 pixmap_mask
*ob_s_close_mask
;
48 /* global appearances */
49 Appearance
*ob_a_focused_unpressed_max
;
50 Appearance
*ob_a_focused_pressed_max
;
51 Appearance
*ob_a_focused_pressed_set_max
;
52 Appearance
*ob_a_unfocused_unpressed_max
;
53 Appearance
*ob_a_unfocused_pressed_max
;
54 Appearance
*ob_a_unfocused_pressed_set_max
;
55 Appearance
*ob_a_focused_unpressed_close
;
56 Appearance
*ob_a_focused_pressed_close
;
57 Appearance
*ob_a_unfocused_unpressed_close
;
58 Appearance
*ob_a_unfocused_pressed_close
;
59 Appearance
*ob_a_focused_unpressed_desk
;
60 Appearance
*ob_a_focused_pressed_desk
;
61 Appearance
*ob_a_focused_pressed_set_desk
;
62 Appearance
*ob_a_unfocused_unpressed_desk
;
63 Appearance
*ob_a_unfocused_pressed_desk
;
64 Appearance
*ob_a_unfocused_pressed_set_desk
;
65 Appearance
*ob_a_focused_unpressed_shade
;
66 Appearance
*ob_a_focused_pressed_shade
;
67 Appearance
*ob_a_focused_pressed_set_shade
;
68 Appearance
*ob_a_unfocused_unpressed_shade
;
69 Appearance
*ob_a_unfocused_pressed_shade
;
70 Appearance
*ob_a_unfocused_pressed_set_shade
;
71 Appearance
*ob_a_focused_unpressed_iconify
;
72 Appearance
*ob_a_focused_pressed_iconify
;
73 Appearance
*ob_a_unfocused_unpressed_iconify
;
74 Appearance
*ob_a_unfocused_pressed_iconify
;
75 Appearance
*ob_a_focused_grip
;
76 Appearance
*ob_a_unfocused_grip
;
77 Appearance
*ob_a_focused_title
;
78 Appearance
*ob_a_unfocused_title
;
79 Appearance
*ob_a_focused_label
;
80 Appearance
*ob_a_unfocused_label
;
81 Appearance
*ob_a_icon
; /* always parentrelative, so no focused/unfocused */
82 Appearance
*ob_a_focused_handle
;
83 Appearance
*ob_a_unfocused_handle
;
85 Appearance
*ob_app_hilite_label
;
86 Appearance
*ob_app_unhilite_label
;
88 static void layout_title(ObFrame
*self
);
89 static void mouse_event(const ObEvent
*e
, ObFrame
*self
);
95 /* create the ~/.openbox/themes/openbox dir */
96 path
= g_build_filename(g_get_home_dir(), ".openbox", "themes", "openbox",
98 mkdir(path
, (S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
|
99 S_IROTH
| S_IWOTH
| S_IXOTH
));
102 ob_s_b_color
= ob_s_cb_unfocused_color
= ob_s_cb_focused_color
=
103 ob_s_title_unfocused_color
= ob_s_title_focused_color
=
104 ob_s_titlebut_unfocused_color
= ob_s_titlebut_focused_color
= NULL
;
106 ob_s_max_set_mask
= ob_s_max_unset_mask
= NULL
;
107 ob_s_desk_set_mask
= ob_s_desk_unset_mask
= NULL
;
108 ob_s_shade_set_mask
= ob_s_shade_unset_mask
= NULL
;
109 ob_s_iconify_mask
= ob_s_close_mask
= NULL
;
111 ob_a_focused_unpressed_max
= appearance_new(Surface_Planar
, 1);
112 ob_a_focused_pressed_max
= appearance_new(Surface_Planar
, 1);
113 ob_a_focused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
114 ob_a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 1);
115 ob_a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 1);
116 ob_a_unfocused_pressed_set_max
= appearance_new(Surface_Planar
, 1);
117 ob_a_focused_unpressed_close
= NULL
;
118 ob_a_focused_pressed_close
= NULL
;
119 ob_a_unfocused_unpressed_close
= NULL
;
120 ob_a_unfocused_pressed_close
= NULL
;
121 ob_a_focused_unpressed_desk
= NULL
;
122 ob_a_focused_pressed_desk
= NULL
;
123 ob_a_focused_pressed_set_desk
= NULL
;
124 ob_a_unfocused_unpressed_desk
= NULL
;
125 ob_a_unfocused_pressed_desk
= NULL
;
126 ob_a_unfocused_pressed_set_desk
= NULL
;
127 ob_a_focused_unpressed_shade
= NULL
;
128 ob_a_focused_pressed_shade
= NULL
;
129 ob_a_focused_pressed_set_shade
= NULL
;
130 ob_a_unfocused_unpressed_shade
= NULL
;
131 ob_a_unfocused_pressed_shade
= NULL
;
132 ob_a_unfocused_pressed_set_shade
= NULL
;
133 ob_a_focused_unpressed_iconify
= NULL
;
134 ob_a_focused_pressed_iconify
= NULL
;
135 ob_a_unfocused_unpressed_iconify
= NULL
;
136 ob_a_unfocused_pressed_iconify
= NULL
;
137 ob_a_focused_grip
= appearance_new(Surface_Planar
, 0);
138 ob_a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
139 ob_a_focused_title
= appearance_new(Surface_Planar
, 0);
140 ob_a_unfocused_title
= appearance_new(Surface_Planar
, 0);
141 ob_a_focused_label
= appearance_new(Surface_Planar
, 1);
142 ob_a_unfocused_label
= appearance_new(Surface_Planar
, 1);
143 ob_a_icon
= appearance_new(Surface_Planar
, 1);
144 ob_a_focused_handle
= appearance_new(Surface_Planar
, 0);
145 ob_a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
146 ob_app_hilite_label
= appearance_new(Surface_Planar
, 1);
147 ob_app_unhilite_label
= appearance_new(Surface_Planar
, 1);
149 if (obtheme_load()) {
150 RECT_SET(ob_a_focused_pressed_desk
->area
, 0, 0,
151 BUTTON_SIZE
, BUTTON_SIZE
);
152 RECT_SET(ob_a_focused_pressed_set_desk
->area
, 0, 0,
153 BUTTON_SIZE
, BUTTON_SIZE
);
154 RECT_SET(ob_a_focused_unpressed_desk
->area
, 0, 0,
155 BUTTON_SIZE
, BUTTON_SIZE
);
156 RECT_SET(ob_a_unfocused_pressed_desk
->area
, 0, 0,
157 BUTTON_SIZE
, BUTTON_SIZE
);
158 RECT_SET(ob_a_unfocused_pressed_set_desk
->area
, 0, 0,
159 BUTTON_SIZE
, BUTTON_SIZE
);
160 RECT_SET(ob_a_unfocused_unpressed_desk
->area
, 0, 0,
161 BUTTON_SIZE
, BUTTON_SIZE
);
162 RECT_SET(ob_a_focused_pressed_shade
->area
, 0, 0,
163 BUTTON_SIZE
, BUTTON_SIZE
);
164 RECT_SET(ob_a_focused_pressed_set_shade
->area
, 0, 0,
165 BUTTON_SIZE
, BUTTON_SIZE
);
166 RECT_SET(ob_a_focused_unpressed_shade
->area
, 0, 0,
167 BUTTON_SIZE
, BUTTON_SIZE
);
168 RECT_SET(ob_a_unfocused_pressed_shade
->area
, 0, 0,
169 BUTTON_SIZE
, BUTTON_SIZE
);
170 RECT_SET(ob_a_unfocused_pressed_set_shade
->area
, 0, 0,
171 BUTTON_SIZE
, BUTTON_SIZE
);
172 RECT_SET(ob_a_unfocused_unpressed_shade
->area
, 0, 0,
173 BUTTON_SIZE
, BUTTON_SIZE
);
174 RECT_SET(ob_a_focused_pressed_iconify
->area
, 0, 0,
175 BUTTON_SIZE
, BUTTON_SIZE
);
176 RECT_SET(ob_a_focused_unpressed_iconify
->area
, 0, 0,
177 BUTTON_SIZE
, BUTTON_SIZE
);
178 RECT_SET(ob_a_unfocused_pressed_iconify
->area
, 0, 0,
179 BUTTON_SIZE
, BUTTON_SIZE
);
180 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
181 BUTTON_SIZE
, BUTTON_SIZE
);
182 RECT_SET(ob_a_unfocused_unpressed_iconify
->area
, 0, 0,
183 BUTTON_SIZE
, BUTTON_SIZE
);
184 RECT_SET(ob_a_focused_pressed_max
->area
, 0, 0,
185 BUTTON_SIZE
, BUTTON_SIZE
);
186 RECT_SET(ob_a_focused_pressed_set_max
->area
, 0, 0,
187 BUTTON_SIZE
, BUTTON_SIZE
);
188 RECT_SET(ob_a_focused_unpressed_max
->area
, 0, 0,
189 BUTTON_SIZE
, BUTTON_SIZE
);
190 RECT_SET(ob_a_unfocused_pressed_max
->area
, 0, 0,
191 BUTTON_SIZE
, BUTTON_SIZE
);
192 RECT_SET(ob_a_unfocused_pressed_set_max
->area
, 0, 0,
193 BUTTON_SIZE
, BUTTON_SIZE
);
194 RECT_SET(ob_a_unfocused_unpressed_max
->area
, 0, 0,
195 BUTTON_SIZE
, BUTTON_SIZE
);
196 RECT_SET(ob_a_focused_pressed_close
->area
, 0, 0,
197 BUTTON_SIZE
, BUTTON_SIZE
);
198 RECT_SET(ob_a_focused_unpressed_close
->area
, 0, 0,
199 BUTTON_SIZE
, BUTTON_SIZE
);
200 RECT_SET(ob_a_unfocused_pressed_close
->area
, 0, 0,
201 BUTTON_SIZE
, BUTTON_SIZE
);
202 RECT_SET(ob_a_unfocused_unpressed_close
->area
, 0, 0,
203 BUTTON_SIZE
, BUTTON_SIZE
);
205 RECT_SET(ob_a_focused_grip
->area
, 0, 0,
206 GRIP_WIDTH
, ob_s_handle_height
);
207 RECT_SET(ob_a_unfocused_grip
->area
, 0, 0,
208 GRIP_WIDTH
, ob_s_handle_height
);
216 if (ob_s_b_color
!= NULL
) color_free(ob_s_b_color
);
217 if (ob_s_cb_unfocused_color
!= NULL
) color_free(ob_s_cb_unfocused_color
);
218 if (ob_s_cb_focused_color
!= NULL
) color_free(ob_s_cb_focused_color
);
219 if (ob_s_title_unfocused_color
!= NULL
) color_free(ob_s_title_unfocused_color
);
220 if (ob_s_title_focused_color
!= NULL
) color_free(ob_s_title_focused_color
);
221 if (ob_s_titlebut_unfocused_color
!= NULL
)
222 color_free(ob_s_titlebut_unfocused_color
);
223 if (ob_s_titlebut_focused_color
!= NULL
)
224 color_free(ob_s_titlebut_focused_color
);
226 if (ob_s_max_set_mask
!= NULL
)
227 pixmap_mask_free(ob_s_max_set_mask
);
228 if (ob_s_max_unset_mask
!= NULL
)
229 pixmap_mask_free(ob_s_max_unset_mask
);
230 if (ob_s_desk_set_mask
!= NULL
)
231 pixmap_mask_free(ob_s_desk_set_mask
);
232 if (ob_s_desk_unset_mask
!= NULL
)
233 pixmap_mask_free(ob_s_desk_unset_mask
);
234 if (ob_s_shade_set_mask
!= NULL
)
235 pixmap_mask_free(ob_s_shade_set_mask
);
236 if (ob_s_shade_unset_mask
!= NULL
)
237 pixmap_mask_free(ob_s_shade_unset_mask
);
238 if (ob_s_iconify_mask
!= NULL
)
239 pixmap_mask_free(ob_s_iconify_mask
);
240 if (ob_s_close_mask
!= NULL
)
241 pixmap_mask_free(ob_s_close_mask
);
243 if (ob_s_winfont
!= NULL
) font_close(ob_s_winfont
);
245 appearance_free(ob_a_focused_unpressed_max
);
246 appearance_free(ob_a_focused_pressed_max
);
247 appearance_free(ob_a_focused_pressed_set_max
);
248 appearance_free(ob_a_unfocused_unpressed_max
);
249 appearance_free(ob_a_unfocused_pressed_max
);
250 appearance_free(ob_a_unfocused_pressed_set_max
);
251 if (ob_a_focused_unpressed_close
!= NULL
)
252 appearance_free(ob_a_focused_unpressed_close
);
253 if (ob_a_focused_pressed_close
!= NULL
)
254 appearance_free(ob_a_focused_pressed_close
);
255 if (ob_a_unfocused_unpressed_close
!= NULL
)
256 appearance_free(ob_a_unfocused_unpressed_close
);
257 if (ob_a_unfocused_pressed_close
!= NULL
)
258 appearance_free(ob_a_unfocused_pressed_close
);
259 if (ob_a_focused_unpressed_desk
!= NULL
)
260 appearance_free(ob_a_focused_unpressed_desk
);
261 if (ob_a_focused_pressed_desk
!= NULL
)
262 appearance_free(ob_a_focused_pressed_desk
);
263 if (ob_a_unfocused_unpressed_desk
!= NULL
)
264 appearance_free(ob_a_unfocused_unpressed_desk
);
265 if (ob_a_unfocused_pressed_desk
!= NULL
)
266 appearance_free(ob_a_unfocused_pressed_desk
);
267 if (ob_a_focused_unpressed_shade
!= NULL
)
268 appearance_free(ob_a_focused_unpressed_shade
);
269 if (ob_a_focused_pressed_shade
!= NULL
)
270 appearance_free(ob_a_focused_pressed_shade
);
271 if (ob_a_unfocused_unpressed_shade
!= NULL
)
272 appearance_free(ob_a_unfocused_unpressed_shade
);
273 if (ob_a_unfocused_pressed_shade
!= NULL
)
274 appearance_free(ob_a_unfocused_pressed_shade
);
275 if (ob_a_focused_unpressed_iconify
!= NULL
)
276 appearance_free(ob_a_focused_unpressed_iconify
);
277 if (ob_a_focused_pressed_iconify
!= NULL
)
278 appearance_free(ob_a_focused_pressed_iconify
);
279 if (ob_a_unfocused_unpressed_iconify
!= NULL
)
280 appearance_free(ob_a_unfocused_unpressed_iconify
);
281 if (ob_a_unfocused_pressed_iconify
!= NULL
)
282 appearance_free(ob_a_unfocused_pressed_iconify
);
283 appearance_free(ob_a_focused_grip
);
284 appearance_free(ob_a_unfocused_grip
);
285 appearance_free(ob_a_focused_title
);
286 appearance_free(ob_a_unfocused_title
);
287 appearance_free(ob_a_focused_label
);
288 appearance_free(ob_a_unfocused_label
);
289 appearance_free(ob_a_icon
);
290 appearance_free(ob_a_focused_handle
);
291 appearance_free(ob_a_unfocused_handle
);
292 appearance_free(ob_app_hilite_label
);
293 appearance_free(ob_app_unhilite_label
);
296 static Window
createWindow(Window parent
, unsigned long mask
,
297 XSetWindowAttributes
*attrib
)
299 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
300 render_depth
, InputOutput
, render_visual
,
307 XSetWindowAttributes attrib
;
311 self
= g_new(ObFrame
, 1);
313 self
->frame
.visible
= FALSE
;
315 /* create all of the decor windows */
316 mask
= CWOverrideRedirect
| CWEventMask
;
317 attrib
.event_mask
= FRAME_EVENTMASK
;
318 attrib
.override_redirect
= TRUE
;
319 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
322 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
325 attrib
.event_mask
= ELEMENT_EVENTMASK
;
326 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
327 self
->label
= createWindow(self
->title
, mask
, &attrib
);
328 self
->max
= createWindow(self
->title
, mask
, &attrib
);
329 self
->close
= createWindow(self
->title
, mask
, &attrib
);
330 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
331 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
332 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
333 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
334 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
336 attrib
.cursor
= ob_cursors
.ll_angle
;
337 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
338 attrib
.cursor
= ob_cursors
.lr_angle
;
339 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
341 /* the other stuff is shown based on decor settings */
342 XMapWindow(ob_display
, self
->frame
.plate
);
343 XMapWindow(ob_display
, self
->lgrip
);
344 XMapWindow(ob_display
, self
->rgrip
);
345 XMapWindow(ob_display
, self
->label
);
347 /* set colors/appearance/sizes for stuff that doesn't change */
348 XSetWindowBorder(ob_display
, self
->frame
.window
, ob_s_b_color
->pixel
);
349 XSetWindowBorder(ob_display
, self
->label
, ob_s_b_color
->pixel
);
350 XSetWindowBorder(ob_display
, self
->rgrip
, ob_s_b_color
->pixel
);
351 XSetWindowBorder(ob_display
, self
->lgrip
, ob_s_b_color
->pixel
);
353 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
354 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
355 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
356 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
357 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
358 XResizeWindow(ob_display
, self
->shade
, BUTTON_SIZE
, BUTTON_SIZE
);
359 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, ob_s_handle_height
);
360 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, ob_s_handle_height
);
362 /* set up the dynamic appearances */
363 self
->a_unfocused_title
= appearance_copy(ob_a_unfocused_title
);
364 self
->a_focused_title
= appearance_copy(ob_a_focused_title
);
365 self
->a_unfocused_label
= appearance_copy(ob_a_unfocused_label
);
366 self
->a_focused_label
= appearance_copy(ob_a_focused_label
);
367 self
->a_unfocused_handle
= appearance_copy(ob_a_unfocused_handle
);
368 self
->a_focused_handle
= appearance_copy(ob_a_focused_handle
);
369 self
->a_icon
= appearance_copy(ob_a_icon
);
371 self
->max_press
= self
->close_press
= self
->desk_press
=
372 self
->iconify_press
= self
->shade_press
= FALSE
;
374 dispatch_register(Event_X_ButtonPress
| Event_X_ButtonRelease
,
375 (EventHandler
)mouse_event
, self
);
380 static void frame_free(ObFrame
*self
)
382 appearance_free(self
->a_unfocused_title
);
383 appearance_free(self
->a_focused_title
);
384 appearance_free(self
->a_unfocused_label
);
385 appearance_free(self
->a_focused_label
);
386 appearance_free(self
->a_unfocused_handle
);
387 appearance_free(self
->a_focused_handle
);
388 appearance_free(self
->a_icon
);
390 XDestroyWindow(ob_display
, self
->frame
.window
);
392 dispatch_register(0, (EventHandler
)mouse_event
, self
);
397 void frame_show(ObFrame
*self
)
399 if (!self
->frame
.visible
) {
400 self
->frame
.visible
= TRUE
;
401 XMapWindow(ob_display
, self
->frame
.window
);
405 void frame_hide(ObFrame
*self
)
407 if (self
->frame
.visible
) {
408 self
->frame
.visible
= FALSE
;
409 self
->frame
.client
->ignore_unmaps
++;
410 XUnmapWindow(ob_display
, self
->frame
.window
);
414 void frame_adjust_shape(ObFrame
*self
)
420 if (!self
->frame
.client
->shaped
) {
421 /* clear the shape on the frame window */
422 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
423 self
->innersize
.left
,
427 /* make the frame's shape match the clients */
428 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
429 self
->innersize
.left
,
431 self
->frame
.client
->window
,
432 ShapeBounding
, ShapeSet
);
435 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
436 xrect
[0].x
= -ob_s_bevel
;
437 xrect
[0].y
= -ob_s_bevel
;
438 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
439 xrect
[0].height
= TITLE_HEIGHT
+
444 if (self
->frame
.client
->decorations
& Decor_Handle
) {
445 xrect
[1].x
= -ob_s_bevel
;
446 xrect
[1].y
= HANDLE_Y(self
);
447 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
448 xrect
[1].height
= ob_s_handle_height
+
453 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
454 ShapeBounding
, 0, 0, xrect
, num
,
455 ShapeUnion
, Unsorted
);
460 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
463 if (self
->frame
.client
->decorations
& Decor_Border
) {
464 self
->bwidth
= ob_s_bwidth
;
465 self
->cbwidth
= ob_s_cbwidth
;
467 self
->bwidth
= self
->cbwidth
= 0;
469 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
470 self
->cbwidth
, self
->cbwidth
);
471 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
472 g_assert(self
->width
> 0);
474 /* set border widths */
475 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
476 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
477 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
478 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
479 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
480 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
482 /* position/size and map/unmap all the windows */
484 /* they all default off, they're turned on in layout_title */
488 self
->iconify_x
= -1;
493 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
494 XMoveResizeWindow(ob_display
, self
->title
,
495 -self
->bwidth
, -self
->bwidth
,
496 self
->width
, TITLE_HEIGHT
);
497 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
498 XMapWindow(ob_display
, self
->title
);
500 RECT_SET(self
->a_focused_title
->area
, 0, 0,
501 self
->width
, TITLE_HEIGHT
);
502 RECT_SET(self
->a_unfocused_title
->area
, 0, 0,
503 self
->width
, TITLE_HEIGHT
);
505 /* layout the title bar elements */
508 XUnmapWindow(ob_display
, self
->title
);
510 if (self
->frame
.client
->decorations
& Decor_Handle
) {
511 XMoveResizeWindow(ob_display
, self
->handle
,
512 -self
->bwidth
, HANDLE_Y(self
),
513 self
->width
, ob_s_handle_height
);
514 XMoveWindow(ob_display
, self
->lgrip
,
515 -self
->bwidth
, -self
->bwidth
);
516 XMoveWindow(ob_display
, self
->rgrip
,
517 -self
->bwidth
+ self
->width
-
518 GRIP_WIDTH
, -self
->bwidth
);
519 self
->innersize
.bottom
+= ob_s_handle_height
+
521 XMapWindow(ob_display
, self
->handle
);
523 if (ob_a_focused_grip
->surface
.data
.planar
.grad
==
524 Background_ParentRelative
)
525 RECT_SET(self
->a_focused_handle
->area
, 0, 0,
526 self
->width
, ob_s_handle_height
);
528 RECT_SET(self
->a_focused_handle
->area
,
529 GRIP_WIDTH
+ self
->bwidth
, 0,
530 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
532 if (ob_a_unfocused_grip
->surface
.data
.planar
.grad
==
533 Background_ParentRelative
)
534 RECT_SET(self
->a_unfocused_handle
->area
, 0, 0,
535 self
->width
, ob_s_handle_height
);
537 RECT_SET(self
->a_unfocused_handle
->area
,
538 GRIP_WIDTH
+ self
->bwidth
, 0,
539 self
->width
- (GRIP_WIDTH
+ self
->bwidth
) * 2,
543 XUnmapWindow(ob_display
, self
->handle
);
547 /* move and resize the plate */
548 XMoveResizeWindow(ob_display
, self
->frame
.plate
,
549 self
->innersize
.left
- self
->cbwidth
,
550 self
->innersize
.top
- self
->cbwidth
,
551 self
->frame
.client
->area
.width
,
552 self
->frame
.client
->area
.height
);
553 /* when the client has StaticGravity, it likes to move around. */
554 XMoveWindow(ob_display
, self
->frame
.client
->window
, 0, 0);
558 STRUT_SET(self
->frame
.size
,
559 self
->innersize
.left
+ self
->bwidth
,
560 self
->innersize
.top
+ self
->bwidth
,
561 self
->innersize
.right
+ self
->bwidth
,
562 self
->innersize
.bottom
+ self
->bwidth
);
565 /* shading can change without being moved or resized */
566 RECT_SET_SIZE(self
->frame
.area
,
567 self
->frame
.client
->area
.width
+
568 self
->frame
.size
.left
+ self
->frame
.size
.right
,
569 (self
->frame
.client
->shaded
? TITLE_HEIGHT
+ self
->bwidth
*2:
570 self
->frame
.client
->area
.height
+
571 self
->frame
.size
.top
+ self
->frame
.size
.bottom
));
574 /* find the new coordinates, done after setting the frame.size, for
575 frame_client_gravity. */
576 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
577 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
578 frame_client_gravity((Frame
*)self
,
579 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
582 /* move and resize the top level frame.
583 shading can change without being moved or resized */
584 XMoveResizeWindow(ob_display
, self
->frame
.window
,
585 self
->frame
.area
.x
, self
->frame
.area
.y
,
587 self
->frame
.area
.height
- self
->bwidth
* 2);
590 obrender_frame(self
);
592 frame_adjust_shape(self
);
596 void frame_adjust_state(ObFrame
*self
)
598 obrender_frame(self
);
601 void frame_adjust_focus(ObFrame
*self
)
603 obrender_frame(self
);
606 void frame_adjust_title(ObFrame
*self
)
608 obrender_frame(self
);
611 void frame_adjust_icon(ObFrame
*self
)
613 obrender_frame(self
);
616 void frame_grab_client(ObFrame
*self
, Client
*client
)
618 self
->frame
.client
= client
;
620 /* reparent the client to the frame */
621 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
623 When reparenting the client window, it is usually not mapped yet, since
624 this occurs from a MapRequest. However, in the case where Openbox is
625 starting up, the window is already mapped, so we'll see unmap events for
626 it. There are 2 unmap events generated that we see, one with the 'event'
627 member set the root window, and one set to the client, but both get
628 handled and need to be ignored.
630 if (ob_state
== State_Starting
)
631 client
->ignore_unmaps
+= 2;
633 /* select the event mask on the client's parent (to receive config/map
634 req's) the ButtonPress is to catch clicks on the client border */
635 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
637 /* map the client so it maps when the frame does */
638 XMapWindow(ob_display
, client
->window
);
640 frame_adjust_area(self
, TRUE
, TRUE
);
642 /* set all the windows for the frame in the client_map */
643 g_hash_table_insert(client_map
, &self
->frame
.window
, client
);
644 g_hash_table_insert(client_map
, &self
->frame
.plate
, client
);
645 g_hash_table_insert(client_map
, &self
->title
, client
);
646 g_hash_table_insert(client_map
, &self
->label
, client
);
647 g_hash_table_insert(client_map
, &self
->max
, client
);
648 g_hash_table_insert(client_map
, &self
->close
, client
);
649 g_hash_table_insert(client_map
, &self
->desk
, client
);
650 g_hash_table_insert(client_map
, &self
->shade
, client
);
651 g_hash_table_insert(client_map
, &self
->icon
, client
);
652 g_hash_table_insert(client_map
, &self
->iconify
, client
);
653 g_hash_table_insert(client_map
, &self
->handle
, client
);
654 g_hash_table_insert(client_map
, &self
->lgrip
, client
);
655 g_hash_table_insert(client_map
, &self
->rgrip
, client
);
658 void frame_release_client(ObFrame
*self
, Client
*client
)
662 g_assert(self
->frame
.client
== client
);
664 /* check if the app has already reparented its window away */
665 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
666 ReparentNotify
, &ev
)) {
667 XPutBackEvent(ob_display
, &ev
);
668 /* re-map the window since the unmanaging process unmaps it */
669 XMapWindow(ob_display
, client
->window
);
671 /* according to the ICCCM - if the client doesn't reparent itself,
672 then we will reparent the window to root for them */
673 XReparentWindow(ob_display
, client
->window
, ob_root
,
678 /* remove all the windows for the frame from the client_map */
679 g_hash_table_remove(client_map
, &self
->frame
.window
);
680 g_hash_table_remove(client_map
, &self
->frame
.plate
);
681 g_hash_table_remove(client_map
, &self
->title
);
682 g_hash_table_remove(client_map
, &self
->label
);
683 g_hash_table_remove(client_map
, &self
->max
);
684 g_hash_table_remove(client_map
, &self
->close
);
685 g_hash_table_remove(client_map
, &self
->desk
);
686 g_hash_table_remove(client_map
, &self
->shade
);
687 g_hash_table_remove(client_map
, &self
->icon
);
688 g_hash_table_remove(client_map
, &self
->iconify
);
689 g_hash_table_remove(client_map
, &self
->handle
);
690 g_hash_table_remove(client_map
, &self
->lgrip
);
691 g_hash_table_remove(client_map
, &self
->rgrip
);
696 static void layout_title(ObFrame
*self
)
700 gboolean n
, d
, i
, l
, m
, c
, s
;
702 n
= d
= i
= l
= m
= c
= s
= FALSE
;
704 /* figure out whats being shown, and the width of the label */
705 self
->label_width
= self
->width
- (ob_s_bevel
+ 1) * 2;
706 for (lc
= config_engine_layout
; *lc
!= '\0'; ++lc
) {
709 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
710 if (n
) { *lc
= ' '; break; } /* rm duplicates */
712 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
715 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
716 if (d
) { *lc
= ' '; break; } /* rm duplicates */
718 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
721 if (!(self
->frame
.client
->decorations
& Decor_Shade
)) break;
722 if (s
) { *lc
= ' '; break; } /* rm duplicates */
724 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
727 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
728 if (i
) { *lc
= ' '; break; } /* rm duplicates */
730 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
733 if (l
) { *lc
= ' '; break; } /* rm duplicates */
737 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
738 if (m
) { *lc
= ' '; break; } /* rm duplicates */
740 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
743 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
744 if (c
) { *lc
= ' '; break; } /* rm duplicates */
746 self
->label_width
-= BUTTON_SIZE
+ ob_s_bevel
+ 1;
750 if (self
->label_width
< 1) self
->label_width
= 1;
752 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
755 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
756 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
757 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
758 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
759 if (!l
) XUnmapWindow(ob_display
, self
->label
);
760 if (!m
) XUnmapWindow(ob_display
, self
->max
);
761 if (!c
) XUnmapWindow(ob_display
, self
->close
);
764 for (lc
= config_engine_layout
; *lc
!= '\0'; ++lc
) {
769 RECT_SET(self
->a_icon
->area
, 0, 0, BUTTON_SIZE
, BUTTON_SIZE
);
770 XMapWindow(ob_display
, self
->icon
);
771 XMoveWindow(ob_display
, self
->icon
, x
, ob_s_bevel
+ 1);
772 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
777 XMapWindow(ob_display
, self
->desk
);
778 XMoveWindow(ob_display
, self
->desk
, x
, ob_s_bevel
+ 1);
779 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
784 XMapWindow(ob_display
, self
->shade
);
785 XMoveWindow(ob_display
, self
->shade
, x
, ob_s_bevel
+ 1);
786 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
791 XMapWindow(ob_display
, self
->iconify
);
792 XMoveWindow(ob_display
, self
->iconify
, x
, ob_s_bevel
+ 1);
793 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
798 XMapWindow(ob_display
, self
->label
);
799 XMoveWindow(ob_display
, self
->label
, x
, ob_s_bevel
);
800 x
+= self
->label_width
+ ob_s_bevel
+ 1;
805 XMapWindow(ob_display
, self
->max
);
806 XMoveWindow(ob_display
, self
->max
, x
, ob_s_bevel
+ 1);
807 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
812 XMapWindow(ob_display
, self
->close
);
813 XMoveWindow(ob_display
, self
->close
, x
, ob_s_bevel
+ 1);
814 x
+= BUTTON_SIZE
+ ob_s_bevel
+ 1;
819 RECT_SET(self
->a_focused_label
->area
, 0, 0,
820 self
->label_width
, LABEL_HEIGHT
);
821 RECT_SET(self
->a_unfocused_label
->area
, 0, 0,
822 self
->label_width
, LABEL_HEIGHT
);
825 static void mouse_event(const ObEvent
*e
, ObFrame
*self
)
828 gboolean press
= e
->type
== Event_X_ButtonPress
;
830 win
= e
->data
.x
.e
->xbutton
.window
;
831 if (win
== self
->max
) {
832 self
->max_press
= press
;
833 obrender_frame(self
);
834 } else if (win
== self
->close
) {
835 self
->close_press
= press
;
836 obrender_frame(self
);
837 } else if (win
== self
->iconify
) {
838 self
->iconify_press
= press
;
839 obrender_frame(self
);
840 } else if (win
== self
->desk
) {
841 self
->desk_press
= press
;
842 obrender_frame(self
);
843 } else if (win
== self
->shade
) {
844 self
->shade_press
= press
;
845 obrender_frame(self
);
849 Context
get_context(Client
*client
, Window win
)
853 if (win
== ob_root
) return Context_Root
;
854 if (client
== NULL
) return Context_None
;
855 if (win
== client
->window
) return Context_Client
;
857 self
= (ObFrame
*) client
->frame
;
858 if (win
== self
->frame
.window
) return Context_Frame
;
859 if (win
== self
->frame
.plate
) return Context_Client
;
860 if (win
== self
->title
) return Context_Titlebar
;
861 if (win
== self
->label
) return Context_Titlebar
;
862 if (win
== self
->handle
) return Context_Handle
;
863 if (win
== self
->lgrip
) return Context_BLCorner
;
864 if (win
== self
->rgrip
) return Context_BRCorner
;
865 if (win
== self
->max
) return Context_Maximize
;
866 if (win
== self
->iconify
) return Context_Iconify
;
867 if (win
== self
->close
) return Context_Close
;
868 if (win
== self
->icon
) return Context_Icon
;
869 if (win
== self
->desk
) return Context_AllDesktops
;
870 if (win
== self
->shade
) return Context_Shade
;