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
);
56 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHWEST
);
57 self
->tlresize
= createWindow(self
->title
, mask
, &attrib
);
58 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHEAST
);
59 self
->trresize
= createWindow(self
->title
, mask
, &attrib
);
62 self
->label
= createWindow(self
->title
, mask
, &attrib
);
63 self
->max
= createWindow(self
->title
, mask
, &attrib
);
64 self
->close
= createWindow(self
->title
, mask
, &attrib
);
65 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
66 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
67 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
68 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
69 self
->handle
= createWindow(self
->window
, mask
, &attrib
);
72 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHWEST
);
73 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
74 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHEAST
);
75 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
77 self
->focused
= FALSE
;
79 /* the other stuff is shown based on decor settings */
80 XMapWindow(ob_display
, self
->plate
);
81 XMapWindow(ob_display
, self
->lgrip
);
82 XMapWindow(ob_display
, self
->rgrip
);
83 XMapWindow(ob_display
, self
->label
);
84 XMapWindow(ob_display
, self
->tlresize
);
85 XMapWindow(ob_display
, self
->trresize
);
87 /* set colors/appearance/sizes for stuff that doesn't change */
88 XSetWindowBorder(ob_display
, self
->window
, ob_rr_theme
->b_color
->pixel
);
89 XSetWindowBorder(ob_display
, self
->label
, ob_rr_theme
->b_color
->pixel
);
90 XSetWindowBorder(ob_display
, self
->rgrip
, ob_rr_theme
->b_color
->pixel
);
91 XSetWindowBorder(ob_display
, self
->lgrip
, ob_rr_theme
->b_color
->pixel
);
93 XResizeWindow(ob_display
, self
->max
,
94 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
95 XResizeWindow(ob_display
, self
->iconify
,
96 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
97 XResizeWindow(ob_display
, self
->icon
,
98 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
99 XResizeWindow(ob_display
, self
->close
,
100 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
101 XResizeWindow(ob_display
, self
->desk
,
102 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
103 XResizeWindow(ob_display
, self
->shade
,
104 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
105 XResizeWindow(ob_display
, self
->lgrip
,
106 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
107 XResizeWindow(ob_display
, self
->rgrip
,
108 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
109 XResizeWindow(ob_display
, self
->tlresize
,
110 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
111 XResizeWindow(ob_display
, self
->trresize
,
112 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
114 /* set up the dynamic appearances */
115 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
116 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
117 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
118 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
119 self
->a_unfocused_handle
=
120 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
121 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
122 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
124 self
->max_press
= self
->close_press
= self
->desk_press
=
125 self
->iconify_press
= self
->shade_press
= FALSE
;
126 self
->max_hover
= self
->close_hover
= self
->desk_hover
=
127 self
->iconify_hover
= self
->shade_hover
= FALSE
;
129 return (ObFrame
*)self
;
132 static void frame_free(ObFrame
*self
)
134 RrAppearanceFree(self
->a_unfocused_title
);
135 RrAppearanceFree(self
->a_focused_title
);
136 RrAppearanceFree(self
->a_unfocused_label
);
137 RrAppearanceFree(self
->a_focused_label
);
138 RrAppearanceFree(self
->a_unfocused_handle
);
139 RrAppearanceFree(self
->a_focused_handle
);
140 RrAppearanceFree(self
->a_icon
);
142 XDestroyWindow(ob_display
, self
->window
);
147 void frame_show(ObFrame
*self
)
149 if (!self
->visible
) {
150 self
->visible
= TRUE
;
151 XMapWindow(ob_display
, self
->window
);
155 void frame_hide(ObFrame
*self
)
158 self
->visible
= FALSE
;
159 self
->client
->ignore_unmaps
++;
160 XUnmapWindow(ob_display
, self
->window
);
164 void frame_adjust_shape(ObFrame
*self
)
170 if (!self
->client
->shaped
) {
171 /* clear the shape on the frame window */
172 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
173 self
->innersize
.left
,
177 /* make the frame's shape match the clients */
178 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
179 self
->innersize
.left
,
181 self
->client
->window
,
182 ShapeBounding
, ShapeSet
);
185 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
186 xrect
[0].x
= -ob_rr_theme
->bevel
;
187 xrect
[0].y
= -ob_rr_theme
->bevel
;
188 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
189 xrect
[0].height
= ob_rr_theme
->title_height
+
194 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
195 xrect
[1].x
= -ob_rr_theme
->bevel
;
196 xrect
[1].y
= FRAME_HANDLE_Y(self
);
197 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
198 xrect
[1].height
= ob_rr_theme
->handle_height
+
203 XShapeCombineRectangles(ob_display
, self
->window
,
204 ShapeBounding
, 0, 0, xrect
, num
,
205 ShapeUnion
, Unsorted
);
210 void frame_adjust_area(ObFrame
*self
, gboolean moved
, gboolean resized
)
213 self
->decorations
= self
->client
->decorations
;
214 if (self
->decorations
& OB_FRAME_DECOR_BORDER
) {
215 self
->bwidth
= ob_rr_theme
->bwidth
;
216 self
->cbwidth
= ob_rr_theme
->cbwidth
;
218 self
->bwidth
= self
->cbwidth
= 0;
220 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
221 self
->cbwidth
, self
->cbwidth
);
222 self
->width
= self
->client
->area
.width
+ self
->cbwidth
* 2;
223 g_assert(self
->width
> 0);
225 /* set border widths */
226 XSetWindowBorderWidth(ob_display
, self
->plate
, self
->cbwidth
);
227 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
228 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
229 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
230 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
231 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
233 /* position/size and map/unmap all the windows */
235 /* they all default off, they're turned on in layout_title */
239 self
->iconify_x
= -1;
244 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
245 XMoveResizeWindow(ob_display
, self
->title
,
246 -self
->bwidth
, -self
->bwidth
,
247 self
->width
, ob_rr_theme
->title_height
);
248 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->bwidth
;
249 XMapWindow(ob_display
, self
->title
);
251 XMoveWindow(ob_display
, self
->tlresize
, 0, 0);
252 XMoveWindow(ob_display
, self
->trresize
,
253 self
->width
- ob_rr_theme
->grip_width
, 0);
255 /* layout the title bar elements */
258 XUnmapWindow(ob_display
, self
->title
);
260 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
261 XMoveResizeWindow(ob_display
, self
->handle
,
262 -self
->bwidth
, FRAME_HANDLE_Y(self
),
263 self
->width
, ob_rr_theme
->handle_height
);
264 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
266 XMapWindow(ob_display
, self
->handle
);
268 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
269 XMoveWindow(ob_display
, self
->lgrip
,
270 -self
->bwidth
, -self
->bwidth
);
271 XMoveWindow(ob_display
, self
->rgrip
,
272 -self
->bwidth
+ self
->width
-
273 ob_rr_theme
->grip_width
, -self
->bwidth
);
274 XMapWindow(ob_display
, self
->lgrip
);
275 XMapWindow(ob_display
, self
->rgrip
);
277 XUnmapWindow(ob_display
, self
->lgrip
);
278 XUnmapWindow(ob_display
, self
->rgrip
);
281 /* XXX make a subwindow with these dimentions?
282 ob_rr_theme->grip_width + self->bwidth, 0,
283 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
284 ob_rr_theme->handle_height);
287 XUnmapWindow(ob_display
, self
->handle
);
289 /* move and resize the plate */
290 XMoveResizeWindow(ob_display
, self
->plate
,
291 self
->innersize
.left
- self
->cbwidth
,
292 self
->innersize
.top
- self
->cbwidth
,
293 self
->client
->area
.width
,
294 self
->client
->area
.height
);
295 /* when the client has StaticGravity, it likes to move around. */
296 XMoveWindow(ob_display
, self
->client
->window
, 0, 0);
298 STRUT_SET(self
->size
,
299 self
->innersize
.left
+ self
->bwidth
,
300 self
->innersize
.top
+ self
->bwidth
,
301 self
->innersize
.right
+ self
->bwidth
,
302 self
->innersize
.bottom
+ self
->bwidth
);
305 /* shading can change without being moved or resized */
306 RECT_SET_SIZE(self
->area
,
307 self
->client
->area
.width
+
308 self
->size
.left
+ self
->size
.right
,
309 (self
->client
->shaded
?
310 ob_rr_theme
->title_height
+ self
->bwidth
*2:
311 self
->client
->area
.height
+
312 self
->size
.top
+ self
->size
.bottom
));
315 /* find the new coordinates, done after setting the frame.size, for
316 frame_client_gravity. */
317 self
->area
.x
= self
->client
->area
.x
;
318 self
->area
.y
= self
->client
->area
.y
;
319 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
322 /* move and resize the top level frame.
323 shading can change without being moved or resized */
324 XMoveResizeWindow(ob_display
, self
->window
,
325 self
->area
.x
, self
->area
.y
,
327 self
->area
.height
- self
->bwidth
* 2);
330 framerender_frame(self
);
332 frame_adjust_shape(self
);
336 void frame_adjust_state(ObFrame
*self
)
338 framerender_frame(self
);
341 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
343 self
->focused
= hilite
;
344 framerender_frame(self
);
347 void frame_adjust_title(ObFrame
*self
)
349 framerender_frame(self
);
352 void frame_adjust_icon(ObFrame
*self
)
354 framerender_frame(self
);
357 void frame_grab_client(ObFrame
*self
, ObClient
*client
)
359 self
->client
= client
;
361 /* reparent the client to the frame */
362 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
364 When reparenting the client window, it is usually not mapped yet, since
365 this occurs from a MapRequest. However, in the case where Openbox is
366 starting up, the window is already mapped, so we'll see unmap events for
367 it. There are 2 unmap events generated that we see, one with the 'event'
368 member set the root window, and one set to the client, but both get
369 handled and need to be ignored.
371 if (ob_state() == OB_STATE_STARTING
)
372 client
->ignore_unmaps
+= 2;
374 /* select the event mask on the client's parent (to receive config/map
375 req's) the ButtonPress is to catch clicks on the client border */
376 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
378 /* map the client so it maps when the frame does */
379 XMapWindow(ob_display
, client
->window
);
381 frame_adjust_area(self
, TRUE
, TRUE
);
383 /* set all the windows for the frame in the window_map */
384 g_hash_table_insert(window_map
, &self
->window
, client
);
385 g_hash_table_insert(window_map
, &self
->plate
, client
);
386 g_hash_table_insert(window_map
, &self
->title
, client
);
387 g_hash_table_insert(window_map
, &self
->label
, client
);
388 g_hash_table_insert(window_map
, &self
->max
, client
);
389 g_hash_table_insert(window_map
, &self
->close
, client
);
390 g_hash_table_insert(window_map
, &self
->desk
, client
);
391 g_hash_table_insert(window_map
, &self
->shade
, client
);
392 g_hash_table_insert(window_map
, &self
->icon
, client
);
393 g_hash_table_insert(window_map
, &self
->iconify
, client
);
394 g_hash_table_insert(window_map
, &self
->handle
, client
);
395 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
396 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
397 g_hash_table_insert(window_map
, &self
->tlresize
, client
);
398 g_hash_table_insert(window_map
, &self
->trresize
, client
);
401 void frame_release_client(ObFrame
*self
, ObClient
*client
)
405 g_assert(self
->client
== client
);
407 /* check if the app has already reparented its window away */
408 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
409 ReparentNotify
, &ev
)) {
410 XPutBackEvent(ob_display
, &ev
);
412 /* re-map the window since the unmanaging process unmaps it */
414 /* XXX ... um no it doesnt it unmaps its parent, the window itself
415 retains its mapped state, no?! XXX
416 XMapWindow(ob_display, client->window); */
418 /* according to the ICCCM - if the client doesn't reparent itself,
419 then we will reparent the window to root for them */
420 XReparentWindow(ob_display
, client
->window
,
421 RootWindow(ob_display
, ob_screen
),
426 /* remove all the windows for the frame from the window_map */
427 g_hash_table_remove(window_map
, &self
->window
);
428 g_hash_table_remove(window_map
, &self
->plate
);
429 g_hash_table_remove(window_map
, &self
->title
);
430 g_hash_table_remove(window_map
, &self
->label
);
431 g_hash_table_remove(window_map
, &self
->max
);
432 g_hash_table_remove(window_map
, &self
->close
);
433 g_hash_table_remove(window_map
, &self
->desk
);
434 g_hash_table_remove(window_map
, &self
->shade
);
435 g_hash_table_remove(window_map
, &self
->icon
);
436 g_hash_table_remove(window_map
, &self
->iconify
);
437 g_hash_table_remove(window_map
, &self
->handle
);
438 g_hash_table_remove(window_map
, &self
->lgrip
);
439 g_hash_table_remove(window_map
, &self
->rgrip
);
440 g_hash_table_remove(window_map
, &self
->tlresize
);
441 g_hash_table_remove(window_map
, &self
->trresize
);
446 static void layout_title(ObFrame
*self
)
450 gboolean n
, d
, i
, l
, m
, c
, s
;
452 n
= d
= i
= l
= m
= c
= s
= FALSE
;
454 /* figure out whats being shown, and the width of the label */
455 self
->label_width
= self
->width
- (ob_rr_theme
->bevel
+ 1) * 2;
456 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
459 if (n
) { *lc
= ' '; break; } /* rm duplicates */
461 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
462 ob_rr_theme
->bevel
+ 1);
465 if (d
) { *lc
= ' '; break; } /* rm duplicates */
467 self
->label_width
-= (ob_rr_theme
->button_size
+
468 ob_rr_theme
->bevel
+ 1);
471 if (s
) { *lc
= ' '; break; } /* rm duplicates */
473 self
->label_width
-= (ob_rr_theme
->button_size
+
474 ob_rr_theme
->bevel
+ 1);
477 if (i
) { *lc
= ' '; break; } /* rm duplicates */
479 self
->label_width
-= (ob_rr_theme
->button_size
+
480 ob_rr_theme
->bevel
+ 1);
483 if (l
) { *lc
= ' '; break; } /* rm duplicates */
487 if (m
) { *lc
= ' '; break; } /* rm duplicates */
489 self
->label_width
-= (ob_rr_theme
->button_size
+
490 ob_rr_theme
->bevel
+ 1);
493 if (c
) { *lc
= ' '; break; } /* rm duplicates */
495 self
->label_width
-= (ob_rr_theme
->button_size
+
496 ob_rr_theme
->bevel
+ 1);
500 if (self
->label_width
< 1) self
->label_width
= 1;
502 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
503 ob_rr_theme
->label_height
);
505 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
506 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
507 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
508 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
509 if (!l
) XUnmapWindow(ob_display
, self
->label
);
510 if (!m
) XUnmapWindow(ob_display
, self
->max
);
511 if (!c
) XUnmapWindow(ob_display
, self
->close
);
513 x
= ob_rr_theme
->bevel
+ 1;
514 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
519 XMapWindow(ob_display
, self
->icon
);
520 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->bevel
);
521 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->bevel
+ 1;
526 XMapWindow(ob_display
, self
->desk
);
527 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->bevel
+ 1);
528 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
533 XMapWindow(ob_display
, self
->shade
);
534 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->bevel
+ 1);
535 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
540 XMapWindow(ob_display
, self
->iconify
);
541 XMoveWindow(ob_display
, self
->iconify
, x
, ob_rr_theme
->bevel
+ 1);
542 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
547 XMapWindow(ob_display
, self
->label
);
548 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->bevel
);
549 x
+= self
->label_width
+ ob_rr_theme
->bevel
+ 1;
554 XMapWindow(ob_display
, self
->max
);
555 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->bevel
+ 1);
556 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
561 XMapWindow(ob_display
, self
->close
);
562 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->bevel
+ 1);
563 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
569 ObFrameContext
frame_context_from_string(char *name
)
571 if (!g_ascii_strcasecmp("root", name
))
572 return OB_FRAME_CONTEXT_ROOT
;
573 else if (!g_ascii_strcasecmp("client", name
))
574 return OB_FRAME_CONTEXT_CLIENT
;
575 else if (!g_ascii_strcasecmp("titlebar", name
))
576 return OB_FRAME_CONTEXT_TITLEBAR
;
577 else if (!g_ascii_strcasecmp("handle", name
))
578 return OB_FRAME_CONTEXT_HANDLE
;
579 else if (!g_ascii_strcasecmp("frame", name
))
580 return OB_FRAME_CONTEXT_FRAME
;
581 else if (!g_ascii_strcasecmp("tlcorner", name
))
582 return OB_FRAME_CONTEXT_TLCORNER
;
583 else if (!g_ascii_strcasecmp("trcorner", name
))
584 return OB_FRAME_CONTEXT_TRCORNER
;
585 else if (!g_ascii_strcasecmp("blcorner", name
))
586 return OB_FRAME_CONTEXT_BLCORNER
;
587 else if (!g_ascii_strcasecmp("brcorner", name
))
588 return OB_FRAME_CONTEXT_BRCORNER
;
589 else if (!g_ascii_strcasecmp("maximize", name
))
590 return OB_FRAME_CONTEXT_MAXIMIZE
;
591 else if (!g_ascii_strcasecmp("alldesktops", name
))
592 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
593 else if (!g_ascii_strcasecmp("shade", name
))
594 return OB_FRAME_CONTEXT_SHADE
;
595 else if (!g_ascii_strcasecmp("iconify", name
))
596 return OB_FRAME_CONTEXT_ICONIFY
;
597 else if (!g_ascii_strcasecmp("icon", name
))
598 return OB_FRAME_CONTEXT_ICON
;
599 else if (!g_ascii_strcasecmp("close", name
))
600 return OB_FRAME_CONTEXT_CLOSE
;
601 return OB_FRAME_CONTEXT_NONE
;
604 ObFrameContext
frame_context(ObClient
*client
, Window win
)
608 if (win
== RootWindow(ob_display
, ob_screen
)) return OB_FRAME_CONTEXT_ROOT
;
609 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
610 if (win
== client
->window
) return OB_FRAME_CONTEXT_CLIENT
;
612 self
= client
->frame
;
613 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
614 if (win
== self
->plate
) return OB_FRAME_CONTEXT_CLIENT
;
615 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
616 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
617 if (win
== self
->handle
) return OB_FRAME_CONTEXT_HANDLE
;
618 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
619 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
620 if (win
== self
->tlresize
) return OB_FRAME_CONTEXT_TLCORNER
;
621 if (win
== self
->trresize
) return OB_FRAME_CONTEXT_TRCORNER
;
622 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
623 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
624 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
625 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
626 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
627 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
629 return OB_FRAME_CONTEXT_NONE
;
632 void frame_client_gravity(ObFrame
*self
, int *x
, int *y
)
635 switch (self
->client
->gravity
) {
637 case NorthWestGravity
:
638 case SouthWestGravity
:
645 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
648 case NorthEastGravity
:
649 case SouthEastGravity
:
651 *x
-= self
->size
.left
+ self
->size
.right
;
656 *x
-= self
->size
.left
;
661 switch (self
->client
->gravity
) {
663 case NorthWestGravity
:
664 case NorthEastGravity
:
671 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
674 case SouthWestGravity
:
675 case SouthEastGravity
:
677 *y
-= self
->size
.top
+ self
->size
.bottom
;
682 *y
-= self
->size
.top
;
687 void frame_frame_gravity(ObFrame
*self
, int *x
, int *y
)
690 switch (self
->client
->gravity
) {
692 case NorthWestGravity
:
694 case SouthWestGravity
:
699 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
701 case NorthEastGravity
:
703 case SouthEastGravity
:
704 *x
+= self
->size
.left
+ self
->size
.right
;
708 *x
+= self
->size
.left
;
713 switch (self
->client
->gravity
) {
715 case NorthWestGravity
:
717 case NorthEastGravity
:
722 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
724 case SouthWestGravity
:
726 case SouthEastGravity
:
727 *y
+= self
->size
.top
+ self
->size
.bottom
;
731 *y
+= self
->size
.top
;