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
->client
->decorations
=
227 self
->decorations
&= ~OB_FRAME_DECOR_HANDLE
;
229 if (self
->client
->max_horz
)
230 self
->bwidth
= self
->cbwidth_x
= 0;
232 STRUT_SET(self
->innersize
,
237 self
->width
= self
->client
->area
.width
+ self
->cbwidth_x
* 2 -
238 (self
->client
->max_horz
? self
->rbwidth
* 2 : 0);
239 self
->width
= MAX(self
->width
, 1); /* no lower than 1 */
241 /* set border widths */
243 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
244 XSetWindowBorderWidth(ob_display
, self
->title
, self
->rbwidth
);
245 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->rbwidth
);
246 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->rbwidth
);
247 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->rbwidth
);
250 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
251 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->rbwidth
+
252 (self
->rbwidth
- self
->bwidth
);
253 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
)
254 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
255 self
->rbwidth
+ (self
->rbwidth
- self
->bwidth
);
257 /* they all default off, they're turned on in layout_title */
261 self
->iconify_x
= -1;
266 /* position/size and map/unmap all the windows */
269 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
270 XMoveResizeWindow(ob_display
, self
->title
,
271 -self
->bwidth
, -self
->bwidth
,
272 self
->width
, ob_rr_theme
->title_height
);
273 XMapWindow(ob_display
, self
->title
);
275 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
276 XMoveWindow(ob_display
, self
->tlresize
, 0, 0);
277 XMoveWindow(ob_display
, self
->trresize
,
278 self
->width
- ob_rr_theme
->grip_width
, 0);
279 XMapWindow(ob_display
, self
->tlresize
);
280 XMapWindow(ob_display
, self
->trresize
);
282 XUnmapWindow(ob_display
, self
->tlresize
);
283 XUnmapWindow(ob_display
, self
->trresize
);
286 XUnmapWindow(ob_display
, self
->title
);
289 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
290 /* layout the title bar elements */
294 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
295 XMoveResizeWindow(ob_display
, self
->handle
,
296 -self
->bwidth
, FRAME_HANDLE_Y(self
),
297 self
->width
, ob_rr_theme
->handle_height
);
298 XMapWindow(ob_display
, self
->handle
);
300 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
301 XMoveWindow(ob_display
, self
->lgrip
,
302 -self
->rbwidth
, -self
->rbwidth
);
303 XMoveWindow(ob_display
, self
->rgrip
,
304 -self
->rbwidth
+ self
->width
-
305 ob_rr_theme
->grip_width
, -self
->rbwidth
);
306 XMapWindow(ob_display
, self
->lgrip
);
307 XMapWindow(ob_display
, self
->rgrip
);
309 XUnmapWindow(ob_display
, self
->lgrip
);
310 XUnmapWindow(ob_display
, self
->rgrip
);
313 /* XXX make a subwindow with these dimentions?
314 ob_rr_theme->grip_width + self->bwidth, 0,
315 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
316 ob_rr_theme->handle_height);
319 XUnmapWindow(ob_display
, self
->handle
);
321 /* move and resize the plate */
322 XMoveResizeWindow(ob_display
, self
->plate
,
323 self
->innersize
.left
- self
->cbwidth_x
,
324 self
->innersize
.top
- self
->cbwidth_y
,
325 self
->client
->area
.width
+ self
->cbwidth_x
* 2,
326 self
->client
->area
.height
+ self
->cbwidth_y
* 2);
327 /* when the client has StaticGravity, it likes to move around. */
328 XMoveWindow(ob_display
, self
->client
->window
,
329 self
->cbwidth_x
, self
->cbwidth_y
);
332 STRUT_SET(self
->size
,
333 self
->innersize
.left
+ self
->bwidth
,
334 self
->innersize
.top
+ self
->bwidth
,
335 self
->innersize
.right
+ self
->bwidth
,
336 self
->innersize
.bottom
+ self
->bwidth
);
339 /* shading can change without being moved or resized */
340 RECT_SET_SIZE(self
->area
,
341 self
->client
->area
.width
+
342 self
->size
.left
+ self
->size
.right
,
343 (self
->client
->shaded
?
344 ob_rr_theme
->title_height
+ self
->bwidth
*2:
345 self
->client
->area
.height
+
346 self
->size
.top
+ self
->size
.bottom
));
349 /* find the new coordinates, done after setting the frame.size, for
350 frame_client_gravity. */
351 self
->area
.x
= self
->client
->area
.x
;
352 self
->area
.y
= self
->client
->area
.y
;
353 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
357 /* move and resize the top level frame.
358 shading can change without being moved or resized */
359 XMoveResizeWindow(ob_display
, self
->window
,
360 self
->area
.x
, self
->area
.y
,
361 self
->area
.width
- self
->bwidth
* 2,
362 self
->area
.height
- self
->bwidth
* 2);
365 framerender_frame(self
);
367 frame_adjust_shape(self
);
372 void frame_adjust_state(ObFrame
*self
)
374 framerender_frame(self
);
377 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
379 self
->focused
= hilite
;
380 framerender_frame(self
);
383 void frame_adjust_title(ObFrame
*self
)
385 framerender_frame(self
);
388 void frame_adjust_icon(ObFrame
*self
)
390 framerender_frame(self
);
393 void frame_grab_client(ObFrame
*self
, ObClient
*client
)
395 self
->client
= client
;
397 /* reparent the client to the frame */
398 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
400 When reparenting the client window, it is usually not mapped yet, since
401 this occurs from a MapRequest. However, in the case where Openbox is
402 starting up, the window is already mapped, so we'll see unmap events for
403 it. There are 2 unmap events generated that we see, one with the 'event'
404 member set the root window, and one set to the client, but both get
405 handled and need to be ignored.
407 if (ob_state() == OB_STATE_STARTING
)
408 client
->ignore_unmaps
+= 2;
410 /* select the event mask on the client's parent (to receive config/map
411 req's) the ButtonPress is to catch clicks on the client border */
412 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
414 /* map the client so it maps when the frame does */
415 XMapWindow(ob_display
, client
->window
);
417 frame_adjust_area(self
, TRUE
, TRUE
, FALSE
);
419 /* set all the windows for the frame in the window_map */
420 g_hash_table_insert(window_map
, &self
->window
, client
);
421 g_hash_table_insert(window_map
, &self
->plate
, client
);
422 g_hash_table_insert(window_map
, &self
->title
, client
);
423 g_hash_table_insert(window_map
, &self
->label
, client
);
424 g_hash_table_insert(window_map
, &self
->max
, client
);
425 g_hash_table_insert(window_map
, &self
->close
, client
);
426 g_hash_table_insert(window_map
, &self
->desk
, client
);
427 g_hash_table_insert(window_map
, &self
->shade
, client
);
428 g_hash_table_insert(window_map
, &self
->icon
, client
);
429 g_hash_table_insert(window_map
, &self
->iconify
, client
);
430 g_hash_table_insert(window_map
, &self
->handle
, client
);
431 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
432 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
433 g_hash_table_insert(window_map
, &self
->tlresize
, client
);
434 g_hash_table_insert(window_map
, &self
->trresize
, client
);
437 void frame_release_client(ObFrame
*self
, ObClient
*client
)
441 g_assert(self
->client
== client
);
443 /* check if the app has already reparented its window away */
444 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
445 ReparentNotify
, &ev
)) {
446 XPutBackEvent(ob_display
, &ev
);
448 /* re-map the window since the unmanaging process unmaps it */
450 /* XXX ... um no it doesnt it unmaps its parent, the window itself
451 retains its mapped state, no?! XXX
452 XMapWindow(ob_display, client->window); */
454 /* according to the ICCCM - if the client doesn't reparent itself,
455 then we will reparent the window to root for them */
456 XReparentWindow(ob_display
, client
->window
,
457 RootWindow(ob_display
, ob_screen
),
462 /* remove all the windows for the frame from the window_map */
463 g_hash_table_remove(window_map
, &self
->window
);
464 g_hash_table_remove(window_map
, &self
->plate
);
465 g_hash_table_remove(window_map
, &self
->title
);
466 g_hash_table_remove(window_map
, &self
->label
);
467 g_hash_table_remove(window_map
, &self
->max
);
468 g_hash_table_remove(window_map
, &self
->close
);
469 g_hash_table_remove(window_map
, &self
->desk
);
470 g_hash_table_remove(window_map
, &self
->shade
);
471 g_hash_table_remove(window_map
, &self
->icon
);
472 g_hash_table_remove(window_map
, &self
->iconify
);
473 g_hash_table_remove(window_map
, &self
->handle
);
474 g_hash_table_remove(window_map
, &self
->lgrip
);
475 g_hash_table_remove(window_map
, &self
->rgrip
);
476 g_hash_table_remove(window_map
, &self
->tlresize
);
477 g_hash_table_remove(window_map
, &self
->trresize
);
482 static void layout_title(ObFrame
*self
)
486 gboolean n
, d
, i
, l
, m
, c
, s
;
488 n
= d
= i
= l
= m
= c
= s
= FALSE
;
490 /* figure out whats being shown, and the width of the label */
491 self
->label_width
= self
->width
- (ob_rr_theme
->bevel
+ 1) * 2;
492 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
495 if (n
) { *lc
= ' '; break; } /* rm duplicates */
497 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
498 ob_rr_theme
->bevel
+ 1);
501 if (d
) { *lc
= ' '; break; } /* rm duplicates */
503 self
->label_width
-= (ob_rr_theme
->button_size
+
504 ob_rr_theme
->bevel
+ 1);
507 if (s
) { *lc
= ' '; break; } /* rm duplicates */
509 self
->label_width
-= (ob_rr_theme
->button_size
+
510 ob_rr_theme
->bevel
+ 1);
513 if (i
) { *lc
= ' '; break; } /* rm duplicates */
515 self
->label_width
-= (ob_rr_theme
->button_size
+
516 ob_rr_theme
->bevel
+ 1);
519 if (l
) { *lc
= ' '; break; } /* rm duplicates */
523 if (m
) { *lc
= ' '; break; } /* rm duplicates */
525 self
->label_width
-= (ob_rr_theme
->button_size
+
526 ob_rr_theme
->bevel
+ 1);
529 if (c
) { *lc
= ' '; break; } /* rm duplicates */
531 self
->label_width
-= (ob_rr_theme
->button_size
+
532 ob_rr_theme
->bevel
+ 1);
536 if (self
->label_width
< 1) self
->label_width
= 1;
538 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
539 ob_rr_theme
->label_height
);
541 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
542 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
543 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
544 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
545 if (!l
) XUnmapWindow(ob_display
, self
->label
);
546 if (!m
) XUnmapWindow(ob_display
, self
->max
);
547 if (!c
) XUnmapWindow(ob_display
, self
->close
);
549 x
= ob_rr_theme
->bevel
+ 1;
550 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
555 XMapWindow(ob_display
, self
->icon
);
556 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->bevel
);
557 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->bevel
+ 1;
562 XMapWindow(ob_display
, self
->desk
);
563 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->bevel
+ 1);
564 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
569 XMapWindow(ob_display
, self
->shade
);
570 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->bevel
+ 1);
571 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
576 XMapWindow(ob_display
, self
->iconify
);
577 XMoveWindow(ob_display
, self
->iconify
, x
, ob_rr_theme
->bevel
+ 1);
578 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
583 XMapWindow(ob_display
, self
->label
);
584 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->bevel
);
585 x
+= self
->label_width
+ ob_rr_theme
->bevel
+ 1;
590 XMapWindow(ob_display
, self
->max
);
591 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->bevel
+ 1);
592 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
597 XMapWindow(ob_display
, self
->close
);
598 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->bevel
+ 1);
599 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
605 ObFrameContext
frame_context_from_string(char *name
)
607 if (!g_ascii_strcasecmp("desktop", name
))
608 return OB_FRAME_CONTEXT_DESKTOP
;
609 else if (!g_ascii_strcasecmp("client", name
))
610 return OB_FRAME_CONTEXT_CLIENT
;
611 else if (!g_ascii_strcasecmp("titlebar", name
))
612 return OB_FRAME_CONTEXT_TITLEBAR
;
613 else if (!g_ascii_strcasecmp("handle", name
))
614 return OB_FRAME_CONTEXT_HANDLE
;
615 else if (!g_ascii_strcasecmp("frame", name
))
616 return OB_FRAME_CONTEXT_FRAME
;
617 else if (!g_ascii_strcasecmp("tlcorner", name
))
618 return OB_FRAME_CONTEXT_TLCORNER
;
619 else if (!g_ascii_strcasecmp("trcorner", name
))
620 return OB_FRAME_CONTEXT_TRCORNER
;
621 else if (!g_ascii_strcasecmp("blcorner", name
))
622 return OB_FRAME_CONTEXT_BLCORNER
;
623 else if (!g_ascii_strcasecmp("brcorner", name
))
624 return OB_FRAME_CONTEXT_BRCORNER
;
625 else if (!g_ascii_strcasecmp("maximize", name
))
626 return OB_FRAME_CONTEXT_MAXIMIZE
;
627 else if (!g_ascii_strcasecmp("alldesktops", name
))
628 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
629 else if (!g_ascii_strcasecmp("shade", name
))
630 return OB_FRAME_CONTEXT_SHADE
;
631 else if (!g_ascii_strcasecmp("iconify", name
))
632 return OB_FRAME_CONTEXT_ICONIFY
;
633 else if (!g_ascii_strcasecmp("icon", name
))
634 return OB_FRAME_CONTEXT_ICON
;
635 else if (!g_ascii_strcasecmp("close", name
))
636 return OB_FRAME_CONTEXT_CLOSE
;
637 return OB_FRAME_CONTEXT_NONE
;
640 ObFrameContext
frame_context(ObClient
*client
, Window win
)
644 if (win
== RootWindow(ob_display
, ob_screen
))
645 return OB_FRAME_CONTEXT_DESKTOP
;
646 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
647 if (win
== client
->window
) {
648 /* conceptually, this is the desktop, as far as users are
650 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
651 return OB_FRAME_CONTEXT_DESKTOP
;
652 return OB_FRAME_CONTEXT_CLIENT
;
655 self
= client
->frame
;
656 if (win
== self
->plate
) {
657 /* conceptually, this is the desktop, as far as users are
659 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
660 return OB_FRAME_CONTEXT_DESKTOP
;
661 return OB_FRAME_CONTEXT_CLIENT
;
664 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
665 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
666 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
667 if (win
== self
->handle
) return OB_FRAME_CONTEXT_HANDLE
;
668 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
669 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
670 if (win
== self
->tlresize
) return OB_FRAME_CONTEXT_TLCORNER
;
671 if (win
== self
->trresize
) return OB_FRAME_CONTEXT_TRCORNER
;
672 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
673 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
674 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
675 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
676 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
677 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
679 return OB_FRAME_CONTEXT_NONE
;
682 void frame_client_gravity(ObFrame
*self
, int *x
, int *y
)
685 switch (self
->client
->gravity
) {
687 case NorthWestGravity
:
688 case SouthWestGravity
:
695 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
698 case NorthEastGravity
:
699 case SouthEastGravity
:
701 *x
-= self
->size
.left
+ self
->size
.right
;
706 *x
-= self
->size
.left
;
711 switch (self
->client
->gravity
) {
713 case NorthWestGravity
:
714 case NorthEastGravity
:
721 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
724 case SouthWestGravity
:
725 case SouthEastGravity
:
727 *y
-= self
->size
.top
+ self
->size
.bottom
;
732 *y
-= self
->size
.top
;
737 void frame_frame_gravity(ObFrame
*self
, int *x
, int *y
)
740 switch (self
->client
->gravity
) {
742 case NorthWestGravity
:
744 case SouthWestGravity
:
749 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
751 case NorthEastGravity
:
753 case SouthEastGravity
:
754 *x
+= self
->size
.left
+ self
->size
.right
;
758 *x
+= self
->size
.left
;
763 switch (self
->client
->gravity
) {
765 case NorthWestGravity
:
767 case NorthEastGravity
:
772 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
774 case SouthWestGravity
:
776 case SouthEastGravity
:
777 *y
+= self
->size
.top
+ self
->size
.bottom
;
781 *y
+= self
->size
.top
;