mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2025-11-20 06:59:50 -05:00
fix: fix focus animation error
This commit is contained in:
parent
e0f114af59
commit
f25386cca2
5 changed files with 175 additions and 112 deletions
|
|
@ -21,10 +21,12 @@ animation_duration_move=500
|
|||
animation_duration_open=400
|
||||
animation_duration_tag=350
|
||||
animation_duration_close=800
|
||||
animation_duration_focus=0
|
||||
animation_curve_open=0.46,1.0,0.29,1
|
||||
animation_curve_move=0.46,1.0,0.29,1
|
||||
animation_curve_tag=0.46,1.0,0.29,1
|
||||
animation_curve_close=0.08,0.92,0,1
|
||||
animation_curve_focus=0.46,1.0,0.29,1
|
||||
|
||||
# Scroller Layout Setting
|
||||
scroller_structs=20
|
||||
|
|
|
|||
|
|
@ -208,12 +208,6 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, int sy,
|
|||
|
||||
if (wlr_xdg_popup_try_from_wlr_surface(surface) != NULL)
|
||||
return;
|
||||
|
||||
float target_opacity = buffer_data->percent + fadein_begin_opacity;
|
||||
if (target_opacity > buffer_data->opacity) {
|
||||
target_opacity = buffer_data->opacity;
|
||||
}
|
||||
wlr_scene_buffer_set_opacity(buffer, target_opacity);
|
||||
}
|
||||
|
||||
void buffer_set_effect(Client *c, BufferData data) {
|
||||
|
|
@ -399,7 +393,6 @@ void client_apply_clip(Client *c, float factor) {
|
|||
bool should_render_client_surface = false;
|
||||
struct ivec2 offset;
|
||||
BufferData buffer_data;
|
||||
float opacity, percent;
|
||||
|
||||
int bw = (int)c->bw;
|
||||
|
||||
|
|
@ -415,30 +408,17 @@ void client_apply_clip(Client *c, float factor) {
|
|||
|
||||
apply_border(c);
|
||||
|
||||
opacity = c->isfullscreen ? 1
|
||||
: c == selmon->sel ? c->focused_opacity
|
||||
: c->unfocused_opacity;
|
||||
|
||||
if (clip_box.width <= 0 || clip_box.height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
||||
|
||||
buffer_set_effect(c, (BufferData){1.0f, 1.0f, clip_box.width,
|
||||
clip_box.height, opacity, opacity,
|
||||
true});
|
||||
buffer_set_effect(
|
||||
c, (BufferData){1.0f, 1.0f, clip_box.width, clip_box.height, true});
|
||||
return;
|
||||
}
|
||||
|
||||
percent =
|
||||
c->animation.action == OPEN && animation_fade_in && !c->nofadein
|
||||
? (double)c->animation.passed_frames / c->animation.total_frames
|
||||
: 1.0;
|
||||
opacity = c->isfullscreen ? 1
|
||||
: c == selmon->sel ? c->focused_opacity
|
||||
: c->unfocused_opacity;
|
||||
|
||||
// 获取窗口动画实时位置矩形
|
||||
unsigned int width, height;
|
||||
client_actual_size(c, &width, &height);
|
||||
|
|
@ -494,8 +474,6 @@ void client_apply_clip(Client *c, float factor) {
|
|||
buffer_data.width_scale = (float)buffer_data.width / acutal_surface_width;
|
||||
buffer_data.height_scale =
|
||||
(float)buffer_data.height / acutal_surface_height;
|
||||
buffer_data.percent = percent;
|
||||
buffer_data.opacity = opacity;
|
||||
|
||||
if (factor == 1.0) {
|
||||
buffer_data.width_scale = 1.0;
|
||||
|
|
@ -927,45 +905,128 @@ bool client_draw_fadeout_frame(Client *c) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void client_set_focused_opacity_animation(Client *c) {
|
||||
float *border_color = get_border_color(c);
|
||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||
sizeof(c->opacity_animation.target_border_color));
|
||||
c->opacity_animation.target_opacity = c->focused_opacity;
|
||||
c->opacity_animation.total_frames =
|
||||
animation_duration_focus / all_output_frame_duration_ms();
|
||||
c->opacity_animation.passed_frames = 0;
|
||||
if (c->opacity_animation.running) {
|
||||
memcpy(c->opacity_animation.initial_border_color,
|
||||
c->opacity_animation.current_border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity =
|
||||
c->opacity_animation.current_opacity;
|
||||
} else {
|
||||
memcpy(c->opacity_animation.initial_border_color, border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity = c->unfocused_opacity;
|
||||
}
|
||||
c->opacity_animation.running = true;
|
||||
}
|
||||
|
||||
void cleint_set_unfocused_opacity_animation(Client *c) {
|
||||
// Start border color animation to unfocused
|
||||
float *border_color = get_border_color(c);
|
||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||
sizeof(c->opacity_animation.target_border_color));
|
||||
// Start opacity animation to unfocused
|
||||
c->opacity_animation.target_opacity = c->unfocused_opacity;
|
||||
c->opacity_animation.total_frames =
|
||||
animation_duration_focus / all_output_frame_duration_ms();
|
||||
c->opacity_animation.passed_frames = 0;
|
||||
|
||||
if (c->opacity_animation.running) {
|
||||
memcpy(c->opacity_animation.initial_border_color,
|
||||
c->opacity_animation.current_border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity =
|
||||
c->opacity_animation.current_opacity;
|
||||
} else {
|
||||
memcpy(c->opacity_animation.initial_border_color, border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity = c->focused_opacity;
|
||||
}
|
||||
|
||||
c->opacity_animation.running = true;
|
||||
}
|
||||
|
||||
bool client_apply_focus_opacity(Client *c) {
|
||||
// Animate focus transitions (opacity + border color)
|
||||
float *border_color = get_border_color(c);
|
||||
if (c->isfullscreen) {
|
||||
c->opacity_animation.running = false;
|
||||
client_set_opacity(c, 1);
|
||||
} else if (c->animation.running && c->animation.action == OPEN) {
|
||||
c->opacity_animation.running = false;
|
||||
float percent =
|
||||
animation_fade_in && !c->nofadein
|
||||
? (double)c->animation.passed_frames / c->animation.total_frames
|
||||
: 1.0;
|
||||
float opacity = c->isfullscreen ? 1
|
||||
: c == selmon->sel ? c->focused_opacity
|
||||
: c->unfocused_opacity;
|
||||
|
||||
float target_opacity = percent + fadein_begin_opacity;
|
||||
if (target_opacity > opacity) {
|
||||
target_opacity = opacity;
|
||||
}
|
||||
client_set_opacity(c, target_opacity);
|
||||
} else if (animations && c->opacity_animation.running) {
|
||||
float linear_progress = (float)c->opacity_animation.passed_frames /
|
||||
c->opacity_animation.total_frames;
|
||||
float eased_progress = find_animation_curve_at(linear_progress, FOCUS);
|
||||
|
||||
c->opacity_animation.current_opacity =
|
||||
c->opacity_animation.initial_opacity +
|
||||
(c->opacity_animation.target_opacity -
|
||||
c->opacity_animation.initial_opacity) *
|
||||
eased_progress;
|
||||
client_set_opacity(c, c->opacity_animation.current_opacity);
|
||||
|
||||
// Animate border color
|
||||
for (int i = 0; i < 4; i++) {
|
||||
c->opacity_animation.current_border_color[i] =
|
||||
c->opacity_animation.initial_border_color[i] +
|
||||
(c->opacity_animation.target_border_color[i] -
|
||||
c->opacity_animation.initial_border_color[i]) *
|
||||
eased_progress;
|
||||
}
|
||||
client_set_border_color(c, c->opacity_animation.current_border_color);
|
||||
if (linear_progress == 1.0f) {
|
||||
c->opacity_animation.running = false;
|
||||
} else {
|
||||
c->opacity_animation.passed_frames++;
|
||||
return true;
|
||||
}
|
||||
} else if (c == selmon->sel) {
|
||||
c->opacity_animation.running = false;
|
||||
c->opacity_animation.current_opacity = c->focused_opacity;
|
||||
memcpy(c->opacity_animation.current_border_color, border_color,
|
||||
sizeof(c->opacity_animation.current_border_color));
|
||||
client_set_opacity(c, c->focused_opacity);
|
||||
} else {
|
||||
c->opacity_animation.running = false;
|
||||
c->opacity_animation.current_opacity = c->unfocused_opacity;
|
||||
memcpy(c->opacity_animation.current_border_color, border_color,
|
||||
sizeof(c->opacity_animation.current_border_color));
|
||||
client_set_opacity(c, c->unfocused_opacity);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool client_draw_frame(Client *c) {
|
||||
|
||||
if (!c || !client_surface(c)->mapped)
|
||||
return false;
|
||||
|
||||
// Animate focus transitions (opacity + border color)
|
||||
if (c->isfullscreen) {
|
||||
client_set_opacity(c, 1);
|
||||
c->current_opacity = 1;
|
||||
c->target_opacity = 1;
|
||||
} else if (c->opacity_animation_frames > 0 && c->opacity_animation_passed < c->opacity_animation_frames) {
|
||||
float linear_progress = (float)c->opacity_animation_passed / c->opacity_animation_frames;
|
||||
float eased_progress = find_animation_curve_at(linear_progress, FOCUS);
|
||||
|
||||
// Animate opacity
|
||||
float opacity_start = (c->target_opacity == c->focused_opacity) ? c->unfocused_opacity : c->focused_opacity;
|
||||
c->current_opacity = opacity_start + (c->target_opacity - opacity_start) * eased_progress;
|
||||
client_set_opacity(c, c->current_opacity);
|
||||
|
||||
// Animate border color
|
||||
bool focusing = (c->target_border_color[0] == focuscolor[0]);
|
||||
float *border_start = focusing ? bordercolor : focuscolor;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
c->current_border_color[i] = border_start[i] + (c->target_border_color[i] - border_start[i]) * eased_progress;
|
||||
}
|
||||
client_set_border_color(c, c->current_border_color);
|
||||
|
||||
c->opacity_animation_passed++;
|
||||
} else {
|
||||
// Animation complete or disabled - apply target values
|
||||
c->current_opacity = c->target_opacity;
|
||||
client_set_opacity(c, c->current_opacity);
|
||||
memcpy(c->current_border_color, c->target_border_color, sizeof(c->current_border_color));
|
||||
client_set_border_color(c, c->current_border_color);
|
||||
if (!c->need_output_flush) {
|
||||
return client_apply_focus_opacity(c);
|
||||
}
|
||||
|
||||
if (!c->need_output_flush)
|
||||
return false;
|
||||
|
||||
if (animations && c->animation.running) {
|
||||
client_animation_next_tick(c);
|
||||
} else {
|
||||
|
|
@ -976,5 +1037,6 @@ bool client_draw_frame(Client *c) {
|
|||
client_apply_clip(c, 1.0);
|
||||
c->need_output_flush = false;
|
||||
}
|
||||
client_apply_focus_opacity(c);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ uint32_t animation_duration_move = 500; // Animation move speed
|
|||
uint32_t animation_duration_open = 400; // Animation open speed
|
||||
uint32_t animation_duration_tag = 300; // Animation tag speed
|
||||
uint32_t animation_duration_close = 300; // Animation close speed
|
||||
uint32_t animation_duration_focus = 400; // Animation focus opacity speed
|
||||
uint32_t animation_duration_focus = 0; // Animation focus opacity speed
|
||||
double animation_curve_move[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||
double animation_curve_open[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||
double animation_curve_tag[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||
double animation_curve_close[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||
double animation_curve_focus[4] = {0.08, 0.82, 0.17, 1}; // 动画曲线
|
||||
double animation_curve_focus[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||
|
||||
/* appearance */
|
||||
unsigned int axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时间间隔
|
||||
|
|
|
|||
|
|
@ -372,3 +372,21 @@ Client *get_next_stack_client(Client *c, bool reverse) {
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float *get_border_color(Client *c) {
|
||||
if (c->isurgent) {
|
||||
return urgentcolor;
|
||||
} else if (c->is_in_scratchpad && selmon && c == selmon->sel) {
|
||||
return scratchpadcolor;
|
||||
} else if (c->isglobal && selmon && c == selmon->sel) {
|
||||
return globalcolor;
|
||||
} else if (c->isoverlay && selmon && c == selmon->sel) {
|
||||
return overlaycolor;
|
||||
} else if (c->ismaximizescreen && selmon && c == selmon->sel) {
|
||||
return maximizescreencolor;
|
||||
} else if (selmon && c == selmon->sel) {
|
||||
return focuscolor;
|
||||
} else {
|
||||
return bordercolor;
|
||||
}
|
||||
}
|
||||
89
src/mango.c
89
src/mango.c
|
|
@ -235,13 +235,23 @@ struct dwl_animation {
|
|||
int action;
|
||||
};
|
||||
|
||||
struct dwl_opacity_animation {
|
||||
bool running;
|
||||
float current_opacity;
|
||||
float target_opacity;
|
||||
float initial_opacity;
|
||||
unsigned int total_frames;
|
||||
unsigned int passed_frames;
|
||||
float current_border_color[4];
|
||||
float target_border_color[4];
|
||||
float initial_border_color[4];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
float width_scale;
|
||||
float height_scale;
|
||||
int width;
|
||||
int height;
|
||||
double percent;
|
||||
float opacity;
|
||||
bool should_scale;
|
||||
} BufferData;
|
||||
|
||||
|
|
@ -324,6 +334,7 @@ struct Client {
|
|||
float scroller_proportion;
|
||||
bool need_output_flush;
|
||||
struct dwl_animation animation;
|
||||
struct dwl_opacity_animation opacity_animation;
|
||||
int isterm, noswallow;
|
||||
int allow_csd;
|
||||
int force_maximize;
|
||||
|
|
@ -339,12 +350,6 @@ struct Client {
|
|||
int isunglobal;
|
||||
float focused_opacity;
|
||||
float unfocused_opacity;
|
||||
float current_opacity;
|
||||
float target_opacity;
|
||||
unsigned int opacity_animation_frames;
|
||||
unsigned int opacity_animation_passed;
|
||||
float current_border_color[4];
|
||||
float target_border_color[4];
|
||||
char oldmonname[128];
|
||||
struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
|
||||
double master_mfact_per, master_inner_per, stack_innder_per;
|
||||
|
|
@ -704,6 +709,8 @@ static void resize_tile_client(Client *grabc, bool isdrag, int offsetx,
|
|||
static void refresh_monitors_workspaces_status(Monitor *m);
|
||||
static void init_client_properties(Client *c);
|
||||
static void request_fresh_all_monitors(void);
|
||||
static bool check_keyboard_rules_validate(struct xkb_rule_names *rules);
|
||||
static float *get_border_color(Client *c);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
|
|
@ -3027,6 +3034,12 @@ void focusclient(Client *c, int lift) {
|
|||
selmon->prevsel = selmon->sel;
|
||||
selmon->sel = c;
|
||||
|
||||
if (selmon->prevsel && !selmon->prevsel->iskilling) {
|
||||
cleint_set_unfocused_opacity_animation(selmon->prevsel);
|
||||
}
|
||||
|
||||
client_set_focused_opacity_animation(c);
|
||||
|
||||
// decide whether need to re-arrange
|
||||
|
||||
if (c && selmon->prevsel &&
|
||||
|
|
@ -3043,13 +3056,6 @@ void focusclient(Client *c, int lift) {
|
|||
|
||||
// change border color
|
||||
c->isurgent = 0;
|
||||
// Start border color animation to focused
|
||||
memcpy(c->target_border_color, focuscolor, sizeof(c->target_border_color));
|
||||
|
||||
// Start opacity animation to focused
|
||||
c->target_opacity = c->focused_opacity;
|
||||
c->opacity_animation_frames = (animation_duration_focus * 60) / 1000; // 60fps
|
||||
c->opacity_animation_passed = 0;
|
||||
}
|
||||
|
||||
if (c && !c->iskilling && c->foreign_toplevel)
|
||||
|
|
@ -3077,24 +3083,17 @@ void focusclient(Client *c, int lift) {
|
|||
* probably other clients */
|
||||
} else if (w && !client_is_unmanaged(w) &&
|
||||
(!c || !client_wants_focus(c))) {
|
||||
// Start border color animation to unfocused
|
||||
memcpy(w->target_border_color, bordercolor, sizeof(w->target_border_color));
|
||||
|
||||
// Start opacity animation to unfocused
|
||||
w->target_opacity = w->unfocused_opacity;
|
||||
w->opacity_animation_frames = (animation_duration_focus * 60) / 1000; // 60fps
|
||||
w->opacity_animation_passed = 0;
|
||||
|
||||
client_activate_surface(old_keyboard_focus_surface, 0);
|
||||
}
|
||||
}
|
||||
printstatus();
|
||||
|
||||
if (!c) {
|
||||
/* With no client, all we have left is to clear focus */
|
||||
if (selmon && selmon->sel)
|
||||
selmon->sel =
|
||||
NULL; // 这个很关键,因为很多地方用到当前窗口做计算,不重置成NULL就会到处有野指针
|
||||
|
||||
if (selmon && selmon->sel &&
|
||||
(!VISIBLEON(selmon->sel, selmon) || selmon->sel->iskilling ||
|
||||
!client_surface(selmon->sel)->mapped))
|
||||
selmon->sel = NULL;
|
||||
|
||||
// clear text input focus state
|
||||
dwl_im_relay_set_focus(dwl_input_method_relay, NULL);
|
||||
|
|
@ -3439,12 +3438,6 @@ void init_client_properties(Client *c) {
|
|||
c->fake_no_border = false;
|
||||
c->focused_opacity = focused_opacity;
|
||||
c->unfocused_opacity = unfocused_opacity;
|
||||
c->current_opacity = unfocused_opacity;
|
||||
c->target_opacity = unfocused_opacity;
|
||||
c->opacity_animation_frames = 0;
|
||||
c->opacity_animation_passed = 0;
|
||||
memcpy(c->current_border_color, bordercolor, sizeof(c->current_border_color));
|
||||
memcpy(c->target_border_color, bordercolor, sizeof(c->target_border_color));
|
||||
c->nofadein = 0;
|
||||
c->nofadeout = 0;
|
||||
c->no_force_center = 0;
|
||||
|
|
@ -4090,23 +4083,11 @@ void requeststartdrag(struct wl_listener *listener, void *data) {
|
|||
void setborder_color(Client *c) {
|
||||
if (!c || !c->mon)
|
||||
return;
|
||||
if (c->isurgent) {
|
||||
client_set_border_color(c, urgentcolor);
|
||||
return;
|
||||
}
|
||||
if (c->is_in_scratchpad && selmon && c == selmon->sel) {
|
||||
client_set_border_color(c, scratchpadcolor);
|
||||
} else if (c->isglobal && selmon && c == selmon->sel) {
|
||||
client_set_border_color(c, globalcolor);
|
||||
} else if (c->isoverlay && selmon && c == selmon->sel) {
|
||||
client_set_border_color(c, overlaycolor);
|
||||
} else if (c->ismaximizescreen && selmon && c == selmon->sel) {
|
||||
client_set_border_color(c, maximizescreencolor);
|
||||
} else if (selmon && c == selmon->sel) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
} else {
|
||||
client_set_border_color(c, bordercolor);
|
||||
}
|
||||
|
||||
float *border_color = get_border_color(c);
|
||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||
sizeof(c->opacity_animation.target_border_color));
|
||||
client_set_border_color(c, border_color);
|
||||
}
|
||||
|
||||
void exchange_two_client(Client *c1, Client *c2) {
|
||||
|
|
@ -5378,9 +5359,9 @@ urgent(struct wl_listener *listener, void *data) {
|
|||
view_in_mon(&(Arg){.ui = c->tags}, true, c->mon, true);
|
||||
focusclient(c, 1);
|
||||
} else if (c != focustop(selmon)) {
|
||||
if (client_surface(c)->mapped)
|
||||
client_set_border_color(c, urgentcolor);
|
||||
c->isurgent = 1;
|
||||
if (client_surface(c)->mapped)
|
||||
setborder_color(c);
|
||||
printstatus();
|
||||
}
|
||||
}
|
||||
|
|
@ -5529,7 +5510,7 @@ void activatex11(struct wl_listener *listener, void *data) {
|
|||
} else if (c != focustop(selmon)) {
|
||||
c->isurgent = 1;
|
||||
if (client_surface(c)->mapped)
|
||||
client_set_border_color(c, urgentcolor);
|
||||
setborder_color(c);
|
||||
}
|
||||
|
||||
if (need_arrange) {
|
||||
|
|
@ -5611,7 +5592,7 @@ void sethints(struct wl_listener *listener, void *data) {
|
|||
printstatus();
|
||||
|
||||
if (c->isurgent && surface && surface->mapped)
|
||||
client_set_border_color(c, urgentcolor);
|
||||
setborder_color(c);
|
||||
}
|
||||
|
||||
void xwaylandready(struct wl_listener *listener, void *data) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue