2 /* Copyright (C) 1999 Dominik Vogt */
3 /* This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 ** This file supplies routines for moving and resizing windows in an animated
31 /* Continuously moves and resized window win from start geometry (s_?) to end
32 * geometry (e_?). Waits for delay_ms milliseconds after each step except the
33 * last (max. 10 seconds per step). The number of steps is determined by the
34 * steps argument (min. 1 and max. 10000). If the pointer ppctMovement is NULL
35 * the steps are all the same width, if it is given it is interpreted as a
36 * pointer to an array of float percent values. These are used to determine the
37 * distance of each step counted from the start position, i.e. 0.0 means the
38 * start position itself, 50.0 is halfway between start and end position and
39 * 100.0 is the end position. Values smaller than 0.0 or bigger than 100.0 are
40 * allowed too. The do_flush flag determines of all requests are sent to the
41 * X server immediately (True) or not (False). The use_hints detrmines if the
42 * min size and resize hints are used */
44 Display
*dpy
, Window win
,
45 int s_x
, int s_y
, int s_w
, int s_h
,
46 int e_x
, int e_y
, int e_w
, int e_h
,
47 int steps
, int delay_ms
, float *ppctMovement
,
48 Bool do_sync
, Bool use_hints
)
55 int g_h
= 0; /* -Wall fixes :o( */
73 /* max. 10 seconds per step */
76 else if (delay_ms
< 0)
87 /* max. 10000 steps */
92 /* no steps, no animation */
93 if (e_w
== 0 || e_h
== 0)
95 XUnmapWindow(dpy
, win
);
99 XMoveResizeWindow(dpy
, win
, e_x
, e_y
, e_w
, e_h
);
100 XMapWindow(dpy
, win
);
101 XMapSubwindows(dpy
, win
);
110 /* Get the mini (re)size hints and do some check consistency */
111 if (use_hints
&& XGetWMNormalHints(dpy
, win
, &hints
, &dummy
))
113 if (hints
.flags
& PMinSize
)
115 if (hints
.min_width
>= 1 && hints
.min_width
<=
117 min_w
= hints
.min_width
;
118 if (hints
.min_height
>= 1 && hints
.min_height
<=
120 min_h
= hints
.min_height
;
122 if (hints
.flags
& PResizeInc
)
124 if (hints
.width_inc
>= 1 && hints
.width_inc
<=
126 inc_w
= hints
.width_inc
;
127 if (hints
.height_inc
>= 1 && hints
.width_inc
<=
129 inc_h
= hints
.height_inc
;
137 if (s_x
+ s_w
== e_x
+ e_w
)
139 if (s_y
+ s_h
== e_y
+ e_h
)
142 /* animate the window */
143 for (i
= 0; i
<= steps
; i
++)
154 if (ppctMovement
== NULL
)
156 f
= (float)i
/ (float)steps
;
160 f
= ppctMovement
[i
] / (float)steps
;
162 x
= (int)((float)s_x
+ (float)(e_x
- s_x
) * f
);
163 y
= (int)((float)s_y
+ (float)(e_y
- s_y
) * f
);
165 w
= s_w
+ (int)(e_w
- s_w
) * i
/ steps
;
166 h
= s_h
+ (int)(e_h
- s_h
) * i
/ steps
;
168 /* take the resize inc in account */
169 g_w
= w
- ((w
- min_w
) % inc_w
);
171 g_h
= h
- ((h
- min_h
) % inc_h
);
174 /* prevent annoying flickering */
184 if (g_w
< min_w
|| g_h
< min_h
)
186 /* don't show zero width/height windows */
189 XUnmapWindow(dpy
, win
);
195 XMoveResizeWindow(dpy
, win
, x
, y
, g_w
, g_h
);
198 XMapWindow(dpy
, win
);
199 XMapSubwindows(dpy
, win
);
203 /* make sure everything is updated */
206 if (us
&& i
< steps
&& is_mapped
)
208 /* don't sleep after the last step */
213 /* if hints and asked size do not agree try to respect the caller */
214 if (e_w
> 0 && e_h
> 0 && (!is_mapped
|| g_w
!= w
|| g_h
!= w
))
216 XMoveResizeWindow(dpy
, win
, x
, y
, w
, h
);
219 XMapWindow(dpy
, win
);
220 XMapSubwindows(dpy
, win
);
228 /* This function returns the top level ancestor of the window 'child'. It
229 * returns None if an error occurs or if the window is a top level window. */
230 Window
GetTopAncestorWindow(Display
*dpy
, Window child
)
233 Window ancestor
= child
;
234 Window last_child
= child
;
236 unsigned int nchildren
;
241 while (ancestor
!= root
)
243 last_child
= ancestor
;
247 dpy
, last_child
, &root
, &ancestor
, &children
,
258 return (last_child
== child
) ? None
: last_child
;
261 /* Given a parent window this function returns a list of children of the
262 * parent window that have the same size, depth, visual and colormap as the
263 * parent window and that have position +0+0 within the parent. If the 'depth'
264 * argument is non-zero it must match the depth of the window. The 'visualid'
265 * and 'colormap' arguments work just the same. The number of matching
266 * children is returned. The list of children is returned in *children. If this
267 * list is non-NULL, it must be free'd with XFree. If an error occurs or the
268 * parent window does not match the required depth, colormap or visualid, the
269 * function returns -1 and NULL in *children. */
270 int GetEqualSizeChildren(
271 Display
*dpy
, Window parent
, int depth
, VisualID visualid
,
272 Colormap colormap
, Window
**ret_children
)
274 XWindowAttributes pxwa
;
275 XWindowAttributes cxwa
;
278 unsigned int nchildren
;
282 if (!XGetWindowAttributes(dpy
, parent
, &pxwa
))
284 if (!XQueryTree(dpy
, parent
, &JunkW
, &JunkW
, &children
, &nchildren
))
286 if (depth
&& pxwa
.depth
!= depth
)
288 if (visualid
&& XVisualIDFromVisual(pxwa
.visual
) != visualid
)
290 if (colormap
&& pxwa
.colormap
!= colormap
)
293 for (i
= 0, j
= 0; i
< nchildren
; i
++)
295 if (XGetWindowAttributes(dpy
, children
[i
], &cxwa
) &&
298 cxwa
.width
== pxwa
.width
&&
299 cxwa
.height
== pxwa
.height
&&
300 (!depth
|| cxwa
.depth
== depth
) &&
303 XVisualIDFromVisual(cxwa
.visual
) == visualid
) &&
304 cxwa
.class == InputOutput
&&
305 (!colormap
|| cxwa
.colormap
== colormap
))
307 children
[j
++] = children
[i
];
319 *ret_children
= children
;