3 #include "extensions.h"
4 #include "framerender.h"
5 #include "render/theme.h"
7 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
8 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
9 ButtonPressMask | ButtonReleaseMask)
10 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
11 ButtonMotionMask | ExposureMask)
13 static void layout_title(Frame
*self
);
17 RECT_SET(theme_a_focused_pressed_desk
->area
, 0, 0,
18 theme_button_size
, theme_button_size
);
19 RECT_SET(theme_a_focused_pressed_set_desk
->area
, 0, 0,
20 theme_button_size
, theme_button_size
);
21 RECT_SET(theme_a_focused_unpressed_desk
->area
, 0, 0,
22 theme_button_size
, theme_button_size
);
23 RECT_SET(theme_a_unfocused_pressed_desk
->area
, 0, 0,
24 theme_button_size
, theme_button_size
);
25 RECT_SET(theme_a_unfocused_pressed_set_desk
->area
, 0, 0,
26 theme_button_size
, theme_button_size
);
27 RECT_SET(theme_a_unfocused_unpressed_desk
->area
, 0, 0,
28 theme_button_size
, theme_button_size
);
29 RECT_SET(theme_a_focused_pressed_shade
->area
, 0, 0,
30 theme_button_size
, theme_button_size
);
31 RECT_SET(theme_a_focused_pressed_set_shade
->area
, 0, 0,
32 theme_button_size
, theme_button_size
);
33 RECT_SET(theme_a_focused_unpressed_shade
->area
, 0, 0,
34 theme_button_size
, theme_button_size
);
35 RECT_SET(theme_a_unfocused_pressed_shade
->area
, 0, 0,
36 theme_button_size
, theme_button_size
);
37 RECT_SET(theme_a_unfocused_pressed_set_shade
->area
, 0, 0,
38 theme_button_size
, theme_button_size
);
39 RECT_SET(theme_a_unfocused_unpressed_shade
->area
, 0, 0,
40 theme_button_size
, theme_button_size
);
41 RECT_SET(theme_a_focused_pressed_iconify
->area
, 0, 0,
42 theme_button_size
, theme_button_size
);
43 RECT_SET(theme_a_focused_unpressed_iconify
->area
, 0, 0,
44 theme_button_size
, theme_button_size
);
45 RECT_SET(theme_a_unfocused_pressed_iconify
->area
, 0, 0,
46 theme_button_size
, theme_button_size
);
47 RECT_SET(theme_a_unfocused_unpressed_iconify
->area
, 0, 0,
48 theme_button_size
, theme_button_size
);
49 RECT_SET(theme_a_unfocused_unpressed_iconify
->area
, 0, 0,
50 theme_button_size
, theme_button_size
);
51 RECT_SET(theme_a_focused_pressed_max
->area
, 0, 0,
52 theme_button_size
, theme_button_size
);
53 RECT_SET(theme_a_focused_pressed_set_max
->area
, 0, 0,
54 theme_button_size
, theme_button_size
);
55 RECT_SET(theme_a_focused_unpressed_max
->area
, 0, 0,
56 theme_button_size
, theme_button_size
);
57 RECT_SET(theme_a_unfocused_pressed_max
->area
, 0, 0,
58 theme_button_size
, theme_button_size
);
59 RECT_SET(theme_a_unfocused_pressed_set_max
->area
, 0, 0,
60 theme_button_size
, theme_button_size
);
61 RECT_SET(theme_a_unfocused_unpressed_max
->area
, 0, 0,
62 theme_button_size
, theme_button_size
);
63 RECT_SET(theme_a_focused_pressed_close
->area
, 0, 0,
64 theme_button_size
, theme_button_size
);
65 RECT_SET(theme_a_focused_unpressed_close
->area
, 0, 0,
66 theme_button_size
, theme_button_size
);
67 RECT_SET(theme_a_unfocused_pressed_close
->area
, 0, 0,
68 theme_button_size
, theme_button_size
);
69 RECT_SET(theme_a_unfocused_unpressed_close
->area
, 0, 0,
70 theme_button_size
, theme_button_size
);
72 RECT_SET(theme_a_focused_grip
->area
, 0, 0,
73 theme_grip_width
, theme_handle_height
);
74 RECT_SET(theme_a_unfocused_grip
->area
, 0, 0,
75 theme_grip_width
, theme_handle_height
);
82 static Window
createWindow(Window parent
, unsigned long mask
,
83 XSetWindowAttributes
*attrib
)
85 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
86 render_depth
, InputOutput
, render_visual
,
93 XSetWindowAttributes attrib
;
97 self
= g_new(Frame
, 1);
99 self
->visible
= FALSE
;
101 /* create all of the decor windows */
102 mask
= CWOverrideRedirect
| CWEventMask
;
103 attrib
.event_mask
= FRAME_EVENTMASK
;
104 attrib
.override_redirect
= TRUE
;
105 self
->window
= createWindow(ob_root
, mask
, &attrib
);
108 self
->plate
= createWindow(self
->window
, mask
, &attrib
);
111 attrib
.event_mask
= ELEMENT_EVENTMASK
;
112 self
->title
= createWindow(self
->window
, mask
, &attrib
);
113 self
->label
= createWindow(self
->title
, mask
, &attrib
);
114 self
->max
= createWindow(self
->title
, mask
, &attrib
);
115 self
->close
= createWindow(self
->title
, mask
, &attrib
);
116 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
117 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
118 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
119 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
120 self
->handle
= createWindow(self
->window
, mask
, &attrib
);
122 attrib
.cursor
= ob_cursors
.ll_angle
;
123 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
124 attrib
.cursor
= ob_cursors
.lr_angle
;
125 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
127 /* the other stuff is shown based on decor settings */
128 XMapWindow(ob_display
, self
->plate
);
129 XMapWindow(ob_display
, self
->lgrip
);
130 XMapWindow(ob_display
, self
->rgrip
);
131 XMapWindow(ob_display
, self
->label
);
133 /* set colors/appearance/sizes for stuff that doesn't change */
134 XSetWindowBorder(ob_display
, self
->window
, theme_b_color
->pixel
);
135 XSetWindowBorder(ob_display
, self
->label
, theme_b_color
->pixel
);
136 XSetWindowBorder(ob_display
, self
->rgrip
, theme_b_color
->pixel
);
137 XSetWindowBorder(ob_display
, self
->lgrip
, theme_b_color
->pixel
);
139 XResizeWindow(ob_display
, self
->max
, theme_button_size
, theme_button_size
);
140 XResizeWindow(ob_display
, self
->iconify
,
141 theme_button_size
, theme_button_size
);
142 XResizeWindow(ob_display
, self
->icon
,
143 theme_button_size
, theme_button_size
);
144 XResizeWindow(ob_display
, self
->close
,
145 theme_button_size
, theme_button_size
);
146 XResizeWindow(ob_display
, self
->desk
,
147 theme_button_size
, theme_button_size
);
148 XResizeWindow(ob_display
, self
->shade
,
149 theme_button_size
, theme_button_size
);
150 XResizeWindow(ob_display
, self
->lgrip
,
151 theme_grip_width
, theme_handle_height
);
152 XResizeWindow(ob_display
, self
->rgrip
,
153 theme_grip_width
, theme_handle_height
);
155 /* set up the dynamic appearances */
156 self
->a_unfocused_title
= appearance_copy(theme_a_unfocused_title
);
157 self
->a_focused_title
= appearance_copy(theme_a_focused_title
);
158 self
->a_unfocused_label
= appearance_copy(theme_a_unfocused_label
);
159 self
->a_focused_label
= appearance_copy(theme_a_focused_label
);
160 self
->a_unfocused_handle
= appearance_copy(theme_a_unfocused_handle
);
161 self
->a_focused_handle
= appearance_copy(theme_a_focused_handle
);
162 self
->a_icon
= appearance_copy(theme_a_icon
);
164 self
->max_press
= self
->close_press
= self
->desk_press
=
165 self
->iconify_press
= self
->shade_press
= FALSE
;
170 static void frame_free(Frame
*self
)
172 appearance_free(self
->a_unfocused_title
);
173 appearance_free(self
->a_focused_title
);
174 appearance_free(self
->a_unfocused_label
);
175 appearance_free(self
->a_focused_label
);
176 appearance_free(self
->a_unfocused_handle
);
177 appearance_free(self
->a_focused_handle
);
178 appearance_free(self
->a_icon
);
180 XDestroyWindow(ob_display
, self
->window
);
185 void frame_show(Frame
*self
)
187 if (!self
->visible
) {
188 self
->visible
= TRUE
;
189 XMapWindow(ob_display
, self
->window
);
193 void frame_hide(Frame
*self
)
196 self
->visible
= FALSE
;
197 self
->client
->ignore_unmaps
++;
198 XUnmapWindow(ob_display
, self
->window
);
202 void frame_adjust_shape(Frame
*self
)
208 if (!self
->client
->shaped
) {
209 /* clear the shape on the frame window */
210 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
211 self
->innersize
.left
,
215 /* make the frame's shape match the clients */
216 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
217 self
->innersize
.left
,
219 self
->client
->window
,
220 ShapeBounding
, ShapeSet
);
223 if (self
->client
->decorations
& Decor_Titlebar
) {
224 xrect
[0].x
= -theme_bevel
;
225 xrect
[0].y
= -theme_bevel
;
226 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
227 xrect
[0].height
= theme_title_height
+
232 if (self
->client
->decorations
& Decor_Handle
) {
233 xrect
[1].x
= -theme_bevel
;
234 xrect
[1].y
= FRAME_HANDLE_Y(self
);
235 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
236 xrect
[1].height
= theme_handle_height
+
241 XShapeCombineRectangles(ob_display
, self
->window
,
242 ShapeBounding
, 0, 0, xrect
, num
,
243 ShapeUnion
, Unsorted
);
248 void frame_adjust_area(Frame
*self
, gboolean moved
, gboolean resized
)
251 if (self
->client
->decorations
& Decor_Border
) {
252 self
->bwidth
= theme_bwidth
;
253 self
->cbwidth
= theme_cbwidth
;
255 self
->bwidth
= self
->cbwidth
= 0;
257 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
258 self
->cbwidth
, self
->cbwidth
);
259 self
->width
= self
->client
->area
.width
+ self
->cbwidth
* 2;
260 g_assert(self
->width
> 0);
262 /* set border widths */
263 XSetWindowBorderWidth(ob_display
, self
->plate
, self
->cbwidth
);
264 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
265 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
266 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
267 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
268 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
270 /* position/size and map/unmap all the windows */
272 /* they all default off, they're turned on in layout_title */
276 self
->iconify_x
= -1;
281 if (self
->client
->decorations
& Decor_Titlebar
) {
282 XMoveResizeWindow(ob_display
, self
->title
,
283 -self
->bwidth
, -self
->bwidth
,
284 self
->width
, theme_title_height
);
285 self
->innersize
.top
+= theme_title_height
+ self
->bwidth
;
286 XMapWindow(ob_display
, self
->title
);
288 RECT_SET(self
->a_focused_title
->area
, 0, 0,
289 self
->width
, theme_title_height
);
290 RECT_SET(self
->a_unfocused_title
->area
, 0, 0,
291 self
->width
, theme_title_height
);
293 /* layout the title bar elements */
296 XUnmapWindow(ob_display
, self
->title
);
298 if (self
->client
->decorations
& Decor_Handle
) {
299 XMoveResizeWindow(ob_display
, self
->handle
,
300 -self
->bwidth
, FRAME_HANDLE_Y(self
),
301 self
->width
, theme_handle_height
);
302 XMoveWindow(ob_display
, self
->lgrip
,
303 -self
->bwidth
, -self
->bwidth
);
304 XMoveWindow(ob_display
, self
->rgrip
,
305 -self
->bwidth
+ self
->width
-
306 theme_grip_width
, -self
->bwidth
);
307 self
->innersize
.bottom
+= theme_handle_height
+
309 XMapWindow(ob_display
, self
->handle
);
311 if (theme_a_focused_grip
->surface
.data
.planar
.grad
==
312 Background_ParentRelative
)
313 RECT_SET(self
->a_focused_handle
->area
, 0, 0,
314 self
->width
, theme_handle_height
);
316 RECT_SET(self
->a_focused_handle
->area
,
317 theme_grip_width
+ self
->bwidth
, 0,
318 self
->width
- (theme_grip_width
+ self
->bwidth
) * 2,
319 theme_handle_height
);
320 if (theme_a_unfocused_grip
->surface
.data
.planar
.grad
==
321 Background_ParentRelative
)
322 RECT_SET(self
->a_unfocused_handle
->area
, 0, 0,
323 self
->width
, theme_handle_height
);
325 RECT_SET(self
->a_unfocused_handle
->area
,
326 theme_grip_width
+ self
->bwidth
, 0,
327 self
->width
- (theme_grip_width
+ self
->bwidth
) * 2,
328 theme_handle_height
);
331 XUnmapWindow(ob_display
, self
->handle
);
335 /* move and resize the plate */
336 XMoveResizeWindow(ob_display
, self
->plate
,
337 self
->innersize
.left
- self
->cbwidth
,
338 self
->innersize
.top
- self
->cbwidth
,
339 self
->client
->area
.width
,
340 self
->client
->area
.height
);
341 /* when the client has StaticGravity, it likes to move around. */
342 XMoveWindow(ob_display
, self
->client
->window
, 0, 0);
346 STRUT_SET(self
->size
,
347 self
->innersize
.left
+ self
->bwidth
,
348 self
->innersize
.top
+ self
->bwidth
,
349 self
->innersize
.right
+ self
->bwidth
,
350 self
->innersize
.bottom
+ self
->bwidth
);
353 /* shading can change without being moved or resized */
354 RECT_SET_SIZE(self
->area
,
355 self
->client
->area
.width
+
356 self
->size
.left
+ self
->size
.right
,
357 (self
->client
->shaded
? theme_title_height
+ self
->bwidth
*2:
358 self
->client
->area
.height
+
359 self
->size
.top
+ self
->size
.bottom
));
362 /* find the new coordinates, done after setting the frame.size, for
363 frame_client_gravity. */
364 self
->area
.x
= self
->client
->area
.x
;
365 self
->area
.y
= self
->client
->area
.y
;
366 frame_client_gravity((Frame
*)self
,
367 &self
->area
.x
, &self
->area
.y
);
370 /* move and resize the top level frame.
371 shading can change without being moved or resized */
372 XMoveResizeWindow(ob_display
, self
->window
,
373 self
->area
.x
, self
->area
.y
,
375 self
->area
.height
- self
->bwidth
* 2);
378 framerender_frame(self
);
380 frame_adjust_shape(self
);
384 void frame_adjust_state(Frame
*self
)
386 framerender_frame(self
);
389 void frame_adjust_focus(Frame
*self
)
391 framerender_frame(self
);
394 void frame_adjust_title(Frame
*self
)
396 framerender_frame(self
);
399 void frame_adjust_icon(Frame
*self
)
401 framerender_frame(self
);
404 void frame_grab_client(Frame
*self
, Client
*client
)
406 self
->client
= client
;
408 /* reparent the client to the frame */
409 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
411 When reparenting the client window, it is usually not mapped yet, since
412 this occurs from a MapRequest. However, in the case where Openbox is
413 starting up, the window is already mapped, so we'll see unmap events for
414 it. There are 2 unmap events generated that we see, one with the 'event'
415 member set the root window, and one set to the client, but both get
416 handled and need to be ignored.
418 if (ob_state
== State_Starting
)
419 client
->ignore_unmaps
+= 2;
421 /* select the event mask on the client's parent (to receive config/map
422 req's) the ButtonPress is to catch clicks on the client border */
423 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
425 /* map the client so it maps when the frame does */
426 XMapWindow(ob_display
, client
->window
);
428 frame_adjust_area(self
, TRUE
, TRUE
);
430 /* set all the windows for the frame in the client_map */
431 g_hash_table_insert(client_map
, &self
->window
, client
);
432 g_hash_table_insert(client_map
, &self
->plate
, client
);
433 g_hash_table_insert(client_map
, &self
->title
, client
);
434 g_hash_table_insert(client_map
, &self
->label
, client
);
435 g_hash_table_insert(client_map
, &self
->max
, client
);
436 g_hash_table_insert(client_map
, &self
->close
, client
);
437 g_hash_table_insert(client_map
, &self
->desk
, client
);
438 g_hash_table_insert(client_map
, &self
->shade
, client
);
439 g_hash_table_insert(client_map
, &self
->icon
, client
);
440 g_hash_table_insert(client_map
, &self
->iconify
, client
);
441 g_hash_table_insert(client_map
, &self
->handle
, client
);
442 g_hash_table_insert(client_map
, &self
->lgrip
, client
);
443 g_hash_table_insert(client_map
, &self
->rgrip
, client
);
446 void frame_release_client(Frame
*self
, Client
*client
)
450 g_assert(self
->client
== client
);
452 /* check if the app has already reparented its window away */
453 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
454 ReparentNotify
, &ev
)) {
455 XPutBackEvent(ob_display
, &ev
);
456 /* re-map the window since the unmanaging process unmaps it */
457 XMapWindow(ob_display
, client
->window
);
459 /* according to the ICCCM - if the client doesn't reparent itself,
460 then we will reparent the window to root for them */
461 XReparentWindow(ob_display
, client
->window
, ob_root
,
466 /* remove all the windows for the frame from the client_map */
467 g_hash_table_remove(client_map
, &self
->window
);
468 g_hash_table_remove(client_map
, &self
->plate
);
469 g_hash_table_remove(client_map
, &self
->title
);
470 g_hash_table_remove(client_map
, &self
->label
);
471 g_hash_table_remove(client_map
, &self
->max
);
472 g_hash_table_remove(client_map
, &self
->close
);
473 g_hash_table_remove(client_map
, &self
->desk
);
474 g_hash_table_remove(client_map
, &self
->shade
);
475 g_hash_table_remove(client_map
, &self
->icon
);
476 g_hash_table_remove(client_map
, &self
->iconify
);
477 g_hash_table_remove(client_map
, &self
->handle
);
478 g_hash_table_remove(client_map
, &self
->lgrip
);
479 g_hash_table_remove(client_map
, &self
->rgrip
);
484 static void layout_title(Frame
*self
)
488 gboolean n
, d
, i
, l
, m
, c
, s
;
490 n
= d
= i
= l
= m
= c
= s
= FALSE
;
492 /* figure out whats being shown, and the width of the label */
493 self
->label_width
= self
->width
- (theme_bevel
+ 1) * 2;
494 for (lc
= theme_title_layout
; *lc
!= '\0'; ++lc
) {
497 if (!(self
->client
->decorations
& Decor_Icon
)) break;
498 if (n
) { *lc
= ' '; break; } /* rm duplicates */
500 self
->label_width
-= theme_button_size
+ theme_bevel
+ 1;
503 if (!(self
->client
->decorations
& Decor_AllDesktops
)) break;
504 if (d
) { *lc
= ' '; break; } /* rm duplicates */
506 self
->label_width
-= theme_button_size
+ theme_bevel
+ 1;
509 if (!(self
->client
->decorations
& Decor_Shade
)) break;
510 if (s
) { *lc
= ' '; break; } /* rm duplicates */
512 self
->label_width
-= theme_button_size
+ theme_bevel
+ 1;
515 if (!(self
->client
->decorations
& Decor_Iconify
)) break;
516 if (i
) { *lc
= ' '; break; } /* rm duplicates */
518 self
->label_width
-= theme_button_size
+ theme_bevel
+ 1;
521 if (l
) { *lc
= ' '; break; } /* rm duplicates */
525 if (!(self
->client
->decorations
& Decor_Maximize
)) break;
526 if (m
) { *lc
= ' '; break; } /* rm duplicates */
528 self
->label_width
-= theme_button_size
+ theme_bevel
+ 1;
531 if (!(self
->client
->decorations
& Decor_Close
)) break;
532 if (c
) { *lc
= ' '; break; } /* rm duplicates */
534 self
->label_width
-= theme_button_size
+ theme_bevel
+ 1;
538 if (self
->label_width
< 1) self
->label_width
= 1;
540 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
543 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
544 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
545 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
546 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
547 if (!l
) XUnmapWindow(ob_display
, self
->label
);
548 if (!m
) XUnmapWindow(ob_display
, self
->max
);
549 if (!c
) XUnmapWindow(ob_display
, self
->close
);
552 for (lc
= theme_title_layout
; *lc
!= '\0'; ++lc
) {
557 RECT_SET(self
->a_icon
->area
, 0, 0,
558 theme_button_size
, theme_button_size
);
559 XMapWindow(ob_display
, self
->icon
);
560 XMoveWindow(ob_display
, self
->icon
, x
, theme_bevel
+ 1);
561 x
+= theme_button_size
+ theme_bevel
+ 1;
566 XMapWindow(ob_display
, self
->desk
);
567 XMoveWindow(ob_display
, self
->desk
, x
, theme_bevel
+ 1);
568 x
+= theme_button_size
+ theme_bevel
+ 1;
573 XMapWindow(ob_display
, self
->shade
);
574 XMoveWindow(ob_display
, self
->shade
, x
, theme_bevel
+ 1);
575 x
+= theme_button_size
+ theme_bevel
+ 1;
580 XMapWindow(ob_display
, self
->iconify
);
581 XMoveWindow(ob_display
, self
->iconify
, x
, theme_bevel
+ 1);
582 x
+= theme_button_size
+ theme_bevel
+ 1;
587 XMapWindow(ob_display
, self
->label
);
588 XMoveWindow(ob_display
, self
->label
, x
, theme_bevel
);
589 x
+= self
->label_width
+ theme_bevel
+ 1;
594 XMapWindow(ob_display
, self
->max
);
595 XMoveWindow(ob_display
, self
->max
, x
, theme_bevel
+ 1);
596 x
+= theme_button_size
+ theme_bevel
+ 1;
601 XMapWindow(ob_display
, self
->close
);
602 XMoveWindow(ob_display
, self
->close
, x
, theme_bevel
+ 1);
603 x
+= theme_button_size
+ theme_bevel
+ 1;
608 RECT_SET(self
->a_focused_label
->area
, 0, 0,
609 self
->label_width
, theme_label_height
);
610 RECT_SET(self
->a_unfocused_label
->area
, 0, 0,
611 self
->label_width
, theme_label_height
);
614 Context
frame_context_from_string(char *name
)
616 if (!g_ascii_strcasecmp("root", name
))
618 else if (!g_ascii_strcasecmp("client", name
))
619 return Context_Client
;
620 else if (!g_ascii_strcasecmp("titlebar", name
))
621 return Context_Titlebar
;
622 else if (!g_ascii_strcasecmp("handle", name
))
623 return Context_Handle
;
624 else if (!g_ascii_strcasecmp("frame", name
))
625 return Context_Frame
;
626 else if (!g_ascii_strcasecmp("blcorner", name
))
627 return Context_BLCorner
;
628 else if (!g_ascii_strcasecmp("tlcorner", name
))
629 return Context_TLCorner
;
630 else if (!g_ascii_strcasecmp("brcorner", name
))
631 return Context_BRCorner
;
632 else if (!g_ascii_strcasecmp("trcorner", name
))
633 return Context_TRCorner
;
634 else if (!g_ascii_strcasecmp("maximize", name
))
635 return Context_Maximize
;
636 else if (!g_ascii_strcasecmp("alldesktops", name
))
637 return Context_AllDesktops
;
638 else if (!g_ascii_strcasecmp("shade", name
))
639 return Context_Shade
;
640 else if (!g_ascii_strcasecmp("iconify", name
))
641 return Context_Iconify
;
642 else if (!g_ascii_strcasecmp("icon", name
))
644 else if (!g_ascii_strcasecmp("close", name
))
645 return Context_Close
;
649 Context
frame_context(Client
*client
, Window win
)
653 if (win
== ob_root
) return Context_Root
;
654 if (client
== NULL
) return Context_None
;
655 if (win
== client
->window
) return Context_Client
;
657 self
= client
->frame
;
658 if (win
== self
->window
) return Context_Frame
;
659 if (win
== self
->plate
) return Context_Client
;
660 if (win
== self
->title
) return Context_Titlebar
;
661 if (win
== self
->label
) return Context_Titlebar
;
662 if (win
== self
->handle
) return Context_Handle
;
663 if (win
== self
->lgrip
) return Context_BLCorner
;
664 if (win
== self
->rgrip
) return Context_BRCorner
;
665 if (win
== self
->max
) return Context_Maximize
;
666 if (win
== self
->iconify
)return Context_Iconify
;
667 if (win
== self
->close
) return Context_Close
;
668 if (win
== self
->icon
) return Context_Icon
;
669 if (win
== self
->desk
) return Context_AllDesktops
;
670 if (win
== self
->shade
) return Context_Shade
;
675 void frame_client_gravity(Frame
*self
, int *x
, int *y
)
678 switch (self
->client
->gravity
) {
680 case NorthWestGravity
:
681 case SouthWestGravity
:
688 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
691 case NorthEastGravity
:
692 case SouthEastGravity
:
694 *x
-= self
->size
.left
+ self
->size
.right
;
699 *x
-= self
->size
.left
;
704 switch (self
->client
->gravity
) {
706 case NorthWestGravity
:
707 case NorthEastGravity
:
714 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
717 case SouthWestGravity
:
718 case SouthEastGravity
:
720 *y
-= self
->size
.top
+ self
->size
.bottom
;
725 *y
-= self
->size
.top
;
730 void frame_frame_gravity(Frame
*self
, int *x
, int *y
)
733 switch (self
->client
->gravity
) {
735 case NorthWestGravity
:
737 case SouthWestGravity
:
742 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
744 case NorthEastGravity
:
746 case SouthEastGravity
:
747 *x
+= self
->size
.left
+ self
->size
.right
;
751 *x
+= self
->size
.left
;
756 switch (self
->client
->gravity
) {
758 case NorthWestGravity
:
760 case SouthWestGravity
:
765 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
767 case NorthEastGravity
:
769 case SouthEastGravity
:
770 *y
+= self
->size
.top
+ self
->size
.bottom
;
774 *y
+= self
->size
.top
;