4 #include "extensions.h"
6 #include "framerender.h"
8 #include "render/theme.h"
10 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
11 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
12 ButtonPressMask | ButtonReleaseMask | \
14 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
15 ButtonMotionMask | ExposureMask | \
16 EnterWindowMask | LeaveWindowMask)
18 #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \
21 static void layout_title(ObFrame
*self
);
22 static void flash_done(gpointer data
);
23 static gboolean
flash_timeout(gpointer data
);
25 static void set_theme_statics(ObFrame
*self
);
26 static void free_theme_statics(ObFrame
*self
);
28 static Window
createWindow(Window parent
, unsigned long mask
,
29 XSetWindowAttributes
*attrib
)
31 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
32 RrDepth(ob_rr_inst
), InputOutput
,
33 RrVisual(ob_rr_inst
), mask
, attrib
);
39 XSetWindowAttributes attrib
;
43 self
= g_new(ObFrame
, 1);
45 self
->visible
= FALSE
;
46 self
->obscured
= TRUE
;
47 self
->decorations
= 0;
48 self
->flashing
= FALSE
;
50 /* create all of the decor windows */
51 mask
= CWOverrideRedirect
| CWEventMask
;
52 attrib
.event_mask
= FRAME_EVENTMASK
;
53 attrib
.override_redirect
= TRUE
;
54 self
->window
= createWindow(RootWindow(ob_display
, ob_screen
),
58 self
->plate
= createWindow(self
->window
, mask
, &attrib
);
61 attrib
.event_mask
= ELEMENT_EVENTMASK
;
62 self
->title
= createWindow(self
->window
, mask
, &attrib
);
65 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHWEST
);
66 self
->tlresize
= createWindow(self
->title
, mask
, &attrib
);
67 attrib
.cursor
= ob_cursor(OB_CURSOR_NORTHEAST
);
68 self
->trresize
= createWindow(self
->title
, mask
, &attrib
);
71 self
->label
= createWindow(self
->title
, mask
, &attrib
);
72 self
->max
= createWindow(self
->title
, mask
, &attrib
);
73 self
->close
= createWindow(self
->title
, mask
, &attrib
);
74 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
75 self
->shade
= createWindow(self
->title
, mask
, &attrib
);
76 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
77 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
78 self
->handle
= createWindow(self
->window
, mask
, &attrib
);
81 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHWEST
);
82 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
83 attrib
.cursor
= ob_cursor(OB_CURSOR_SOUTHEAST
);
84 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
86 self
->focused
= FALSE
;
88 /* the other stuff is shown based on decor settings */
89 XMapWindow(ob_display
, self
->plate
);
90 XMapWindow(ob_display
, self
->lgrip
);
91 XMapWindow(ob_display
, self
->rgrip
);
92 XMapWindow(ob_display
, self
->label
);
94 self
->max_press
= self
->close_press
= self
->desk_press
=
95 self
->iconify_press
= self
->shade_press
= FALSE
;
96 self
->max_hover
= self
->close_hover
= self
->desk_hover
=
97 self
->iconify_hover
= self
->shade_hover
= FALSE
;
99 set_theme_statics(self
);
101 return (ObFrame
*)self
;
104 static void set_theme_statics(ObFrame
*self
)
106 /* set colors/appearance/sizes for stuff that doesn't change */
107 XSetWindowBorder(ob_display
, self
->window
, ob_rr_theme
->b_color
->pixel
);
108 XSetWindowBorder(ob_display
, self
->title
, ob_rr_theme
->b_color
->pixel
);
109 XSetWindowBorder(ob_display
, self
->handle
, ob_rr_theme
->b_color
->pixel
);
110 XSetWindowBorder(ob_display
, self
->rgrip
, ob_rr_theme
->b_color
->pixel
);
111 XSetWindowBorder(ob_display
, self
->lgrip
, ob_rr_theme
->b_color
->pixel
);
113 XResizeWindow(ob_display
, self
->max
,
114 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
115 XResizeWindow(ob_display
, self
->iconify
,
116 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
117 XResizeWindow(ob_display
, self
->icon
,
118 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
119 XResizeWindow(ob_display
, self
->close
,
120 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
121 XResizeWindow(ob_display
, self
->desk
,
122 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
123 XResizeWindow(ob_display
, self
->shade
,
124 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
125 XResizeWindow(ob_display
, self
->lgrip
,
126 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
127 XResizeWindow(ob_display
, self
->rgrip
,
128 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
129 XResizeWindow(ob_display
, self
->tlresize
,
130 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
131 XResizeWindow(ob_display
, self
->trresize
,
132 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
134 /* set up the dynamic appearances */
135 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
136 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
137 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
138 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
139 self
->a_unfocused_handle
=
140 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
141 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
142 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
145 static void free_theme_statics(ObFrame
*self
)
147 RrAppearanceFree(self
->a_unfocused_title
);
148 RrAppearanceFree(self
->a_focused_title
);
149 RrAppearanceFree(self
->a_unfocused_label
);
150 RrAppearanceFree(self
->a_focused_label
);
151 RrAppearanceFree(self
->a_unfocused_handle
);
152 RrAppearanceFree(self
->a_focused_handle
);
153 RrAppearanceFree(self
->a_icon
);
156 static void frame_free(ObFrame
*self
)
158 free_theme_statics(self
);
160 XDestroyWindow(ob_display
, self
->window
);
165 void frame_show(ObFrame
*self
)
167 if (!self
->visible
) {
168 self
->visible
= TRUE
;
169 XMapWindow(ob_display
, self
->window
);
173 void frame_hide(ObFrame
*self
)
176 self
->visible
= FALSE
;
177 self
->client
->ignore_unmaps
++;
178 XUnmapWindow(ob_display
, self
->window
);
182 void frame_adjust_theme(ObFrame
*self
)
184 free_theme_statics(self
);
185 set_theme_statics(self
);
186 frame_adjust_area(self
, TRUE
, TRUE
, FALSE
);
189 void frame_adjust_shape(ObFrame
*self
)
195 if (!self
->client
->shaped
) {
196 /* clear the shape on the frame window */
197 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
198 self
->innersize
.left
,
202 /* make the frame's shape match the clients */
203 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
204 self
->innersize
.left
,
206 self
->client
->window
,
207 ShapeBounding
, ShapeSet
);
210 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
211 xrect
[0].x
= -ob_rr_theme
->bwidth
;
212 xrect
[0].y
= -ob_rr_theme
->bwidth
;
213 xrect
[0].width
= self
->width
+ self
->rbwidth
* 2;
214 xrect
[0].height
= ob_rr_theme
->title_height
+
219 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
) {
220 xrect
[1].x
= -ob_rr_theme
->bwidth
;
221 xrect
[1].y
= FRAME_HANDLE_Y(self
);
222 xrect
[1].width
= self
->width
+ self
->rbwidth
* 2;
223 xrect
[1].height
= ob_rr_theme
->handle_height
+
228 XShapeCombineRectangles(ob_display
, self
->window
,
229 ShapeBounding
, 0, 0, xrect
, num
,
230 ShapeUnion
, Unsorted
);
235 void frame_adjust_area(ObFrame
*self
, gboolean moved
,
236 gboolean resized
, gboolean fake
)
239 self
->decorations
= self
->client
->decorations
;
240 self
->max_horz
= self
->client
->max_horz
;
242 if (self
->decorations
& OB_FRAME_DECOR_BORDER
) {
243 self
->bwidth
= ob_rr_theme
->bwidth
;
244 self
->cbwidth_x
= self
->cbwidth_y
= ob_rr_theme
->cbwidth
;
246 self
->bwidth
= self
->cbwidth_x
= self
->cbwidth_y
= 0;
248 self
->rbwidth
= self
->bwidth
;
251 self
->bwidth
= self
->cbwidth_x
= 0;
253 STRUT_SET(self
->innersize
,
258 self
->width
= self
->client
->area
.width
+ self
->cbwidth_x
* 2 -
259 (self
->max_horz
? self
->rbwidth
* 2 : 0);
260 self
->width
= MAX(self
->width
, 1); /* no lower than 1 */
262 /* set border widths */
264 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
265 XSetWindowBorderWidth(ob_display
, self
->title
, self
->rbwidth
);
266 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->rbwidth
);
267 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->rbwidth
);
268 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->rbwidth
);
271 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
272 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->rbwidth
+
273 (self
->rbwidth
- self
->bwidth
);
274 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
&&
275 ob_rr_theme
->show_handle
)
276 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
277 self
->rbwidth
+ (self
->rbwidth
- self
->bwidth
);
279 /* they all default off, they're turned on in layout_title */
283 self
->iconify_x
= -1;
288 /* position/size and map/unmap all the windows */
291 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
292 XMoveResizeWindow(ob_display
, self
->title
,
293 -self
->bwidth
, -self
->bwidth
,
294 self
->width
, ob_rr_theme
->title_height
);
295 XMapWindow(ob_display
, self
->title
);
297 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
298 XMoveWindow(ob_display
, self
->tlresize
, 0, 0);
299 XMoveWindow(ob_display
, self
->trresize
,
300 self
->width
- ob_rr_theme
->grip_width
, 0);
301 XMapWindow(ob_display
, self
->tlresize
);
302 XMapWindow(ob_display
, self
->trresize
);
304 XUnmapWindow(ob_display
, self
->tlresize
);
305 XUnmapWindow(ob_display
, self
->trresize
);
308 XUnmapWindow(ob_display
, self
->title
);
311 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
312 /* layout the title bar elements */
316 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
&&
317 ob_rr_theme
->show_handle
)
319 XMoveResizeWindow(ob_display
, self
->handle
,
320 -self
->bwidth
, FRAME_HANDLE_Y(self
),
321 self
->width
, ob_rr_theme
->handle_height
);
322 XMapWindow(ob_display
, self
->handle
);
324 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
325 XMoveWindow(ob_display
, self
->lgrip
,
326 -self
->rbwidth
, -self
->rbwidth
);
327 XMoveWindow(ob_display
, self
->rgrip
,
328 -self
->rbwidth
+ self
->width
-
329 ob_rr_theme
->grip_width
, -self
->rbwidth
);
330 XMapWindow(ob_display
, self
->lgrip
);
331 XMapWindow(ob_display
, self
->rgrip
);
333 XUnmapWindow(ob_display
, self
->lgrip
);
334 XUnmapWindow(ob_display
, self
->rgrip
);
337 /* XXX make a subwindow with these dimentions?
338 ob_rr_theme->grip_width + self->bwidth, 0,
339 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
340 ob_rr_theme->handle_height);
343 XUnmapWindow(ob_display
, self
->handle
);
345 /* move and resize the plate */
346 XMoveResizeWindow(ob_display
, self
->plate
,
347 self
->innersize
.left
- self
->cbwidth_x
,
348 self
->innersize
.top
- self
->cbwidth_y
,
349 self
->client
->area
.width
+ self
->cbwidth_x
* 2,
350 self
->client
->area
.height
+ self
->cbwidth_y
* 2);
351 /* when the client has StaticGravity, it likes to move around. */
352 XMoveWindow(ob_display
, self
->client
->window
,
353 self
->cbwidth_x
, self
->cbwidth_y
);
356 STRUT_SET(self
->size
,
357 self
->innersize
.left
+ self
->bwidth
,
358 self
->innersize
.top
+ self
->bwidth
,
359 self
->innersize
.right
+ self
->bwidth
,
360 self
->innersize
.bottom
+ self
->bwidth
);
363 /* shading can change without being moved or resized */
364 RECT_SET_SIZE(self
->area
,
365 self
->client
->area
.width
+
366 self
->size
.left
+ self
->size
.right
,
367 (self
->client
->shaded
?
368 ob_rr_theme
->title_height
+ self
->rbwidth
* 2:
369 self
->client
->area
.height
+
370 self
->size
.top
+ self
->size
.bottom
));
373 /* find the new coordinates, done after setting the frame.size, for
374 frame_client_gravity. */
375 self
->area
.x
= self
->client
->area
.x
;
376 self
->area
.y
= self
->client
->area
.y
;
377 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
381 /* move and resize the top level frame.
382 shading can change without being moved or resized */
383 XMoveResizeWindow(ob_display
, self
->window
,
384 self
->area
.x
, self
->area
.y
,
385 self
->area
.width
- self
->bwidth
* 2,
386 self
->area
.height
- self
->bwidth
* 2);
389 framerender_frame(self
);
391 frame_adjust_shape(self
);
396 void frame_adjust_state(ObFrame
*self
)
398 framerender_frame(self
);
401 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
403 self
->focused
= hilite
;
404 framerender_frame(self
);
407 void frame_adjust_title(ObFrame
*self
)
409 framerender_frame(self
);
412 void frame_adjust_icon(ObFrame
*self
)
414 framerender_frame(self
);
417 void frame_grab_client(ObFrame
*self
, ObClient
*client
)
419 self
->client
= client
;
421 /* reparent the client to the frame */
422 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
424 When reparenting the client window, it is usually not mapped yet, since
425 this occurs from a MapRequest. However, in the case where Openbox is
426 starting up, the window is already mapped, so we'll see unmap events for
427 it. There are 2 unmap events generated that we see, one with the 'event'
428 member set the root window, and one set to the client, but both get
429 handled and need to be ignored.
431 if (ob_state() == OB_STATE_STARTING
)
432 client
->ignore_unmaps
+= 2;
434 /* select the event mask on the client's parent (to receive config/map
435 req's) the ButtonPress is to catch clicks on the client border */
436 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
438 /* map the client so it maps when the frame does */
439 XMapWindow(ob_display
, client
->window
);
441 frame_adjust_area(self
, TRUE
, TRUE
, FALSE
);
443 /* set all the windows for the frame in the window_map */
444 g_hash_table_insert(window_map
, &self
->window
, client
);
445 g_hash_table_insert(window_map
, &self
->plate
, client
);
446 g_hash_table_insert(window_map
, &self
->title
, client
);
447 g_hash_table_insert(window_map
, &self
->label
, client
);
448 g_hash_table_insert(window_map
, &self
->max
, client
);
449 g_hash_table_insert(window_map
, &self
->close
, client
);
450 g_hash_table_insert(window_map
, &self
->desk
, client
);
451 g_hash_table_insert(window_map
, &self
->shade
, client
);
452 g_hash_table_insert(window_map
, &self
->icon
, client
);
453 g_hash_table_insert(window_map
, &self
->iconify
, client
);
454 g_hash_table_insert(window_map
, &self
->handle
, client
);
455 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
456 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
457 g_hash_table_insert(window_map
, &self
->tlresize
, client
);
458 g_hash_table_insert(window_map
, &self
->trresize
, client
);
461 void frame_release_client(ObFrame
*self
, ObClient
*client
)
465 g_assert(self
->client
== client
);
467 /* check if the app has already reparented its window away */
468 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
469 ReparentNotify
, &ev
)) {
470 XPutBackEvent(ob_display
, &ev
);
472 /* re-map the window since the unmanaging process unmaps it */
474 /* XXX ... um no it doesnt it unmaps its parent, the window itself
475 retains its mapped state, no?! XXX
476 XMapWindow(ob_display, client->window); */
478 /* according to the ICCCM - if the client doesn't reparent itself,
479 then we will reparent the window to root for them */
480 XReparentWindow(ob_display
, client
->window
,
481 RootWindow(ob_display
, ob_screen
),
486 /* remove all the windows for the frame from the window_map */
487 g_hash_table_remove(window_map
, &self
->window
);
488 g_hash_table_remove(window_map
, &self
->plate
);
489 g_hash_table_remove(window_map
, &self
->title
);
490 g_hash_table_remove(window_map
, &self
->label
);
491 g_hash_table_remove(window_map
, &self
->max
);
492 g_hash_table_remove(window_map
, &self
->close
);
493 g_hash_table_remove(window_map
, &self
->desk
);
494 g_hash_table_remove(window_map
, &self
->shade
);
495 g_hash_table_remove(window_map
, &self
->icon
);
496 g_hash_table_remove(window_map
, &self
->iconify
);
497 g_hash_table_remove(window_map
, &self
->handle
);
498 g_hash_table_remove(window_map
, &self
->lgrip
);
499 g_hash_table_remove(window_map
, &self
->rgrip
);
500 g_hash_table_remove(window_map
, &self
->tlresize
);
501 g_hash_table_remove(window_map
, &self
->trresize
);
503 ob_main_loop_timeout_remove_data(ob_main_loop
, flash_timeout
, self
);
508 static void layout_title(ObFrame
*self
)
512 gboolean n
, d
, i
, l
, m
, c
, s
;
514 n
= d
= i
= l
= m
= c
= s
= FALSE
;
516 /* figure out whats being shown, and the width of the label */
517 self
->label_width
= self
->width
- (ob_rr_theme
->padding
+ 1) * 2;
518 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
521 if (n
) { *lc
= ' '; break; } /* rm duplicates */
523 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
524 ob_rr_theme
->padding
+ 1);
527 if (d
) { *lc
= ' '; break; } /* rm duplicates */
529 self
->label_width
-= (ob_rr_theme
->button_size
+
530 ob_rr_theme
->padding
+ 1);
533 if (s
) { *lc
= ' '; break; } /* rm duplicates */
535 self
->label_width
-= (ob_rr_theme
->button_size
+
536 ob_rr_theme
->padding
+ 1);
539 if (i
) { *lc
= ' '; break; } /* rm duplicates */
541 self
->label_width
-= (ob_rr_theme
->button_size
+
542 ob_rr_theme
->padding
+ 1);
545 if (l
) { *lc
= ' '; break; } /* rm duplicates */
549 if (m
) { *lc
= ' '; break; } /* rm duplicates */
551 self
->label_width
-= (ob_rr_theme
->button_size
+
552 ob_rr_theme
->padding
+ 1);
555 if (c
) { *lc
= ' '; break; } /* rm duplicates */
557 self
->label_width
-= (ob_rr_theme
->button_size
+
558 ob_rr_theme
->padding
+ 1);
562 if (self
->label_width
< 1) self
->label_width
= 1;
564 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
565 ob_rr_theme
->label_height
);
567 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
568 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
569 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
570 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
571 if (!l
) XUnmapWindow(ob_display
, self
->label
);
572 if (!m
) XUnmapWindow(ob_display
, self
->max
);
573 if (!c
) XUnmapWindow(ob_display
, self
->close
);
575 x
= ob_rr_theme
->padding
+ 1;
576 for (lc
= config_title_layout
; *lc
!= '\0'; ++lc
) {
581 XMapWindow(ob_display
, self
->icon
);
582 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->padding
);
583 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->padding
+ 1;
588 XMapWindow(ob_display
, self
->desk
);
589 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->padding
+ 1);
590 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->padding
+ 1;
595 XMapWindow(ob_display
, self
->shade
);
596 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->padding
+ 1);
597 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->padding
+ 1;
602 XMapWindow(ob_display
, self
->iconify
);
603 XMoveWindow(ob_display
,self
->iconify
, x
, ob_rr_theme
->padding
+ 1);
604 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->padding
+ 1;
609 XMapWindow(ob_display
, self
->label
);
610 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->padding
);
611 x
+= self
->label_width
+ ob_rr_theme
->padding
+ 1;
616 XMapWindow(ob_display
, self
->max
);
617 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->padding
+ 1);
618 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->padding
+ 1;
623 XMapWindow(ob_display
, self
->close
);
624 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->padding
+ 1);
625 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->padding
+ 1;
631 ObFrameContext
frame_context_from_string(char *name
)
633 if (!g_ascii_strcasecmp("desktop", name
))
634 return OB_FRAME_CONTEXT_DESKTOP
;
635 else if (!g_ascii_strcasecmp("client", name
))
636 return OB_FRAME_CONTEXT_CLIENT
;
637 else if (!g_ascii_strcasecmp("titlebar", name
))
638 return OB_FRAME_CONTEXT_TITLEBAR
;
639 else if (!g_ascii_strcasecmp("handle", name
))
640 return OB_FRAME_CONTEXT_HANDLE
;
641 else if (!g_ascii_strcasecmp("frame", name
))
642 return OB_FRAME_CONTEXT_FRAME
;
643 else if (!g_ascii_strcasecmp("tlcorner", name
))
644 return OB_FRAME_CONTEXT_TLCORNER
;
645 else if (!g_ascii_strcasecmp("trcorner", name
))
646 return OB_FRAME_CONTEXT_TRCORNER
;
647 else if (!g_ascii_strcasecmp("blcorner", name
))
648 return OB_FRAME_CONTEXT_BLCORNER
;
649 else if (!g_ascii_strcasecmp("brcorner", name
))
650 return OB_FRAME_CONTEXT_BRCORNER
;
651 else if (!g_ascii_strcasecmp("maximize", name
))
652 return OB_FRAME_CONTEXT_MAXIMIZE
;
653 else if (!g_ascii_strcasecmp("alldesktops", name
))
654 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
655 else if (!g_ascii_strcasecmp("shade", name
))
656 return OB_FRAME_CONTEXT_SHADE
;
657 else if (!g_ascii_strcasecmp("iconify", name
))
658 return OB_FRAME_CONTEXT_ICONIFY
;
659 else if (!g_ascii_strcasecmp("icon", name
))
660 return OB_FRAME_CONTEXT_ICON
;
661 else if (!g_ascii_strcasecmp("close", name
))
662 return OB_FRAME_CONTEXT_CLOSE
;
663 return OB_FRAME_CONTEXT_NONE
;
666 ObFrameContext
frame_context(ObClient
*client
, Window win
)
670 if (win
== RootWindow(ob_display
, ob_screen
))
671 return OB_FRAME_CONTEXT_DESKTOP
;
672 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
673 if (win
== client
->window
) {
674 /* conceptually, this is the desktop, as far as users are
676 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
677 return OB_FRAME_CONTEXT_DESKTOP
;
678 return OB_FRAME_CONTEXT_CLIENT
;
681 self
= client
->frame
;
682 if (win
== self
->plate
) {
683 /* conceptually, this is the desktop, as far as users are
685 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
686 return OB_FRAME_CONTEXT_DESKTOP
;
687 return OB_FRAME_CONTEXT_CLIENT
;
690 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
691 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
692 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
693 if (win
== self
->handle
) return OB_FRAME_CONTEXT_HANDLE
;
694 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
695 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
696 if (win
== self
->tlresize
) return OB_FRAME_CONTEXT_TLCORNER
;
697 if (win
== self
->trresize
) return OB_FRAME_CONTEXT_TRCORNER
;
698 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
699 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
700 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
701 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
702 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
703 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
705 return OB_FRAME_CONTEXT_NONE
;
708 void frame_client_gravity(ObFrame
*self
, int *x
, int *y
)
711 switch (self
->client
->gravity
) {
713 case NorthWestGravity
:
714 case SouthWestGravity
:
721 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
724 case NorthEastGravity
:
725 case SouthEastGravity
:
727 *x
-= self
->size
.left
+ self
->size
.right
;
732 *x
-= self
->size
.left
;
737 switch (self
->client
->gravity
) {
739 case NorthWestGravity
:
740 case NorthEastGravity
:
747 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
750 case SouthWestGravity
:
751 case SouthEastGravity
:
753 *y
-= self
->size
.top
+ self
->size
.bottom
;
758 *y
-= self
->size
.top
;
763 void frame_frame_gravity(ObFrame
*self
, int *x
, int *y
)
766 switch (self
->client
->gravity
) {
768 case NorthWestGravity
:
770 case SouthWestGravity
:
775 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
777 case NorthEastGravity
:
779 case SouthEastGravity
:
780 *x
+= self
->size
.left
+ self
->size
.right
;
784 *x
+= self
->size
.left
;
789 switch (self
->client
->gravity
) {
791 case NorthWestGravity
:
793 case NorthEastGravity
:
798 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
800 case SouthWestGravity
:
802 case SouthEastGravity
:
803 *y
+= self
->size
.top
+ self
->size
.bottom
;
807 *y
+= self
->size
.top
;
812 static void flash_done(gpointer data
)
814 ObFrame
*self
= data
;
816 if (self
->focused
!= self
->flash_on
)
817 frame_adjust_focus(self
, self
->focused
);
820 static gboolean
flash_timeout(gpointer data
)
822 ObFrame
*self
= data
;
825 g_get_current_time(&now
);
826 if (now
.tv_sec
> self
->flash_end
.tv_sec
||
827 (now
.tv_sec
== self
->flash_end
.tv_sec
&&
828 now
.tv_usec
>= self
->flash_end
.tv_usec
))
829 self
->flashing
= FALSE
;
832 return FALSE
; /* we are done */
834 self
->flash_on
= !self
->flash_on
;
838 focused
= self
->focused
; /* save the focused flag */
839 frame_adjust_focus(self
, self
->flash_on
);
840 self
->focused
= focused
;
843 return TRUE
; /* go again */
846 void frame_flash_start(ObFrame
*self
)
848 self
->flash_on
= self
->focused
;
851 ob_main_loop_timeout_add(ob_main_loop
,
852 G_USEC_PER_SEC
* 0.75,
856 g_get_current_time(&self
->flash_end
);
857 g_time_val_add(&self
->flash_end
, G_USEC_PER_SEC
* 5);
859 self
->flashing
= TRUE
;
862 void frame_flash_stop(ObFrame
*self
)
864 self
->flashing
= FALSE
;