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
);
85 /* set colors/appearance/sizes for stuff that doesn't change */
86 XSetWindowBorder(ob_display
, self
->window
, ob_rr_theme
->b_color
->pixel
);
87 XSetWindowBorder(ob_display
, self
->title
, ob_rr_theme
->b_color
->pixel
);
88 XSetWindowBorder(ob_display
, self
->handle
, ob_rr_theme
->b_color
->pixel
);
89 XSetWindowBorder(ob_display
, self
->rgrip
, ob_rr_theme
->b_color
->pixel
);
90 XSetWindowBorder(ob_display
, self
->lgrip
, ob_rr_theme
->b_color
->pixel
);
92 XResizeWindow(ob_display
, self
->max
,
93 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
94 XResizeWindow(ob_display
, self
->iconify
,
95 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
96 XResizeWindow(ob_display
, self
->icon
,
97 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
98 XResizeWindow(ob_display
, self
->close
,
99 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
100 XResizeWindow(ob_display
, self
->desk
,
101 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
102 XResizeWindow(ob_display
, self
->shade
,
103 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
104 XResizeWindow(ob_display
, self
->lgrip
,
105 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
106 XResizeWindow(ob_display
, self
->rgrip
,
107 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
108 XResizeWindow(ob_display
, self
->tlresize
,
109 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
110 XResizeWindow(ob_display
, self
->trresize
,
111 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
113 /* set up the dynamic appearances */
114 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
115 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
116 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
117 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
118 self
->a_unfocused_handle
=
119 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
120 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
121 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
123 self
->max_press
= self
->close_press
= self
->desk_press
=
124 self
->iconify_press
= self
->shade_press
= FALSE
;
125 self
->max_hover
= self
->close_hover
= self
->desk_hover
=
126 self
->iconify_hover
= self
->shade_hover
= FALSE
;
128 return (ObFrame
*)self
;
131 static void frame_free(ObFrame
*self
)
133 RrAppearanceFree(self
->a_unfocused_title
);
134 RrAppearanceFree(self
->a_focused_title
);
135 RrAppearanceFree(self
->a_unfocused_label
);
136 RrAppearanceFree(self
->a_focused_label
);
137 RrAppearanceFree(self
->a_unfocused_handle
);
138 RrAppearanceFree(self
->a_focused_handle
);
139 RrAppearanceFree(self
->a_icon
);
141 XDestroyWindow(ob_display
, self
->window
);
146 void frame_show(ObFrame
*self
)
148 if (!self
->visible
) {
149 self
->visible
= TRUE
;
150 XMapWindow(ob_display
, self
->window
);
154 void frame_hide(ObFrame
*self
)
157 self
->visible
= FALSE
;
158 self
->client
->ignore_unmaps
++;
159 XUnmapWindow(ob_display
, self
->window
);
163 void frame_adjust_shape(ObFrame
*self
)
169 if (!self
->client
->shaped
) {
170 /* clear the shape on the frame window */
171 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
172 self
->innersize
.left
,
176 /* make the frame's shape match the clients */
177 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
178 self
->innersize
.left
,
180 self
->client
->window
,
181 ShapeBounding
, ShapeSet
);
184 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
185 xrect
[0].x
= -ob_rr_theme
->bwidth
;
186 xrect
[0].y
= -ob_rr_theme
->bwidth
;
187 xrect
[0].width
= self
->width
+ self
->rbwidth
* 2;
188 xrect
[0].height
= ob_rr_theme
->title_height
+
193 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
194 xrect
[1].x
= -ob_rr_theme
->bwidth
;
195 xrect
[1].y
= FRAME_HANDLE_Y(self
);
196 xrect
[1].width
= self
->width
+ self
->rbwidth
* 2;
197 xrect
[1].height
= ob_rr_theme
->handle_height
+
202 XShapeCombineRectangles(ob_display
, self
->window
,
203 ShapeBounding
, 0, 0, xrect
, num
,
204 ShapeUnion
, Unsorted
);
209 void frame_adjust_area(ObFrame
*self
, gboolean moved
,
210 gboolean resized
, gboolean fake
)
213 self
->decorations
= self
->client
->decorations
;
215 if (self
->decorations
& OB_FRAME_DECOR_BORDER
) {
216 self
->bwidth
= ob_rr_theme
->bwidth
;
217 self
->cbwidth_x
= self
->cbwidth_y
= ob_rr_theme
->cbwidth
;
219 self
->bwidth
= self
->cbwidth_x
= self
->cbwidth_y
= 0;
221 self
->rbwidth
= self
->bwidth
;
223 if (self
->client
->max_vert
&& self
->client
->max_horz
)
224 self
->decorations
&= ~OB_FRAME_DECOR_HANDLE
;
226 if (self
->client
->max_horz
)
227 self
->bwidth
= self
->cbwidth_x
= 0;
229 STRUT_SET(self
->innersize
,
234 self
->width
= self
->client
->area
.width
+ self
->cbwidth_x
* 2 -
235 (self
->client
->max_horz
? self
->rbwidth
* 2 : 0);
236 self
->width
= MAX(self
->width
, 1); /* no lower than 1 */
238 /* set border widths */
240 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
241 XSetWindowBorderWidth(ob_display
, self
->title
, self
->rbwidth
);
242 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->rbwidth
);
243 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->rbwidth
);
244 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->rbwidth
);
247 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
248 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->rbwidth
+
249 (self
->rbwidth
- self
->bwidth
);
250 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
)
251 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
252 self
->rbwidth
+ (self
->rbwidth
- self
->bwidth
);
254 /* they all default off, they're turned on in layout_title */
258 self
->iconify_x
= -1;
263 /* position/size and map/unmap all the windows */
266 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
267 XMoveResizeWindow(ob_display
, self
->title
,
268 -self
->bwidth
, -self
->bwidth
,
269 self
->width
, ob_rr_theme
->title_height
);
270 XMapWindow(ob_display
, self
->title
);
272 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
273 XMoveWindow(ob_display
, self
->tlresize
, 0, 0);
274 XMoveWindow(ob_display
, self
->trresize
,
275 self
->width
- ob_rr_theme
->grip_width
, 0);
276 XMapWindow(ob_display
, self
->tlresize
);
277 XMapWindow(ob_display
, self
->trresize
);
279 XUnmapWindow(ob_display
, self
->tlresize
);
280 XUnmapWindow(ob_display
, self
->trresize
);
283 XUnmapWindow(ob_display
, self
->title
);
286 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
287 /* layout the title bar elements */
291 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
292 XMoveResizeWindow(ob_display
, self
->handle
,
293 -self
->bwidth
, FRAME_HANDLE_Y(self
),
294 self
->width
, ob_rr_theme
->handle_height
);
295 XMapWindow(ob_display
, self
->handle
);
297 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
298 XMoveWindow(ob_display
, self
->lgrip
,
299 -self
->rbwidth
, -self
->rbwidth
);
300 XMoveWindow(ob_display
, self
->rgrip
,
301 -self
->rbwidth
+ self
->width
-
302 ob_rr_theme
->grip_width
, -self
->rbwidth
);
303 XMapWindow(ob_display
, self
->lgrip
);
304 XMapWindow(ob_display
, self
->rgrip
);
306 XUnmapWindow(ob_display
, self
->lgrip
);
307 XUnmapWindow(ob_display
, self
->rgrip
);
310 /* XXX make a subwindow with these dimentions?
311 ob_rr_theme->grip_width + self->bwidth, 0,
312 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
313 ob_rr_theme->handle_height);
316 XUnmapWindow(ob_display
, self
->handle
);
318 /* move and resize the plate */
319 XMoveResizeWindow(ob_display
, self
->plate
,
320 self
->innersize
.left
- self
->cbwidth_x
,
321 self
->innersize
.top
- self
->cbwidth_y
,
322 self
->client
->area
.width
+ self
->cbwidth_x
* 2,
323 self
->client
->area
.height
+ self
->cbwidth_y
* 2);
324 /* when the client has StaticGravity, it likes to move around. */
325 XMoveWindow(ob_display
, self
->client
->window
,
326 self
->cbwidth_x
, self
->cbwidth_y
);
329 STRUT_SET(self
->size
,
330 self
->innersize
.left
+ self
->bwidth
,
331 self
->innersize
.top
+ self
->bwidth
,
332 self
->innersize
.right
+ self
->bwidth
,
333 self
->innersize
.bottom
+ self
->bwidth
);
336 /* shading can change without being moved or resized */
337 RECT_SET_SIZE(self
->area
,
338 self
->client
->area
.width
+
339 self
->size
.left
+ self
->size
.right
,
340 (self
->client
->shaded
?
341 ob_rr_theme
->title_height
+ self
->bwidth
*2:
342 self
->client
->area
.height
+
343 self
->size
.top
+ self
->size
.bottom
));
346 /* find the new coordinates, done after setting the frame.size, for
347 frame_client_gravity. */
348 self
->area
.x
= self
->client
->area
.x
;
349 self
->area
.y
= self
->client
->area
.y
;
350 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
354 /* move and resize the top level frame.
355 shading can change without being moved or resized */
356 XMoveResizeWindow(ob_display
, self
->window
,
357 self
->area
.x
, self
->area
.y
,
358 self
->area
.width
- self
->bwidth
* 2,
359 self
->area
.height
- self
->bwidth
* 2);
362 framerender_frame(self
);
364 frame_adjust_shape(self
);
369 void frame_adjust_state(ObFrame
*self
)
371 framerender_frame(self
);
374 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
376 self
->focused
= hilite
;
377 framerender_frame(self
);
380 void frame_adjust_title(ObFrame
*self
)
382 framerender_frame(self
);
385 void frame_adjust_icon(ObFrame
*self
)
387 framerender_frame(self
);
390 void frame_grab_client(ObFrame
*self
, ObClient
*client
)
392 self
->client
= client
;
394 /* reparent the client to the frame */
395 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
397 When reparenting the client window, it is usually not mapped yet, since
398 this occurs from a MapRequest. However, in the case where Openbox is
399 starting up, the window is already mapped, so we'll see unmap events for
400 it. There are 2 unmap events generated that we see, one with the 'event'
401 member set the root window, and one set to the client, but both get
402 handled and need to be ignored.
404 if (ob_state() == OB_STATE_STARTING
)
405 client
->ignore_unmaps
+= 2;
407 /* select the event mask on the client's parent (to receive config/map
408 req's) the ButtonPress is to catch clicks on the client border */
409 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
411 /* map the client so it maps when the frame does */
412 XMapWindow(ob_display
, client
->window
);
414 frame_adjust_area(self
, TRUE
, TRUE
, FALSE
);
416 /* set all the windows for the frame in the window_map */
417 g_hash_table_insert(window_map
, &self
->window
, client
);
418 g_hash_table_insert(window_map
, &self
->plate
, client
);
419 g_hash_table_insert(window_map
, &self
->title
, client
);
420 g_hash_table_insert(window_map
, &self
->label
, client
);
421 g_hash_table_insert(window_map
, &self
->max
, client
);
422 g_hash_table_insert(window_map
, &self
->close
, client
);
423 g_hash_table_insert(window_map
, &self
->desk
, client
);
424 g_hash_table_insert(window_map
, &self
->shade
, client
);
425 g_hash_table_insert(window_map
, &self
->icon
, client
);
426 g_hash_table_insert(window_map
, &self
->iconify
, client
);
427 g_hash_table_insert(window_map
, &self
->handle
, client
);
428 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
429 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
430 g_hash_table_insert(window_map
, &self
->tlresize
, client
);
431 g_hash_table_insert(window_map
, &self
->trresize
, client
);
434 void frame_release_client(ObFrame
*self
, ObClient
*client
)
438 g_assert(self
->client
== client
);
440 /* check if the app has already reparented its window away */
441 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
442 ReparentNotify
, &ev
)) {
443 XPutBackEvent(ob_display
, &ev
);
445 /* re-map the window since the unmanaging process unmaps it */
447 /* XXX ... um no it doesnt it unmaps its parent, the window itself
448 retains its mapped state, no?! XXX
449 XMapWindow(ob_display, client->window); */
451 /* according to the ICCCM - if the client doesn't reparent itself,
452 then we will reparent the window to root for them */
453 XReparentWindow(ob_display
, client
->window
,
454 RootWindow(ob_display
, ob_screen
),
459 /* remove all the windows for the frame from the window_map */
460 g_hash_table_remove(window_map
, &self
->window
);
461 g_hash_table_remove(window_map
, &self
->plate
);
462 g_hash_table_remove(window_map
, &self
->title
);
463 g_hash_table_remove(window_map
, &self
->label
);
464 g_hash_table_remove(window_map
, &self
->max
);
465 g_hash_table_remove(window_map
, &self
->close
);
466 g_hash_table_remove(window_map
, &self
->desk
);
467 g_hash_table_remove(window_map
, &self
->shade
);
468 g_hash_table_remove(window_map
, &self
->icon
);
469 g_hash_table_remove(window_map
, &self
->iconify
);
470 g_hash_table_remove(window_map
, &self
->handle
);
471 g_hash_table_remove(window_map
, &self
->lgrip
);
472 g_hash_table_remove(window_map
, &self
->rgrip
);
473 g_hash_table_remove(window_map
, &self
->tlresize
);
474 g_hash_table_remove(window_map
, &self
->trresize
);
479 static void layout_title(ObFrame
*self
)
483 gboolean n
, d
, i
, l
, m
, c
, s
;
485 n
= d
= i
= l
= m
= c
= s
= FALSE
;
487 /* figure out whats being shown, and the width of the label */
488 self
->label_width
= self
->width
- (ob_rr_theme
->bevel
+ 1) * 2;
489 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
492 if (n
) { *lc
= ' '; break; } /* rm duplicates */
494 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
495 ob_rr_theme
->bevel
+ 1);
498 if (d
) { *lc
= ' '; break; } /* rm duplicates */
500 self
->label_width
-= (ob_rr_theme
->button_size
+
501 ob_rr_theme
->bevel
+ 1);
504 if (s
) { *lc
= ' '; break; } /* rm duplicates */
506 self
->label_width
-= (ob_rr_theme
->button_size
+
507 ob_rr_theme
->bevel
+ 1);
510 if (i
) { *lc
= ' '; break; } /* rm duplicates */
512 self
->label_width
-= (ob_rr_theme
->button_size
+
513 ob_rr_theme
->bevel
+ 1);
516 if (l
) { *lc
= ' '; break; } /* rm duplicates */
520 if (m
) { *lc
= ' '; break; } /* rm duplicates */
522 self
->label_width
-= (ob_rr_theme
->button_size
+
523 ob_rr_theme
->bevel
+ 1);
526 if (c
) { *lc
= ' '; break; } /* rm duplicates */
528 self
->label_width
-= (ob_rr_theme
->button_size
+
529 ob_rr_theme
->bevel
+ 1);
533 if (self
->label_width
< 1) self
->label_width
= 1;
535 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
536 ob_rr_theme
->label_height
);
538 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
539 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
540 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
541 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
542 if (!l
) XUnmapWindow(ob_display
, self
->label
);
543 if (!m
) XUnmapWindow(ob_display
, self
->max
);
544 if (!c
) XUnmapWindow(ob_display
, self
->close
);
546 x
= ob_rr_theme
->bevel
+ 1;
547 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
552 XMapWindow(ob_display
, self
->icon
);
553 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->bevel
);
554 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->bevel
+ 1;
559 XMapWindow(ob_display
, self
->desk
);
560 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->bevel
+ 1);
561 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
566 XMapWindow(ob_display
, self
->shade
);
567 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->bevel
+ 1);
568 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
573 XMapWindow(ob_display
, self
->iconify
);
574 XMoveWindow(ob_display
, self
->iconify
, x
, ob_rr_theme
->bevel
+ 1);
575 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
580 XMapWindow(ob_display
, self
->label
);
581 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->bevel
);
582 x
+= self
->label_width
+ ob_rr_theme
->bevel
+ 1;
587 XMapWindow(ob_display
, self
->max
);
588 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->bevel
+ 1);
589 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
594 XMapWindow(ob_display
, self
->close
);
595 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->bevel
+ 1);
596 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
602 ObFrameContext
frame_context_from_string(char *name
)
604 if (!g_ascii_strcasecmp("root", name
))
605 return OB_FRAME_CONTEXT_ROOT
;
606 else if (!g_ascii_strcasecmp("client", name
))
607 return OB_FRAME_CONTEXT_CLIENT
;
608 else if (!g_ascii_strcasecmp("titlebar", name
))
609 return OB_FRAME_CONTEXT_TITLEBAR
;
610 else if (!g_ascii_strcasecmp("handle", name
))
611 return OB_FRAME_CONTEXT_HANDLE
;
612 else if (!g_ascii_strcasecmp("frame", name
))
613 return OB_FRAME_CONTEXT_FRAME
;
614 else if (!g_ascii_strcasecmp("tlcorner", name
))
615 return OB_FRAME_CONTEXT_TLCORNER
;
616 else if (!g_ascii_strcasecmp("trcorner", name
))
617 return OB_FRAME_CONTEXT_TRCORNER
;
618 else if (!g_ascii_strcasecmp("blcorner", name
))
619 return OB_FRAME_CONTEXT_BLCORNER
;
620 else if (!g_ascii_strcasecmp("brcorner", name
))
621 return OB_FRAME_CONTEXT_BRCORNER
;
622 else if (!g_ascii_strcasecmp("maximize", name
))
623 return OB_FRAME_CONTEXT_MAXIMIZE
;
624 else if (!g_ascii_strcasecmp("alldesktops", name
))
625 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
626 else if (!g_ascii_strcasecmp("shade", name
))
627 return OB_FRAME_CONTEXT_SHADE
;
628 else if (!g_ascii_strcasecmp("iconify", name
))
629 return OB_FRAME_CONTEXT_ICONIFY
;
630 else if (!g_ascii_strcasecmp("icon", name
))
631 return OB_FRAME_CONTEXT_ICON
;
632 else if (!g_ascii_strcasecmp("close", name
))
633 return OB_FRAME_CONTEXT_CLOSE
;
634 return OB_FRAME_CONTEXT_NONE
;
637 ObFrameContext
frame_context(ObClient
*client
, Window win
)
641 if (win
== RootWindow(ob_display
, ob_screen
)) return OB_FRAME_CONTEXT_ROOT
;
642 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
643 if (win
== client
->window
) return OB_FRAME_CONTEXT_CLIENT
;
645 self
= client
->frame
;
646 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
647 if (win
== self
->plate
) return OB_FRAME_CONTEXT_CLIENT
;
648 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
649 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
650 if (win
== self
->handle
) return OB_FRAME_CONTEXT_HANDLE
;
651 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
652 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
653 if (win
== self
->tlresize
) return OB_FRAME_CONTEXT_TLCORNER
;
654 if (win
== self
->trresize
) return OB_FRAME_CONTEXT_TRCORNER
;
655 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
656 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
657 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
658 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
659 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
660 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
662 return OB_FRAME_CONTEXT_NONE
;
665 void frame_client_gravity(ObFrame
*self
, int *x
, int *y
)
668 switch (self
->client
->gravity
) {
670 case NorthWestGravity
:
671 case SouthWestGravity
:
678 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
681 case NorthEastGravity
:
682 case SouthEastGravity
:
684 *x
-= self
->size
.left
+ self
->size
.right
;
689 *x
-= self
->size
.left
;
694 switch (self
->client
->gravity
) {
696 case NorthWestGravity
:
697 case NorthEastGravity
:
704 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
707 case SouthWestGravity
:
708 case SouthEastGravity
:
710 *y
-= self
->size
.top
+ self
->size
.bottom
;
715 *y
-= self
->size
.top
;
720 void frame_frame_gravity(ObFrame
*self
, int *x
, int *y
)
723 switch (self
->client
->gravity
) {
725 case NorthWestGravity
:
727 case SouthWestGravity
:
732 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
734 case NorthEastGravity
:
736 case SouthEastGravity
:
737 *x
+= self
->size
.left
+ self
->size
.right
;
741 *x
+= self
->size
.left
;
746 switch (self
->client
->gravity
) {
748 case NorthWestGravity
:
750 case NorthEastGravity
:
755 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
757 case SouthWestGravity
:
759 case SouthEastGravity
:
760 *y
+= self
->size
.top
+ self
->size
.bottom
;
764 *y
+= self
->size
.top
;