+
+static gboolean frame_animate_iconify(gpointer p)
+{
+ ObFrame *self = p;
+ gint step = self->iconify_animation_step;
+ gint absstep, nextstep;
+ gint x, y, w, h;
+ gint iconx, icony, iconw;
+
+ if (self->client->icon_geometry.width == 0) {
+ /* there is no icon geometry set so just go straight down */
+ Rect *a = screen_physical_area();
+ iconx = self->area.x + self->area.width / 2 + 32;
+ icony = a->y + a->width;
+ iconw = 64;
+ } else {
+ iconx = self->client->icon_geometry.x;
+ icony = self->client->icon_geometry.y;
+ iconw = self->client->icon_geometry.width;
+ }
+
+ if (step >= 0)
+ absstep = FRAME_ANIMATE_ICONIFY_STEPS - step + 1;
+ else
+ absstep = FRAME_ANIMATE_ICONIFY_STEPS + step + 1;
+
+ if (step >= 0) {
+ /* start where the frame is supposed to be */
+ x = self->area.x;
+ y = self->area.y;
+ w = self->area.width - self->bwidth * 2;
+ h = self->area.height - self->bwidth * 2;
+ } else {
+ /* start at the icon */
+ x = iconx;
+ y = icony;
+ w = iconw;
+ h = self->innersize.top; /* just the titlebar */
+ }
+
+ if (step != 0) {
+ gint dx, dy, dw;
+ dx = self->area.x - iconx;
+ dy = self->area.y - icony;
+ dw = self->area.width - self->bwidth * 2 - iconw;
+ /* if restoring, we move in the opposite direction */
+ if (step < 0) { dx = -dx; dy = -dy; dw = -dw; }
+ x = x - dx / FRAME_ANIMATE_ICONIFY_STEPS * absstep;
+ y = y - dy / FRAME_ANIMATE_ICONIFY_STEPS * absstep;
+ w = w - dw / FRAME_ANIMATE_ICONIFY_STEPS * absstep;
+ h = self->innersize.top; /* just the titlebar */
+ }
+
+ /* move one step forward */
+ self->iconify_animation_step = step + (step < 0 ? 1 : (step > 0 ? -1 : 0));
+
+ /* call the callback when it's done */
+ if (step == 0 && self->iconify_animation_cb)
+ self->iconify_animation_cb(self->iconify_animation_data);
+
+ /* move to the next spot (after the callback for the animation ending) */
+ XMoveResizeWindow(ob_display, self->window, x, y, w, h);
+ XFlush(ob_display);
+
+ return step != 0; /* repeat until step is 0 */
+}
+
+void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying,
+ ObFrameIconifyAnimateFunc callback,
+ gpointer data)
+{
+ if (iconifying) {
+ if (self->iconify_animation_step == 0) /* wasnt doing anything */
+ self->iconify_animation_step = FRAME_ANIMATE_ICONIFY_STEPS;
+ else if (self->iconify_animation_step < 0) /* was deiconifying */
+ self->iconify_animation_step =
+ FRAME_ANIMATE_ICONIFY_STEPS + self->iconify_animation_step;
+ } else {
+ if (self->iconify_animation_step == 0) /* wasnt doing anything */
+ self->iconify_animation_step = -FRAME_ANIMATE_ICONIFY_STEPS;
+ else if (self->iconify_animation_step > 0) /* was iconifying */
+ self->iconify_animation_step =
+ -FRAME_ANIMATE_ICONIFY_STEPS + self->iconify_animation_step;
+ }
+ self->iconify_animation_cb = callback;
+ self->iconify_animation_data = data;
+
+ if (self->iconify_animation_step == FRAME_ANIMATE_ICONIFY_STEPS ||
+ self->iconify_animation_step == -FRAME_ANIMATE_ICONIFY_STEPS)
+ {
+ ob_main_loop_timeout_remove(ob_main_loop, frame_animate_iconify);
+ ob_main_loop_timeout_add(ob_main_loop,
+ FRAME_ANIMATE_ICONIFY_TIME /
+ FRAME_ANIMATE_ICONIFY_STEPS,
+ frame_animate_iconify, self,
+ g_direct_equal, NULL);
+ /* do the first step */
+ frame_animate_iconify(self);
+ }
+}