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 | \
13 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
14 ButtonMotionMask | ExposureMask | \
15 EnterWindowMask | LeaveWindowMask)
17 #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \
20 static void layout_title(ObFrame
*self
);
22 static Window
createWindow(Window parent
, unsigned long mask
,
23 XSetWindowAttributes
*attrib
)
25 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
26 RrDepth(ob_rr_inst
), InputOutput
,
27 RrVisual(ob_rr_inst
), mask
, attrib
);
33 XSetWindowAttributes attrib
;
37 self
= g_new(ObFrame
, 1);
39 self
->visible
= FALSE
;
40 self
->obscured
= TRUE
;
41 self
->decorations
= 0;
43 /* create all of the decor windows */
44 mask
= CWOverrideRedirect
| CWEventMask
;
45 attrib
.event_mask
= FRAME_EVENTMASK
;
46 attrib
.override_redirect
= TRUE
;
47 self
->window
= createWindow(RootWindow(ob_display
, ob_screen
),
51 self
->plate
= createWindow(self
->window
, mask
, &attrib
);
54 attrib
.event_mask
= ELEMENT_EVENTMASK
;
55 self
->title
= createWindow(self
->window
, mask
, &attrib
);
58 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHWEST
);
59 self
->tlresize
= createWindow(self
->title
, mask
, &attrib
);
60 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHEAST
);
61 self
->trresize
= createWindow(self
->title
, mask
, &attrib
);
64 self
->label
= createWindow(self
->title
, mask
, &attrib
);
65 self
->max
= createWindow(self
->title
, mask
, &attrib
);
66 self
->close
= createWindow(self
->title
, mask
, &attrib
);
67 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
68 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
69 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
70 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
71 self
->handle
= createWindow(self
->window
, mask
, &attrib
);
74 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHWEST
);
75 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
76 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHEAST
);
77 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
79 self
->focused
= FALSE
;
81 /* the other stuff is shown based on decor settings */
82 XMapWindow(ob_display
, self
->plate
);
83 XMapWindow(ob_display
, self
->lgrip
);
84 XMapWindow(ob_display
, self
->rgrip
);
85 XMapWindow(ob_display
, self
->label
);
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
->title
, ob_rr_theme
->b_color
->pixel
);
90 XSetWindowBorder(ob_display
, self
->handle
, ob_rr_theme
->b_color
->pixel
);
91 XSetWindowBorder(ob_display
, self
->rgrip
, ob_rr_theme
->b_color
->pixel
);
92 XSetWindowBorder(ob_display
, self
->lgrip
, ob_rr_theme
->b_color
->pixel
);
94 XResizeWindow(ob_display
, self
->max
,
95 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
96 XResizeWindow(ob_display
, self
->iconify
,
97 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
98 XResizeWindow(ob_display
, self
->icon
,
99 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
100 XResizeWindow(ob_display
, self
->close
,
101 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
102 XResizeWindow(ob_display
, self
->desk
,
103 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
104 XResizeWindow(ob_display
, self
->shade
,
105 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
106 XResizeWindow(ob_display
, self
->lgrip
,
107 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
108 XResizeWindow(ob_display
, self
->rgrip
,
109 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
110 XResizeWindow(ob_display
, self
->tlresize
,
111 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
112 XResizeWindow(ob_display
, self
->trresize
,
113 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
115 /* set up the dynamic appearances */
116 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
117 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
118 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
119 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
120 self
->a_unfocused_handle
=
121 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
122 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
123 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
125 self
->max_press
= self
->close_press
= self
->desk_press
=
126 self
->iconify_press
= self
->shade_press
= FALSE
;
127 self
->max_hover
= self
->close_hover
= self
->desk_hover
=
128 self
->iconify_hover
= self
->shade_hover
= FALSE
;
130 return (ObFrame
*)self
;
133 static void frame_free(ObFrame
*self
)
135 RrAppearanceFree(self
->a_unfocused_title
);
136 RrAppearanceFree(self
->a_focused_title
);
137 RrAppearanceFree(self
->a_unfocused_label
);
138 RrAppearanceFree(self
->a_focused_label
);
139 RrAppearanceFree(self
->a_unfocused_handle
);
140 RrAppearanceFree(self
->a_focused_handle
);
141 RrAppearanceFree(self
->a_icon
);
143 XDestroyWindow(ob_display
, self
->window
);
148 void frame_show(ObFrame
*self
)
150 if (!self
->visible
) {
151 self
->visible
= TRUE
;
152 XMapWindow(ob_display
, self
->window
);
156 void frame_hide(ObFrame
*self
)
159 self
->visible
= FALSE
;
160 self
->client
->ignore_unmaps
++;
161 XUnmapWindow(ob_display
, self
->window
);
165 void frame_adjust_shape(ObFrame
*self
)
171 if (!self
->client
->shaped
) {
172 /* clear the shape on the frame window */
173 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
174 self
->innersize
.left
,
178 /* make the frame's shape match the clients */
179 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
180 self
->innersize
.left
,
182 self
->client
->window
,
183 ShapeBounding
, ShapeSet
);
186 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
187 xrect
[0].x
= -ob_rr_theme
->bwidth
;
188 xrect
[0].y
= -ob_rr_theme
->bwidth
;
189 xrect
[0].width
= self
->width
+ self
->rbwidth
* 2;
190 xrect
[0].height
= ob_rr_theme
->title_height
+
195 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
196 xrect
[1].x
= -ob_rr_theme
->bwidth
;
197 xrect
[1].y
= FRAME_HANDLE_Y(self
);
198 xrect
[1].width
= self
->width
+ self
->rbwidth
* 2;
199 xrect
[1].height
= ob_rr_theme
->handle_height
+
204 XShapeCombineRectangles(ob_display
, self
->window
,
205 ShapeBounding
, 0, 0, xrect
, num
,
206 ShapeUnion
, Unsorted
);
211 void frame_adjust_area(ObFrame
*self
, gboolean moved
,
212 gboolean resized
, gboolean fake
)
215 self
->decorations
= self
->client
->decorations
;
217 if (self
->decorations
& OB_FRAME_DECOR_BORDER
) {
218 self
->bwidth
= ob_rr_theme
->bwidth
;
219 self
->cbwidth_x
= self
->cbwidth_y
= ob_rr_theme
->cbwidth
;
221 self
->bwidth
= self
->cbwidth_x
= self
->cbwidth_y
= 0;
223 self
->rbwidth
= self
->bwidth
;
225 if (self
->client
->max_vert
&& self
->client
->max_horz
)
226 self
->decorations
&= ~OB_FRAME_DECOR_HANDLE
;
228 if (self
->client
->max_horz
)
229 self
->bwidth
= self
->cbwidth_x
= 0;
231 STRUT_SET(self
->innersize
,
236 self
->width
= self
->client
->area
.width
+ self
->cbwidth_x
* 2 -
237 (self
->client
->max_horz
? self
->rbwidth
* 2 : 0);
238 self
->width
= MAX(self
->width
, 1); /* no lower than 1 */
240 /* set border widths */
242 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
243 XSetWindowBorderWidth(ob_display
, self
->title
, self
->rbwidth
);
244 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->rbwidth
);
245 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->rbwidth
);
246 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->rbwidth
);
249 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
250 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->rbwidth
+
251 (self
->rbwidth
- self
->bwidth
);
252 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
)
253 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
254 self
->rbwidth
+ (self
->rbwidth
- self
->bwidth
);
256 /* they all default off, they're turned on in layout_title */
260 self
->iconify_x
= -1;
265 /* position/size and map/unmap all the windows */
268 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
269 XMoveResizeWindow(ob_display
, self
->title
,
270 -self
->bwidth
, -self
->bwidth
,
271 self
->width
, ob_rr_theme
->title_height
);
272 XMapWindow(ob_display
, self
->title
);
274 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
275 XMoveWindow(ob_display
, self
->tlresize
, 0, 0);
276 XMoveWindow(ob_display
, self
->trresize
,
277 self
->width
- ob_rr_theme
->grip_width
, 0);
278 XMapWindow(ob_display
, self
->tlresize
);
279 XMapWindow(ob_display
, self
->trresize
);
281 XUnmapWindow(ob_display
, self
->tlresize
);
282 XUnmapWindow(ob_display
, self
->trresize
);
285 XUnmapWindow(ob_display
, self
->title
);
288 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
289 /* layout the title bar elements */
293 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
294 XMoveResizeWindow(ob_display
, self
->handle
,
295 -self
->bwidth
, FRAME_HANDLE_Y(self
),
296 self
->width
, ob_rr_theme
->handle_height
);
297 XMapWindow(ob_display
, self
->handle
);
299 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
300 XMoveWindow(ob_display
, self
->lgrip
,
301 -self
->rbwidth
, -self
->rbwidth
);
302 XMoveWindow(ob_display
, self
->rgrip
,
303 -self
->rbwidth
+ self
->width
-
304 ob_rr_theme
->grip_width
, -self
->rbwidth
);
305 XMapWindow(ob_display
, self
->lgrip
);
306 XMapWindow(ob_display
, self
->rgrip
);
308 XUnmapWindow(ob_display
, self
->lgrip
);
309 XUnmapWindow(ob_display
, self
->rgrip
);
312 /* XXX make a subwindow with these dimentions?
313 ob_rr_theme->grip_width + self->bwidth, 0,
314 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
315 ob_rr_theme->handle_height);
318 XUnmapWindow(ob_display
, self
->handle
);
320 /* move and resize the plate */
321 XMoveResizeWindow(ob_display
, self
->plate
,
322 self
->innersize
.left
- self
->cbwidth_x
,
323 self
->innersize
.top
- self
->cbwidth_y
,
324 self
->client
->area
.width
+ self
->cbwidth_x
* 2,
325 self
->client
->area
.height
+ self
->cbwidth_y
* 2);
326 /* when the client has StaticGravity, it likes to move around. */
327 XMoveWindow(ob_display
, self
->client
->window
,
328 self
->cbwidth_x
, self
->cbwidth_y
);
331 STRUT_SET(self
->size
,
332 self
->innersize
.left
+ self
->bwidth
,
333 self
->innersize
.top
+ self
->bwidth
,
334 self
->innersize
.right
+ self
->bwidth
,
335 self
->innersize
.bottom
+ self
->bwidth
);
338 /* shading can change without being moved or resized */
339 RECT_SET_SIZE(self
->area
,
340 self
->client
->area
.width
+
341 self
->size
.left
+ self
->size
.right
,
342 (self
->client
->shaded
?
343 ob_rr_theme
->title_height
+ self
->bwidth
*2:
344 self
->client
->area
.height
+
345 self
->size
.top
+ self
->size
.bottom
));
348 /* find the new coordinates, done after setting the frame.size, for
349 frame_client_gravity. */
350 self
->area
.x
= self
->client
->area
.x
;
351 self
->area
.y
= self
->client
->area
.y
;
352 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
356 /* move and resize the top level frame.
357 shading can change without being moved or resized */
358 XMoveResizeWindow(ob_display
, self
->window
,
359 self
->area
.x
, self
->area
.y
,
360 self
->area
.width
- self
->bwidth
* 2,
361 self
->area
.height
- self
->bwidth
* 2);
364 framerender_frame(self
);
366 frame_adjust_shape(self
);
371 void frame_adjust_state(ObFrame
*self
)
373 framerender_frame(self
);
376 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
378 self
->focused
= hilite
;
379 framerender_frame(self
);
382 void frame_adjust_title(ObFrame
*self
)
384 framerender_frame(self
);
387 void frame_adjust_icon(ObFrame
*self
)
389 framerender_frame(self
);
392 void frame_grab_client(ObFrame
*self
, ObClient
*client
)
394 self
->client
= client
;
396 /* reparent the client to the frame */
397 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
399 When reparenting the client window, it is usually not mapped yet, since
400 this occurs from a MapRequest. However, in the case where Openbox is
401 starting up, the window is already mapped, so we'll see unmap events for
402 it. There are 2 unmap events generated that we see, one with the 'event'
403 member set the root window, and one set to the client, but both get
404 handled and need to be ignored.
406 if (ob_state() == OB_STATE_STARTING
)
407 client
->ignore_unmaps
+= 2;
409 /* select the event mask on the client's parent (to receive config/map
410 req's) the ButtonPress is to catch clicks on the client border */
411 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
413 /* map the client so it maps when the frame does */
414 XMapWindow(ob_display
, client
->window
);
416 frame_adjust_area(self
, TRUE
, TRUE
, FALSE
);
418 /* set all the windows for the frame in the window_map */
419 g_hash_table_insert(window_map
, &self
->window
, client
);
420 g_hash_table_insert(window_map
, &self
->plate
, client
);
421 g_hash_table_insert(window_map
, &self
->title
, client
);
422 g_hash_table_insert(window_map
, &self
->label
, client
);
423 g_hash_table_insert(window_map
, &self
->max
, client
);
424 g_hash_table_insert(window_map
, &self
->close
, client
);
425 g_hash_table_insert(window_map
, &self
->desk
, client
);
426 g_hash_table_insert(window_map
, &self
->shade
, client
);
427 g_hash_table_insert(window_map
, &self
->icon
, client
);
428 g_hash_table_insert(window_map
, &self
->iconify
, client
);
429 g_hash_table_insert(window_map
, &self
->handle
, client
);
430 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
431 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
432 g_hash_table_insert(window_map
, &self
->tlresize
, client
);
433 g_hash_table_insert(window_map
, &self
->trresize
, client
);
436 void frame_release_client(ObFrame
*self
, ObClient
*client
)
440 g_assert(self
->client
== client
);
442 /* check if the app has already reparented its window away */
443 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
444 ReparentNotify
, &ev
)) {
445 XPutBackEvent(ob_display
, &ev
);
447 /* re-map the window since the unmanaging process unmaps it */
449 /* XXX ... um no it doesnt it unmaps its parent, the window itself
450 retains its mapped state, no?! XXX
451 XMapWindow(ob_display, client->window); */
453 /* according to the ICCCM - if the client doesn't reparent itself,
454 then we will reparent the window to root for them */
455 XReparentWindow(ob_display
, client
->window
,
456 RootWindow(ob_display
, ob_screen
),
461 /* remove all the windows for the frame from the window_map */
462 g_hash_table_remove(window_map
, &self
->window
);
463 g_hash_table_remove(window_map
, &self
->plate
);
464 g_hash_table_remove(window_map
, &self
->title
);
465 g_hash_table_remove(window_map
, &self
->label
);
466 g_hash_table_remove(window_map
, &self
->max
);
467 g_hash_table_remove(window_map
, &self
->close
);
468 g_hash_table_remove(window_map
, &self
->desk
);
469 g_hash_table_remove(window_map
, &self
->shade
);
470 g_hash_table_remove(window_map
, &self
->icon
);
471 g_hash_table_remove(window_map
, &self
->iconify
);
472 g_hash_table_remove(window_map
, &self
->handle
);
473 g_hash_table_remove(window_map
, &self
->lgrip
);
474 g_hash_table_remove(window_map
, &self
->rgrip
);
475 g_hash_table_remove(window_map
, &self
->tlresize
);
476 g_hash_table_remove(window_map
, &self
->trresize
);
481 static void layout_title(ObFrame
*self
)
485 gboolean n
, d
, i
, l
, m
, c
, s
;
487 n
= d
= i
= l
= m
= c
= s
= FALSE
;
489 /* figure out whats being shown, and the width of the label */
490 self
->label_width
= self
->width
- (ob_rr_theme
->bevel
+ 1) * 2;
491 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
494 if (n
) { *lc
= ' '; break; } /* rm duplicates */
496 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
497 ob_rr_theme
->bevel
+ 1);
500 if (d
) { *lc
= ' '; break; } /* rm duplicates */
502 self
->label_width
-= (ob_rr_theme
->button_size
+
503 ob_rr_theme
->bevel
+ 1);
506 if (s
) { *lc
= ' '; break; } /* rm duplicates */
508 self
->label_width
-= (ob_rr_theme
->button_size
+
509 ob_rr_theme
->bevel
+ 1);
512 if (i
) { *lc
= ' '; break; } /* rm duplicates */
514 self
->label_width
-= (ob_rr_theme
->button_size
+
515 ob_rr_theme
->bevel
+ 1);
518 if (l
) { *lc
= ' '; break; } /* rm duplicates */
522 if (m
) { *lc
= ' '; break; } /* rm duplicates */
524 self
->label_width
-= (ob_rr_theme
->button_size
+
525 ob_rr_theme
->bevel
+ 1);
528 if (c
) { *lc
= ' '; break; } /* rm duplicates */
530 self
->label_width
-= (ob_rr_theme
->button_size
+
531 ob_rr_theme
->bevel
+ 1);
535 if (self
->label_width
< 1) self
->label_width
= 1;
537 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
538 ob_rr_theme
->label_height
);
540 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
541 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
542 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
543 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
544 if (!l
) XUnmapWindow(ob_display
, self
->label
);
545 if (!m
) XUnmapWindow(ob_display
, self
->max
);
546 if (!c
) XUnmapWindow(ob_display
, self
->close
);
548 x
= ob_rr_theme
->bevel
+ 1;
549 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
554 XMapWindow(ob_display
, self
->icon
);
555 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->bevel
);
556 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->bevel
+ 1;
561 XMapWindow(ob_display
, self
->desk
);
562 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->bevel
+ 1);
563 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
568 XMapWindow(ob_display
, self
->shade
);
569 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->bevel
+ 1);
570 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
575 XMapWindow(ob_display
, self
->iconify
);
576 XMoveWindow(ob_display
, self
->iconify
, x
, ob_rr_theme
->bevel
+ 1);
577 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
582 XMapWindow(ob_display
, self
->label
);
583 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->bevel
);
584 x
+= self
->label_width
+ ob_rr_theme
->bevel
+ 1;
589 XMapWindow(ob_display
, self
->max
);
590 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->bevel
+ 1);
591 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
596 XMapWindow(ob_display
, self
->close
);
597 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->bevel
+ 1);
598 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
604 ObFrameContext
frame_context_from_string(char *name
)
606 if (!g_ascii_strcasecmp("desktop", name
))
607 return OB_FRAME_CONTEXT_DESKTOP
;
608 else if (!g_ascii_strcasecmp("client", name
))
609 return OB_FRAME_CONTEXT_CLIENT
;
610 else if (!g_ascii_strcasecmp("titlebar", name
))
611 return OB_FRAME_CONTEXT_TITLEBAR
;
612 else if (!g_ascii_strcasecmp("handle", name
))
613 return OB_FRAME_CONTEXT_HANDLE
;
614 else if (!g_ascii_strcasecmp("frame", name
))
615 return OB_FRAME_CONTEXT_FRAME
;
616 else if (!g_ascii_strcasecmp("tlcorner", name
))
617 return OB_FRAME_CONTEXT_TLCORNER
;
618 else if (!g_ascii_strcasecmp("trcorner", name
))
619 return OB_FRAME_CONTEXT_TRCORNER
;
620 else if (!g_ascii_strcasecmp("blcorner", name
))
621 return OB_FRAME_CONTEXT_BLCORNER
;
622 else if (!g_ascii_strcasecmp("brcorner", name
))
623 return OB_FRAME_CONTEXT_BRCORNER
;
624 else if (!g_ascii_strcasecmp("maximize", name
))
625 return OB_FRAME_CONTEXT_MAXIMIZE
;
626 else if (!g_ascii_strcasecmp("alldesktops", name
))
627 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
628 else if (!g_ascii_strcasecmp("shade", name
))
629 return OB_FRAME_CONTEXT_SHADE
;
630 else if (!g_ascii_strcasecmp("iconify", name
))
631 return OB_FRAME_CONTEXT_ICONIFY
;
632 else if (!g_ascii_strcasecmp("icon", name
))
633 return OB_FRAME_CONTEXT_ICON
;
634 else if (!g_ascii_strcasecmp("close", name
))
635 return OB_FRAME_CONTEXT_CLOSE
;
636 return OB_FRAME_CONTEXT_NONE
;
639 ObFrameContext
frame_context(ObClient
*client
, Window win
)
643 if (win
== RootWindow(ob_display
, ob_screen
))
644 return OB_FRAME_CONTEXT_DESKTOP
;
645 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
646 if (win
== client
->window
) {
647 /* conceptually, this is the desktop, as far as users are
649 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
650 return OB_FRAME_CONTEXT_DESKTOP
;
651 return OB_FRAME_CONTEXT_CLIENT
;
654 self
= client
->frame
;
655 if (win
== self
->plate
) {
656 /* conceptually, this is the desktop, as far as users are
658 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
659 return OB_FRAME_CONTEXT_DESKTOP
;
660 return OB_FRAME_CONTEXT_CLIENT
;
663 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
664 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
665 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
666 if (win
== self
->handle
) return OB_FRAME_CONTEXT_HANDLE
;
667 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
668 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
669 if (win
== self
->tlresize
) return OB_FRAME_CONTEXT_TLCORNER
;
670 if (win
== self
->trresize
) return OB_FRAME_CONTEXT_TRCORNER
;
671 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
672 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
673 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
674 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
675 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
676 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
678 return OB_FRAME_CONTEXT_NONE
;
681 void frame_client_gravity(ObFrame
*self
, int *x
, int *y
)
684 switch (self
->client
->gravity
) {
686 case NorthWestGravity
:
687 case SouthWestGravity
:
694 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
697 case NorthEastGravity
:
698 case SouthEastGravity
:
700 *x
-= self
->size
.left
+ self
->size
.right
;
705 *x
-= self
->size
.left
;
710 switch (self
->client
->gravity
) {
712 case NorthWestGravity
:
713 case NorthEastGravity
:
720 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
723 case SouthWestGravity
:
724 case SouthEastGravity
:
726 *y
-= self
->size
.top
+ self
->size
.bottom
;
731 *y
-= self
->size
.top
;
736 void frame_frame_gravity(ObFrame
*self
, int *x
, int *y
)
739 switch (self
->client
->gravity
) {
741 case NorthWestGravity
:
743 case SouthWestGravity
:
748 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
750 case NorthEastGravity
:
752 case SouthEastGravity
:
753 *x
+= self
->size
.left
+ self
->size
.right
;
757 *x
+= self
->size
.left
;
762 switch (self
->client
->gravity
) {
764 case NorthWestGravity
:
766 case NorthEastGravity
:
771 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
773 case SouthWestGravity
:
775 case SouthEastGravity
:
776 *y
+= self
->size
.top
+ self
->size
.bottom
;
780 *y
+= self
->size
.top
;