4 #include "extensions.h"
6 #include "framerender.h"
7 #include "render/theme.h"
9 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
10 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
11 ButtonPressMask | ButtonReleaseMask)
12 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
13 ButtonMotionMask | ExposureMask | \
14 EnterWindowMask | LeaveWindowMask)
16 #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \
19 static void layout_title(ObFrame
*self
);
21 static Window
createWindow(Window parent
, unsigned long mask
,
22 XSetWindowAttributes
*attrib
)
24 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
25 RrDepth(ob_rr_inst
), InputOutput
,
26 RrVisual(ob_rr_inst
), mask
, attrib
);
32 XSetWindowAttributes attrib
;
36 self
= g_new(ObFrame
, 1);
38 self
->visible
= FALSE
;
39 self
->decorations
= 0;
41 /* create all of the decor windows */
42 mask
= CWOverrideRedirect
| CWEventMask
;
43 attrib
.event_mask
= FRAME_EVENTMASK
;
44 attrib
.override_redirect
= TRUE
;
45 self
->window
= createWindow(RootWindow(ob_display
, ob_screen
),
49 self
->plate
= createWindow(self
->window
, mask
, &attrib
);
52 attrib
.event_mask
= ELEMENT_EVENTMASK
;
53 self
->title
= createWindow(self
->window
, mask
, &attrib
);
54 self
->label
= createWindow(self
->title
, mask
, &attrib
);
55 self
->max
= createWindow(self
->title
, mask
, &attrib
);
56 self
->close
= createWindow(self
->title
, mask
, &attrib
);
57 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
58 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
59 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
60 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
61 self
->handle
= createWindow(self
->window
, mask
, &attrib
);
63 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHWEST
);
64 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
65 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHEAST
);
66 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
67 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHWEST
);
68 self
->tlresize
= createWindow(self
->title
, mask
, &attrib
);
69 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHEAST
);
70 self
->trresize
= createWindow(self
->title
, mask
, &attrib
);
72 self
->focused
= FALSE
;
74 /* the other stuff is shown based on decor settings */
75 XMapWindow(ob_display
, self
->plate
);
76 XMapWindow(ob_display
, self
->lgrip
);
77 XMapWindow(ob_display
, self
->rgrip
);
78 XMapWindow(ob_display
, self
->label
);
79 XMapWindow(ob_display
, self
->tlresize
);
80 XMapWindow(ob_display
, self
->trresize
);
82 /* set colors/appearance/sizes for stuff that doesn't change */
83 XSetWindowBorder(ob_display
, self
->window
, ob_rr_theme
->b_color
->pixel
);
84 XSetWindowBorder(ob_display
, self
->label
, ob_rr_theme
->b_color
->pixel
);
85 XSetWindowBorder(ob_display
, self
->rgrip
, ob_rr_theme
->b_color
->pixel
);
86 XSetWindowBorder(ob_display
, self
->lgrip
, ob_rr_theme
->b_color
->pixel
);
88 XResizeWindow(ob_display
, self
->max
,
89 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
90 XResizeWindow(ob_display
, self
->iconify
,
91 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
92 XResizeWindow(ob_display
, self
->icon
,
93 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
94 XResizeWindow(ob_display
, self
->close
,
95 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
96 XResizeWindow(ob_display
, self
->desk
,
97 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
98 XResizeWindow(ob_display
, self
->shade
,
99 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
100 XResizeWindow(ob_display
, self
->lgrip
,
101 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
102 XResizeWindow(ob_display
, self
->rgrip
,
103 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
104 XResizeWindow(ob_display
, self
->tlresize
,
105 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
106 XResizeWindow(ob_display
, self
->trresize
,
107 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
109 /* set up the dynamic appearances */
110 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
111 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
112 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
113 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
114 self
->a_unfocused_handle
=
115 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
116 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
117 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
119 self
->max_press
= self
->close_press
= self
->desk_press
=
120 self
->iconify_press
= self
->shade_press
= FALSE
;
121 self
->max_hover
= self
->close_hover
= self
->desk_hover
=
122 self
->iconify_hover
= self
->shade_hover
= FALSE
;
124 return (ObFrame
*)self
;
127 static void frame_free(ObFrame
*self
)
129 RrAppearanceFree(self
->a_unfocused_title
);
130 RrAppearanceFree(self
->a_focused_title
);
131 RrAppearanceFree(self
->a_unfocused_label
);
132 RrAppearanceFree(self
->a_focused_label
);
133 RrAppearanceFree(self
->a_unfocused_handle
);
134 RrAppearanceFree(self
->a_focused_handle
);
135 RrAppearanceFree(self
->a_icon
);
137 XDestroyWindow(ob_display
, self
->window
);
142 void frame_show(ObFrame
*self
)
144 if (!self
->visible
) {
145 self
->visible
= TRUE
;
146 XMapWindow(ob_display
, self
->window
);
150 void frame_hide(ObFrame
*self
)
153 self
->visible
= FALSE
;
154 self
->client
->ignore_unmaps
++;
155 XUnmapWindow(ob_display
, self
->window
);
159 void frame_adjust_shape(ObFrame
*self
)
165 if (!self
->client
->shaped
) {
166 /* clear the shape on the frame window */
167 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
168 self
->innersize
.left
,
172 /* make the frame's shape match the clients */
173 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
174 self
->innersize
.left
,
176 self
->client
->window
,
177 ShapeBounding
, ShapeSet
);
180 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
181 xrect
[0].x
= -ob_rr_theme
->bevel
;
182 xrect
[0].y
= -ob_rr_theme
->bevel
;
183 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
184 xrect
[0].height
= ob_rr_theme
->title_height
+
189 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
190 xrect
[1].x
= -ob_rr_theme
->bevel
;
191 xrect
[1].y
= FRAME_HANDLE_Y(self
);
192 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
193 xrect
[1].height
= ob_rr_theme
->handle_height
+
198 XShapeCombineRectangles(ob_display
, self
->window
,
199 ShapeBounding
, 0, 0, xrect
, num
,
200 ShapeUnion
, Unsorted
);
205 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
208 self
->decorations
= self
->client
->decorations
;
209 if (self
->decorations
& OB_FRAME_DECOR_BORDER
) {
210 self
->bwidth
= ob_rr_theme
->bwidth
;
211 self
->cbwidth
= ob_rr_theme
->cbwidth
;
213 self
->bwidth
= self
->cbwidth
= 0;
215 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
216 self
->cbwidth
, self
->cbwidth
);
217 self
->width
= self
->client
->area
.width
+ self
->cbwidth
* 2;
218 g_assert(self
->width
> 0);
220 /* set border widths */
221 XSetWindowBorderWidth(ob_display
, self
->plate
, self
->cbwidth
);
222 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
223 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
224 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
225 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
226 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
228 /* position/size and map/unmap all the windows */
230 /* they all default off, they're turned on in layout_title */
234 self
->iconify_x
= -1;
239 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
240 XMoveResizeWindow(ob_display
, self
->title
,
241 -self
->bwidth
, -self
->bwidth
,
242 self
->width
, ob_rr_theme
->title_height
);
243 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->bwidth
;
244 XMapWindow(ob_display
, self
->title
);
246 XMoveWindow(ob_display
, self
->tlresize
, 0, 0);
247 XMoveWindow(ob_display
, self
->trresize
,
248 self
->width
- ob_rr_theme
->grip_width
, 0);
250 /* layout the title bar elements */
253 XUnmapWindow(ob_display
, self
->title
);
255 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
256 XMoveResizeWindow(ob_display
, self
->handle
,
257 -self
->bwidth
, FRAME_HANDLE_Y(self
),
258 self
->width
, ob_rr_theme
->handle_height
);
259 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
261 XMapWindow(ob_display
, self
->handle
);
263 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
264 XMoveWindow(ob_display
, self
->lgrip
,
265 -self
->bwidth
, -self
->bwidth
);
266 XMoveWindow(ob_display
, self
->rgrip
,
267 -self
->bwidth
+ self
->width
-
268 ob_rr_theme
->grip_width
, -self
->bwidth
);
269 XMapWindow(ob_display
, self
->lgrip
);
270 XMapWindow(ob_display
, self
->rgrip
);
272 XUnmapWindow(ob_display
, self
->lgrip
);
273 XUnmapWindow(ob_display
, self
->rgrip
);
276 /* XXX make a subwindow with these dimentions?
277 ob_rr_theme->grip_width + self->bwidth, 0,
278 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
279 ob_rr_theme->handle_height);
282 XUnmapWindow(ob_display
, self
->handle
);
284 /* move and resize the plate */
285 XMoveResizeWindow(ob_display
, self
->plate
,
286 self
->innersize
.left
- self
->cbwidth
,
287 self
->innersize
.top
- self
->cbwidth
,
288 self
->client
->area
.width
,
289 self
->client
->area
.height
);
290 /* when the client has StaticGravity, it likes to move around. */
291 XMoveWindow(ob_display
, self
->client
->window
, 0, 0);
293 STRUT_SET(self
->size
,
294 self
->innersize
.left
+ self
->bwidth
,
295 self
->innersize
.top
+ self
->bwidth
,
296 self
->innersize
.right
+ self
->bwidth
,
297 self
->innersize
.bottom
+ self
->bwidth
);
300 /* shading can change without being moved or resized */
301 RECT_SET_SIZE(self
->area
,
302 self
->client
->area
.width
+
303 self
->size
.left
+ self
->size
.right
,
304 (self
->client
->shaded
?
305 ob_rr_theme
->title_height
+ self
->bwidth
*2:
306 self
->client
->area
.height
+
307 self
->size
.top
+ self
->size
.bottom
));
310 /* find the new coordinates, done after setting the frame.size, for
311 frame_client_gravity. */
312 self
->area
.x
= self
->client
->area
.x
;
313 self
->area
.y
= self
->client
->area
.y
;
314 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
317 /* move and resize the top level frame.
318 shading can change without being moved or resized */
319 XMoveResizeWindow(ob_display
, self
->window
,
320 self
->area
.x
, self
->area
.y
,
322 self
->area
.height
- self
->bwidth
* 2);
325 framerender_frame(self
);
327 frame_adjust_shape(self
);
331 void frame_adjust_state(ObFrame
*self
)
333 framerender_frame(self
);
336 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
338 self
->focused
= hilite
;
339 framerender_frame(self
);
342 void frame_adjust_title(ObFrame
*self
)
344 framerender_frame(self
);
347 void frame_adjust_icon(ObFrame
*self
)
349 framerender_frame(self
);
352 void frame_grab_client(ObFrame
*self
, ObClient
*client
)
354 self
->client
= client
;
356 /* reparent the client to the frame */
357 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
359 When reparenting the client window, it is usually not mapped yet, since
360 this occurs from a MapRequest. However, in the case where Openbox is
361 starting up, the window is already mapped, so we'll see unmap events for
362 it. There are 2 unmap events generated that we see, one with the 'event'
363 member set the root window, and one set to the client, but both get
364 handled and need to be ignored.
366 if (ob_state() == OB_STATE_STARTING
)
367 client
->ignore_unmaps
+= 2;
369 /* select the event mask on the client's parent (to receive config/map
370 req's) the ButtonPress is to catch clicks on the client border */
371 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
373 /* map the client so it maps when the frame does */
374 XMapWindow(ob_display
, client
->window
);
376 frame_adjust_area(self
, TRUE
, TRUE
);
378 /* set all the windows for the frame in the window_map */
379 g_hash_table_insert(window_map
, &self
->window
, client
);
380 g_hash_table_insert(window_map
, &self
->plate
, client
);
381 g_hash_table_insert(window_map
, &self
->title
, client
);
382 g_hash_table_insert(window_map
, &self
->label
, client
);
383 g_hash_table_insert(window_map
, &self
->max
, client
);
384 g_hash_table_insert(window_map
, &self
->close
, client
);
385 g_hash_table_insert(window_map
, &self
->desk
, client
);
386 g_hash_table_insert(window_map
, &self
->shade
, client
);
387 g_hash_table_insert(window_map
, &self
->icon
, client
);
388 g_hash_table_insert(window_map
, &self
->iconify
, client
);
389 g_hash_table_insert(window_map
, &self
->handle
, client
);
390 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
391 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
392 g_hash_table_insert(window_map
, &self
->tlresize
, client
);
393 g_hash_table_insert(window_map
, &self
->trresize
, client
);
396 void frame_release_client(ObFrame
*self
, ObClient
*client
)
400 g_assert(self
->client
== client
);
402 /* check if the app has already reparented its window away */
403 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
404 ReparentNotify
, &ev
)) {
405 XPutBackEvent(ob_display
, &ev
);
407 /* re-map the window since the unmanaging process unmaps it */
409 /* XXX ... um no it doesnt it unmaps its parent, the window itself
410 retains its mapped state, no?! XXX
411 XMapWindow(ob_display, client->window); */
413 /* according to the ICCCM - if the client doesn't reparent itself,
414 then we will reparent the window to root for them */
415 XReparentWindow(ob_display
, client
->window
,
416 RootWindow(ob_display
, ob_screen
),
421 /* remove all the windows for the frame from the window_map */
422 g_hash_table_remove(window_map
, &self
->window
);
423 g_hash_table_remove(window_map
, &self
->plate
);
424 g_hash_table_remove(window_map
, &self
->title
);
425 g_hash_table_remove(window_map
, &self
->label
);
426 g_hash_table_remove(window_map
, &self
->max
);
427 g_hash_table_remove(window_map
, &self
->close
);
428 g_hash_table_remove(window_map
, &self
->desk
);
429 g_hash_table_remove(window_map
, &self
->shade
);
430 g_hash_table_remove(window_map
, &self
->icon
);
431 g_hash_table_remove(window_map
, &self
->iconify
);
432 g_hash_table_remove(window_map
, &self
->handle
);
433 g_hash_table_remove(window_map
, &self
->lgrip
);
434 g_hash_table_remove(window_map
, &self
->rgrip
);
435 g_hash_table_remove(window_map
, &self
->tlresize
);
436 g_hash_table_remove(window_map
, &self
->trresize
);
441 static void layout_title(ObFrame
*self
)
445 gboolean n
, d
, i
, l
, m
, c
, s
;
447 n
= d
= i
= l
= m
= c
= s
= FALSE
;
449 /* figure out whats being shown, and the width of the label */
450 self
->label_width
= self
->width
- (ob_rr_theme
->bevel
+ 1) * 2;
451 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
454 if (n
) { *lc
= ' '; break; } /* rm duplicates */
456 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
457 ob_rr_theme
->bevel
+ 1);
460 if (d
) { *lc
= ' '; break; } /* rm duplicates */
462 self
->label_width
-= (ob_rr_theme
->button_size
+
463 ob_rr_theme
->bevel
+ 1);
466 if (s
) { *lc
= ' '; break; } /* rm duplicates */
468 self
->label_width
-= (ob_rr_theme
->button_size
+
469 ob_rr_theme
->bevel
+ 1);
472 if (i
) { *lc
= ' '; break; } /* rm duplicates */
474 self
->label_width
-= (ob_rr_theme
->button_size
+
475 ob_rr_theme
->bevel
+ 1);
478 if (l
) { *lc
= ' '; break; } /* rm duplicates */
482 if (m
) { *lc
= ' '; break; } /* rm duplicates */
484 self
->label_width
-= (ob_rr_theme
->button_size
+
485 ob_rr_theme
->bevel
+ 1);
488 if (c
) { *lc
= ' '; break; } /* rm duplicates */
490 self
->label_width
-= (ob_rr_theme
->button_size
+
491 ob_rr_theme
->bevel
+ 1);
495 if (self
->label_width
< 1) self
->label_width
= 1;
497 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
498 ob_rr_theme
->label_height
);
500 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
501 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
502 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
503 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
504 if (!l
) XUnmapWindow(ob_display
, self
->label
);
505 if (!m
) XUnmapWindow(ob_display
, self
->max
);
506 if (!c
) XUnmapWindow(ob_display
, self
->close
);
508 x
= ob_rr_theme
->bevel
+ 1;
509 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
514 XMapWindow(ob_display
, self
->icon
);
515 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->bevel
);
516 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->bevel
+ 1;
521 XMapWindow(ob_display
, self
->desk
);
522 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->bevel
+ 1);
523 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
528 XMapWindow(ob_display
, self
->shade
);
529 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->bevel
+ 1);
530 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
535 XMapWindow(ob_display
, self
->iconify
);
536 XMoveWindow(ob_display
, self
->iconify
, x
, ob_rr_theme
->bevel
+ 1);
537 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
542 XMapWindow(ob_display
, self
->label
);
543 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->bevel
);
544 x
+= self
->label_width
+ ob_rr_theme
->bevel
+ 1;
549 XMapWindow(ob_display
, self
->max
);
550 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->bevel
+ 1);
551 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
556 XMapWindow(ob_display
, self
->close
);
557 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->bevel
+ 1);
558 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
564 ObFrameContext
frame_context_from_string(char *name
)
566 if (!g_ascii_strcasecmp("root", name
))
567 return OB_FRAME_CONTEXT_ROOT
;
568 else if (!g_ascii_strcasecmp("client", name
))
569 return OB_FRAME_CONTEXT_CLIENT
;
570 else if (!g_ascii_strcasecmp("titlebar", name
))
571 return OB_FRAME_CONTEXT_TITLEBAR
;
572 else if (!g_ascii_strcasecmp("handle", name
))
573 return OB_FRAME_CONTEXT_HANDLE
;
574 else if (!g_ascii_strcasecmp("frame", name
))
575 return OB_FRAME_CONTEXT_FRAME
;
576 else if (!g_ascii_strcasecmp("tlcorner", name
))
577 return OB_FRAME_CONTEXT_TLCORNER
;
578 else if (!g_ascii_strcasecmp("trcorner", name
))
579 return OB_FRAME_CONTEXT_TRCORNER
;
580 else if (!g_ascii_strcasecmp("blcorner", name
))
581 return OB_FRAME_CONTEXT_BLCORNER
;
582 else if (!g_ascii_strcasecmp("brcorner", name
))
583 return OB_FRAME_CONTEXT_BRCORNER
;
584 else if (!g_ascii_strcasecmp("maximize", name
))
585 return OB_FRAME_CONTEXT_MAXIMIZE
;
586 else if (!g_ascii_strcasecmp("alldesktops", name
))
587 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
588 else if (!g_ascii_strcasecmp("shade", name
))
589 return OB_FRAME_CONTEXT_SHADE
;
590 else if (!g_ascii_strcasecmp("iconify", name
))
591 return OB_FRAME_CONTEXT_ICONIFY
;
592 else if (!g_ascii_strcasecmp("icon", name
))
593 return OB_FRAME_CONTEXT_ICON
;
594 else if (!g_ascii_strcasecmp("close", name
))
595 return OB_FRAME_CONTEXT_CLOSE
;
596 return OB_FRAME_CONTEXT_NONE
;
599 ObFrameContext
frame_context(ObClient
*client
, Window win
)
603 if (win
== RootWindow(ob_display
, ob_screen
)) return OB_FRAME_CONTEXT_ROOT
;
604 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
605 if (win
== client
->window
) return OB_FRAME_CONTEXT_CLIENT
;
607 self
= client
->frame
;
608 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
609 if (win
== self
->plate
) return OB_FRAME_CONTEXT_CLIENT
;
610 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
611 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
612 if (win
== self
->handle
) return OB_FRAME_CONTEXT_HANDLE
;
613 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
614 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
615 if (win
== self
->tlresize
) return OB_FRAME_CONTEXT_TLCORNER
;
616 if (win
== self
->trresize
) return OB_FRAME_CONTEXT_TRCORNER
;
617 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
618 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
619 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
620 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
621 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
622 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
624 return OB_FRAME_CONTEXT_NONE
;
627 void frame_client_gravity(ObFrame
*self
, int *x
, int *y
)
630 switch (self
->client
->gravity
) {
632 case NorthWestGravity
:
633 case SouthWestGravity
:
640 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
643 case NorthEastGravity
:
644 case SouthEastGravity
:
646 *x
-= self
->size
.left
+ self
->size
.right
;
651 *x
-= self
->size
.left
;
656 switch (self
->client
->gravity
) {
658 case NorthWestGravity
:
659 case NorthEastGravity
:
666 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
669 case SouthWestGravity
:
670 case SouthEastGravity
:
672 *y
-= self
->size
.top
+ self
->size
.bottom
;
677 *y
-= self
->size
.top
;
682 void frame_frame_gravity(ObFrame
*self
, int *x
, int *y
)
685 switch (self
->client
->gravity
) {
687 case NorthWestGravity
:
689 case SouthWestGravity
:
694 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
696 case NorthEastGravity
:
698 case SouthEastGravity
:
699 *x
+= self
->size
.left
+ self
->size
.right
;
703 *x
+= self
->size
.left
;
708 switch (self
->client
->gravity
) {
710 case NorthWestGravity
:
712 case NorthEastGravity
:
717 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
719 case SouthWestGravity
:
721 case SouthEastGravity
:
722 *y
+= self
->size
.top
+ self
->size
.bottom
;
726 *y
+= self
->size
.top
;