X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fframe.c;h=be4e688dff71c89ae6e7ec79f09467292ee3e73d;hb=370b5ba27d77c3eecb984f2efa64a4263d454112;hp=a07c60e46f9c4333f99e8d1765bc933ba5e483f3;hpb=cf67851d6d36eb45ae722ad017ecaf91ba4c21fd;p=chaz%2Fopenbox diff --git a/openbox/frame.c b/openbox/frame.c index a07c60e4..be4e688d 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -27,6 +27,7 @@ #include "mainloop.h" #include "focus.h" #include "moveresize.h" +#include "screen.h" #include "render/theme.h" #define PLATE_EVENTMASK (SubstructureRedirectMask | FocusChangeMask) @@ -41,8 +42,8 @@ from the frame. */ #define INNER_EVENTMASK (ButtonPressMask) -#define FRAME_ANIMATE_ICONIFY_STEPS 20 -#define FRAME_ANIMATE_ICONIFY_TIME (G_USEC_PER_SEC/5) +#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */ +#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */ #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \ f->cbwidth_y) @@ -257,11 +258,12 @@ void frame_hide(ObFrame *self) { if (self->visible) { self->visible = FALSE; - self->client->ignore_unmaps += 1; + if (!frame_iconify_animating(self)) + XUnmapWindow(ob_display, self->window); /* we unmap the client itself so that we can get MapRequest events, and because the ICCCM tells us to! */ - XUnmapWindow(ob_display, self->window); XUnmapWindow(ob_display, self->client->window); + self->client->ignore_unmaps += 1; } } @@ -480,17 +482,18 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->client->area.height); } - if (!fake && !self->iconify_animation_step) { - /* move and resize the top level frame. - shading can change without being moved or resized. - - but don't do this during an iconify animation. it will be - reflected afterwards. - */ - XMoveResizeWindow(ob_display, self->window, - self->area.x, self->area.y, - self->area.width - self->bwidth * 2, - self->area.height - self->bwidth * 2); + if (!fake) { + if (!frame_iconify_animating(self)) + /* move and resize the top level frame. + shading can change without being moved or resized. + + but don't do this during an iconify animation. it will be + reflected afterwards. + */ + XMoveResizeWindow(ob_display, self->window, + self->area.x, self->area.y, + self->area.width - self->bwidth * 2, + self->area.height - self->bwidth * 2); if (resized) { framerender_frame(self); @@ -505,6 +508,8 @@ void frame_adjust_area(ObFrame *self, gboolean moved, vals[3] = self->size.bottom; PROP_SETA32(self->client->window, net_frame_extents, cardinal, vals, 4); + PROP_SETA32(self->client->window, kde_net_wm_frame_strut, + cardinal, vals, 4); } /* if this occurs while we are focus cycling, the indicator needs to @@ -838,10 +843,6 @@ ObFrameContext frame_context(ObClient *client, Window win) if (win == RootWindow(ob_display, ob_screen)) return OB_FRAME_CONTEXT_DESKTOP; if (client == NULL) return OB_FRAME_CONTEXT_NONE; - - self = client->frame; - if (self->iconify_animation_step) return OB_FRAME_CONTEXT_NONE; - if (win == client->window) { /* conceptually, this is the desktop, as far as users are concerned */ @@ -850,6 +851,7 @@ ObFrameContext frame_context(ObClient *client, Window win) return OB_FRAME_CONTEXT_CLIENT; } + self = client->frame; if (win == self->inner || win == self->plate) { /* conceptually, this is the desktop, as far as users are concerned */ @@ -1035,13 +1037,28 @@ void frame_flash_stop(ObFrame *self) self->flashing = FALSE; } +static gulong frame_animate_iconify_time_left(ObFrame *self, + const GTimeVal *now) +{ + glong sec, usec; + sec = self->iconify_animation_end.tv_sec - now->tv_sec; + usec = self->iconify_animation_end.tv_usec - now->tv_usec; + if (usec < 0) { + usec += G_USEC_PER_SEC; + sec--; + } + /* no negative values */ + return MAX(sec * G_USEC_PER_SEC + usec, 0); +} + 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; + GTimeVal now; + gulong time; + gboolean iconifying; if (self->client->icon_geometry.width == 0) { /* there is no icon geometry set so just go straight down */ @@ -1055,12 +1072,13 @@ static gboolean frame_animate_iconify(gpointer p) iconw = self->client->icon_geometry.width; } - if (step >= 0) - absstep = FRAME_ANIMATE_ICONIFY_STEPS - step + 1; - else - absstep = FRAME_ANIMATE_ICONIFY_STEPS + step + 1; + iconifying = self->iconify_animation_going > 0; - if (step >= 0) { + /* how far do we have left to go ? */ + g_get_current_time(&now); + time = frame_animate_iconify_time_left(self, &now); + + if (time == 0 || iconifying) { /* start where the frame is supposed to be */ x = self->area.x; y = self->area.y; @@ -1074,64 +1092,99 @@ static gboolean frame_animate_iconify(gpointer p) h = self->innersize.top; /* just the titlebar */ } - if (step != 0) { - gint dx, dy, dw; + if (time > 0) { + glong dx, dy, dw; + glong elapsed; + 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; + if (!iconifying) { dx = -dx; dy = -dy; dw = -dw; } + + elapsed = FRAME_ANIMATE_ICONIFY_TIME - time; + x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME; + y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME; + w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME; h = self->innersize.top; /* just the titlebar */ } - /* move one step forward */ - self->iconify_animation_step = step + (step < 0 ? 1 : (step > 0 ? -1 : 0)); + if (time == 0) + frame_end_iconify_animation(self); + else { + XMoveResizeWindow(ob_display, self->window, x, y, w, h); + XFlush(ob_display); + } - /* call the callback when it's done */ - if (step == 0 && self->iconify_animation_cb) - self->iconify_animation_cb(self->iconify_animation_data); + return time > 0; /* repeat until we're out of time */ +} - /* move to the next spot (after the callback for the animation ending) */ - XMoveResizeWindow(ob_display, self->window, x, y, w, h); - XFlush(ob_display); +void frame_end_iconify_animation(ObFrame *self) +{ + /* see if there is an animation going */ + if (self->iconify_animation_going == 0) return; - return step != 0; /* repeat until step is 0 */ + if (!self->visible) + XUnmapWindow(ob_display, self->window); + + /* we're not animating any more ! */ + self->iconify_animation_going = 0; + + XMoveResizeWindow(ob_display, self->window, + self->area.x, self->area.y, + self->area.width - self->bwidth * 2, + self->area.height - self->bwidth * 2); + XFlush(ob_display); } -void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying, - ObFrameIconifyAnimateFunc callback, - gpointer data) +void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying) { - 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; + gulong time; + gboolean new_anim = FALSE; + gboolean set_end = TRUE; + GTimeVal now; + + /* if there is no titlebar, just don't animate for now + XXX it would be nice tho.. */ + if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) + return; + + /* get the current time */ + g_get_current_time(&now); + + /* get how long until the end */ + time = FRAME_ANIMATE_ICONIFY_TIME; + if (self->iconify_animation_going) { + if (!!iconifying != (self->iconify_animation_going > 0)) { + /* animation was already going on in the opposite direction */ + time = time - frame_animate_iconify_time_left(self, &now); + } else + /* animation was already going in the same direction */ + set_end = FALSE; + } else + new_anim = TRUE; + self->iconify_animation_going = iconifying ? 1 : -1; + + /* set the ending time */ + if (set_end) { + self->iconify_animation_end.tv_sec = now.tv_sec; + self->iconify_animation_end.tv_usec = now.tv_usec; + g_time_val_add(&self->iconify_animation_end, time); } - 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) - { + if (new_anim) { ob_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify, self, FALSE); ob_main_loop_timeout_add(ob_main_loop, - FRAME_ANIMATE_ICONIFY_TIME / - FRAME_ANIMATE_ICONIFY_STEPS, + FRAME_ANIMATE_ICONIFY_STEP_TIME, frame_animate_iconify, self, g_direct_equal, NULL); + /* do the first step */ frame_animate_iconify(self); + + /* show it during the animation even if it is not "visible" */ + if (!self->visible) + XMapWindow(ob_display, self->window); } }