1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 frame.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
26 #include "framerender.h"
27 #include "focus_cycle.h"
28 #include "focus_cycle_indicator.h"
29 #include "moveresize.h"
31 #include "render/theme.h"
32 #include "obt/display.h"
34 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
35 ButtonPressMask | ButtonReleaseMask | \
36 SubstructureRedirectMask | FocusChangeMask)
37 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
38 ButtonMotionMask | PointerMotionMask | \
39 EnterWindowMask | LeaveWindowMask)
41 #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
42 #define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
44 #define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b)
46 static void flash_done(gpointer data
);
47 static gboolean
flash_timeout(gpointer data
);
49 static void layout_title(ObFrame
*self
);
50 static void set_theme_statics(ObFrame
*self
);
51 static void free_theme_statics(ObFrame
*self
);
52 static gboolean
frame_animate_iconify(gpointer self
);
53 static void frame_adjust_cursors(ObFrame
*self
);
55 static Window
createWindow(Window parent
, Visual
*visual
,
56 gulong mask
, XSetWindowAttributes
*attrib
)
58 return XCreateWindow(obt_display
, parent
, 0, 0, 1, 1, 0,
59 (visual
? 32 : RrDepth(ob_rr_inst
)), InputOutput
,
60 (visual
? visual
: RrVisual(ob_rr_inst
)),
65 static Visual
*check_32bit_client(ObClient
*c
)
67 XWindowAttributes wattrib
;
70 /* we're already running at 32 bit depth, yay. we don't need to use their
72 if (RrDepth(ob_rr_inst
) == 32)
75 ret
= XGetWindowAttributes(obt_display
, c
->window
, &wattrib
);
76 g_assert(ret
!= BadDrawable
);
77 g_assert(ret
!= BadWindow
);
79 if (wattrib
.depth
== 32)
80 return wattrib
.visual
;
84 ObFrame
*frame_new(ObClient
*client
)
86 XSetWindowAttributes attrib
;
91 self
= g_new0(ObFrame
, 1);
92 self
->client
= client
;
94 visual
= check_32bit_client(client
);
96 /* create the non-visible decor windows */
100 /* client has a 32-bit visual */
101 mask
|= CWColormap
| CWBackPixel
| CWBorderPixel
;
102 /* create a colormap with the visual */
103 self
->colormap
= attrib
.colormap
=
104 XCreateColormap(obt_display
,
105 RootWindow(obt_display
, ob_screen
),
107 attrib
.background_pixel
= BlackPixel(obt_display
, ob_screen
);
108 attrib
.border_pixel
= BlackPixel(obt_display
, ob_screen
);
110 self
->window
= createWindow(RootWindow(obt_display
, ob_screen
), visual
,
113 /* create the visible decor windows */
117 /* client has a 32-bit visual */
118 mask
|= CWColormap
| CWBackPixel
| CWBorderPixel
;
119 attrib
.colormap
= RrColormap(ob_rr_inst
);
122 self
->backback
= createWindow(self
->window
, NULL
, mask
, &attrib
);
123 self
->backfront
= createWindow(self
->backback
, NULL
, mask
, &attrib
);
126 attrib
.event_mask
= ELEMENT_EVENTMASK
;
127 self
->innerleft
= createWindow(self
->window
, NULL
, mask
, &attrib
);
128 self
->innertop
= createWindow(self
->window
, NULL
, mask
, &attrib
);
129 self
->innerright
= createWindow(self
->window
, NULL
, mask
, &attrib
);
130 self
->innerbottom
= createWindow(self
->window
, NULL
, mask
, &attrib
);
132 self
->innerblb
= createWindow(self
->innerbottom
, NULL
, mask
, &attrib
);
133 self
->innerbrb
= createWindow(self
->innerbottom
, NULL
, mask
, &attrib
);
134 self
->innerbll
= createWindow(self
->innerleft
, NULL
, mask
, &attrib
);
135 self
->innerbrr
= createWindow(self
->innerright
, NULL
, mask
, &attrib
);
137 self
->title
= createWindow(self
->window
, NULL
, mask
, &attrib
);
138 self
->titleleft
= createWindow(self
->window
, NULL
, mask
, &attrib
);
139 self
->titletop
= createWindow(self
->window
, NULL
, mask
, &attrib
);
140 self
->titletopleft
= createWindow(self
->window
, NULL
, mask
, &attrib
);
141 self
->titletopright
= createWindow(self
->window
, NULL
, mask
, &attrib
);
142 self
->titleright
= createWindow(self
->window
, NULL
, mask
, &attrib
);
143 self
->titlebottom
= createWindow(self
->window
, NULL
, mask
, &attrib
);
145 self
->topresize
= createWindow(self
->title
, NULL
, mask
, &attrib
);
146 self
->tltresize
= createWindow(self
->title
, NULL
, mask
, &attrib
);
147 self
->tllresize
= createWindow(self
->title
, NULL
, mask
, &attrib
);
148 self
->trtresize
= createWindow(self
->title
, NULL
, mask
, &attrib
);
149 self
->trrresize
= createWindow(self
->title
, NULL
, mask
, &attrib
);
151 self
->left
= createWindow(self
->window
, NULL
, mask
, &attrib
);
152 self
->right
= createWindow(self
->window
, NULL
, mask
, &attrib
);
154 self
->label
= createWindow(self
->title
, NULL
, mask
, &attrib
);
155 self
->max
= createWindow(self
->title
, NULL
, mask
, &attrib
);
156 self
->close
= createWindow(self
->title
, NULL
, mask
, &attrib
);
157 self
->desk
= createWindow(self
->title
, NULL
, mask
, &attrib
);
158 self
->shade
= createWindow(self
->title
, NULL
, mask
, &attrib
);
159 self
->icon
= createWindow(self
->title
, NULL
, mask
, &attrib
);
160 self
->iconify
= createWindow(self
->title
, NULL
, mask
, &attrib
);
162 self
->handle
= createWindow(self
->window
, NULL
, mask
, &attrib
);
163 self
->lgrip
= createWindow(self
->handle
, NULL
, mask
, &attrib
);
164 self
->rgrip
= createWindow(self
->handle
, NULL
, mask
, &attrib
);
166 self
->handleleft
= createWindow(self
->handle
, NULL
, mask
, &attrib
);
167 self
->handleright
= createWindow(self
->handle
, NULL
, mask
, &attrib
);
169 self
->handletop
= createWindow(self
->window
, NULL
, mask
, &attrib
);
170 self
->handlebottom
= createWindow(self
->window
, NULL
, mask
, &attrib
);
171 self
->lgripleft
= createWindow(self
->window
, NULL
, mask
, &attrib
);
172 self
->lgriptop
= createWindow(self
->window
, NULL
, mask
, &attrib
);
173 self
->lgripbottom
= createWindow(self
->window
, NULL
, mask
, &attrib
);
174 self
->rgripright
= createWindow(self
->window
, NULL
, mask
, &attrib
);
175 self
->rgriptop
= createWindow(self
->window
, NULL
, mask
, &attrib
);
176 self
->rgripbottom
= createWindow(self
->window
, NULL
, mask
, &attrib
);
178 self
->focused
= FALSE
;
180 /* the other stuff is shown based on decor settings */
181 XMapWindow(obt_display
, self
->label
);
182 XMapWindow(obt_display
, self
->backback
);
183 XMapWindow(obt_display
, self
->backfront
);
185 self
->max_press
= self
->close_press
= self
->desk_press
=
186 self
->iconify_press
= self
->shade_press
= FALSE
;
187 self
->max_hover
= self
->close_hover
= self
->desk_hover
=
188 self
->iconify_hover
= self
->shade_hover
= FALSE
;
190 set_theme_statics(self
);
192 return (ObFrame
*)self
;
195 static void set_theme_statics(ObFrame
*self
)
197 /* set colors/appearance/sizes for stuff that doesn't change */
198 XResizeWindow(obt_display
, self
->max
,
199 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
200 XResizeWindow(obt_display
, self
->iconify
,
201 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
202 XResizeWindow(obt_display
, self
->icon
,
203 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
204 XResizeWindow(obt_display
, self
->close
,
205 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
206 XResizeWindow(obt_display
, self
->desk
,
207 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
208 XResizeWindow(obt_display
, self
->shade
,
209 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
210 XResizeWindow(obt_display
, self
->tltresize
,
211 ob_rr_theme
->grip_width
, ob_rr_theme
->paddingy
+ 1);
212 XResizeWindow(obt_display
, self
->trtresize
,
213 ob_rr_theme
->grip_width
, ob_rr_theme
->paddingy
+ 1);
214 XResizeWindow(obt_display
, self
->tllresize
,
215 ob_rr_theme
->paddingx
+ 1, ob_rr_theme
->title_height
);
216 XResizeWindow(obt_display
, self
->trrresize
,
217 ob_rr_theme
->paddingx
+ 1, ob_rr_theme
->title_height
);
219 /* set up the dynamic appearances */
220 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
221 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
222 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
223 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
224 self
->a_unfocused_handle
=
225 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
226 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
227 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
230 static void free_theme_statics(ObFrame
*self
)
232 RrAppearanceFree(self
->a_unfocused_title
);
233 RrAppearanceFree(self
->a_focused_title
);
234 RrAppearanceFree(self
->a_unfocused_label
);
235 RrAppearanceFree(self
->a_focused_label
);
236 RrAppearanceFree(self
->a_unfocused_handle
);
237 RrAppearanceFree(self
->a_focused_handle
);
238 RrAppearanceFree(self
->a_icon
);
241 void frame_free(ObFrame
*self
)
243 free_theme_statics(self
);
245 XDestroyWindow(obt_display
, self
->window
);
247 XFreeColormap(obt_display
, self
->colormap
);
252 void frame_show(ObFrame
*self
)
254 if (!self
->visible
) {
255 self
->visible
= TRUE
;
256 framerender_frame(self
);
257 /* Grab the server to make sure that the frame window is mapped before
258 the client gets its MapNotify, i.e. to make sure the client is
259 _visible_ when it gets MapNotify. */
261 XMapWindow(obt_display
, self
->client
->window
);
262 XMapWindow(obt_display
, self
->window
);
267 void frame_hide(ObFrame
*self
)
270 self
->visible
= FALSE
;
271 if (!frame_iconify_animating(self
))
272 XUnmapWindow(obt_display
, self
->window
);
273 /* we unmap the client itself so that we can get MapRequest
274 events, and because the ICCCM tells us to! */
275 XUnmapWindow(obt_display
, self
->client
->window
);
276 self
->client
->ignore_unmaps
+= 1;
280 void frame_adjust_theme(ObFrame
*self
)
282 free_theme_statics(self
);
283 set_theme_statics(self
);
286 void frame_adjust_shape(ObFrame
*self
)
292 if (!self
->client
->shaped
) {
293 /* clear the shape on the frame window */
294 XShapeCombineMask(obt_display
, self
->window
, ShapeBounding
,
299 /* make the frame's shape match the clients */
300 XShapeCombineShape(obt_display
, self
->window
, ShapeBounding
,
303 self
->client
->window
,
304 ShapeBounding
, ShapeSet
);
307 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
310 xrect
[0].width
= self
->area
.width
;
311 xrect
[0].height
= self
->size
.top
;
315 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
&&
316 ob_rr_theme
->handle_height
> 0)
319 xrect
[1].y
= FRAME_HANDLE_Y(self
);
320 xrect
[1].width
= self
->area
.width
;
321 xrect
[1].height
= ob_rr_theme
->handle_height
+
326 XShapeCombineRectangles(obt_display
, self
->window
,
327 ShapeBounding
, 0, 0, xrect
, num
,
328 ShapeUnion
, Unsorted
);
333 void frame_adjust_area(ObFrame
*self
, gboolean moved
,
334 gboolean resized
, gboolean fake
)
338 oldsize
= self
->size
;
341 /* do this before changing the frame's status like max_horz max_vert */
342 frame_adjust_cursors(self
);
344 self
->functions
= self
->client
->functions
;
345 self
->decorations
= self
->client
->decorations
;
346 self
->max_horz
= self
->client
->max_horz
;
347 self
->max_vert
= self
->client
->max_vert
;
348 self
->shaded
= self
->client
->shaded
;
350 if (self
->decorations
& OB_FRAME_DECOR_BORDER
||
351 (self
->client
->undecorated
&& config_theme_keepborder
))
352 self
->bwidth
= ob_rr_theme
->fbwidth
;
356 if (self
->decorations
& OB_FRAME_DECOR_BORDER
) {
357 self
->cbwidth_l
= self
->cbwidth_r
= ob_rr_theme
->cbwidthx
;
358 self
->cbwidth_t
= self
->cbwidth_b
= ob_rr_theme
->cbwidthy
;
360 self
->cbwidth_l
= self
->cbwidth_t
=
361 self
->cbwidth_r
= self
->cbwidth_b
= 0;
363 if (self
->max_horz
) {
364 self
->cbwidth_l
= self
->cbwidth_r
= 0;
365 self
->width
= self
->client
->area
.width
;
369 self
->width
= self
->client
->area
.width
+
370 self
->cbwidth_l
+ self
->cbwidth_r
;
372 /* some elements are sized based of the width, so don't let them have
374 self
->width
= MAX(self
->width
,
375 (ob_rr_theme
->grip_width
+ self
->bwidth
) * 2 + 1);
377 STRUT_SET(self
->size
,
378 self
->cbwidth_l
+ (!self
->max_horz
? self
->bwidth
: 0),
380 (!self
->max_horz
|| !self
->max_vert
||
381 !self
->client
->undecorated
? self
->bwidth
: 0),
382 self
->cbwidth_r
+ (!self
->max_horz
? self
->bwidth
: 0),
384 (!self
->max_horz
|| !self
->max_vert
? self
->bwidth
: 0));
386 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
)
387 self
->size
.top
+= ob_rr_theme
->title_height
+ self
->bwidth
;
388 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
&&
389 ob_rr_theme
->handle_height
> 0)
391 self
->size
.bottom
+= ob_rr_theme
->handle_height
+ self
->bwidth
;
394 /* position/size and map/unmap all the windows */
397 gint innercornerheight
=
398 ob_rr_theme
->grip_width
- self
->size
.bottom
;
400 if (self
->cbwidth_l
) {
401 XMoveResizeWindow(obt_display
, self
->innerleft
,
402 self
->size
.left
- self
->cbwidth_l
,
404 self
->cbwidth_l
, self
->client
->area
.height
);
406 XMapWindow(obt_display
, self
->innerleft
);
408 XUnmapWindow(obt_display
, self
->innerleft
);
410 if (self
->cbwidth_l
&& innercornerheight
> 0) {
411 XMoveResizeWindow(obt_display
, self
->innerbll
,
413 self
->client
->area
.height
-
414 (ob_rr_theme
->grip_width
-
417 ob_rr_theme
->grip_width
- self
->size
.bottom
);
419 XMapWindow(obt_display
, self
->innerbll
);
421 XUnmapWindow(obt_display
, self
->innerbll
);
423 if (self
->cbwidth_r
) {
424 XMoveResizeWindow(obt_display
, self
->innerright
,
425 self
->size
.left
+ self
->client
->area
.width
,
427 self
->cbwidth_r
, self
->client
->area
.height
);
429 XMapWindow(obt_display
, self
->innerright
);
431 XUnmapWindow(obt_display
, self
->innerright
);
433 if (self
->cbwidth_r
&& innercornerheight
> 0) {
434 XMoveResizeWindow(obt_display
, self
->innerbrr
,
436 self
->client
->area
.height
-
437 (ob_rr_theme
->grip_width
-
440 ob_rr_theme
->grip_width
- self
->size
.bottom
);
442 XMapWindow(obt_display
, self
->innerbrr
);
444 XUnmapWindow(obt_display
, self
->innerbrr
);
446 if (self
->cbwidth_t
) {
447 XMoveResizeWindow(obt_display
, self
->innertop
,
448 self
->size
.left
- self
->cbwidth_l
,
449 self
->size
.top
- self
->cbwidth_t
,
450 self
->client
->area
.width
+
451 self
->cbwidth_l
+ self
->cbwidth_r
,
454 XMapWindow(obt_display
, self
->innertop
);
456 XUnmapWindow(obt_display
, self
->innertop
);
458 if (self
->cbwidth_b
) {
459 XMoveResizeWindow(obt_display
, self
->innerbottom
,
460 self
->size
.left
- self
->cbwidth_l
,
461 self
->size
.top
+ self
->client
->area
.height
,
462 self
->client
->area
.width
+
463 self
->cbwidth_l
+ self
->cbwidth_r
,
466 XMoveResizeWindow(obt_display
, self
->innerblb
,
468 ob_rr_theme
->grip_width
+ self
->bwidth
,
470 XMoveResizeWindow(obt_display
, self
->innerbrb
,
471 self
->client
->area
.width
+
472 self
->cbwidth_l
+ self
->cbwidth_r
-
473 (ob_rr_theme
->grip_width
+ self
->bwidth
),
475 ob_rr_theme
->grip_width
+ self
->bwidth
,
478 XMapWindow(obt_display
, self
->innerbottom
);
479 XMapWindow(obt_display
, self
->innerblb
);
480 XMapWindow(obt_display
, self
->innerbrb
);
482 XUnmapWindow(obt_display
, self
->innerbottom
);
483 XUnmapWindow(obt_display
, self
->innerblb
);
484 XUnmapWindow(obt_display
, self
->innerbrb
);
490 /* height of titleleft and titleright */
491 titlesides
= (!self
->max_horz
? ob_rr_theme
->grip_width
: 0);
493 XMoveResizeWindow(obt_display
, self
->titletop
,
494 ob_rr_theme
->grip_width
+ self
->bwidth
, 0,
495 /* width + bwidth*2 - bwidth*2 - grips*2 */
496 self
->width
- ob_rr_theme
->grip_width
* 2,
498 XMoveResizeWindow(obt_display
, self
->titletopleft
,
500 ob_rr_theme
->grip_width
+ self
->bwidth
,
502 XMoveResizeWindow(obt_display
, self
->titletopright
,
503 self
->client
->area
.width
+
504 self
->size
.left
+ self
->size
.right
-
505 ob_rr_theme
->grip_width
- self
->bwidth
,
507 ob_rr_theme
->grip_width
+ self
->bwidth
,
510 if (titlesides
> 0) {
511 XMoveResizeWindow(obt_display
, self
->titleleft
,
515 XMoveResizeWindow(obt_display
, self
->titleright
,
516 self
->client
->area
.width
+
517 self
->size
.left
+ self
->size
.right
-
523 XMapWindow(obt_display
, self
->titleleft
);
524 XMapWindow(obt_display
, self
->titleright
);
526 XUnmapWindow(obt_display
, self
->titleleft
);
527 XUnmapWindow(obt_display
, self
->titleright
);
530 XMapWindow(obt_display
, self
->titletop
);
531 XMapWindow(obt_display
, self
->titletopleft
);
532 XMapWindow(obt_display
, self
->titletopright
);
534 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
535 XMoveResizeWindow(obt_display
, self
->titlebottom
,
536 (self
->max_horz
? 0 : self
->bwidth
),
537 ob_rr_theme
->title_height
+ self
->bwidth
,
541 XMapWindow(obt_display
, self
->titlebottom
);
543 XUnmapWindow(obt_display
, self
->titlebottom
);
545 XUnmapWindow(obt_display
, self
->titlebottom
);
547 XUnmapWindow(obt_display
, self
->titletop
);
548 XUnmapWindow(obt_display
, self
->titletopleft
);
549 XUnmapWindow(obt_display
, self
->titletopright
);
550 XUnmapWindow(obt_display
, self
->titleleft
);
551 XUnmapWindow(obt_display
, self
->titleright
);
554 if (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
) {
555 XMoveResizeWindow(obt_display
, self
->title
,
556 (self
->max_horz
? 0 : self
->bwidth
),
558 self
->width
, ob_rr_theme
->title_height
);
560 XMapWindow(obt_display
, self
->title
);
562 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
563 XMoveResizeWindow(obt_display
, self
->topresize
,
564 ob_rr_theme
->grip_width
,
566 self
->width
- ob_rr_theme
->grip_width
*2,
567 ob_rr_theme
->paddingy
+ 1);
569 XMoveWindow(obt_display
, self
->tltresize
, 0, 0);
570 XMoveWindow(obt_display
, self
->tllresize
, 0, 0);
571 XMoveWindow(obt_display
, self
->trtresize
,
572 self
->width
- ob_rr_theme
->grip_width
, 0);
573 XMoveWindow(obt_display
, self
->trrresize
,
574 self
->width
- ob_rr_theme
->paddingx
- 1, 0);
576 XMapWindow(obt_display
, self
->topresize
);
577 XMapWindow(obt_display
, self
->tltresize
);
578 XMapWindow(obt_display
, self
->tllresize
);
579 XMapWindow(obt_display
, self
->trtresize
);
580 XMapWindow(obt_display
, self
->trrresize
);
582 XUnmapWindow(obt_display
, self
->topresize
);
583 XUnmapWindow(obt_display
, self
->tltresize
);
584 XUnmapWindow(obt_display
, self
->tllresize
);
585 XUnmapWindow(obt_display
, self
->trtresize
);
586 XUnmapWindow(obt_display
, self
->trrresize
);
589 XUnmapWindow(obt_display
, self
->title
);
592 if ((self
->decorations
& OB_FRAME_DECOR_TITLEBAR
))
593 /* layout the title bar elements */
597 gint sidebwidth
= self
->max_horz
? 0 : self
->bwidth
;
599 if (self
->bwidth
&& self
->size
.bottom
) {
600 XMoveResizeWindow(obt_display
, self
->handlebottom
,
601 ob_rr_theme
->grip_width
+
602 self
->bwidth
+ sidebwidth
,
603 self
->size
.top
+ self
->client
->area
.height
+
604 self
->size
.bottom
- self
->bwidth
,
605 self
->width
- (ob_rr_theme
->grip_width
+
611 XMoveResizeWindow(obt_display
, self
->lgripleft
,
614 self
->client
->area
.height
+
617 ob_rr_theme
->grip_width
:
618 self
->size
.bottom
- self
->cbwidth_b
),
621 ob_rr_theme
->grip_width
:
622 self
->size
.bottom
- self
->cbwidth_b
));
623 XMoveResizeWindow(obt_display
, self
->rgripright
,
625 self
->client
->area
.width
+
626 self
->size
.right
- self
->bwidth
,
628 self
->client
->area
.height
+
631 ob_rr_theme
->grip_width
:
632 self
->size
.bottom
- self
->cbwidth_b
),
635 ob_rr_theme
->grip_width
:
636 self
->size
.bottom
- self
->cbwidth_b
));
638 XMapWindow(obt_display
, self
->lgripleft
);
639 XMapWindow(obt_display
, self
->rgripright
);
641 XUnmapWindow(obt_display
, self
->lgripleft
);
642 XUnmapWindow(obt_display
, self
->rgripright
);
645 XMoveResizeWindow(obt_display
, self
->lgripbottom
,
647 self
->size
.top
+ self
->client
->area
.height
+
648 self
->size
.bottom
- self
->bwidth
,
649 ob_rr_theme
->grip_width
+ self
->bwidth
,
651 XMoveResizeWindow(obt_display
, self
->rgripbottom
,
652 self
->size
.left
+ self
->client
->area
.width
+
653 self
->size
.right
- self
->bwidth
- sidebwidth
-
654 ob_rr_theme
->grip_width
,
655 self
->size
.top
+ self
->client
->area
.height
+
656 self
->size
.bottom
- self
->bwidth
,
657 ob_rr_theme
->grip_width
+ self
->bwidth
,
660 XMapWindow(obt_display
, self
->handlebottom
);
661 XMapWindow(obt_display
, self
->lgripbottom
);
662 XMapWindow(obt_display
, self
->rgripbottom
);
664 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
&&
665 ob_rr_theme
->handle_height
> 0)
667 XMoveResizeWindow(obt_display
, self
->handletop
,
668 ob_rr_theme
->grip_width
+
669 self
->bwidth
+ sidebwidth
,
670 FRAME_HANDLE_Y(self
),
671 self
->width
- (ob_rr_theme
->grip_width
+
674 XMapWindow(obt_display
, self
->handletop
);
676 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
677 XMoveResizeWindow(obt_display
, self
->handleleft
,
678 ob_rr_theme
->grip_width
,
681 ob_rr_theme
->handle_height
);
682 XMoveResizeWindow(obt_display
, self
->handleright
,
684 ob_rr_theme
->grip_width
-
688 ob_rr_theme
->handle_height
);
690 XMoveResizeWindow(obt_display
, self
->lgriptop
,
692 FRAME_HANDLE_Y(self
),
693 ob_rr_theme
->grip_width
+
696 XMoveResizeWindow(obt_display
, self
->rgriptop
,
698 self
->client
->area
.width
+
699 self
->size
.right
- self
->bwidth
-
700 sidebwidth
- ob_rr_theme
->grip_width
,
701 FRAME_HANDLE_Y(self
),
702 ob_rr_theme
->grip_width
+
706 XMapWindow(obt_display
, self
->handleleft
);
707 XMapWindow(obt_display
, self
->handleright
);
708 XMapWindow(obt_display
, self
->lgriptop
);
709 XMapWindow(obt_display
, self
->rgriptop
);
711 XUnmapWindow(obt_display
, self
->handleleft
);
712 XUnmapWindow(obt_display
, self
->handleright
);
713 XUnmapWindow(obt_display
, self
->lgriptop
);
714 XUnmapWindow(obt_display
, self
->rgriptop
);
717 XUnmapWindow(obt_display
, self
->handleleft
);
718 XUnmapWindow(obt_display
, self
->handleright
);
719 XUnmapWindow(obt_display
, self
->lgriptop
);
720 XUnmapWindow(obt_display
, self
->rgriptop
);
722 XUnmapWindow(obt_display
, self
->handletop
);
725 XUnmapWindow(obt_display
, self
->handleleft
);
726 XUnmapWindow(obt_display
, self
->handleright
);
727 XUnmapWindow(obt_display
, self
->lgriptop
);
728 XUnmapWindow(obt_display
, self
->rgriptop
);
730 XUnmapWindow(obt_display
, self
->handletop
);
732 XUnmapWindow(obt_display
, self
->handlebottom
);
733 XUnmapWindow(obt_display
, self
->lgripleft
);
734 XUnmapWindow(obt_display
, self
->rgripright
);
735 XUnmapWindow(obt_display
, self
->lgripbottom
);
736 XUnmapWindow(obt_display
, self
->rgripbottom
);
739 if (self
->decorations
& OB_FRAME_DECOR_HANDLE
&&
740 ob_rr_theme
->handle_height
> 0)
742 XMoveResizeWindow(obt_display
, self
->handle
,
744 FRAME_HANDLE_Y(self
) + self
->bwidth
,
745 self
->width
, ob_rr_theme
->handle_height
);
746 XMapWindow(obt_display
, self
->handle
);
748 if (self
->decorations
& OB_FRAME_DECOR_GRIPS
) {
749 XMoveResizeWindow(obt_display
, self
->lgrip
,
751 ob_rr_theme
->grip_width
,
752 ob_rr_theme
->handle_height
);
753 XMoveResizeWindow(obt_display
, self
->rgrip
,
754 self
->width
- ob_rr_theme
->grip_width
,
756 ob_rr_theme
->grip_width
,
757 ob_rr_theme
->handle_height
);
759 XMapWindow(obt_display
, self
->lgrip
);
760 XMapWindow(obt_display
, self
->rgrip
);
762 XUnmapWindow(obt_display
, self
->lgrip
);
763 XUnmapWindow(obt_display
, self
->rgrip
);
766 XUnmapWindow(obt_display
, self
->lgrip
);
767 XUnmapWindow(obt_display
, self
->rgrip
);
769 XUnmapWindow(obt_display
, self
->handle
);
772 if (self
->bwidth
&& !self
->max_horz
&&
773 (self
->client
->area
.height
+ self
->size
.top
+
774 self
->size
.bottom
) > ob_rr_theme
->grip_width
* 2)
776 XMoveResizeWindow(obt_display
, self
->left
,
778 self
->bwidth
+ ob_rr_theme
->grip_width
,
780 self
->client
->area
.height
+
781 self
->size
.top
+ self
->size
.bottom
-
782 ob_rr_theme
->grip_width
* 2);
784 XMapWindow(obt_display
, self
->left
);
786 XUnmapWindow(obt_display
, self
->left
);
788 if (self
->bwidth
&& !self
->max_horz
&&
789 (self
->client
->area
.height
+ self
->size
.top
+
790 self
->size
.bottom
) > ob_rr_theme
->grip_width
* 2)
792 XMoveResizeWindow(obt_display
, self
->right
,
793 self
->client
->area
.width
+ self
->cbwidth_l
+
794 self
->cbwidth_r
+ self
->bwidth
,
795 self
->bwidth
+ ob_rr_theme
->grip_width
,
797 self
->client
->area
.height
+
798 self
->size
.top
+ self
->size
.bottom
-
799 ob_rr_theme
->grip_width
* 2);
801 XMapWindow(obt_display
, self
->right
);
803 XUnmapWindow(obt_display
, self
->right
);
805 XMoveResizeWindow(obt_display
, self
->backback
,
806 self
->size
.left
, self
->size
.top
,
807 self
->client
->area
.width
,
808 self
->client
->area
.height
);
812 /* shading can change without being moved or resized */
813 RECT_SET_SIZE(self
->area
,
814 self
->client
->area
.width
+
815 self
->size
.left
+ self
->size
.right
,
816 (self
->client
->shaded
?
817 ob_rr_theme
->title_height
+ self
->bwidth
* 2:
818 self
->client
->area
.height
+
819 self
->size
.top
+ self
->size
.bottom
));
821 if ((moved
|| resized
) && !fake
) {
822 /* find the new coordinates, done after setting the frame.size, for
823 frame_client_gravity. */
824 self
->area
.x
= self
->client
->area
.x
;
825 self
->area
.y
= self
->client
->area
.y
;
826 frame_client_gravity(self
, &self
->area
.x
, &self
->area
.y
);
830 if (!frame_iconify_animating(self
))
831 /* move and resize the top level frame.
832 shading can change without being moved or resized.
834 but don't do this during an iconify animation. it will be
835 reflected afterwards.
837 XMoveResizeWindow(obt_display
, self
->window
,
843 /* when the client has StaticGravity, it likes to move around.
844 also this correctly positions the client when it maps.
845 this also needs to be run when the frame's decorations sizes change!
847 XMoveWindow(obt_display
, self
->client
->window
,
848 self
->size
.left
, self
->size
.top
);
851 self
->need_render
= TRUE
;
852 framerender_frame(self
);
853 frame_adjust_shape(self
);
856 if (!STRUT_EQUAL(self
->size
, oldsize
)) {
858 vals
[0] = self
->size
.left
;
859 vals
[1] = self
->size
.right
;
860 vals
[2] = self
->size
.top
;
861 vals
[3] = self
->size
.bottom
;
862 PROP_SETA32(self
->client
->window
, net_frame_extents
,
864 PROP_SETA32(self
->client
->window
, kde_net_wm_frame_strut
,
868 /* if this occurs while we are focus cycling, the indicator needs to
870 if (focus_cycle_target
== self
->client
)
871 focus_cycle_draw_indicator(self
->client
);
873 if (resized
&& (self
->decorations
& OB_FRAME_DECOR_TITLEBAR
))
874 XResizeWindow(obt_display
, self
->label
, self
->label_width
,
875 ob_rr_theme
->label_height
);
879 static void frame_adjust_cursors(ObFrame
*self
)
881 if ((self
->functions
& OB_CLIENT_FUNC_RESIZE
) !=
882 (self
->client
->functions
& OB_CLIENT_FUNC_RESIZE
) ||
883 self
->max_horz
!= self
->client
->max_horz
||
884 self
->max_vert
!= self
->client
->max_vert
||
885 self
->shaded
!= self
->client
->shaded
)
887 gboolean r
= (self
->client
->functions
& OB_CLIENT_FUNC_RESIZE
) &&
888 !(self
->client
->max_horz
&& self
->client
->max_vert
);
889 gboolean topbot
= !self
->client
->max_vert
;
890 gboolean sh
= self
->client
->shaded
;
891 XSetWindowAttributes a
;
893 /* these ones turn off when max vert, and some when shaded */
894 a
.cursor
= ob_cursor(r
&& topbot
&& !sh
?
895 OB_CURSOR_NORTH
: OB_CURSOR_NONE
);
896 XChangeWindowAttributes(obt_display
, self
->topresize
, CWCursor
, &a
);
897 XChangeWindowAttributes(obt_display
, self
->titletop
, CWCursor
, &a
);
898 a
.cursor
= ob_cursor(r
&& topbot
? OB_CURSOR_SOUTH
: OB_CURSOR_NONE
);
899 XChangeWindowAttributes(obt_display
, self
->handle
, CWCursor
, &a
);
900 XChangeWindowAttributes(obt_display
, self
->handletop
, CWCursor
, &a
);
901 XChangeWindowAttributes(obt_display
, self
->handlebottom
, CWCursor
, &a
);
902 XChangeWindowAttributes(obt_display
, self
->innerbottom
, CWCursor
, &a
);
904 /* these ones change when shaded */
905 a
.cursor
= ob_cursor(r
? (sh
? OB_CURSOR_WEST
: OB_CURSOR_NORTHWEST
) :
907 XChangeWindowAttributes(obt_display
, self
->titleleft
, CWCursor
, &a
);
908 XChangeWindowAttributes(obt_display
, self
->tltresize
, CWCursor
, &a
);
909 XChangeWindowAttributes(obt_display
, self
->tllresize
, CWCursor
, &a
);
910 XChangeWindowAttributes(obt_display
, self
->titletopleft
, CWCursor
, &a
);
911 a
.cursor
= ob_cursor(r
? (sh
? OB_CURSOR_EAST
: OB_CURSOR_NORTHEAST
) :
913 XChangeWindowAttributes(obt_display
, self
->titleright
, CWCursor
, &a
);
914 XChangeWindowAttributes(obt_display
, self
->trtresize
, CWCursor
, &a
);
915 XChangeWindowAttributes(obt_display
, self
->trrresize
, CWCursor
, &a
);
916 XChangeWindowAttributes(obt_display
, self
->titletopright
, CWCursor
,&a
);
918 /* these ones are pretty static */
919 a
.cursor
= ob_cursor(r
? OB_CURSOR_WEST
: OB_CURSOR_NONE
);
920 XChangeWindowAttributes(obt_display
, self
->left
, CWCursor
, &a
);
921 XChangeWindowAttributes(obt_display
, self
->innerleft
, CWCursor
, &a
);
922 a
.cursor
= ob_cursor(r
? OB_CURSOR_EAST
: OB_CURSOR_NONE
);
923 XChangeWindowAttributes(obt_display
, self
->right
, CWCursor
, &a
);
924 XChangeWindowAttributes(obt_display
, self
->innerright
, CWCursor
, &a
);
925 a
.cursor
= ob_cursor(r
? OB_CURSOR_SOUTHWEST
: OB_CURSOR_NONE
);
926 XChangeWindowAttributes(obt_display
, self
->lgrip
, CWCursor
, &a
);
927 XChangeWindowAttributes(obt_display
, self
->handleleft
, CWCursor
, &a
);
928 XChangeWindowAttributes(obt_display
, self
->lgripleft
, CWCursor
, &a
);
929 XChangeWindowAttributes(obt_display
, self
->lgriptop
, CWCursor
, &a
);
930 XChangeWindowAttributes(obt_display
, self
->lgripbottom
, CWCursor
, &a
);
931 XChangeWindowAttributes(obt_display
, self
->innerbll
, CWCursor
, &a
);
932 XChangeWindowAttributes(obt_display
, self
->innerblb
, CWCursor
, &a
);
933 a
.cursor
= ob_cursor(r
? OB_CURSOR_SOUTHEAST
: OB_CURSOR_NONE
);
934 XChangeWindowAttributes(obt_display
, self
->rgrip
, CWCursor
, &a
);
935 XChangeWindowAttributes(obt_display
, self
->handleright
, CWCursor
, &a
);
936 XChangeWindowAttributes(obt_display
, self
->rgripright
, CWCursor
, &a
);
937 XChangeWindowAttributes(obt_display
, self
->rgriptop
, CWCursor
, &a
);
938 XChangeWindowAttributes(obt_display
, self
->rgripbottom
, CWCursor
, &a
);
939 XChangeWindowAttributes(obt_display
, self
->innerbrr
, CWCursor
, &a
);
940 XChangeWindowAttributes(obt_display
, self
->innerbrb
, CWCursor
, &a
);
944 void frame_adjust_client_area(ObFrame
*self
)
946 /* adjust the window which is there to prevent flashing on unmap */
947 XMoveResizeWindow(obt_display
, self
->backfront
, 0, 0,
948 self
->client
->area
.width
,
949 self
->client
->area
.height
);
952 void frame_adjust_state(ObFrame
*self
)
954 self
->need_render
= TRUE
;
955 framerender_frame(self
);
958 void frame_adjust_focus(ObFrame
*self
, gboolean hilite
)
960 self
->focused
= hilite
;
961 self
->need_render
= TRUE
;
962 framerender_frame(self
);
966 void frame_adjust_title(ObFrame
*self
)
968 self
->need_render
= TRUE
;
969 framerender_frame(self
);
972 void frame_adjust_icon(ObFrame
*self
)
974 self
->need_render
= TRUE
;
975 framerender_frame(self
);
978 void frame_grab_client(ObFrame
*self
)
980 /* DO NOT map the client window here. we used to do that, but it is bogus.
981 we need to set up the client's dimensions and everything before we
982 send a mapnotify or we create race conditions.
985 /* reparent the client to the frame */
986 XReparentWindow(obt_display
, self
->client
->window
, self
->window
, 0, 0);
989 When reparenting the client window, it is usually not mapped yet, since
990 this occurs from a MapRequest. However, in the case where Openbox is
991 starting up, the window is already mapped, so we'll see an unmap event
994 if (ob_state() == OB_STATE_STARTING
)
995 ++self
->client
->ignore_unmaps
;
997 /* select the event mask on the client's parent (to receive config/map
998 req's) the ButtonPress is to catch clicks on the client border */
999 XSelectInput(obt_display
, self
->window
, FRAME_EVENTMASK
);
1001 /* set all the windows for the frame in the window_map */
1002 g_hash_table_insert(window_map
, &self
->window
, self
->client
);
1003 g_hash_table_insert(window_map
, &self
->backback
, self
->client
);
1004 g_hash_table_insert(window_map
, &self
->backfront
, self
->client
);
1005 g_hash_table_insert(window_map
, &self
->innerleft
, self
->client
);
1006 g_hash_table_insert(window_map
, &self
->innertop
, self
->client
);
1007 g_hash_table_insert(window_map
, &self
->innerright
, self
->client
);
1008 g_hash_table_insert(window_map
, &self
->innerbottom
, self
->client
);
1009 g_hash_table_insert(window_map
, &self
->innerblb
, self
->client
);
1010 g_hash_table_insert(window_map
, &self
->innerbll
, self
->client
);
1011 g_hash_table_insert(window_map
, &self
->innerbrb
, self
->client
);
1012 g_hash_table_insert(window_map
, &self
->innerbrr
, self
->client
);
1013 g_hash_table_insert(window_map
, &self
->title
, self
->client
);
1014 g_hash_table_insert(window_map
, &self
->label
, self
->client
);
1015 g_hash_table_insert(window_map
, &self
->max
, self
->client
);
1016 g_hash_table_insert(window_map
, &self
->close
, self
->client
);
1017 g_hash_table_insert(window_map
, &self
->desk
, self
->client
);
1018 g_hash_table_insert(window_map
, &self
->shade
, self
->client
);
1019 g_hash_table_insert(window_map
, &self
->icon
, self
->client
);
1020 g_hash_table_insert(window_map
, &self
->iconify
, self
->client
);
1021 g_hash_table_insert(window_map
, &self
->handle
, self
->client
);
1022 g_hash_table_insert(window_map
, &self
->lgrip
, self
->client
);
1023 g_hash_table_insert(window_map
, &self
->rgrip
, self
->client
);
1024 g_hash_table_insert(window_map
, &self
->topresize
, self
->client
);
1025 g_hash_table_insert(window_map
, &self
->tltresize
, self
->client
);
1026 g_hash_table_insert(window_map
, &self
->tllresize
, self
->client
);
1027 g_hash_table_insert(window_map
, &self
->trtresize
, self
->client
);
1028 g_hash_table_insert(window_map
, &self
->trrresize
, self
->client
);
1029 g_hash_table_insert(window_map
, &self
->left
, self
->client
);
1030 g_hash_table_insert(window_map
, &self
->right
, self
->client
);
1031 g_hash_table_insert(window_map
, &self
->titleleft
, self
->client
);
1032 g_hash_table_insert(window_map
, &self
->titletop
, self
->client
);
1033 g_hash_table_insert(window_map
, &self
->titletopleft
, self
->client
);
1034 g_hash_table_insert(window_map
, &self
->titletopright
, self
->client
);
1035 g_hash_table_insert(window_map
, &self
->titleright
, self
->client
);
1036 g_hash_table_insert(window_map
, &self
->titlebottom
, self
->client
);
1037 g_hash_table_insert(window_map
, &self
->handleleft
, self
->client
);
1038 g_hash_table_insert(window_map
, &self
->handletop
, self
->client
);
1039 g_hash_table_insert(window_map
, &self
->handleright
, self
->client
);
1040 g_hash_table_insert(window_map
, &self
->handlebottom
, self
->client
);
1041 g_hash_table_insert(window_map
, &self
->lgripleft
, self
->client
);
1042 g_hash_table_insert(window_map
, &self
->lgriptop
, self
->client
);
1043 g_hash_table_insert(window_map
, &self
->lgripbottom
, self
->client
);
1044 g_hash_table_insert(window_map
, &self
->rgripright
, self
->client
);
1045 g_hash_table_insert(window_map
, &self
->rgriptop
, self
->client
);
1046 g_hash_table_insert(window_map
, &self
->rgripbottom
, self
->client
);
1049 void frame_release_client(ObFrame
*self
)
1052 gboolean reparent
= TRUE
;
1054 /* if there was any animation going on, kill it */
1055 obt_main_loop_timeout_remove_data(ob_main_loop
, frame_animate_iconify
,
1058 /* check if the app has already reparented its window away */
1059 while (XCheckTypedWindowEvent(obt_display
, self
->client
->window
,
1060 ReparentNotify
, &ev
))
1062 /* This check makes sure we don't catch our own reparent action to
1063 our frame window. This doesn't count as the app reparenting itself
1066 Reparent events that are generated by us are just discarded here.
1067 They are of no consequence to us anyhow.
1069 if (ev
.xreparent
.parent
!= self
->window
) {
1071 XPutBackEvent(obt_display
, &ev
);
1077 /* according to the ICCCM - if the client doesn't reparent itself,
1078 then we will reparent the window to root for them */
1079 XReparentWindow(obt_display
, self
->client
->window
,
1080 RootWindow(obt_display
, ob_screen
),
1081 self
->client
->area
.x
,
1082 self
->client
->area
.y
);
1085 /* remove all the windows for the frame from the window_map */
1086 g_hash_table_remove(window_map
, &self
->window
);
1087 g_hash_table_remove(window_map
, &self
->backback
);
1088 g_hash_table_remove(window_map
, &self
->backfront
);
1089 g_hash_table_remove(window_map
, &self
->innerleft
);
1090 g_hash_table_remove(window_map
, &self
->innertop
);
1091 g_hash_table_remove(window_map
, &self
->innerright
);
1092 g_hash_table_remove(window_map
, &self
->innerbottom
);
1093 g_hash_table_remove(window_map
, &self
->innerblb
);
1094 g_hash_table_remove(window_map
, &self
->innerbll
);
1095 g_hash_table_remove(window_map
, &self
->innerbrb
);
1096 g_hash_table_remove(window_map
, &self
->innerbrr
);
1097 g_hash_table_remove(window_map
, &self
->title
);
1098 g_hash_table_remove(window_map
, &self
->label
);
1099 g_hash_table_remove(window_map
, &self
->max
);
1100 g_hash_table_remove(window_map
, &self
->close
);
1101 g_hash_table_remove(window_map
, &self
->desk
);
1102 g_hash_table_remove(window_map
, &self
->shade
);
1103 g_hash_table_remove(window_map
, &self
->icon
);
1104 g_hash_table_remove(window_map
, &self
->iconify
);
1105 g_hash_table_remove(window_map
, &self
->handle
);
1106 g_hash_table_remove(window_map
, &self
->lgrip
);
1107 g_hash_table_remove(window_map
, &self
->rgrip
);
1108 g_hash_table_remove(window_map
, &self
->topresize
);
1109 g_hash_table_remove(window_map
, &self
->tltresize
);
1110 g_hash_table_remove(window_map
, &self
->tllresize
);
1111 g_hash_table_remove(window_map
, &self
->trtresize
);
1112 g_hash_table_remove(window_map
, &self
->trrresize
);
1113 g_hash_table_remove(window_map
, &self
->left
);
1114 g_hash_table_remove(window_map
, &self
->right
);
1115 g_hash_table_remove(window_map
, &self
->titleleft
);
1116 g_hash_table_remove(window_map
, &self
->titletop
);
1117 g_hash_table_remove(window_map
, &self
->titletopleft
);
1118 g_hash_table_remove(window_map
, &self
->titletopright
);
1119 g_hash_table_remove(window_map
, &self
->titleright
);
1120 g_hash_table_remove(window_map
, &self
->titlebottom
);
1121 g_hash_table_remove(window_map
, &self
->handleleft
);
1122 g_hash_table_remove(window_map
, &self
->handletop
);
1123 g_hash_table_remove(window_map
, &self
->handleright
);
1124 g_hash_table_remove(window_map
, &self
->handlebottom
);
1125 g_hash_table_remove(window_map
, &self
->lgripleft
);
1126 g_hash_table_remove(window_map
, &self
->lgriptop
);
1127 g_hash_table_remove(window_map
, &self
->lgripbottom
);
1128 g_hash_table_remove(window_map
, &self
->rgripright
);
1129 g_hash_table_remove(window_map
, &self
->rgriptop
);
1130 g_hash_table_remove(window_map
, &self
->rgripbottom
);
1132 obt_main_loop_timeout_remove_data(ob_main_loop
, flash_timeout
, self
, TRUE
);
1135 /* is there anything present between us and the label? */
1136 static gboolean
is_button_present(ObFrame
*self
, const gchar
*lc
, gint dir
) {
1137 for (; *lc
!= '\0' && lc
>= config_title_layout
; lc
+= dir
) {
1138 if (*lc
== ' ') continue; /* it was invalid */
1139 if (*lc
== 'N' && self
->decorations
& OB_FRAME_DECOR_ICON
)
1141 if (*lc
== 'D' && self
->decorations
& OB_FRAME_DECOR_ALLDESKTOPS
)
1143 if (*lc
== 'S' && self
->decorations
& OB_FRAME_DECOR_SHADE
)
1145 if (*lc
== 'I' && self
->decorations
& OB_FRAME_DECOR_ICONIFY
)
1147 if (*lc
== 'M' && self
->decorations
& OB_FRAME_DECOR_MAXIMIZE
)
1149 if (*lc
== 'C' && self
->decorations
& OB_FRAME_DECOR_CLOSE
)
1151 if (*lc
== 'L') return FALSE
;
1156 static void layout_title(ObFrame
*self
)
1161 const gint bwidth
= ob_rr_theme
->button_size
+ ob_rr_theme
->paddingx
+ 1;
1162 /* position of the left most button */
1163 const gint left
= ob_rr_theme
->paddingx
+ 1;
1164 /* position of the right most button */
1165 const gint right
= self
->width
;
1167 /* turn them all off */
1168 self
->icon_on
= self
->desk_on
= self
->shade_on
= self
->iconify_on
=
1169 self
->max_on
= self
->close_on
= self
->label_on
= FALSE
;
1170 self
->label_width
= self
->width
- (ob_rr_theme
->paddingx
+ 1) * 2;
1171 self
->leftmost
= self
->rightmost
= OB_FRAME_CONTEXT_NONE
;
1173 /* figure out what's being show, find each element's position, and the
1176 do the ones before the label, then after the label,
1177 i will be +1 the first time through when working to the left,
1178 and -1 the second time through when working to the right */
1179 for (i
= 1; i
>= -1; i
-=2) {
1181 ObFrameContext
*firstcon
;
1185 lc
= config_title_layout
;
1186 firstcon
= &self
->leftmost
;
1189 lc
= config_title_layout
+ strlen(config_title_layout
)-1;
1190 firstcon
= &self
->rightmost
;
1193 /* stop at the end of the string (or the label, which calls break) */
1194 for (; *lc
!= '\0' && lc
>= config_title_layout
; lc
+=i
) {
1197 self
->label_on
= TRUE
;
1200 break; /* break the for loop, do other side of label */
1201 } else if (*lc
== 'N') {
1202 if (firstcon
) *firstcon
= OB_FRAME_CONTEXT_ICON
;
1203 if ((self
->icon_on
= is_button_present(self
, lc
, i
))) {
1204 /* icon is bigger than buttons */
1205 self
->label_width
-= bwidth
+ 2;
1206 if (i
> 0) self
->icon_x
= x
;
1207 x
+= i
* (bwidth
+ 2);
1208 if (i
< 0) self
->icon_x
= x
;
1210 } else if (*lc
== 'D') {
1211 if (firstcon
) *firstcon
= OB_FRAME_CONTEXT_ALLDESKTOPS
;
1212 if ((self
->desk_on
= is_button_present(self
, lc
, i
))) {
1213 self
->label_width
-= bwidth
;
1214 if (i
> 0) self
->desk_x
= x
;
1216 if (i
< 0) self
->desk_x
= x
;
1218 } else if (*lc
== 'S') {
1219 if (firstcon
) *firstcon
= OB_FRAME_CONTEXT_SHADE
;
1220 if ((self
->shade_on
= is_button_present(self
, lc
, i
))) {
1221 self
->label_width
-= bwidth
;
1222 if (i
> 0) self
->shade_x
= x
;
1224 if (i
< 0) self
->shade_x
= x
;
1226 } else if (*lc
== 'I') {
1227 if (firstcon
) *firstcon
= OB_FRAME_CONTEXT_ICONIFY
;
1228 if ((self
->iconify_on
= is_button_present(self
, lc
, i
))) {
1229 self
->label_width
-= bwidth
;
1230 if (i
> 0) self
->iconify_x
= x
;
1232 if (i
< 0) self
->iconify_x
= x
;
1234 } else if (*lc
== 'M') {
1235 if (firstcon
) *firstcon
= OB_FRAME_CONTEXT_MAXIMIZE
;
1236 if ((self
->max_on
= is_button_present(self
, lc
, i
))) {
1237 self
->label_width
-= bwidth
;
1238 if (i
> 0) self
->max_x
= x
;
1240 if (i
< 0) self
->max_x
= x
;
1242 } else if (*lc
== 'C') {
1243 if (firstcon
) *firstcon
= OB_FRAME_CONTEXT_CLOSE
;
1244 if ((self
->close_on
= is_button_present(self
, lc
, i
))) {
1245 self
->label_width
-= bwidth
;
1246 if (i
> 0) self
->close_x
= x
;
1248 if (i
< 0) self
->close_x
= x
;
1251 continue; /* don't set firstcon */
1256 /* position and map the elements */
1257 if (self
->icon_on
) {
1258 XMapWindow(obt_display
, self
->icon
);
1259 XMoveWindow(obt_display
, self
->icon
, self
->icon_x
,
1260 ob_rr_theme
->paddingy
);
1262 XUnmapWindow(obt_display
, self
->icon
);
1264 if (self
->desk_on
) {
1265 XMapWindow(obt_display
, self
->desk
);
1266 XMoveWindow(obt_display
, self
->desk
, self
->desk_x
,
1267 ob_rr_theme
->paddingy
+ 1);
1269 XUnmapWindow(obt_display
, self
->desk
);
1271 if (self
->shade_on
) {
1272 XMapWindow(obt_display
, self
->shade
);
1273 XMoveWindow(obt_display
, self
->shade
, self
->shade_x
,
1274 ob_rr_theme
->paddingy
+ 1);
1276 XUnmapWindow(obt_display
, self
->shade
);
1278 if (self
->iconify_on
) {
1279 XMapWindow(obt_display
, self
->iconify
);
1280 XMoveWindow(obt_display
, self
->iconify
, self
->iconify_x
,
1281 ob_rr_theme
->paddingy
+ 1);
1283 XUnmapWindow(obt_display
, self
->iconify
);
1286 XMapWindow(obt_display
, self
->max
);
1287 XMoveWindow(obt_display
, self
->max
, self
->max_x
,
1288 ob_rr_theme
->paddingy
+ 1);
1290 XUnmapWindow(obt_display
, self
->max
);
1292 if (self
->close_on
) {
1293 XMapWindow(obt_display
, self
->close
);
1294 XMoveWindow(obt_display
, self
->close
, self
->close_x
,
1295 ob_rr_theme
->paddingy
+ 1);
1297 XUnmapWindow(obt_display
, self
->close
);
1299 if (self
->label_on
) {
1300 self
->label_width
= MAX(1, self
->label_width
); /* no lower than 1 */
1301 XMapWindow(obt_display
, self
->label
);
1302 XMoveWindow(obt_display
, self
->label
, self
->label_x
,
1303 ob_rr_theme
->paddingy
);
1305 XUnmapWindow(obt_display
, self
->label
);
1308 ObFrameContext
frame_context_from_string(const gchar
*name
)
1310 if (!g_ascii_strcasecmp("Desktop", name
))
1311 return OB_FRAME_CONTEXT_DESKTOP
;
1312 else if (!g_ascii_strcasecmp("Root", name
))
1313 return OB_FRAME_CONTEXT_ROOT
;
1314 else if (!g_ascii_strcasecmp("Client", name
))
1315 return OB_FRAME_CONTEXT_CLIENT
;
1316 else if (!g_ascii_strcasecmp("Titlebar", name
))
1317 return OB_FRAME_CONTEXT_TITLEBAR
;
1318 else if (!g_ascii_strcasecmp("Frame", name
))
1319 return OB_FRAME_CONTEXT_FRAME
;
1320 else if (!g_ascii_strcasecmp("TLCorner", name
))
1321 return OB_FRAME_CONTEXT_TLCORNER
;
1322 else if (!g_ascii_strcasecmp("TRCorner", name
))
1323 return OB_FRAME_CONTEXT_TRCORNER
;
1324 else if (!g_ascii_strcasecmp("BLCorner", name
))
1325 return OB_FRAME_CONTEXT_BLCORNER
;
1326 else if (!g_ascii_strcasecmp("BRCorner", name
))
1327 return OB_FRAME_CONTEXT_BRCORNER
;
1328 else if (!g_ascii_strcasecmp("Top", name
))
1329 return OB_FRAME_CONTEXT_TOP
;
1330 else if (!g_ascii_strcasecmp("Bottom", name
))
1331 return OB_FRAME_CONTEXT_BOTTOM
;
1332 else if (!g_ascii_strcasecmp("Left", name
))
1333 return OB_FRAME_CONTEXT_LEFT
;
1334 else if (!g_ascii_strcasecmp("Right", name
))
1335 return OB_FRAME_CONTEXT_RIGHT
;
1336 else if (!g_ascii_strcasecmp("Maximize", name
))
1337 return OB_FRAME_CONTEXT_MAXIMIZE
;
1338 else if (!g_ascii_strcasecmp("AllDesktops", name
))
1339 return OB_FRAME_CONTEXT_ALLDESKTOPS
;
1340 else if (!g_ascii_strcasecmp("Shade", name
))
1341 return OB_FRAME_CONTEXT_SHADE
;
1342 else if (!g_ascii_strcasecmp("Iconify", name
))
1343 return OB_FRAME_CONTEXT_ICONIFY
;
1344 else if (!g_ascii_strcasecmp("Icon", name
))
1345 return OB_FRAME_CONTEXT_ICON
;
1346 else if (!g_ascii_strcasecmp("Close", name
))
1347 return OB_FRAME_CONTEXT_CLOSE
;
1348 else if (!g_ascii_strcasecmp("MoveResize", name
))
1349 return OB_FRAME_CONTEXT_MOVE_RESIZE
;
1350 return OB_FRAME_CONTEXT_NONE
;
1353 ObFrameContext
frame_context(ObClient
*client
, Window win
, gint x
, gint y
)
1357 if (moveresize_in_progress
)
1358 return OB_FRAME_CONTEXT_MOVE_RESIZE
;
1360 if (win
== RootWindow(obt_display
, ob_screen
))
1361 return OB_FRAME_CONTEXT_ROOT
;
1362 if (client
== NULL
) return OB_FRAME_CONTEXT_NONE
;
1363 if (win
== client
->window
) {
1364 /* conceptually, this is the desktop, as far as users are
1366 if (client
->type
== OB_CLIENT_TYPE_DESKTOP
)
1367 return OB_FRAME_CONTEXT_DESKTOP
;
1368 return OB_FRAME_CONTEXT_CLIENT
;
1371 self
= client
->frame
;
1373 /* when the user clicks in the corners of the titlebar and the client
1374 is fully maximized, then treat it like they clicked in the
1375 button that is there */
1376 if (self
->max_horz
&& self
->max_vert
&&
1377 (win
== self
->title
|| win
== self
->titletop
||
1378 win
== self
->titleleft
|| win
== self
->titletopleft
||
1379 win
== self
->titleright
|| win
== self
->titletopright
))
1381 /* get the mouse coords in reference to the whole frame */
1385 /* these windows are down a border width from the top of the frame */
1386 if (win
== self
->title
||
1387 win
== self
->titleleft
|| win
== self
->titleright
)
1390 /* title is a border width in from the edge */
1391 if (win
== self
->title
)
1393 /* titletop is a bit to the right */
1394 else if (win
== self
->titletop
)
1395 fx
+= ob_rr_theme
->grip_width
+ self
->bwidth
;
1396 /* titletopright is way to the right edge */
1397 else if (win
== self
->titletopright
)
1398 fx
+= self
->area
.width
- (ob_rr_theme
->grip_width
+ self
->bwidth
);
1399 /* titleright is even more way to the right edge */
1400 else if (win
== self
->titleright
)
1401 fx
+= self
->area
.width
- self
->bwidth
;
1403 /* figure out if we're over the area that should be considered a
1405 if (fy
< self
->bwidth
+ ob_rr_theme
->paddingy
+ 1 +
1406 ob_rr_theme
->button_size
)
1408 if (fx
< (self
->bwidth
+ ob_rr_theme
->paddingx
+ 1 +
1409 ob_rr_theme
->button_size
))
1411 if (self
->leftmost
!= OB_FRAME_CONTEXT_NONE
)
1412 return self
->leftmost
;
1414 else if (fx
>= (self
->area
.width
-
1415 (self
->bwidth
+ ob_rr_theme
->paddingx
+ 1 +
1416 ob_rr_theme
->button_size
)))
1418 if (self
->rightmost
!= OB_FRAME_CONTEXT_NONE
)
1419 return self
->rightmost
;
1423 /* there is no resizing maximized windows so make them the titlebar
1425 return OB_FRAME_CONTEXT_TITLEBAR
;
1427 else if (self
->max_vert
&&
1428 (win
== self
->titletop
|| win
== self
->topresize
))
1429 /* can't resize vertically when max vert */
1430 return OB_FRAME_CONTEXT_TITLEBAR
;
1431 else if (self
->shaded
&&
1432 (win
== self
->titletop
|| win
== self
->topresize
))
1433 /* can't resize vertically when shaded */
1434 return OB_FRAME_CONTEXT_TITLEBAR
;
1436 if (win
== self
->window
) return OB_FRAME_CONTEXT_FRAME
;
1437 if (win
== self
->label
) return OB_FRAME_CONTEXT_TITLEBAR
;
1438 if (win
== self
->handle
) return OB_FRAME_CONTEXT_BOTTOM
;
1439 if (win
== self
->handletop
) return OB_FRAME_CONTEXT_BOTTOM
;
1440 if (win
== self
->handlebottom
) return OB_FRAME_CONTEXT_BOTTOM
;
1441 if (win
== self
->handleleft
) return OB_FRAME_CONTEXT_BLCORNER
;
1442 if (win
== self
->lgrip
) return OB_FRAME_CONTEXT_BLCORNER
;
1443 if (win
== self
->lgripleft
) return OB_FRAME_CONTEXT_BLCORNER
;
1444 if (win
== self
->lgriptop
) return OB_FRAME_CONTEXT_BLCORNER
;
1445 if (win
== self
->lgripbottom
) return OB_FRAME_CONTEXT_BLCORNER
;
1446 if (win
== self
->handleright
) return OB_FRAME_CONTEXT_BRCORNER
;
1447 if (win
== self
->rgrip
) return OB_FRAME_CONTEXT_BRCORNER
;
1448 if (win
== self
->rgripright
) return OB_FRAME_CONTEXT_BRCORNER
;
1449 if (win
== self
->rgriptop
) return OB_FRAME_CONTEXT_BRCORNER
;
1450 if (win
== self
->rgripbottom
) return OB_FRAME_CONTEXT_BRCORNER
;
1451 if (win
== self
->title
) return OB_FRAME_CONTEXT_TITLEBAR
;
1452 if (win
== self
->titlebottom
) return OB_FRAME_CONTEXT_TITLEBAR
;
1453 if (win
== self
->titleleft
) return OB_FRAME_CONTEXT_TLCORNER
;
1454 if (win
== self
->titletopleft
) return OB_FRAME_CONTEXT_TLCORNER
;
1455 if (win
== self
->titleright
) return OB_FRAME_CONTEXT_TRCORNER
;
1456 if (win
== self
->titletopright
) return OB_FRAME_CONTEXT_TRCORNER
;
1457 if (win
== self
->titletop
) return OB_FRAME_CONTEXT_TOP
;
1458 if (win
== self
->topresize
) return OB_FRAME_CONTEXT_TOP
;
1459 if (win
== self
->tltresize
) return OB_FRAME_CONTEXT_TLCORNER
;
1460 if (win
== self
->tllresize
) return OB_FRAME_CONTEXT_TLCORNER
;
1461 if (win
== self
->trtresize
) return OB_FRAME_CONTEXT_TRCORNER
;
1462 if (win
== self
->trrresize
) return OB_FRAME_CONTEXT_TRCORNER
;
1463 if (win
== self
->left
) return OB_FRAME_CONTEXT_LEFT
;
1464 if (win
== self
->right
) return OB_FRAME_CONTEXT_RIGHT
;
1465 if (win
== self
->innertop
) return OB_FRAME_CONTEXT_TITLEBAR
;
1466 if (win
== self
->innerleft
) return OB_FRAME_CONTEXT_LEFT
;
1467 if (win
== self
->innerbottom
) return OB_FRAME_CONTEXT_BOTTOM
;
1468 if (win
== self
->innerright
) return OB_FRAME_CONTEXT_RIGHT
;
1469 if (win
== self
->innerbll
) return OB_FRAME_CONTEXT_BLCORNER
;
1470 if (win
== self
->innerblb
) return OB_FRAME_CONTEXT_BLCORNER
;
1471 if (win
== self
->innerbrr
) return OB_FRAME_CONTEXT_BRCORNER
;
1472 if (win
== self
->innerbrb
) return OB_FRAME_CONTEXT_BRCORNER
;
1473 if (win
== self
->max
) return OB_FRAME_CONTEXT_MAXIMIZE
;
1474 if (win
== self
->iconify
) return OB_FRAME_CONTEXT_ICONIFY
;
1475 if (win
== self
->close
) return OB_FRAME_CONTEXT_CLOSE
;
1476 if (win
== self
->icon
) return OB_FRAME_CONTEXT_ICON
;
1477 if (win
== self
->desk
) return OB_FRAME_CONTEXT_ALLDESKTOPS
;
1478 if (win
== self
->shade
) return OB_FRAME_CONTEXT_SHADE
;
1480 return OB_FRAME_CONTEXT_NONE
;
1483 void frame_client_gravity(ObFrame
*self
, gint
*x
, gint
*y
)
1486 switch (self
->client
->gravity
) {
1488 case NorthWestGravity
:
1489 case SouthWestGravity
:
1496 /* the middle of the client will be the middle of the frame */
1497 *x
-= (self
->size
.right
- self
->size
.left
) / 2;
1500 case NorthEastGravity
:
1501 case SouthEastGravity
:
1503 /* the right side of the client will be the right side of the frame */
1504 *x
-= self
->size
.right
+ self
->size
.left
-
1505 self
->client
->border_width
* 2;
1510 /* the client's position won't move */
1511 *x
-= self
->size
.left
- self
->client
->border_width
;
1516 switch (self
->client
->gravity
) {
1518 case NorthWestGravity
:
1519 case NorthEastGravity
:
1526 /* the middle of the client will be the middle of the frame */
1527 *y
-= (self
->size
.bottom
- self
->size
.top
) / 2;
1530 case SouthWestGravity
:
1531 case SouthEastGravity
:
1533 /* the bottom of the client will be the bottom of the frame */
1534 *y
-= self
->size
.bottom
+ self
->size
.top
-
1535 self
->client
->border_width
* 2;
1540 /* the client's position won't move */
1541 *y
-= self
->size
.top
- self
->client
->border_width
;
1546 void frame_frame_gravity(ObFrame
*self
, gint
*x
, gint
*y
)
1549 switch (self
->client
->gravity
) {
1551 case NorthWestGravity
:
1553 case SouthWestGravity
:
1558 /* the middle of the client will be the middle of the frame */
1559 *x
+= (self
->size
.right
- self
->size
.left
) / 2;
1561 case NorthEastGravity
:
1563 case SouthEastGravity
:
1564 /* the right side of the client will be the right side of the frame */
1565 *x
+= self
->size
.right
+ self
->size
.left
-
1566 self
->client
->border_width
* 2;
1570 /* the client's position won't move */
1571 *x
+= self
->size
.left
- self
->client
->border_width
;
1576 switch (self
->client
->gravity
) {
1578 case NorthWestGravity
:
1580 case NorthEastGravity
:
1585 /* the middle of the client will be the middle of the frame */
1586 *y
+= (self
->size
.bottom
- self
->size
.top
) / 2;
1588 case SouthWestGravity
:
1590 case SouthEastGravity
:
1591 /* the bottom of the client will be the bottom of the frame */
1592 *y
+= self
->size
.bottom
+ self
->size
.top
-
1593 self
->client
->border_width
* 2;
1597 /* the client's position won't move */
1598 *y
+= self
->size
.top
- self
->client
->border_width
;
1603 void frame_rect_to_frame(ObFrame
*self
, Rect
*r
)
1605 r
->width
+= self
->size
.left
+ self
->size
.right
;
1606 r
->height
+= self
->size
.top
+ self
->size
.bottom
;
1607 frame_client_gravity(self
, &r
->x
, &r
->y
);
1610 void frame_rect_to_client(ObFrame
*self
, Rect
*r
)
1612 r
->width
-= self
->size
.left
+ self
->size
.right
;
1613 r
->height
-= self
->size
.top
+ self
->size
.bottom
;
1614 frame_frame_gravity(self
, &r
->x
, &r
->y
);
1617 static void flash_done(gpointer data
)
1619 ObFrame
*self
= data
;
1621 if (self
->focused
!= self
->flash_on
)
1622 frame_adjust_focus(self
, self
->focused
);
1625 static gboolean
flash_timeout(gpointer data
)
1627 ObFrame
*self
= data
;
1630 g_get_current_time(&now
);
1631 if (now
.tv_sec
> self
->flash_end
.tv_sec
||
1632 (now
.tv_sec
== self
->flash_end
.tv_sec
&&
1633 now
.tv_usec
>= self
->flash_end
.tv_usec
))
1634 self
->flashing
= FALSE
;
1636 if (!self
->flashing
)
1637 return FALSE
; /* we are done */
1639 self
->flash_on
= !self
->flash_on
;
1640 if (!self
->focused
) {
1641 frame_adjust_focus(self
, self
->flash_on
);
1642 self
->focused
= FALSE
;
1645 return TRUE
; /* go again */
1648 void frame_flash_start(ObFrame
*self
)
1650 self
->flash_on
= self
->focused
;
1652 if (!self
->flashing
)
1653 obt_main_loop_timeout_add(ob_main_loop
,
1654 G_USEC_PER_SEC
* 0.6,
1659 g_get_current_time(&self
->flash_end
);
1660 g_time_val_add(&self
->flash_end
, G_USEC_PER_SEC
* 5);
1662 self
->flashing
= TRUE
;
1665 void frame_flash_stop(ObFrame
*self
)
1667 self
->flashing
= FALSE
;
1670 static gulong
frame_animate_iconify_time_left(ObFrame
*self
,
1671 const GTimeVal
*now
)
1674 sec
= self
->iconify_animation_end
.tv_sec
- now
->tv_sec
;
1675 usec
= self
->iconify_animation_end
.tv_usec
- now
->tv_usec
;
1677 usec
+= G_USEC_PER_SEC
;
1680 /* no negative values */
1681 return MAX(sec
* G_USEC_PER_SEC
+ usec
, 0);
1684 static gboolean
frame_animate_iconify(gpointer p
)
1688 gint iconx
, icony
, iconw
;
1691 gboolean iconifying
;
1693 if (self
->client
->icon_geometry
.width
== 0) {
1694 /* there is no icon geometry set so just go straight down */
1695 Rect
*a
= screen_physical_area_monitor
1696 (screen_find_monitor(&self
->area
));
1697 iconx
= self
->area
.x
+ self
->area
.width
/ 2 + 32;
1698 icony
= a
->y
+ a
->width
;
1702 iconx
= self
->client
->icon_geometry
.x
;
1703 icony
= self
->client
->icon_geometry
.y
;
1704 iconw
= self
->client
->icon_geometry
.width
;
1707 iconifying
= self
->iconify_animation_going
> 0;
1709 /* how far do we have left to go ? */
1710 g_get_current_time(&now
);
1711 time
= frame_animate_iconify_time_left(self
, &now
);
1713 if (time
== 0 || iconifying
) {
1714 /* start where the frame is supposed to be */
1717 w
= self
->area
.width
;
1718 h
= self
->area
.height
;
1720 /* start at the icon */
1724 h
= self
->size
.top
; /* just the titlebar */
1731 dx
= self
->area
.x
- iconx
;
1732 dy
= self
->area
.y
- icony
;
1733 dw
= self
->area
.width
- self
->bwidth
* 2 - iconw
;
1734 /* if restoring, we move in the opposite direction */
1735 if (!iconifying
) { dx
= -dx
; dy
= -dy
; dw
= -dw
; }
1737 elapsed
= FRAME_ANIMATE_ICONIFY_TIME
- time
;
1738 x
= x
- (dx
* elapsed
) / FRAME_ANIMATE_ICONIFY_TIME
;
1739 y
= y
- (dy
* elapsed
) / FRAME_ANIMATE_ICONIFY_TIME
;
1740 w
= w
- (dw
* elapsed
) / FRAME_ANIMATE_ICONIFY_TIME
;
1741 h
= self
->size
.top
; /* just the titlebar */
1745 frame_end_iconify_animation(self
);
1747 XMoveResizeWindow(obt_display
, self
->window
, x
, y
, w
, h
);
1748 XFlush(obt_display
);
1751 return time
> 0; /* repeat until we're out of time */
1754 void frame_end_iconify_animation(ObFrame
*self
)
1756 /* see if there is an animation going */
1757 if (self
->iconify_animation_going
== 0) return;
1760 XUnmapWindow(obt_display
, self
->window
);
1762 /* Send a ConfigureNotify when the animation is done, this fixes
1763 KDE's pager showing the window in the wrong place. since the
1764 window is mapped at a different location and is then moved, we
1765 need to send the synthetic configurenotify, since apps may have
1766 read the position when the client mapped, apparently. */
1767 client_reconfigure(self
->client
, TRUE
);
1770 /* we're not animating any more ! */
1771 self
->iconify_animation_going
= 0;
1773 XMoveResizeWindow(obt_display
, self
->window
,
1774 self
->area
.x
, self
->area
.y
,
1775 self
->area
.width
, self
->area
.height
);
1776 /* we delay re-rendering until after we're done animating */
1777 framerender_frame(self
);
1778 XFlush(obt_display
);
1781 void frame_begin_iconify_animation(ObFrame
*self
, gboolean iconifying
)
1784 gboolean new_anim
= FALSE
;
1785 gboolean set_end
= TRUE
;
1788 /* if there is no titlebar, just don't animate for now
1789 XXX it would be nice tho.. */
1790 if (!(self
->decorations
& OB_FRAME_DECOR_TITLEBAR
))
1793 /* get the current time */
1794 g_get_current_time(&now
);
1796 /* get how long until the end */
1797 time
= FRAME_ANIMATE_ICONIFY_TIME
;
1798 if (self
->iconify_animation_going
) {
1799 if (!!iconifying
!= (self
->iconify_animation_going
> 0)) {
1800 /* animation was already going on in the opposite direction */
1801 time
= time
- frame_animate_iconify_time_left(self
, &now
);
1803 /* animation was already going in the same direction */
1807 self
->iconify_animation_going
= iconifying
? 1 : -1;
1809 /* set the ending time */
1811 self
->iconify_animation_end
.tv_sec
= now
.tv_sec
;
1812 self
->iconify_animation_end
.tv_usec
= now
.tv_usec
;
1813 g_time_val_add(&self
->iconify_animation_end
, time
);
1817 obt_main_loop_timeout_remove_data(ob_main_loop
, frame_animate_iconify
,
1819 obt_main_loop_timeout_add(ob_main_loop
,
1820 FRAME_ANIMATE_ICONIFY_STEP_TIME
,
1821 frame_animate_iconify
, self
,
1822 g_direct_equal
, NULL
);
1824 /* do the first step */
1825 frame_animate_iconify(self
);
1827 /* show it during the animation even if it is not "visible" */
1829 XMapWindow(obt_display
, self
->window
);