Skip to content

Commit

Permalink
Implement animations
Browse files Browse the repository at this point in the history
Squashed all the stuff:

init

Update README.md

options

performance

Animation no longer jumps if started in the middle of an animation

Doubled default transition length

Minor bugfix, preformance

Track x and y separately to aviod jumping in mid-animation repositioning

Added video to readme

docs

docs

fixed graphical glitch with non-transparent windows

now animates window scaling too (but only if the window grows)

added options for size transitions

and actually respect the new options..

and actually respect the new options..

added center-spawn option

added center-spawn-screen option

fixed center spawn

added no-scale-down

goofed

remember old windows

remember old windows

docs

fixed shadow

fixed shadow

fixed shadow

fixed shadow

lost no-scale-down due to revert

lost spawn-center due to revert

Fixed yshui#2

fix missing window borders
  • Loading branch information
BlackCapCoder authored and sandsmark committed Jun 25, 2020
1 parent fd6ff82 commit 51fdb8b
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 7 deletions.
5 changes: 5 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,8 @@ static inline void wintype_arr_enable(bool arr[]) {
arr[i] = true;
}
}

/**
* Get current system clock in milliseconds.
*/
int64_t get_time_ms(void);
9 changes: 9 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,15 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
*opt = (struct options){
.backend = BKEND_XRENDER,
.glx_no_stencil = false,
.transition_length = 300,
.transition_pow_x = 1.5,
.transition_pow_y = 1.5,
.transition_pow_w = 1.5,
.transition_pow_h = 1.5,
.size_transition = true,
.no_scale_down = false,
.spawn_center_screen = false,
.spawn_center = true,
.mark_wmwin_focused = false,
.mark_ovredir_focused = false,
.detect_rounded_corners = false,
Expand Down
18 changes: 18 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ typedef struct options {
bool glx_no_stencil;
/// Whether to avoid rebinding pixmap on window damage.
bool glx_no_rebind_pixmap;
/// Length of window transitions
int transition_length;
/// For smoothing on the x-coordinate of window animations
float transition_pow_x;
/// For smoothing on the y-coordinate of window animations
float transition_pow_y;
/// For smoothing on the width of window animations
float transition_pow_w;
/// For smoothing on the height of window animations
float transition_pow_h;
/// Wether to animate on window size change
bool size_transition;
/// Wether to scale new windows in from the center of the screen
bool spawn_center_screen;
/// Wether to scale new windows in from their center
bool spawn_center;
/// Does not animate downscaling
bool no_scale_down;
/// Custom fragment shader for painting windows, as a string.
char *glx_fshader_win_str;
/// Whether to detect rounded corners.
Expand Down
23 changes: 23 additions & 0 deletions src/config_libconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,29 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
// -O (fade_out_step)
if (config_lookup_float(&cfg, "fade-out-step", &dval))
opt->fade_out_step = normalize_d(dval);
// --transition-length
if (config_lookup_int(&cfg, "transition-length", &ival))
opt->transition_length = ival;
// --transition-pow-x
if (config_lookup_float(&cfg, "transition-pow-x", &dval))
opt->transition_pow_x = dval;
// --transition-pow-y
if (config_lookup_float(&cfg, "transition-pow-y", &dval))
opt->transition_pow_y = dval;
// --transition-pow-w
if (config_lookup_float(&cfg, "transition-pow-w", &dval))
opt->transition_pow_w = dval;
// --transition-pow-h
if (config_lookup_float(&cfg, "transition-pow-h", &dval))
opt->transition_pow_h = dval;
// --size-transition
lcfg_lookup_bool(&cfg, "size-transition", &opt->size_transition);
// --spawn-center-screen
lcfg_lookup_bool(&cfg, "spawn-center-screen", &opt->spawn_center_screen);
// --spawn-center
lcfg_lookup_bool(&cfg, "spawn-center", &opt->spawn_center);
// --no-scale-down
lcfg_lookup_bool(&cfg, "no-scale-down", &opt->no_scale_down);
// -r (shadow_radius)
config_lookup_int(&cfg, "shadow-radius", &opt->shadow_radius);
// -o (shadow_opacity)
Expand Down
103 changes: 100 additions & 3 deletions src/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,106 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {

auto mw = (struct managed_win *)w;

float t = get_time_ms();
if (mw->oldX == -10000 && mw->oldY == -10000 && mw->oldW == 0 && mw->oldH == 0) {
if (!mw->isOld) {
/* mw->isOld = true; */

if (ps->o.spawn_center_screen) {
mw->oldX = ps->root_width/2;
mw->oldY = ps->root_height/2;
mw->oldW = 1;
mw->oldH = 1;
} else if (ps->o.spawn_center) {
mw->oldX = ce->x + ce->width/2;
mw->oldY = ce->y + ce->height/2;
mw->oldW = 1;
mw->oldH = 1;
} else {
mw->oldX = ce->x;
mw->oldY = ce->y;
mw->oldW = ce->width;
mw->oldH = ce->height;
}
} else {
mw->oldX = ce->x;
mw->oldY = ce->y;
mw->oldW = ce->width;
mw->oldH = ce->height;
}

mw->newX = ce->x;
mw->newY = ce->y;
mw->newW = ce->width;
mw->newH = ce->height;
mw->moveTimeX = t;
mw->moveTimeY = t;
mw->moveTimeW = t;
mw->moveTimeH = t;
} else {
if (mw->newX == mw->g.x && mw->newY == mw->g.y) {
mw->oldX = mw->g.x;
mw->oldY = mw->g.y;
mw->oldW = mw->g.width;
mw->oldH = mw->g.height;
mw->moveTimeX = t;
mw->moveTimeY = t;
mw->moveTimeW = t;
mw->moveTimeH = t;
}
if (mw->newX != ce->x || mw->newY != ce->y || mw->newW != ce->width || mw->newH != ce->height) {
float moveDx = ((float) t - mw->moveTimeX) / ps->o.transition_length;
float moveDy = ((float) t - mw->moveTimeY) / ps->o.transition_length;
float moveDw = ((float) t - mw->moveTimeW) / ps->o.transition_length;
float moveDh = ((float) t - mw->moveTimeH) / ps->o.transition_length;

if (mw->moveTimeX != 0.0 && moveDx < 1.0 && mw->oldX != mw->newX) {
float oldMoveDx = pow((float) (mw->newX - mw->g.x) / (float) (mw->newX - ce->x), 1 / ps->o.transition_pow_x);
float fakeT = (t - oldMoveDx * (float) ps->o.transition_length);
/* printf("X: %f,%f\n", fakeT, t); */
mw->moveTimeX = isnanf(fakeT)? t : fakeT;
} else {
mw->moveTimeX = t;
}
if (mw->moveTimeY != 0.0 && moveDy < 1.0 && mw->oldY != mw->newY) {
float oldMoveDy = pow((float) (mw->newY - mw->g.y) / (float) (mw->newY - ce->y), 1 / ps->o.transition_pow_y);
float fakeT = (t - oldMoveDy * (float) ps->o.transition_length);
/* printf("Y: %f,%f\n", fakeT, t); */
mw->moveTimeY = isnanf(fakeT)? t : fakeT;
} else {
mw->moveTimeY = t;
}
if (mw->moveTimeW != 0.0 && moveDw < 1.0 && mw->oldW != mw->newW) {
float oldMoveDw = pow((float) (mw->newW - mw->g.width) / (float) (mw->newW - ce->width), 1 / ps->o.transition_pow_w);
float fakeT = (t - oldMoveDw * (float) ps->o.transition_length);
/* printf("Y: %f,%f\n", fakeT, t); */
mw->moveTimeW = isnanf(fakeT)? t : fakeT;
} else {
mw->moveTimeW = t;
}
if (mw->moveTimeH != 0.0 && moveDh < 1.0 && mw->oldH != mw->newH) {
float oldMoveDh = pow((float) (mw->newH - mw->g.height) / (float) (mw->newH - ce->height), 1 / ps->o.transition_pow_h);
float fakeT = (t - oldMoveDh * (float) ps->o.transition_length);
/* printf("Y: %f,%f\n", fakeT, t); */
mw->moveTimeH = isnanf(fakeT)? t : fakeT;
} else {
mw->moveTimeH = t;
}

mw->oldX = mw->newX;
mw->oldY = mw->newY;
mw->oldW = mw->newW;
mw->oldH = mw->newH;
mw->newX = ce->x;
mw->newY = ce->y;
mw->newW = ce->width;
mw->newH = ce->height;

if (ps->o.no_scale_down && mw->newW < mw->oldW) { mw->oldW = mw->newW; }
if (ps->o.no_scale_down && mw->newH < mw->oldH) { mw->oldH = mw->newH; }
}
}

if (mw->state == WSTATE_UNMAPPED || mw->state == WSTATE_UNMAPPING ||
mw->state == WSTATE_DESTROYING) {
// Only restack the window to make sure we can handle future restack
Expand All @@ -218,9 +318,6 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
factor_change = true;
}

mw->g.x = ce->x;
mw->g.y = ce->y;

if (mw->g.width != ce->width || mw->g.height != ce->height ||
mw->g.border_width != ce->border_width) {
log_trace("Window size changed, %dx%d -> %dx%d", mw->g.width,
Expand Down
53 changes: 52 additions & 1 deletion src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static inline void free_xinerama_info(session_t *ps) {
/**
* Get current system clock in milliseconds.
*/
static inline int64_t get_time_ms(void) {
int64_t get_time_ms(void) {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return (int64_t)tp.tv_sec * 1000 + (int64_t)tp.tv_nsec / 1000000;
Expand Down Expand Up @@ -676,6 +676,57 @@ static struct managed_win *paint_preprocess(session_t *ps, bool *fade_running) {
}
}

win_stack_foreach_managed(w, &ps->window_stack) {
bool posChanged = (w->oldX != -10000 && w->oldY != -10000 && w->oldW != 0 && w->oldH != 0)
&& (w->g.x != w->newX || w->g.y != w->newY || w->g.width != w->newW || w->g.height != w->newH);

if (posChanged) {
float t = get_time_ms();
float moveDx = (t - w->moveTimeX) / ps->o.transition_length;
float moveDy = (t - w->moveTimeY) / ps->o.transition_length;
float moveDw = (t - w->moveTimeW) / ps->o.transition_length;
float moveDh = (t - w->moveTimeH) / ps->o.transition_length;
if (moveDx >= 1.0) moveDx = 1.0;
if (moveDy >= 1.0) moveDy = 1.0;
if (moveDw >= 1.0) moveDw = 1.0;
if (moveDh >= 1.0) moveDh = 1.0;

float q = pow (moveDx, ps->o.transition_pow_x);
float k = pow (moveDy, ps->o.transition_pow_y);
float g = pow (moveDw, ps->o.transition_pow_w);
float z = pow (moveDh, ps->o.transition_pow_h);

float x = (float) w->oldX * (1-q) + (float) w->newX * q;
float y = (float) w->oldY * (1-k) + (float) w->newY * k;
float W = (float) w->oldW * (1-g) + (float) w->newW * g;
float h = (float) w->oldH * (1-z) + (float) w->newH * z;

add_damage_from_win(ps, w);
w->g.x = (int) x;
w->g.y = (int) y;
if (ps->o.size_transition) {
w->g.width = (int) W;
w->g.height = (int) h;
}

/* w->to_paint = true; */
w->mode = WMODE_TRANS;
*fade_running = true;
}
// TODO
//if ((w->shadow && posChanged) || (ps->o.size_transition && w->pixmap_damaged)) {
// rc_region_unref(&w->extents);
// rc_region_unref(&w->border_size);
// w->extents = win_extents(ps, w);
// calc_win_size(ps, w);

// if (ps->shape_exists && ps->o.shadow_ignore_shaped
// && ps->o.detect_rounded_corners && w->bounding_shaped)
// win_update_shape(ps, w);
//}
/* add_damage_win(ps, w); */
}

// Opacity will not change, from now on.
rc_region_t *last_reg_ignore = rc_region_new();

Expand Down
9 changes: 6 additions & 3 deletions src/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,8 +529,10 @@ static void paint_root(session_t *ps, const region_t *reg_paint) {
* Generate shadow <code>Picture</code> for a window.
*/
static bool win_build_shadow(session_t *ps, struct managed_win *w, double opacity) {
const int width = w->widthb;
const int height = w->heightb;
/* const int width = w->widthb; */
/* const int height = w->heightb; */
const int width = w->newW; // TODO!
const int height = w->newH;
// log_trace("(): building shadow for %s %d %d", w->name, width, height);

xcb_image_t *shadow_image = NULL;
Expand Down Expand Up @@ -909,7 +911,8 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
pixman_region32_intersect(&reg_tmp, &reg_tmp, &bshape);
pixman_region32_fini(&bshape);

if (pixman_region32_not_empty(&reg_tmp)) {
reg_tmp = region;
if (pixman_region32_not_empty(&reg_tmp) || true) {
set_tgt_clip(ps, &reg_tmp);
// Blur window background
if (w->blur_background &&
Expand Down
14 changes: 14 additions & 0 deletions src/win.c
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,12 @@ struct win *fill_win(session_t *ps, struct win *w) {
.dim = false,
.invert_color = false,
.blur_background = false,

.oldX = -10000,
.oldY = -10000,
.oldW = 0,
.oldH = 0,

.reg_ignore = NULL,
// The following ones are updated for other reasons
.pixmap_damaged = false, // updated by damage events
Expand Down Expand Up @@ -1772,6 +1778,7 @@ static void destroy_win_finish(session_t *ps, struct win *w) {

static void map_win_finish(struct managed_win *w) {
w->in_openclose = false;
w->isOld = true;
w->state = WSTATE_MAPPED;
}

Expand Down Expand Up @@ -2080,6 +2087,13 @@ void map_win_start(session_t *ps, struct managed_win *w) {
// XXX Can we assume map_state is always viewable?
w->a.map_state = XCB_MAP_STATE_VIEWABLE;

if (!w->isOld) {
w->oldX = -10000;
w->oldY = -10000;
w->oldW = 0;
w->oldH = 0;
}

win_update_screen(ps, w);

// Set window event mask before reading properties so that no property
Expand Down
7 changes: 7 additions & 0 deletions src/win.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ struct managed_win {
/// Whether to blur window background.
bool blur_background;

/// Animation state
int oldX; int oldY; int oldW; int oldH;
int newX; int newY; int newW; int newH;
float moveTimeX; float moveTimeY;
float moveTimeW; float moveTimeH;
bool isOld;

#ifdef CONFIG_OPENGL
/// Textures and FBO background blur use.
glx_blur_cache_t glx_blur_cache;
Expand Down

0 comments on commit 51fdb8b

Please sign in to comment.