diff --git a/config.conf b/config.conf index 3bc5f88..6c1953c 100644 --- a/config.conf +++ b/config.conf @@ -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 diff --git a/src/animation/client.h b/src/animation/client.h index 184abf6..6ad9049 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -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; } diff --git a/src/config/preset.h b/src/config/preset.h index 63ca5fc..f19252b 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -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; // 滚轮绑定动作的触发的时间间隔 diff --git a/src/fetch/client.h b/src/fetch/client.h index ce93a3b..6e67522 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -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; + } +} \ No newline at end of file diff --git a/src/mango.c b/src/mango.c index e17471f..5600f20 100644 --- a/src/mango.c +++ b/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) {