diff --git a/README.md b/README.md index af1d297..7818c36 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Scroller Layout https://github.com/user-attachments/assets/c9bf9415-fad1-4400-bcdc-3ad2d76de85a -Layer animaiton +Layer animation https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0 @@ -82,7 +82,6 @@ yay -S mangowc-git ``` ## Gentoo Linux - The package is in the community-maintained repository called GURU. First, add GURU repository: @@ -100,6 +99,16 @@ Finally, install the package: emerge --ask --verbose gui-wm/mangowc ``` +## Fedora Linux +The package is in the third-party Terra repository. +First, add the [Terra Repository](https://terra.fyralabs.com/). + +Then, install the package: + +```bash +dnf install mangowc +``` + ## Other ```bash @@ -172,7 +181,9 @@ git clone https://github.com/DreamMaoMao/mango-config.git ~/.config/mango ## Config Documentation -Refer to the [wiki](https://github.com/DreamMaoMao/mango/wiki/) +Refer to the repo wiki [wiki](https://github.com/DreamMaoMao/mango/wiki/) + +or the website docs [docs](https://mangowc.vercel.app/docs) # NixOS + Home-manager diff --git a/config.conf b/config.conf index 4c8d8d3..5483a14 100644 --- a/config.conf +++ b/config.conf @@ -48,6 +48,8 @@ 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 +animation_curve_opafadeout=0.5,0.5,0.5,0.5 +animation_curve_opafadein=0.46,1.0,0.29,1 # Scroller Layout Setting scroller_structs=20 @@ -75,7 +77,7 @@ overviewgappo=30 no_border_when_single=0 axis_bind_apply_timeout=100 focus_on_activate=1 -inhibit_regardless_of_visibility=0 +idleinhibit_ignore_visible=0 sloppyfocus=1 warpcursor=1 focus_cross_monitor=0 diff --git a/mangowc.scm b/mangowc.scm new file mode 100644 index 0000000..9c55d43 --- /dev/null +++ b/mangowc.scm @@ -0,0 +1,64 @@ +(define-module (mangowc) + #:use-module (guix download) + #:use-module (guix git-download) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (guix utils) + #:use-module (gnu packages wm) + #:use-module (gnu packages freedesktop) + #:use-module (gnu packages xdisorg) + #:use-module (gnu packages pciutils) + #:use-module (gnu packages admin) + #:use-module (gnu packages pcre) + #:use-module (gnu packages xorg) + #:use-module (gnu packages build-tools) + #:use-module (gnu packages ninja) + #:use-module (gnu packages pkg-config) + #:use-module (guix build-system meson) + #:use-module (guix licenses)) + + +(define-public mangowc-git + (package + (name "mangowc") + (version "git") + (source (local-file "." "mangowc-checkout" + #:recursive? #t + #:select? (or (git-predicate (current-source-directory)) + (const #t)))) + (build-system meson-build-system) + (arguments + (list + #:configure-flags + #~(list (string-append "-Dsysconfdir=" #$output "/etc")) + #:phases + #~(modify-phases %standard-phases + (add-before 'configure 'patch-meson + (lambda _ + (substitute* "meson.build" + (("'-DSYSCONFDIR=\\\"@0@\\\"'.format\\('/etc'\\)") + "'-DSYSCONFDIR=\"@0@\"'.format(sysconfdir)") + (("sysconfdir = sysconfdir.substring\\(prefix.length\\(\\)\\)") + ""))))))) + (inputs (list wayland + libinput + libdrm + libxkbcommon + pixman + libdisplay-info + libliftoff + hwdata + seatd + pcre2 + libxcb + xcb-util-wm + wlroots + scenefx)) + (native-inputs (list pkg-config wayland-protocols)) + (home-page "https://github.com/DreamMaoMao/mangowc") + (synopsis "Wayland compositor based on wlroots and scenefx") + (description "A Wayland compositor based on wlroots and scenefx, +inspired by dwl but aiming to be more feature-rich.") + (license gpl3))) + +mangowc-git diff --git a/meson.build b/meson.build index 460328e..9f197ab 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mango', ['c', 'cpp'], - version : '0.10.7', + version : '0.10.8', ) subdir('protocols') diff --git a/nix/default.nix b/nix/default.nix index b72977d..6085565 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -13,60 +13,64 @@ wayland-scanner, xcbutilwm, xwayland, - enableXWayland ? true, meson, ninja, scenefx, wlroots_0_19, libGL, -}: let + enableXWayland ? true, + debug ? false, +}: +stdenv.mkDerivation { pname = "mango"; -in - stdenv.mkDerivation { - inherit pname; - version = "nightly"; + version = "nightly"; - src = builtins.path { - path = ../.; - name = "source"; - }; + src = builtins.path { + path = ../.; + name = "source"; + }; - nativeBuildInputs = [ - meson - ninja - pkg-config - wayland-scanner + mesonFlags = [ + (lib.mesonEnable "xwayland" enableXWayland) + (lib.mesonBool "asan" debug) + ]; + + nativeBuildInputs = [ + meson + ninja + pkg-config + wayland-scanner + ]; + + buildInputs = + [ + libinput + libxcb + libxkbcommon + pcre2 + pixman + wayland + wayland-protocols + wlroots_0_19 + scenefx + libGL + ] + ++ lib.optionals enableXWayland [ + libX11 + xcbutilwm + xwayland ]; - buildInputs = - [ - libinput - libxcb - libxkbcommon - pcre2 - pixman - wayland - wayland-protocols - wlroots_0_19 - scenefx - libGL - ] - ++ lib.optionals enableXWayland [ - libX11 - xcbutilwm - xwayland - ]; + passthru = { + providedSessions = ["mango"]; + }; - passthru = { - providedSessions = ["mango"]; - }; - - meta = { - mainProgram = "mango"; - description = "A streamlined but feature-rich Wayland compositor"; - homepage = "https://github.com/DreamMaoMao/mango"; - license = lib.licenses.gpl3Plus; - maintainers = []; - platforms = lib.platforms.unix; - }; - } + meta = { + mainProgram = "mango"; + description = "A streamlined but feature-rich Wayland compositor"; + homepage = "https://github.com/DreamMaoMao/mango"; + license = lib.licenses.gpl3Plus; + maintainers = []; + platforms = lib.platforms.unix; + }; +} diff --git a/src/animation/client.h b/src/animation/client.h index d5cf5f6..9ad6dfe 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -240,7 +240,7 @@ void buffer_set_effect(Client *c, BufferData data) { if (c == grabc) data.should_scale = false; - if (c->isfullscreen || + if (c->isnoradius || c->isfullscreen || (no_radius_when_single && !c->isfloating && !c->ismaximizescreen && c->mon && c->mon->visible_tiling_clients == 1)) { data.corner_location = CORNER_LOCATION_NONE; @@ -356,12 +356,14 @@ void apply_border(Client *c) { return; bool hit_no_border = check_hit_no_border(c); - enum corner_location current_corner_location = - c->isfullscreen || (no_radius_when_single && !c->isfloating && - !c->ismaximizescreen && c->mon && - c->mon->visible_tiling_clients == 1) - ? CORNER_LOCATION_NONE - : CORNER_LOCATION_ALL; + enum corner_location current_corner_location; + if (c->isfullscreen || + (no_radius_when_single && !c->isfloating && !c->ismaximizescreen && + c->mon && c->mon->visible_tiling_clients == 1)) { + current_corner_location = CORNER_LOCATION_NONE; + } else { + current_corner_location = set_client_corner_location(c); + } // Handle no-border cases if (hit_no_border && smartgaps) { @@ -633,6 +635,7 @@ void fadeout_client_animation_next_tick(Client *c) { int type = c->animation.action = c->animation.action; double factor = find_animation_curve_at(animation_passed, type); + uint32_t width = c->animation.initial.width + (c->current.width - c->animation.initial.width) * factor; uint32_t height = @@ -653,7 +656,13 @@ void fadeout_client_animation_next_tick(Client *c) { .height = height, }; - double opacity = MAX(fadeout_begin_opacity - animation_passed, 0); + double opacity_eased_progress = + find_animation_curve_at(animation_passed, OPAFADEOUT); + + double percent = fadeout_begin_opacity - + (opacity_eased_progress * fadeout_begin_opacity); + + double opacity = MAX(percent, 0); if (animation_fade_out && !c->nofadeout) wlr_scene_node_for_each_buffer(&c->scene->node, @@ -704,10 +713,10 @@ void client_animation_next_tick(Client *c) { c->animation.initial.height + (c->current.height - c->animation.initial.height) * factor; - uint32_t x = c->animation.initial.x + - (c->current.x - c->animation.initial.x) * factor; - uint32_t y = c->animation.initial.y + - (c->current.y - c->animation.initial.y) * factor; + int32_t x = c->animation.initial.x + + (c->current.x - c->animation.initial.x) * factor; + int32_t y = c->animation.initial.y + + (c->current.y - c->animation.initial.y) * factor; wlr_scene_node_set_position(&c->scene->node, x, y); c->animation.current = (struct wlr_box){ @@ -1112,8 +1121,11 @@ bool client_apply_focus_opacity(Client *c) { ? (double)passed_time / (double)c->animation.duration : 1.0; + double opacity_eased_progress = + find_animation_curve_at(linear_progress, OPAFADEIN); + float percent = - animation_fade_in && !c->nofadein ? linear_progress : 1.0; + animation_fade_in && !c->nofadein ? opacity_eased_progress : 1.0; float opacity = c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; diff --git a/src/animation/common.h b/src/animation/common.h index 2ff6744..0f662d6 100644 --- a/src/animation/common.h +++ b/src/animation/common.h @@ -11,6 +11,10 @@ struct dvec2 calculate_animation_curve_at(double t, int type) { animation_curve = animation_curve_close; } else if (type == FOCUS) { animation_curve = animation_curve_focus; + } else if (type == OPAFADEIN) { + animation_curve = animation_curve_opafadein; + } else if (type == OPAFADEOUT) { + animation_curve = animation_curve_opafadeout; } else { animation_curve = animation_curve_move; } @@ -32,6 +36,10 @@ void init_baked_points(void) { calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_close)); baked_points_focus = calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_focus)); + baked_points_opafadein = + calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_opafadein)); + baked_points_opafadeout = + calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_opafadeout)); for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { baked_points_move[i] = calculate_animation_curve_at( @@ -53,6 +61,14 @@ void init_baked_points(void) { baked_points_focus[i] = calculate_animation_curve_at( (double)i / (BAKED_POINTS_COUNT - 1), FOCUS); } + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { + baked_points_opafadein[i] = calculate_animation_curve_at( + (double)i / (BAKED_POINTS_COUNT - 1), OPAFADEIN); + } + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { + baked_points_opafadeout[i] = calculate_animation_curve_at( + (double)i / (BAKED_POINTS_COUNT - 1), OPAFADEOUT); + } } double find_animation_curve_at(double t, int type) { @@ -71,6 +87,10 @@ double find_animation_curve_at(double t, int type) { baked_points = baked_points_close; } else if (type == FOCUS) { baked_points = baked_points_focus; + } else if (type == OPAFADEIN) { + baked_points = baked_points_opafadein; + } else if (type == OPAFADEOUT) { + baked_points = baked_points_opafadeout; } else { baked_points = baked_points_move; } diff --git a/src/animation/layer.h b/src/animation/layer.h index e36ddd1..57e0c14 100644 --- a/src/animation/layer.h +++ b/src/animation/layer.h @@ -276,7 +276,13 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) { .height = height, }; - double opacity = MAX(fadeout_begin_opacity - animation_passed, 0.0f); + double opacity_eased_progress = + find_animation_curve_at(animation_passed, OPAFADEOUT); + + double percent = fadeout_begin_opacity - + (opacity_eased_progress * fadeout_begin_opacity); + + double opacity = MAX(percent, 0.0f); if (animation_fade_out) wlr_scene_node_for_each_buffer(&l->scene->node, @@ -318,9 +324,13 @@ void layer_animation_next_tick(LayerSurface *l) { uint32_t y = l->animation.initial.y + (l->current.y - l->animation.initial.y) * factor; - double opacity = MIN(fadein_begin_opacity + - animation_passed * (1.0 - fadein_begin_opacity), - 1.0f); + double opacity_eased_progress = + find_animation_curve_at(animation_passed, OPAFADEIN); + + double opacity = + MIN(fadein_begin_opacity + + opacity_eased_progress * (1.0 - fadein_begin_opacity), + 1.0f); if (animation_fade_in) wlr_scene_node_for_each_buffer(&l->scene->node, diff --git a/src/client/client.h b/src/client/client.h index 10ecfdf..bc7706d 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -153,20 +153,6 @@ static inline void client_get_geometry(Client *c, struct wlr_box *geom) { *geom = c->surface.xdg->geometry; } -static inline Client *get_client_from_surface(struct wlr_surface *surface) { - if (!surface) - return NULL; - - // 从 surface 的 data 指针获取 scene tree - struct wlr_scene_tree *scene_tree = surface->data; - if (!scene_tree) - return NULL; - - // 从 scene tree 的 node data 获取 Client - Client *c = scene_tree->node.data; - return c; -} - static inline Client *client_get_parent(Client *c) { Client *p = NULL; #ifdef XWAYLAND diff --git a/src/config/parse_config.h b/src/config/parse_config.h index d845e2a..074b522 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -43,6 +43,7 @@ typedef struct { bool isdefaultmode; bool islockapply; bool isreleaseapply; + bool ispassapply; } KeyBinding; typedef struct { @@ -63,6 +64,7 @@ typedef struct { const char *layer_animation_type_close; int isnoborder; int isnoshadow; + int isnoradius; int isnoanimation; int isopensilent; int istagsilent; @@ -193,6 +195,8 @@ typedef struct { double animation_curve_tag[4]; double animation_curve_close[4]; double animation_curve_focus[4]; + double animation_curve_opafadein[4]; + double animation_curve_opafadeout[4]; int scroller_structs; float scroller_default_proportion; @@ -235,7 +239,7 @@ typedef struct { uint32_t axis_bind_apply_timeout; uint32_t focus_on_activate; - int inhibit_regardless_of_visibility; + int idleinhibit_ignore_visible; int sloppyfocus; int warpcursor; @@ -262,6 +266,8 @@ typedef struct { uint32_t send_events_mode; uint32_t button_map; + double axis_scroll_factor; + int blur; int blur_layer; int blur_optimized; @@ -443,6 +449,9 @@ void parse_bind_flags(const char *str, KeyBinding *kb) { case 'r': kb->isreleaseapply = true; break; + case 'p': + kb->ispassapply = true; + break; default: // 忽略其他字符或可根据需要处理错误 break; @@ -1177,6 +1186,22 @@ void parse_option(Config *config, char *key, char *value) { "Error: Failed to parse animation_curve_focus: %s\n", value); } + } else if (strcmp(key, "animation_curve_opafadein") == 0) { + int num = + parse_double_array(value, config->animation_curve_opafadein, 4); + if (num != 4) { + fprintf(stderr, + "Error: Failed to parse animation_curve_opafadein: %s\n", + value); + } + } else if (strcmp(key, "animation_curve_opafadeout") == 0) { + int num = + parse_double_array(value, config->animation_curve_opafadeout, 4); + if (num != 4) { + fprintf(stderr, + "Error: Failed to parse animation_curve_opafadeout: %s\n", + value); + } } else if (strcmp(key, "scroller_structs") == 0) { config->scroller_structs = atoi(value); } else if (strcmp(key, "scroller_default_proportion") == 0) { @@ -1434,8 +1459,8 @@ void parse_option(Config *config, char *key, char *value) { config->focus_on_activate = atoi(value); } else if (strcmp(key, "numlockon") == 0) { config->numlockon = atoi(value); - } else if (strcmp(key, "inhibit_regardless_of_visibility") == 0) { - config->inhibit_regardless_of_visibility = atoi(value); + } else if (strcmp(key, "idleinhibit_ignore_visible") == 0) { + config->idleinhibit_ignore_visible = atoi(value); } else if (strcmp(key, "sloppyfocus") == 0) { config->sloppyfocus = atoi(value); } else if (strcmp(key, "warpcursor") == 0) { @@ -1482,6 +1507,8 @@ void parse_option(Config *config, char *key, char *value) { config->send_events_mode = atoi(value); } else if (strcmp(key, "button_map") == 0) { config->button_map = atoi(value); + } else if (strcmp(key, "axis_scroll_factor") == 0) { + config->axis_scroll_factor = atof(value); } else if (strcmp(key, "gappih") == 0) { config->gappih = atoi(value); } else if (strcmp(key, "gappiv") == 0) { @@ -1679,6 +1706,7 @@ void parse_option(Config *config, char *key, char *value) { rule->isfullscreen = -1; rule->isnoborder = -1; rule->isnoshadow = -1; + rule->isnoradius = -1; rule->isnoanimation = -1; rule->isopensilent = -1; rule->istagsilent = -1; @@ -1768,6 +1796,8 @@ void parse_option(Config *config, char *key, char *value) { rule->isnoborder = atoi(val); } else if (strcmp(key, "isnoshadow") == 0) { rule->isnoshadow = atoi(val); + } else if (strcmp(key, "isnoradius") == 0) { + rule->isnoradius = atoi(val); } else if (strcmp(key, "isnoanimation") == 0) { rule->isnoanimation = atoi(val); } else if (strcmp(key, "isopensilent") == 0) { @@ -1956,7 +1986,7 @@ void parse_option(Config *config, char *key, char *value) { config->exec_once_count++; - } else if (regex_match("^bind[s|l|r]*$", key)) { + } else if (regex_match("^bind[s|l|r|p]*$", key)) { config->key_bindings = realloc(config->key_bindings, (config->key_bindings_count + 1) * sizeof(KeyBinding)); @@ -2394,6 +2424,14 @@ void free_baked_points(void) { free(baked_points_focus); baked_points_focus = NULL; } + if (baked_points_opafadein) { + free(baked_points_opafadein); + baked_points_opafadein = NULL; + } + if (baked_points_opafadeout) { + free(baked_points_opafadeout); + baked_points_opafadeout = NULL; + } } void free_config(void) { @@ -2705,8 +2743,8 @@ void override_config(void) { axis_bind_apply_timeout = CLAMP_INT(config.axis_bind_apply_timeout, 0, 1000); focus_on_activate = CLAMP_INT(config.focus_on_activate, 0, 1); - inhibit_regardless_of_visibility = - CLAMP_INT(config.inhibit_regardless_of_visibility, 0, 1); + idleinhibit_ignore_visible = + CLAMP_INT(config.idleinhibit_ignore_visible, 0, 1); sloppyfocus = CLAMP_INT(config.sloppyfocus, 0, 1); warpcursor = CLAMP_INT(config.warpcursor, 0, 1); focus_cross_monitor = CLAMP_INT(config.focus_cross_monitor, 0, 1); @@ -2750,6 +2788,7 @@ void override_config(void) { click_method = CLAMP_INT(config.click_method, 0, 2); send_events_mode = CLAMP_INT(config.send_events_mode, 0, 2); button_map = CLAMP_INT(config.button_map, 0, 1); + axis_scroll_factor = CLAMP_FLOAT(config.axis_scroll_factor, 0.1f, 10.0f); // 外观设置 gappih = CLAMP_INT(config.gappih, 0, 1000); @@ -2806,6 +2845,10 @@ void override_config(void) { sizeof(animation_curve_close)); memcpy(animation_curve_focus, config.animation_curve_focus, sizeof(animation_curve_focus)); + memcpy(animation_curve_opafadein, config.animation_curve_opafadein, + sizeof(animation_curve_opafadein)); + memcpy(animation_curve_opafadeout, config.animation_curve_opafadeout, + sizeof(animation_curve_opafadeout)); } void set_value_default() { @@ -2873,6 +2916,7 @@ void set_value_default() { config.exchange_cross_monitor = exchange_cross_monitor; config.scratchpad_cross_monitor = scratchpad_cross_monitor; config.focus_cross_tag = focus_cross_tag; + config.axis_scroll_factor = axis_scroll_factor; config.view_current_to_back = view_current_to_back; config.single_scratchpad = single_scratchpad; config.xwayland_persistence = xwayland_persistence; @@ -2888,8 +2932,8 @@ void set_value_default() { config.enable_floating_snap = enable_floating_snap; config.swipe_min_threshold = swipe_min_threshold; - config.inhibit_regardless_of_visibility = - inhibit_regardless_of_visibility; /* 1 means idle inhibitors will + config.idleinhibit_ignore_visible = + idleinhibit_ignore_visible; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ @@ -2954,6 +2998,10 @@ void set_value_default() { sizeof(animation_curve_close)); memcpy(config.animation_curve_focus, animation_curve_focus, sizeof(animation_curve_focus)); + memcpy(config.animation_curve_opafadein, animation_curve_opafadein, + sizeof(animation_curve_opafadein)); + memcpy(config.animation_curve_opafadeout, animation_curve_opafadeout, + sizeof(animation_curve_opafadeout)); memcpy(config.rootcolor, rootcolor, sizeof(rootcolor)); memcpy(config.bordercolor, bordercolor, sizeof(bordercolor)); @@ -3156,9 +3204,37 @@ void reapply_monitor_rules(void) { } void reapply_cursor_style(void) { - if (cursor_mgr) + if (hide_source) { + wl_event_source_timer_update(hide_source, 0); + wl_event_source_remove(hide_source); + hide_source = NULL; + } + + wlr_cursor_unset_image(cursor); + + wlr_cursor_set_surface(cursor, NULL, 0, 0); + + if (cursor_mgr) { wlr_xcursor_manager_destroy(cursor_mgr); + cursor_mgr = NULL; + } + cursor_mgr = wlr_xcursor_manager_create(config.cursor_theme, cursor_size); + + Monitor *m = NULL; + wl_list_for_each(m, &mons, link) { + wlr_xcursor_manager_load(cursor_mgr, m->wlr_output->scale); + } + + wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); + + hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy), + hidecursor, cursor); + if (cursor_hidden) { + wlr_cursor_unset_image(cursor); + } else { + wl_event_source_timer_update(hide_source, cursor_hide_timeout * 1000); + } } void reapply_border(void) { @@ -3278,5 +3354,5 @@ int reload_config(const Arg *arg) { parse_config(); reset_option(); printstatus(); - return 0; + return 1; } diff --git a/src/config/preset.h b/src/config/preset.h index ed743a8..31f514f 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -26,11 +26,13 @@ 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 = 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.46, 1.0, 0.29, 0.99}; // 动画曲线 +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.46, 1.0, 0.29, 0.99}; // 动画曲线 +double animation_curve_opafadein[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线 +double animation_curve_opafadeout[4] = {0.5, 0.5, 0.5, 0.5}; // 动画曲线 /* appearance */ uint32_t axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时间间隔 @@ -78,7 +80,7 @@ uint32_t cursor_hide_timeout = 0; uint32_t swipe_min_threshold = 1; -int inhibit_regardless_of_visibility = +int idleinhibit_ignore_visible = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ uint32_t borderpx = 4; /* border pixel of windows */ @@ -104,7 +106,7 @@ int xwayland_persistence = 1; /* xwayland persistence */ int syncobj_enable = 0; int adaptive_sync = 0; int allow_lock_transparent = 0; -double drag_refresh_interval = 30.0; +double drag_refresh_interval = 16.0; int allow_tearing = TEARING_DISABLED; int allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; @@ -176,6 +178,8 @@ LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; +double axis_scroll_factor = 1.0; + /* You can choose between: LIBINPUT_CONFIG_SEND_EVENTS_ENABLED LIBINPUT_CONFIG_SEND_EVENTS_DISABLED diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index c167915..6544cab 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -173,15 +173,17 @@ int toggle_trackpad_enable(const Arg *arg) { int focusmon(const Arg *arg) { Client *c = NULL; Monitor *m = NULL; + Monitor *tm = NULL; if (arg->i != UNDIR) { - m = dirtomon(arg->i); + tm = dirtomon(arg->i); } else if (arg->v) { wl_list_for_each(m, &mons, link) { if (!m->wlr_output->enabled) { continue; } if (regex_match(arg->v, m->wlr_output->name)) { + tm = m; break; } } @@ -189,10 +191,10 @@ int focusmon(const Arg *arg) { return 0; } - if (!m || !m->wlr_output->enabled || m == selmon) + if (!tm || !tm->wlr_output->enabled || tm == selmon) return 0; - selmon = m; + selmon = tm; if (warpcursor) { warp_cursor_to_selmon(selmon); } @@ -713,14 +715,26 @@ int centerwin(const Arg *arg) { Client *c = NULL; c = selmon->sel; - if (!c || c->isfullscreen) + if (!c || c->isfullscreen || c->ismaximizescreen) return 0; - if (!c->isfloating) - setfloating(c, true); - c->float_geom = setclient_coordinate_center(c, c->geom, 0, 0); - c->iscustomsize = 1; - resize(c, c->float_geom, 1); + if (c->isfloating) { + c->float_geom = setclient_coordinate_center(c, c->geom, 0, 0); + c->iscustomsize = 1; + resize(c, c->float_geom, 1); + return 0; + } + + if (!is_scroller_layout(selmon)) + return 0; + + if (selmon->pertag->ltidxs[selmon->pertag->curtag]->id == SCROLLER) { + c->geom.x = selmon->w.x + (selmon->w.width - c->geom.width) / 2; + } else { + c->geom.y = selmon->w.y + (selmon->w.height - c->geom.height) / 2; + } + + arrange(selmon, false); return 0; } @@ -1549,4 +1563,4 @@ int toggle_monitor(const Arg *arg) { } } return 0; -} \ No newline at end of file +} diff --git a/src/ext-protocol/ext-workspace.h b/src/ext-protocol/ext-workspace.h index d4e0e51..8ff53cc 100644 --- a/src/ext-protocol/ext-workspace.h +++ b/src/ext-protocol/ext-workspace.h @@ -1,8 +1,8 @@ #include "wlr_ext_workspace_v1.h" #define EXT_WORKSPACE_ENABLE_CAPS \ - WLR_EXT_WORKSPACE_HANDLE_V1_CAP_ACTIVATE | \ - WLR_EXT_WORKSPACE_HANDLE_V1_CAP_DEACTIVATE + EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \ + EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_DEACTIVATE typedef struct Monitor Monitor; diff --git a/src/ext-protocol/foreign-toplevel.h b/src/ext-protocol/foreign-toplevel.h index 3b81948..01c384f 100644 --- a/src/ext-protocol/foreign-toplevel.h +++ b/src/ext-protocol/foreign-toplevel.h @@ -6,14 +6,9 @@ void handle_foreign_activate_request(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, foreign_activate_request); uint32_t target; - if (c && c->swallowing) + if (c->swallowing) return; - if (c && !c->isminimized && c == selmon->sel) { - set_minimized(c); - return; - } - if (c->isminimized) { c->is_in_scratchpad = 0; c->isnamedscratchpad = 0; @@ -27,29 +22,82 @@ void handle_foreign_activate_request(struct wl_listener *listener, void *data) { target = get_tags_first_tag(c->tags); view_in_mon(&(Arg){.ui = target}, true, c->mon, true); focusclient(c, 1); - wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); +} + +void handle_foreign_maximize_request(struct wl_listener *listener, void *data) { + Client *c = wl_container_of(listener, c, foreign_maximize_request); + struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data; + + if (c->swallowing) + return; + + if (c->ismaximizescreen && !event->maximized) { + setmaximizescreen(c, 0); + return; + } + + if (!c->ismaximizescreen && event->maximized) { + setmaximizescreen(c, 1); + return; + } +} + +void handle_foreign_minimize_request(struct wl_listener *listener, void *data) { + Client *c = wl_container_of(listener, c, foreign_minimize_request); + struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data; + + if (c->swallowing) + return; + + if (!c->isminimized && event->minimized) { + set_minimized(c); + return; + } + + if (c->isminimized && !event->minimized) { + c->is_in_scratchpad = 0; + c->isnamedscratchpad = 0; + c->is_scratchpad_show = 0; + setborder_color(c); + show_hide_client(c); + arrange(c->mon, true); + return; + } } void handle_foreign_fullscreen_request(struct wl_listener *listener, void *data) { - return; + + Client *c = wl_container_of(listener, c, foreign_fullscreen_request); + struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data; + + if (c->swallowing) + return; + + if (c->isfullscreen && !event->fullscreen) { + setfullscreen(c, 0); + return; + } + + if (!c->isfullscreen && event->fullscreen) { + setfullscreen(c, 1); + return; + } } void handle_foreign_close_request(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, foreign_close_request); - if (c) { - pending_kill_client(c); - } + pending_kill_client(c); } void handle_foreign_destroy(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, foreign_destroy); - if (c) { - wl_list_remove(&c->foreign_activate_request.link); - wl_list_remove(&c->foreign_fullscreen_request.link); - wl_list_remove(&c->foreign_close_request.link); - wl_list_remove(&c->foreign_destroy.link); - } + wl_list_remove(&c->foreign_activate_request.link); + wl_list_remove(&c->foreign_minimize_request.link); + wl_list_remove(&c->foreign_maximize_request.link); + wl_list_remove(&c->foreign_fullscreen_request.link); + wl_list_remove(&c->foreign_close_request.link); + wl_list_remove(&c->foreign_destroy.link); } void remove_foreign_topleve(Client *c) { @@ -67,6 +115,10 @@ void add_foreign_toplevel(Client *c) { if (c->foreign_toplevel) { LISTEN(&(c->foreign_toplevel->events.request_activate), &c->foreign_activate_request, handle_foreign_activate_request); + LISTEN(&(c->foreign_toplevel->events.request_minimize), + &c->foreign_minimize_request, handle_foreign_minimize_request); + LISTEN(&(c->foreign_toplevel->events.request_maximize), + &c->foreign_maximize_request, handle_foreign_maximize_request); LISTEN(&(c->foreign_toplevel->events.request_fullscreen), &c->foreign_fullscreen_request, handle_foreign_fullscreen_request); diff --git a/src/ext-protocol/tearing.h b/src/ext-protocol/tearing.h index 5ad36e8..8e02656 100644 --- a/src/ext-protocol/tearing.h +++ b/src/ext-protocol/tearing.h @@ -13,7 +13,10 @@ static void handle_controller_set_hint(struct wl_listener *listener, void *data) { struct tearing_controller *controller = wl_container_of(listener, controller, set_hint); - Client *c = get_client_from_surface(controller->tearing_control->surface); + Client *c = NULL; + + toplevel_from_wlr_surface(controller->tearing_control->surface, &c, NULL); + if (c) { /* * tearing_control->current is actually an enum: diff --git a/src/ext-protocol/wlr_ext_workspace_v1.c b/src/ext-protocol/wlr_ext_workspace_v1.c index 3f80e9f..2d781b3 100644 --- a/src/ext-protocol/wlr_ext_workspace_v1.c +++ b/src/ext-protocol/wlr_ext_workspace_v1.c @@ -29,7 +29,7 @@ struct wlr_ext_workspace_v1_request { // ACTIVATE / DEACTIVATE / ASSIGN / REMOVE struct wlr_ext_workspace_handle_v1 *workspace; - struct wl_list link; // wlr_ext_workspace_manager_client_v1.requests + struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests }; struct wlr_ext_workspace_v1_group_output { @@ -41,33 +41,40 @@ struct wlr_ext_workspace_v1_group_output { }; // These structs wrap wl_resource of each interface to access the request queue -// (wlr_ext_workspace_manager_client_v1.requests) assigned per manager resource +// (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager +// resource -struct wlr_ext_workspace_manager_client_v1 { +struct wlr_ext_workspace_manager_v1_resource { struct wl_resource *resource; struct wlr_ext_workspace_manager_v1 *manager; - struct wl_list requests; // wlr_ext_workspace_v1_request.link - struct wl_list link; // wlr_ext_workspace_manager_v1.clients + struct wl_list requests; // wlr_ext_workspace_v1_request.link + struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link + struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link + struct wl_list link; // wlr_ext_workspace_manager_v1.resources }; -struct wlr_ext_workspace_group_client_v1 { +struct wlr_ext_workspace_group_v1_resource { struct wl_resource *resource; struct wlr_ext_workspace_group_handle_v1 *group; - struct wlr_ext_workspace_manager_client_v1 *manager; - struct wl_list link; // wlr_ext_workspace_group_v1.clients + struct wlr_ext_workspace_manager_v1_resource *manager; + struct wl_list link; // wlr_ext_workspace_group_v1.resources + struct wl_list + manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources }; -struct wlr_ext_workspace_client_v1 { +struct wlr_ext_workspace_v1_resource { struct wl_resource *resource; struct wlr_ext_workspace_handle_v1 *workspace; - struct wlr_ext_workspace_manager_client_v1 *manager; - struct wl_list link; // wlr_ext_workspace_v1.clients + struct wlr_ext_workspace_manager_v1_resource *manager; + struct wl_list link; // wlr_ext_workspace_v1.resources + struct wl_list + manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources }; static const struct ext_workspace_group_handle_v1_interface group_impl; -static struct wlr_ext_workspace_group_client_v1 * -group_client_from_resource(struct wl_resource *resource) { +static struct wlr_ext_workspace_group_v1_resource * +group_resource_from_resource(struct wl_resource *resource) { assert(wl_resource_instance_of( resource, &ext_workspace_group_handle_v1_interface, &group_impl)); return wl_resource_get_user_data(resource); @@ -75,8 +82,8 @@ group_client_from_resource(struct wl_resource *resource) { static const struct ext_workspace_handle_v1_interface workspace_impl; -static struct wlr_ext_workspace_client_v1 * -workspace_client_from_resource(struct wl_resource *resource) { +static struct wlr_ext_workspace_v1_resource * +workspace_resource_from_resource(struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface, &workspace_impl)); return wl_resource_get_user_data(resource); @@ -84,8 +91,8 @@ workspace_client_from_resource(struct wl_resource *resource) { static const struct ext_workspace_manager_v1_interface manager_impl; -static struct wlr_ext_workspace_manager_client_v1 * -manager_client_from_resource(struct wl_resource *resource) { +static struct wlr_ext_workspace_manager_v1_resource * +manager_resource_from_resource(struct wl_resource *resource) { assert(wl_resource_instance_of( resource, &ext_workspace_manager_v1_interface, &manager_impl)); return wl_resource_get_user_data(resource); @@ -98,9 +105,9 @@ static void workspace_handle_destroy(struct wl_client *client, static void workspace_handle_activate(struct wl_client *client, struct wl_resource *workspace_resource) { - struct wlr_ext_workspace_client_v1 *workspace = - workspace_client_from_resource(workspace_resource); - if (!workspace) { + struct wlr_ext_workspace_v1_resource *workspace_res = + workspace_resource_from_resource(workspace_resource); + if (!workspace_res) { return; } @@ -110,16 +117,16 @@ static void workspace_handle_activate(struct wl_client *client, return; } req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE; - req->workspace = workspace->workspace; - wl_list_insert(workspace->manager->requests.prev, &req->link); + req->workspace = workspace_res->workspace; + wl_list_insert(workspace_res->manager->requests.prev, &req->link); } static void workspace_handle_deactivate(struct wl_client *client, struct wl_resource *workspace_resource) { - struct wlr_ext_workspace_client_v1 *workspace = - workspace_client_from_resource(workspace_resource); - if (!workspace) { + struct wlr_ext_workspace_v1_resource *workspace_res = + workspace_resource_from_resource(workspace_resource); + if (!workspace_res) { return; } @@ -129,18 +136,18 @@ workspace_handle_deactivate(struct wl_client *client, return; } req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE; - req->workspace = workspace->workspace; - wl_list_insert(workspace->manager->requests.prev, &req->link); + req->workspace = workspace_res->workspace; + wl_list_insert(workspace_res->manager->requests.prev, &req->link); } static void workspace_handle_assign(struct wl_client *client, struct wl_resource *workspace_resource, struct wl_resource *group_resource) { - struct wlr_ext_workspace_client_v1 *workspace = - workspace_client_from_resource(workspace_resource); - struct wlr_ext_workspace_group_client_v1 *group = - group_client_from_resource(group_resource); - if (!workspace || !group) { + struct wlr_ext_workspace_v1_resource *workspace_res = + workspace_resource_from_resource(workspace_resource); + struct wlr_ext_workspace_group_v1_resource *group_res = + group_resource_from_resource(group_resource); + if (!workspace_res || !group_res) { return; } @@ -150,16 +157,16 @@ static void workspace_handle_assign(struct wl_client *client, return; } req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN; - req->group = group->group; - req->workspace = workspace->workspace; - wl_list_insert(workspace->manager->requests.prev, &req->link); + req->group = group_res->group; + req->workspace = workspace_res->workspace; + wl_list_insert(workspace_res->manager->requests.prev, &req->link); } static void workspace_handle_remove(struct wl_client *client, struct wl_resource *workspace_resource) { - struct wlr_ext_workspace_client_v1 *workspace = - workspace_client_from_resource(workspace_resource); - if (!workspace) { + struct wlr_ext_workspace_v1_resource *workspace_res = + workspace_resource_from_resource(workspace_resource); + if (!workspace_res) { return; } @@ -169,8 +176,8 @@ static void workspace_handle_remove(struct wl_client *client, return; } req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE; - req->workspace = workspace->workspace; - wl_list_insert(workspace->manager->requests.prev, &req->link); + req->workspace = workspace_res->workspace; + wl_list_insert(workspace_res->manager->requests.prev, &req->link); } static const struct ext_workspace_handle_v1_interface workspace_impl = { @@ -184,9 +191,9 @@ static const struct ext_workspace_handle_v1_interface workspace_impl = { static void group_handle_create_workspace(struct wl_client *client, struct wl_resource *group_resource, const char *name) { - struct wlr_ext_workspace_group_client_v1 *group = - group_client_from_resource(group_resource); - if (!group) { + struct wlr_ext_workspace_group_v1_resource *group_res = + group_resource_from_resource(group_resource); + if (!group_res) { return; } @@ -195,9 +202,15 @@ static void group_handle_create_workspace(struct wl_client *client, wl_resource_post_no_memory(group_resource); return; } + req->name = strdup(name); + if (!req->name) { + free(req); + wl_resource_post_no_memory(group_resource); + return; + } req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE; - req->group = group->group; - wl_list_insert(group->manager->requests.prev, &req->link); + req->group = group_res->group; + wl_list_insert(group_res->manager->requests.prev, &req->link); } static void group_handle_destroy(struct wl_client *client, @@ -210,89 +223,94 @@ static const struct ext_workspace_group_handle_v1_interface group_impl = { .destroy = group_handle_destroy, }; -static void -destroy_workspace_client(struct wlr_ext_workspace_client_v1 *workspace_client) { - wl_list_remove(&workspace_client->link); - wl_resource_set_user_data(workspace_client->resource, NULL); - free(workspace_client); +static void destroy_workspace_resource( + struct wlr_ext_workspace_v1_resource *workspace_res) { + wl_list_remove(&workspace_res->link); + wl_list_remove(&workspace_res->manager_resource_link); + wl_resource_set_user_data(workspace_res->resource, NULL); + free(workspace_res); } static void workspace_resource_destroy(struct wl_resource *resource) { - struct wlr_ext_workspace_client_v1 *workspace_client = - workspace_client_from_resource(resource); - if (workspace_client) { - destroy_workspace_client(workspace_client); + struct wlr_ext_workspace_v1_resource *workspace_res = + workspace_resource_from_resource(resource); + if (workspace_res) { + destroy_workspace_resource(workspace_res); } } -static struct wlr_ext_workspace_client_v1 *create_workspace_client( +static struct wlr_ext_workspace_v1_resource *create_workspace_resource( struct wlr_ext_workspace_handle_v1 *workspace, - struct wlr_ext_workspace_manager_client_v1 *manager_client) { - struct wlr_ext_workspace_client_v1 *workspace_client = - calloc(1, sizeof(*workspace_client)); - if (!workspace_client) { + struct wlr_ext_workspace_manager_v1_resource *manager_res) { + struct wlr_ext_workspace_v1_resource *workspace_res = + calloc(1, sizeof(*workspace_res)); + if (!workspace_res) { return NULL; } - struct wl_client *client = wl_resource_get_client(manager_client->resource); - workspace_client->resource = wl_resource_create( - client, &ext_workspace_handle_v1_interface, - wl_resource_get_version(manager_client->resource), 0); - if (!workspace_client->resource) { - free(workspace_client); + struct wl_client *client = wl_resource_get_client(manager_res->resource); + workspace_res->resource = + wl_resource_create(client, &ext_workspace_handle_v1_interface, + wl_resource_get_version(manager_res->resource), 0); + if (!workspace_res->resource) { + free(workspace_res); return NULL; } - wl_resource_set_implementation(workspace_client->resource, &workspace_impl, - workspace_client, - workspace_resource_destroy); + wl_resource_set_implementation(workspace_res->resource, &workspace_impl, + workspace_res, workspace_resource_destroy); - workspace_client->workspace = workspace; - workspace_client->manager = manager_client; - wl_list_insert(&workspace->clients, &workspace_client->link); + workspace_res->workspace = workspace; + workspace_res->manager = manager_res; + wl_list_insert(&workspace->resources, &workspace_res->link); + wl_list_insert(&manager_res->workspace_resources, + &workspace_res->manager_resource_link); - return workspace_client; + return workspace_res; } static void -destroy_group_client(struct wlr_ext_workspace_group_client_v1 *group_client) { - wl_list_remove(&group_client->link); - wl_resource_set_user_data(group_client->resource, NULL); - free(group_client); +destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) { + wl_list_remove(&group_res->link); + wl_list_remove(&group_res->manager_resource_link); + wl_resource_set_user_data(group_res->resource, NULL); + free(group_res); } static void group_handle_resource_destroy(struct wl_resource *resource) { - struct wlr_ext_workspace_group_client_v1 *group_client = - group_client_from_resource(resource); - if (group_client) { - destroy_group_client(group_client); + struct wlr_ext_workspace_group_v1_resource *group_res = + group_resource_from_resource(resource); + if (group_res) { + destroy_group_resource(group_res); } } -static struct wlr_ext_workspace_group_client_v1 *create_group_client( +static struct wlr_ext_workspace_group_v1_resource *create_group_resource( struct wlr_ext_workspace_group_handle_v1 *group, - struct wlr_ext_workspace_manager_client_v1 *manager_client) { - struct wlr_ext_workspace_group_client_v1 *group_client = - calloc(1, sizeof(*group_client)); - if (!group_client) { + struct wlr_ext_workspace_manager_v1_resource *manager_res) { + struct wlr_ext_workspace_group_v1_resource *group_res = + calloc(1, sizeof(*group_res)); + if (!group_res) { return NULL; } - struct wl_client *client = wl_resource_get_client(manager_client->resource); - uint32_t version = wl_resource_get_version(manager_client->resource); - group_client->resource = wl_resource_create( + struct wl_client *client = wl_resource_get_client(manager_res->resource); + uint32_t version = wl_resource_get_version(manager_res->resource); + group_res->resource = wl_resource_create( client, &ext_workspace_group_handle_v1_interface, version, 0); - if (group_client->resource == NULL) { - free(group_client); + if (group_res->resource == NULL) { + free(group_res); return NULL; } - wl_resource_set_implementation(group_client->resource, &group_impl, - group_client, group_handle_resource_destroy); + wl_resource_set_implementation(group_res->resource, &group_impl, group_res, + group_handle_resource_destroy); - group_client->group = group; - group_client->manager = manager_client; - wl_list_insert(&group->clients, &group_client->link); + group_res->group = group; + group_res->manager = manager_res; + wl_list_insert(&group->resources, &group_res->link); + wl_list_insert(&manager_res->group_resources, + &group_res->manager_resource_link); - return group_client; + return group_res; } static void destroy_request(struct wlr_ext_workspace_v1_request *req) { @@ -303,18 +321,22 @@ static void destroy_request(struct wlr_ext_workspace_v1_request *req) { static void manager_handle_commit(struct wl_client *client, struct wl_resource *resource) { - struct wlr_ext_workspace_manager_client_v1 *manager = - manager_client_from_resource(resource); - if (!manager) { + struct wlr_ext_workspace_manager_v1_resource *manager_res = + manager_resource_from_resource(resource); + if (!manager_res) { return; } struct wlr_ext_workspace_v1_request *req, *tmp; - wl_list_for_each_safe(req, tmp, &manager->requests, link) { + wl_list_for_each_safe(req, tmp, &manager_res->requests, link) { switch (req->type) { - case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE: + case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:; + struct wlr_ext_workspace_group_handle_v1_create_workspace_event + event = { + .name = req->name, + }; wl_signal_emit_mutable(&req->group->events.create_workspace, - req->name); + &event); break; case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE: wl_signal_emit_mutable(&req->workspace->events.activate, NULL); @@ -323,13 +345,11 @@ static void manager_handle_commit(struct wl_client *client, wl_signal_emit_mutable(&req->workspace->events.deactivate, NULL); break; case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN: - wl_signal_emit_mutable(&req->workspace->events.assign, &req->group); + wl_signal_emit_mutable(&req->workspace->events.assign, req->group); break; case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE: wl_signal_emit_mutable(&req->workspace->events.remove, NULL); break; - default: - abort(); } destroy_request(req); } @@ -338,9 +358,9 @@ static void manager_handle_commit(struct wl_client *client, static void handle_idle(void *data) { struct wlr_ext_workspace_manager_v1 *manager = data; - struct wlr_ext_workspace_manager_client_v1 *manager_client; - wl_list_for_each(manager_client, &manager->clients, link) { - ext_workspace_manager_v1_send_done(manager_client->resource); + struct wlr_ext_workspace_manager_v1_resource *manager_res; + wl_list_for_each(manager_res, &manager->resources, link) { + ext_workspace_manager_v1_send_done(manager_res->resource); } manager->idle_source = NULL; } @@ -354,9 +374,9 @@ manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) { } static void -workspace_send_details(struct wlr_ext_workspace_client_v1 *workspace_client) { - struct wlr_ext_workspace_handle_v1 *workspace = workspace_client->workspace; - struct wl_resource *resource = workspace_client->resource; +workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) { + struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace; + struct wl_resource *resource = workspace_res->resource; ext_workspace_handle_v1_send_capabilities(resource, workspace->caps); if (workspace->coordinates.size > 0) { @@ -384,29 +404,41 @@ static const struct ext_workspace_manager_v1_interface manager_impl = { .stop = manager_handle_stop, }; -static void destroy_manager_client( - struct wlr_ext_workspace_manager_client_v1 *manager_client) { +static void destroy_manager_resource( + struct wlr_ext_workspace_manager_v1_resource *manager_res) { struct wlr_ext_workspace_v1_request *req, *tmp; - wl_list_for_each_safe(req, tmp, &manager_client->requests, link) { + wl_list_for_each_safe(req, tmp, &manager_res->requests, link) { destroy_request(req); } - wl_list_remove(&manager_client->link); - wl_resource_set_user_data(manager_client->resource, NULL); - free(manager_client); + struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2; + wl_list_for_each_safe(workspace_res, tmp2, + &manager_res->workspace_resources, + manager_resource_link) { + destroy_workspace_resource(workspace_res); + } + struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3; + wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources, + manager_resource_link) { + destroy_group_resource(group_res); + } + + wl_list_remove(&manager_res->link); + wl_resource_set_user_data(manager_res->resource, NULL); + free(manager_res); } static void manager_resource_destroy(struct wl_resource *resource) { - struct wlr_ext_workspace_manager_client_v1 *manager_client = - manager_client_from_resource(resource); - if (manager_client) { - destroy_manager_client(manager_client); + struct wlr_ext_workspace_manager_v1_resource *manager_res = + manager_resource_from_resource(resource); + if (manager_res) { + destroy_manager_resource(manager_res); } } static void -group_send_details(struct wlr_ext_workspace_group_client_v1 *group_client) { - struct wlr_ext_workspace_group_handle_v1 *group = group_client->group; - struct wl_resource *resource = group_client->resource; +group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) { + struct wlr_ext_workspace_group_handle_v1 *group = group_res->group; + struct wl_resource *resource = group_res->resource; struct wl_client *client = wl_resource_get_client(resource); ext_workspace_group_handle_v1_send_capabilities(resource, group->caps); @@ -430,65 +462,67 @@ static void manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { struct wlr_ext_workspace_manager_v1 *manager = data; - struct wlr_ext_workspace_manager_client_v1 *manager_client = - calloc(1, sizeof(*manager_client)); - if (!manager_client) { + struct wlr_ext_workspace_manager_v1_resource *manager_res = + calloc(1, sizeof(*manager_res)); + if (!manager_res) { wl_client_post_no_memory(client); return; } - manager_client->manager = manager; - wl_list_init(&manager_client->requests); - wl_list_insert(&manager->clients, &manager_client->link); + manager_res->manager = manager; + wl_list_init(&manager_res->requests); + wl_list_init(&manager_res->workspace_resources); + wl_list_init(&manager_res->group_resources); - manager_client->resource = wl_resource_create( + manager_res->resource = wl_resource_create( client, &ext_workspace_manager_v1_interface, version, id); - if (!manager_client->resource) { - free(manager_client); + if (!manager_res->resource) { + free(manager_res); wl_client_post_no_memory(client); return; } - wl_resource_set_implementation(manager_client->resource, &manager_impl, - manager_client, manager_resource_destroy); + wl_resource_set_implementation(manager_res->resource, &manager_impl, + manager_res, manager_resource_destroy); + wl_list_insert(&manager->resources, &manager_res->link); struct wlr_ext_workspace_group_handle_v1 *group; wl_list_for_each(group, &manager->groups, link) { - struct wlr_ext_workspace_group_client_v1 *group_client = - create_group_client(group, manager_client); - if (!group_client) { - wl_resource_post_no_memory(manager_client->resource); + struct wlr_ext_workspace_group_v1_resource *group_res = + create_group_resource(group, manager_res); + if (!group_res) { + wl_resource_post_no_memory(manager_res->resource); continue; } - ext_workspace_manager_v1_send_workspace_group(manager_client->resource, - group_client->resource); - group_send_details(group_client); + ext_workspace_manager_v1_send_workspace_group(manager_res->resource, + group_res->resource); + group_send_details(group_res); } struct wlr_ext_workspace_handle_v1 *workspace; wl_list_for_each(workspace, &manager->workspaces, link) { - struct wlr_ext_workspace_client_v1 *workspace_client = - create_workspace_client(workspace, manager_client); - if (!workspace) { - wl_client_post_no_memory(client); + struct wlr_ext_workspace_v1_resource *workspace_res = + create_workspace_resource(workspace, manager_res); + if (!workspace_res) { + wl_resource_post_no_memory(manager_res->resource); continue; } - ext_workspace_manager_v1_send_workspace(manager_client->resource, - workspace_client->resource); - workspace_send_details(workspace_client); + ext_workspace_manager_v1_send_workspace(manager_res->resource, + workspace_res->resource); + workspace_send_details(workspace_res); if (!workspace->group) { continue; } - struct wlr_ext_workspace_group_client_v1 *group_client; - wl_list_for_each(group_client, &workspace->group->clients, link) { - if (group_client->manager == manager_client) { + struct wlr_ext_workspace_group_v1_resource *group_res; + wl_list_for_each(group_res, &workspace->group->resources, link) { + if (group_res->manager == manager_res) { ext_workspace_group_handle_v1_send_workspace_enter( - group_client->resource, workspace_client->resource); + group_res->resource, workspace_res->resource); } } } - manager_schedule_done(manager); + ext_workspace_manager_v1_send_done(manager_res->resource); } static void manager_handle_display_destroy(struct wl_listener *listener, @@ -509,9 +543,9 @@ static void manager_handle_display_destroy(struct wl_listener *listener, wlr_ext_workspace_handle_v1_destroy(workspace); } - struct wlr_ext_workspace_manager_client_v1 *manager_client, *tmp3; - wl_list_for_each_safe(manager_client, tmp3, &manager->clients, link) { - destroy_manager_client(manager_client); + struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3; + wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) { + destroy_manager_resource(manager_res); } if (manager->idle_source) { @@ -548,7 +582,7 @@ wlr_ext_workspace_manager_v1_create(struct wl_display *display, wl_list_init(&manager->groups); wl_list_init(&manager->workspaces); - wl_list_init(&manager->clients); + wl_list_init(&manager->resources); wl_signal_init(&manager->events.destroy); return manager; @@ -566,22 +600,22 @@ wlr_ext_workspace_group_handle_v1_create( group->caps = caps; wl_list_init(&group->outputs); - wl_list_init(&group->clients); + wl_list_init(&group->resources); wl_signal_init(&group->events.create_workspace); wl_signal_init(&group->events.destroy); wl_list_insert(manager->groups.prev, &group->link); - struct wlr_ext_workspace_manager_client_v1 *manager_client; - wl_list_for_each(manager_client, &manager->clients, link) { - struct wlr_ext_workspace_group_client_v1 *group_client = - create_group_client(group, manager_client); - if (!group_client) { + struct wlr_ext_workspace_manager_v1_resource *manager_res; + wl_list_for_each(manager_res, &manager->resources, link) { + struct wlr_ext_workspace_group_v1_resource *group_res = + create_group_resource(group, manager_res); + if (!group_res) { continue; } - ext_workspace_manager_v1_send_workspace_group(manager_client->resource, - group_client->resource); - group_send_details(group_client); + ext_workspace_manager_v1_send_workspace_group(manager_res->resource, + group_res->resource); + group_send_details(group_res); } manager_schedule_done(manager); @@ -594,19 +628,19 @@ workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace, struct wlr_ext_workspace_group_handle_v1 *group, bool enter) { - struct wlr_ext_workspace_client_v1 *workspace_client; - wl_list_for_each(workspace_client, &workspace->clients, link) { - struct wlr_ext_workspace_group_client_v1 *group_client; - wl_list_for_each(group_client, &group->clients, link) { - if (group_client->manager != workspace_client->manager) { + struct wlr_ext_workspace_v1_resource *workspace_res; + wl_list_for_each(workspace_res, &workspace->resources, link) { + struct wlr_ext_workspace_group_v1_resource *group_res; + wl_list_for_each(group_res, &group->resources, link) { + if (group_res->manager != workspace_res->manager) { continue; } if (enter) { ext_workspace_group_handle_v1_send_workspace_enter( - group_client->resource, workspace_client->resource); + group_res->resource, workspace_res->resource); } else { ext_workspace_group_handle_v1_send_workspace_leave( - group_client->resource, workspace_client->resource); + group_res->resource, workspace_res->resource); } } } @@ -625,10 +659,9 @@ destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) { static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output, bool enter) { - struct wlr_ext_workspace_group_client_v1 *group_client; - wl_list_for_each(group_client, &group->clients, link) { - struct wl_client *client = - wl_resource_get_client(group_client->resource); + struct wlr_ext_workspace_group_v1_resource *group_res; + wl_list_for_each(group_res, &group->resources, link) { + struct wl_client *client = wl_resource_get_client(group_res->resource); struct wl_resource *output_resource; wl_resource_for_each(output_resource, &output->resources) { @@ -637,10 +670,10 @@ static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group, } if (enter) { ext_workspace_group_handle_v1_send_output_enter( - group_client->resource, output_resource); + group_res->resource, output_resource); } else { ext_workspace_group_handle_v1_send_output_leave( - group_client->resource, output_resource); + group_res->resource, output_resource); } } } @@ -650,6 +683,10 @@ static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group, void wlr_ext_workspace_group_handle_v1_destroy( struct wlr_ext_workspace_group_handle_v1 *group) { + if (!group) { + return; + } + wl_signal_emit_mutable(&group->events.destroy, NULL); assert(wl_list_empty(&group->events.create_workspace.listener_list)); @@ -663,16 +700,16 @@ void wlr_ext_workspace_group_handle_v1_destroy( } } - struct wlr_ext_workspace_group_client_v1 *group_client, *tmp; - wl_list_for_each_safe(group_client, tmp, &group->clients, link) { - ext_workspace_group_handle_v1_send_removed(group_client->resource); - destroy_group_client(group_client); + struct wlr_ext_workspace_group_v1_resource *group_res, *tmp; + wl_list_for_each_safe(group_res, tmp, &group->resources, link) { + ext_workspace_group_handle_v1_send_removed(group_res->resource); + destroy_group_resource(group_res); } - struct wlr_ext_workspace_manager_client_v1 *manager_client; - wl_list_for_each(manager_client, &group->manager->clients, link) { + struct wlr_ext_workspace_manager_v1_resource *manager_res; + wl_list_for_each(manager_res, &group->manager->resources, link) { struct wlr_ext_workspace_v1_request *req, *tmp2; - wl_list_for_each_safe(req, tmp2, &manager_client->requests, link) { + wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) { if (req->group == group) { destroy_request(req); } @@ -697,11 +734,11 @@ static void handle_output_bind(struct wl_listener *listener, void *data) { struct wlr_output_event_bind *event = data; struct wl_client *client = wl_resource_get_client(event->resource); - struct wlr_ext_workspace_group_client_v1 *group_client; - wl_list_for_each(group_client, &group_output->group->clients, link) { - if (wl_resource_get_client(group_client->resource) == client) { - ext_workspace_group_handle_v1_send_output_enter( - group_client->resource, event->resource); + struct wlr_ext_workspace_group_v1_resource *group_res; + wl_list_for_each(group_res, &group_output->group->resources, link) { + if (wl_resource_get_client(group_res->resource) == client) { + ext_workspace_group_handle_v1_send_output_enter(group_res->resource, + event->resource); } } @@ -778,11 +815,12 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager, if (id) { workspace->id = strdup(id); if (!workspace->id) { + free(workspace); return NULL; } } - wl_list_init(&workspace->clients); + wl_list_init(&workspace->resources); wl_array_init(&workspace->coordinates); wl_signal_init(&workspace->events.activate); wl_signal_init(&workspace->events.deactivate); @@ -792,16 +830,16 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager, wl_list_insert(&manager->workspaces, &workspace->link); - struct wlr_ext_workspace_manager_client_v1 *manager_client; - wl_list_for_each(manager_client, &manager->clients, link) { - struct wlr_ext_workspace_client_v1 *workspace_client = - create_workspace_client(workspace, manager_client); - if (!workspace_client) { + struct wlr_ext_workspace_manager_v1_resource *manager_res; + wl_list_for_each(manager_res, &manager->resources, link) { + struct wlr_ext_workspace_v1_resource *workspace_res = + create_workspace_resource(workspace, manager_res); + if (!workspace_res) { continue; } - ext_workspace_manager_v1_send_workspace(manager_client->resource, - workspace_client->resource); - workspace_send_details(workspace_client); + ext_workspace_manager_v1_send_workspace(manager_res->resource, + workspace_res->resource); + workspace_send_details(workspace_res); } manager_schedule_done(manager); @@ -811,6 +849,10 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager, void wlr_ext_workspace_handle_v1_destroy( struct wlr_ext_workspace_handle_v1 *workspace) { + if (!workspace) { + return; + } + wl_signal_emit_mutable(&workspace->events.destroy, NULL); assert(wl_list_empty(&workspace->events.activate.listener_list)); @@ -823,16 +865,16 @@ void wlr_ext_workspace_handle_v1_destroy( workspace_send_group(workspace, workspace->group, false); } - struct wlr_ext_workspace_client_v1 *workspace_client, *tmp; - wl_list_for_each_safe(workspace_client, tmp, &workspace->clients, link) { - ext_workspace_handle_v1_send_removed(workspace_client->resource); - destroy_workspace_client(workspace_client); + struct wlr_ext_workspace_v1_resource *workspace_res, *tmp; + wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) { + ext_workspace_handle_v1_send_removed(workspace_res->resource); + destroy_workspace_resource(workspace_res); } - struct wlr_ext_workspace_manager_client_v1 *manager_client; - wl_list_for_each(manager_client, &workspace->manager->clients, link) { + struct wlr_ext_workspace_manager_v1_resource *manager_res; + wl_list_for_each(manager_res, &workspace->manager->resources, link) { struct wlr_ext_workspace_v1_request *req, *tmp2; - wl_list_for_each_safe(req, tmp2, &manager_client->requests, link) { + wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) { if (req->workspace == workspace) { destroy_request(req); } @@ -856,7 +898,7 @@ void wlr_ext_workspace_handle_v1_set_group( } if (workspace->group) { - workspace_send_group(workspace, group, false); + workspace_send_group(workspace, workspace->group, false); } workspace->group = group; if (group) { @@ -878,9 +920,9 @@ void wlr_ext_workspace_handle_v1_set_name( return; } - struct wlr_ext_workspace_client_v1 *workspace_client; - wl_list_for_each(workspace_client, &workspace->clients, link) { - ext_workspace_handle_v1_send_name(workspace_client->resource, + struct wlr_ext_workspace_v1_resource *workspace_res; + wl_list_for_each(workspace_res, &workspace->resources, link) { + ext_workspace_handle_v1_send_name(workspace_res->resource, workspace->name); } @@ -905,9 +947,9 @@ void wlr_ext_workspace_handle_v1_set_coordinates( wl_array_init(&workspace->coordinates); wl_array_copy(&workspace->coordinates, coordinates); - struct wlr_ext_workspace_client_v1 *workspace_client; - wl_list_for_each(workspace_client, &workspace->clients, link) { - ext_workspace_handle_v1_send_coordinates(workspace_client->resource, + struct wlr_ext_workspace_v1_resource *workspace_res; + wl_list_for_each(workspace_res, &workspace->resources, link) { + ext_workspace_handle_v1_send_coordinates(workspace_res->resource, &workspace->coordinates); } @@ -927,9 +969,9 @@ static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace, return; } - struct wlr_ext_workspace_client_v1 *workspace_client; - wl_list_for_each(workspace_client, &workspace->clients, link) { - ext_workspace_handle_v1_send_state(workspace_client->resource, + struct wlr_ext_workspace_v1_resource *workspace_res; + wl_list_for_each(workspace_res, &workspace->resources, link) { + ext_workspace_handle_v1_send_state(workspace_res->resource, workspace->state); } diff --git a/src/ext-protocol/wlr_ext_workspace_v1.h b/src/ext-protocol/wlr_ext_workspace_v1.h index e1d285b..a2a733b 100644 --- a/src/ext-protocol/wlr_ext_workspace_v1.h +++ b/src/ext-protocol/wlr_ext_workspace_v1.h @@ -2,32 +2,11 @@ // TODO: remove this file // refer: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5115 -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H -#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H - +#include #include struct wlr_output; -enum wlr_ext_workspace_group_handle_v1_cap { - WLR_EXT_WORKSPACE_GROUP_HANDLE_V1_CAP_CREATE_WORKSPACE = 1 << 0, -}; - -enum wlr_ext_workspace_handle_v1_cap { - WLR_EXT_WORKSPACE_HANDLE_V1_CAP_ACTIVATE = 1 << 0, - WLR_EXT_WORKSPACE_HANDLE_V1_CAP_DEACTIVATE = 1 << 1, - WLR_EXT_WORKSPACE_HANDLE_V1_CAP_REMOVE = 1 << 2, - WLR_EXT_WORKSPACE_HANDLE_V1_CAP_ASSIGN = 1 << 3, -}; - struct wlr_ext_workspace_manager_v1 { struct wl_global *global; struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link @@ -37,24 +16,33 @@ struct wlr_ext_workspace_manager_v1 { struct wl_signal destroy; } events; - struct wl_list clients; // wlr_ext_workspace_manager_client_v1.link - struct wl_event_source *idle_source; - struct wl_event_loop *event_loop; - struct wl_listener display_destroy; + struct { + struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link + struct wl_event_source *idle_source; + struct wl_event_loop *event_loop; + struct wl_listener display_destroy; + }; +}; + +struct wlr_ext_workspace_group_handle_v1_create_workspace_event { + const char *name; }; struct wlr_ext_workspace_group_handle_v1 { struct wlr_ext_workspace_manager_v1 *manager; - uint32_t caps; // wlr_ext_workspace_group_handle_v1_cap + uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities struct { - struct wl_signal create_workspace; // const char * + struct wl_signal + create_workspace; // wlr_ext_workspace_group_handle_v1_create_workspace_event struct wl_signal destroy; } events; struct wl_list link; // wlr_ext_workspace_manager_v1.groups - struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link - struct wl_list clients; // wlr_ext_workspace_manager_client_v1.link + struct { + struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link + struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link + }; }; struct wlr_ext_workspace_handle_v1 { @@ -63,7 +51,7 @@ struct wlr_ext_workspace_handle_v1 { char *id; char *name; struct wl_array coordinates; - uint32_t caps; // wlr_ext_workspace_handle_v1_cap + uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities uint32_t state; // ext_workspace_handle_v1_state struct { @@ -74,9 +62,11 @@ struct wlr_ext_workspace_handle_v1 { struct wl_signal destroy; } events; - struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces; + struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces - struct wl_list clients; + struct { + struct wl_list resources; // wlr_ext_workspace_v1_resource.link + }; }; struct wlr_ext_workspace_manager_v1 * @@ -114,5 +104,3 @@ void wlr_ext_workspace_handle_v1_set_urgent( struct wlr_ext_workspace_handle_v1 *workspace, bool enabled); void wlr_ext_workspace_handle_v1_set_hidden( struct wlr_ext_workspace_handle_v1 *workspace, bool enabled); - -#endif diff --git a/src/fetch/client.h b/src/fetch/client.h index 2f971d3..0ddd879 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -348,7 +348,7 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } free(tempClients); // 释放内存 - if(tempSameMonitorFocusClients) { + if (tempSameMonitorFocusClients) { return tempSameMonitorFocusClients; } else { return tempFocusClients; @@ -387,30 +387,21 @@ Client *focustop(Monitor *m) { Client *get_next_stack_client(Client *c, bool reverse) { if (!c || !c->mon) - return NULL; // 添加输入检查 + return NULL; Client *next = NULL; if (reverse) { wl_list_for_each_reverse(next, &c->link, link) { - if (!next) - continue; // 安全检查 + if (&next->link == &clients) + continue; /* wrap past the sentinel node */ - if (c->mon->has_visible_fullscreen_client && !next->isfloating && - !next->isfullscreen) - continue; - - // 添加更安全的 VISIBLEON 检查 if (next != c && next->mon && VISIBLEON(next, c->mon)) return next; } } else { wl_list_for_each(next, &c->link, link) { - if (!next) - continue; // 安全检查 - - if (c->mon->has_visible_fullscreen_client && !next->isfloating && - !next->isfullscreen) - continue; + if (&next->link == &clients) + continue; /* wrap past the sentinel node */ if (next != c && next->mon && VISIBLEON(next, c->mon)) return next; diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 3fb25a4..a7805af 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -5,7 +5,7 @@ void set_size_per(Monitor *m, Client *c) { if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) { c->master_mfact_per = fc->master_mfact_per; c->master_inner_per = fc->master_inner_per; - c->stack_innder_per = fc->stack_innder_per; + c->stack_inner_per = fc->stack_inner_per; found = true; break; } @@ -14,7 +14,7 @@ void set_size_per(Monitor *m, Client *c) { if (!found) { c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag]; c->master_inner_per = 1.0f; - c->stack_innder_per = 1.0f; + c->stack_inner_per = 1.0f; } } @@ -70,7 +70,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, // 记录初始状态 grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; - grabc->old_stack_innder_per = grabc->stack_innder_per; + grabc->old_stack_inner_per = grabc->stack_inner_per; grabc->cursor_in_upper_half = cursor->y < grabc->geom.y + grabc->geom.height / 2; grabc->cursor_in_left_half = @@ -86,7 +86,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, } else { grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; - grabc->old_stack_innder_per = grabc->stack_innder_per; + grabc->old_stack_inner_per = grabc->stack_inner_per; grabc->drag_begin_geom = grabc->geom; grabc->cursor_in_upper_half = true; grabc->cursor_in_left_half = false; @@ -100,7 +100,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, } else { delta_x = (float)(offsetx) * (1 - grabc->old_master_mfact_per) / grabc->drag_begin_geom.width; - delta_y = (float)(offsety) * (grabc->old_stack_innder_per) / + delta_y = (float)(offsety) * (grabc->old_stack_inner_per) / grabc->drag_begin_geom.height; } bool moving_up; @@ -182,12 +182,12 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, // 直接设置新的比例,基于初始值 + 变化量 float new_master_mfact_per = grabc->old_master_mfact_per + delta_x; float new_master_inner_per = grabc->old_master_inner_per + delta_y; - float new_stack_innder_per = grabc->old_stack_innder_per + delta_y; + float new_stack_inner_per = grabc->old_stack_inner_per + delta_y; // 应用限制,确保比例在合理范围内 new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per)); new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per)); - new_stack_innder_per = fmaxf(0.1f, fminf(0.9f, new_stack_innder_per)); + new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per)); // 应用到所有平铺窗口 wl_list_for_each(tc, &clients, link) { @@ -197,7 +197,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, } grabc->master_inner_per = new_master_inner_per; - grabc->stack_innder_per = new_stack_innder_per; + grabc->stack_inner_per = new_stack_inner_per; if (!isdrag) { arrange(grabc->mon, false); @@ -250,7 +250,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, // 记录初始状态 grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; - grabc->old_stack_innder_per = grabc->stack_innder_per; + grabc->old_stack_inner_per = grabc->stack_inner_per; grabc->cursor_in_upper_half = cursor->y < grabc->geom.y + grabc->geom.height / 2; grabc->cursor_in_left_half = @@ -267,7 +267,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, } else { grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; - grabc->old_stack_innder_per = grabc->stack_innder_per; + grabc->old_stack_inner_per = grabc->stack_inner_per; grabc->drag_begin_geom = grabc->geom; grabc->cursor_in_upper_half = true; grabc->cursor_in_left_half = false; @@ -280,7 +280,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, delta_y = (float)(offsety) * (grabc->old_master_mfact_per) / grabc->drag_begin_geom.height; } else { - delta_x = (float)(offsetx) * (grabc->old_stack_innder_per) / + delta_x = (float)(offsetx) * (grabc->old_stack_inner_per) / grabc->drag_begin_geom.width; delta_y = (float)(offsety) * (1 - grabc->old_master_mfact_per) / grabc->drag_begin_geom.height; @@ -338,13 +338,13 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, delta_y; // 垂直:delta_y调整主区域高度 float new_master_inner_per = grabc->old_master_inner_per + delta_x; // 垂直:delta_x调整主区域内部宽度 - float new_stack_innder_per = grabc->old_stack_innder_per + - delta_x; // 垂直:delta_x调整栈区域内部宽度 + float new_stack_inner_per = grabc->old_stack_inner_per + + delta_x; // 垂直:delta_x调整栈区域内部宽度 // 应用限制,确保比例在合理范围内 new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per)); new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per)); - new_stack_innder_per = fmaxf(0.1f, fminf(0.9f, new_stack_innder_per)); + new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per)); // 应用到所有平铺窗口 wl_list_for_each(tc, &clients, link) { @@ -354,7 +354,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, } grabc->master_inner_per = new_master_inner_per; - grabc->stack_innder_per = new_stack_innder_per; + grabc->stack_inner_per = new_stack_inner_per; if (!isdrag) { arrange(grabc->mon, false); @@ -402,7 +402,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int offsetx, int offsety, } else { grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; - grabc->old_stack_innder_per = grabc->stack_innder_per; + grabc->old_stack_inner_per = grabc->stack_inner_per; grabc->drag_begin_geom = grabc->geom; grabc->old_scroller_pproportion = grabc->scroller_proportion; grabc->cursor_in_upper_half = false; @@ -485,7 +485,8 @@ void resize_tile_client(Client *grabc, bool isdrag, int offsetx, int offsety, const Layout *current_layout = grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag]; if (current_layout->id == TILE || current_layout->id == DECK || - current_layout->id == CENTER_TILE || current_layout->id == RIGHT_TILE + current_layout->id == CENTER_TILE || current_layout->id == RIGHT_TILE || + (current_layout->id == TGMIX && grabc->mon->visible_tiling_clients <= 3) ) { resize_tile_master_horizontal(grabc, isdrag, offsetx, offsety, time, @@ -516,20 +517,18 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, wl_list_for_each(c, &clients, link) { if (VISIBLEON(c, m) && ISTILED(c)) { - - if (total_master_inner_percent <= 0.0) - return; - if (i < m->pertag->nmasters[m->pertag->curtag]) { + if (total_master_inner_percent > 0.0 && i < nmasters) { c->ismaster = true; - c->stack_innder_per = stack_num ? 1.0f / stack_num : 1.0f; + c->stack_inner_per = stack_num ? 1.0f / stack_num : 1.0f; c->master_inner_per = c->master_inner_per / total_master_inner_percent; } else { c->ismaster = false; - c->master_inner_per = 1.0f / master_num; - c->stack_innder_per = + c->master_inner_per = + master_num > 0 ? 1.0f / master_num : 1.0f; + c->stack_inner_per = total_stack_hight_percent - ? c->stack_innder_per / total_stack_hight_percent + ? c->stack_inner_per / total_stack_hight_percent : 1.0f; } i++; @@ -538,17 +537,14 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, } else { wl_list_for_each(c, &clients, link) { if (VISIBLEON(c, m) && ISTILED(c)) { - - if (total_master_inner_percent <= 0.0) - return; - if (i < m->pertag->nmasters[m->pertag->curtag]) { + if (total_master_inner_percent > 0.0 && i < nmasters) { c->ismaster = true; if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) { - c->stack_innder_per = + c->stack_inner_per = stack_num > 1 ? 1.0f / ((stack_num - 1) / 2) : 1.0f; } else { - c->stack_innder_per = + c->stack_inner_per = stack_num > 1 ? 2.0f / stack_num : 1.0f; } @@ -558,17 +554,18 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, stack_index = i - nmasters; c->ismaster = false; - c->master_inner_per = 1.0f / master_num; + c->master_inner_per = + master_num > 0 ? 1.0f / master_num : 1.0f; if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) { - c->stack_innder_per = + c->stack_inner_per = total_right_stack_hight_percent - ? c->stack_innder_per / + ? c->stack_inner_per / total_right_stack_hight_percent : 1.0f; } else { - c->stack_innder_per = + c->stack_inner_per = total_left_stack_hight_percent - ? c->stack_innder_per / + ? c->stack_inner_per / total_left_stack_hight_percent : 1.0f; } @@ -582,7 +579,7 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, void // 17 arrange(Monitor *m, bool want_animation) { Client *c = NULL; - double total_stack_innder_percent = 0; + double total_stack_inner_percent = 0; double total_master_inner_percent = 0; double total_right_stack_hight_percent = 0; double total_left_stack_hight_percent = 0; @@ -600,7 +597,6 @@ arrange(Monitor *m, bool want_animation) { m->visible_clients = 0; m->visible_tiling_clients = 0; m->visible_scroll_tiling_clients = 0; - m->has_visible_fullscreen_client = false; wl_list_for_each(c, &clients, link) { @@ -614,9 +610,6 @@ arrange(Monitor *m, bool want_animation) { if (!c->isunglobal) m->visible_clients++; - if (c->isfullscreen) - m->has_visible_fullscreen_client = true; - if (ISTILED(c)) { m->visible_tiling_clients++; } @@ -637,22 +630,22 @@ arrange(Monitor *m, bool want_animation) { if (VISIBLEON(c, m)) { if (ISTILED(c)) { - if (i < m->pertag->nmasters[m->pertag->curtag]) { + if (i < nmasters) { master_num++; total_master_inner_percent += c->master_inner_per; } else { stack_num++; - total_stack_innder_percent += c->stack_innder_per; + total_stack_inner_percent += c->stack_inner_per; stack_index = i - nmasters; if ((stack_index % 2) ^ (m->visible_tiling_clients % 2 == 0)) { c->isleftstack = false; total_right_stack_hight_percent += - c->stack_innder_per; + c->stack_inner_per; } else { c->isleftstack = true; total_left_stack_hight_percent += - c->stack_innder_per; + c->stack_inner_per; } } @@ -673,7 +666,7 @@ arrange(Monitor *m, bool want_animation) { reset_size_per_mon( m, m->visible_tiling_clients, total_left_stack_hight_percent, - total_right_stack_hight_percent, total_stack_innder_percent, + total_right_stack_hight_percent, total_stack_inner_percent, total_master_inner_percent, master_num, stack_num); if (m->isoverview) { @@ -686,4 +679,6 @@ arrange(Monitor *m, bool want_animation) { motionnotify(0, NULL, 0, 0, 0, 0); checkidleinhibitor(NULL); } + + printstatus(); } diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index 9a6a595..a9d6248 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -23,10 +23,6 @@ void grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { cw = (m->w.width - 2 * target_gappo) * single_width_ratio; @@ -49,10 +45,6 @@ void grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { if (i == 0) { @@ -99,10 +91,7 @@ void grid(Monitor *m) { if (c->mon != m) continue; - c->bw = - m->visible_tiling_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { cx = m->w.x + (i % cols) * (cw + target_gappi); @@ -386,6 +375,8 @@ void center_tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; + stack_num = n - master_num; if (n == 0) @@ -422,6 +413,19 @@ void center_tile(Monitor *m) { // 判断是否需要主区域铺满 int should_overspread = center_master_overspread && (n <= nmasters); + uint32_t master_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_left_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num / 2 - 1)); + float slave_left_surplus_ratio = 1.0; + + uint32_t slave_right_surplus_height = + (m->w.height - 2 * cur_gappov - + cur_gappiv * ie * ((stack_num + 1) / 2 - 1)); + float slave_right_surplus_ratio = 1.0; + if (n > nmasters || !should_overspread) { // 计算主区域宽度(居中模式) mw = nmasters ? (m->w.width - 2 * cur_gappoh - cur_gappih * ie) * mfact @@ -466,9 +470,11 @@ void center_tile(Monitor *m) { // 主区域窗口 r = MIN(n, nmasters) - i; if (c->master_inner_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (master_num - 1)) * - c->master_inner_per; + h = master_surplus_height * c->master_inner_per / + master_surplus_ratio; + master_surplus_height = master_surplus_height - h; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - my - cur_gappov - @@ -493,17 +499,17 @@ void center_tile(Monitor *m) { if (n - nmasters == 1) { // 单个堆叠窗口 r = n - i; - if (c->stack_innder_per > 0.0f) { + if (c->stack_inner_per > 0.0f) { h = (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1)) * - c->stack_innder_per; + c->stack_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - ety - cur_gappov - cur_gappiv * ie * (r - 1)) / r; - c->stack_innder_per = h / (m->w.height - ety - cur_gappov - - cur_gappiv * ie * (r - 1)); + c->stack_inner_per = h / (m->w.height - ety - cur_gappov - + cur_gappiv * ie * (r - 1)); c->master_mfact_per = mfact; } @@ -529,16 +535,19 @@ void center_tile(Monitor *m) { if ((stack_index % 2) ^ (n % 2 == 0)) { // 右侧堆叠窗口 - if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * ((stack_num + 1) / 2 - 1)) * - c->stack_innder_per; + if (c->stack_inner_per > 0.0f) { + h = slave_right_surplus_height * c->stack_inner_per / + slave_right_surplus_ratio; + slave_right_surplus_height = + slave_right_surplus_height - h; + slave_right_surplus_ratio = + slave_right_surplus_ratio - c->stack_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - ety - cur_gappov - cur_gappiv * ie * (r - 1)) / r; - c->stack_innder_per = + c->stack_inner_per = h / (m->w.height - ety - cur_gappov - cur_gappiv * ie * (r - 1)); c->master_mfact_per = mfact; @@ -555,16 +564,19 @@ void center_tile(Monitor *m) { ety += c->geom.height + cur_gappiv * ie; } else { // 左侧堆叠窗口 - if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (stack_num / 2 - 1)) * - c->stack_innder_per; + if (c->stack_inner_per > 0.0f) { + h = slave_left_surplus_height * c->stack_inner_per / + slave_left_surplus_ratio; + slave_left_surplus_height = + slave_left_surplus_height - h; + slave_left_surplus_ratio = + slave_left_surplus_ratio - c->stack_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - oty - cur_gappov - cur_gappiv * ie * (r - 1)) / r; - c->stack_innder_per = + c->stack_inner_per = h / (m->w.height - oty - cur_gappov - cur_gappiv * ie * (r - 1)); c->master_mfact_per = mfact; @@ -595,6 +607,7 @@ void tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; stack_num = n - master_num; if (n == 0) @@ -627,15 +640,26 @@ void tile(Monitor *m) { mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie; i = 0; my = ty = cur_gappov; + + uint32_t master_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1)); + float slave_surplus_ratio = 1.0; + wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; if (i < m->pertag->nmasters[m->pertag->curtag]) { r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i; if (c->master_inner_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (master_num - 1)) * - c->master_inner_per; + h = master_surplus_height * c->master_inner_per / + master_surplus_ratio; + master_surplus_height = master_surplus_height - h; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - my - cur_gappov - @@ -654,21 +678,22 @@ void tile(Monitor *m) { my += c->geom.height + cur_gappiv * ie; } else { r = n - i; - if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (stack_num - 1)) * - c->stack_innder_per; + if (c->stack_inner_per > 0.0f) { + h = slave_surplus_height * c->stack_inner_per / + slave_surplus_ratio; + slave_surplus_height = slave_surplus_height - h; + slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - ty - cur_gappov - cur_gappiv * ie * (r - 1)) / r; - c->stack_innder_per = h / (m->w.height - ty - cur_gappov - - cur_gappiv * ie * (r - 1)); + c->stack_inner_per = h / (m->w.height - ty - cur_gappov - + cur_gappiv * ie * (r - 1)); c->master_mfact_per = mfact; } - // wlr_log(WLR_ERROR, "stack_innder_per: %f", c->stack_innder_per); + // wlr_log(WLR_ERROR, "stack_inner_per: %f", c->stack_inner_per); resize(c, (struct wlr_box){.x = m->w.x + mw + cur_gappoh, @@ -692,6 +717,7 @@ void right_tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; stack_num = n - master_num; if (n == 0) @@ -724,15 +750,26 @@ void right_tile(Monitor *m) { mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie; i = 0; my = ty = cur_gappov; + + uint32_t master_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1)); + float slave_surplus_ratio = 1.0; + wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; if (i < m->pertag->nmasters[m->pertag->curtag]) { r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i; if (c->master_inner_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (master_num - 1)) * - c->master_inner_per; + h = master_surplus_height * c->master_inner_per / + master_surplus_ratio; + master_surplus_height = master_surplus_height - h; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - my - cur_gappov - @@ -752,21 +789,22 @@ void right_tile(Monitor *m) { my += c->geom.height + cur_gappiv * ie; } else { r = n - i; - if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (stack_num - 1)) * - c->stack_innder_per; + if (c->stack_inner_per > 0.0f) { + h = slave_surplus_height * c->stack_inner_per / + slave_surplus_ratio; + slave_surplus_height = slave_surplus_height - h; + slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - ty - cur_gappov - cur_gappiv * ie * (r - 1)) / r; - c->stack_innder_per = h / (m->w.height - ty - cur_gappov - - cur_gappiv * ie * (r - 1)); + c->stack_inner_per = h / (m->w.height - ty - cur_gappov - + cur_gappiv * ie * (r - 1)); c->master_mfact_per = mfact; } - // wlr_log(WLR_ERROR, "stack_innder_per: %f", c->stack_innder_per); + // wlr_log(WLR_ERROR, "stack_inner_per: %f", c->stack_inner_per); resize(c, (struct wlr_box){.x = m->w.x + cur_gappoh, @@ -802,4 +840,15 @@ monocle(Monitor *m) { } if ((c = focustop(m))) wlr_scene_node_raise_to_top(&c->scene->node); +} + +void tgmix(Monitor *m) { + uint32_t n = m->visible_tiling_clients; + if (n <= 3) { + tile(m); + return; + } else { + grid(m); + return; + } } \ No newline at end of file diff --git a/src/layout/layout.h b/src/layout/layout.h index 62a3227..169ab11 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -11,6 +11,7 @@ static void vertical_overview(Monitor *m); static void vertical_grid(Monitor *m); static void vertical_scroller(Monitor *m); static void vertical_deck(Monitor *mon); +static void tgmix(Monitor *m); /* layout(s) */ Layout overviewlayout = {"󰃇", overview, "overview"}; @@ -27,6 +28,7 @@ enum { VERTICAL_GRID, VERTICAL_DECK, RIGHT_TILE, + TGMIX, }; Layout layouts[] = { @@ -44,4 +46,5 @@ Layout layouts[] = { {"VT", vertical_tile, "vertical_tile", VERTICAL_TILE}, // 垂直平铺布局 {"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局 {"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局 + {"TG", tgmix, "tgmix", TGMIX}, // 混合布局 }; \ No newline at end of file diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 5badc72..b6dd27d 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -8,6 +8,7 @@ void vertical_tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; stack_num = n - master_num; if (n == 0) @@ -40,15 +41,26 @@ void vertical_tile(Monitor *m) { i = 0; mx = tx = cur_gapih; + + uint32_t master_surplus_width = + (m->w.width - 2 * cur_gapih - cur_gapih * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_surplus_width = + (m->w.width - 2 * cur_gapih - cur_gapih * ie * (stack_num - 1)); + float slave_surplus_ratio = 1.0; + wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; if (i < m->pertag->nmasters[m->pertag->curtag]) { r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i; if (c->master_inner_per > 0.0f) { - w = (m->w.width - 2 * cur_gapih - - cur_gapih * ie * (master_num - 1)) * - c->master_inner_per; + w = master_surplus_width * c->master_inner_per / + master_surplus_ratio; + master_surplus_width = master_surplus_width - w; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { w = (m->w.width - mx - cur_gapih - cur_gapih * ie * (r - 1)) / @@ -66,16 +78,17 @@ void vertical_tile(Monitor *m) { mx += c->geom.width + cur_gapih * ie; } else { r = n - i; - if (c->stack_innder_per > 0.0f) { - w = (m->w.width - 2 * cur_gapih - - cur_gapih * ie * (stack_num - 1)) * - c->stack_innder_per; + if (c->stack_inner_per > 0.0f) { + w = slave_surplus_width * c->stack_inner_per / + slave_surplus_ratio; + slave_surplus_width = slave_surplus_width - w; + slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per; c->master_mfact_per = mfact; } else { w = (m->w.width - tx - cur_gapih - cur_gapih * ie * (r - 1)) / r; - c->stack_innder_per = w / (m->w.width - tx - cur_gapih - - cur_gapih * ie * (r - 1)); + c->stack_inner_per = w / (m->w.width - tx - cur_gapih - + cur_gapih * ie * (r - 1)); c->master_mfact_per = mfact; } @@ -363,10 +376,6 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { ch = (m->w.height - 2 * target_gappo) * single_height_ratio; @@ -390,10 +399,6 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { if (i == 0) { @@ -436,10 +441,6 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; - c->bw = - m->visible_tiling_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { cx = m->w.x + (i / rows) * (cw + target_gappi); diff --git a/src/mango.c b/src/mango.c index 8811c84..4570a20 100644 --- a/src/mango.c +++ b/src/mango.c @@ -165,7 +165,7 @@ enum { }; /* EWMH atoms */ #endif enum { UP, DOWN, LEFT, RIGHT, UNDIR }; /* smartmovewin */ -enum { NONE, OPEN, MOVE, CLOSE, TAG, FOCUS }; +enum { NONE, OPEN, MOVE, CLOSE, TAG, FOCUS, OPAFADEIN, OPAFADEOUT }; enum { UNFOLD, FOLD, INVALIDFOLD }; enum { PREV, NEXT }; enum { STATE_UNSPECIFIED = 0, STATE_ENABLED, STATE_DISABLED }; @@ -351,6 +351,8 @@ struct Client { struct wl_listener foreign_fullscreen_request; struct wl_listener foreign_close_request; struct wl_listener foreign_destroy; + struct wl_listener foreign_minimize_request; + struct wl_listener foreign_maximize_request; struct wl_listener set_decoration_mode; struct wl_listener destroy_decoration; @@ -362,6 +364,7 @@ struct Client { int isglobal; int isnoborder; int isnoshadow; + int isnoradius; int isnoanimation; int isopensilent; int istagsilent; @@ -392,8 +395,8 @@ struct Client { float unfocused_opacity; char oldmonname[128]; int noblur; - double master_mfact_per, master_inner_per, stack_innder_per; - double old_master_mfact_per, old_master_inner_per, old_stack_innder_per; + double master_mfact_per, master_inner_per, stack_inner_per; + double old_master_mfact_per, old_master_inner_per, old_stack_inner_per; double old_scroller_pproportion; bool ismaster; bool cursor_in_upper_half, cursor_in_left_half; @@ -506,7 +509,6 @@ struct Monitor { uint32_t visible_clients; uint32_t visible_tiling_clients; uint32_t visible_scroll_tiling_clients; - bool has_visible_fullscreen_client; struct wlr_scene_optimized_blur *blur; char last_surface_ws_name[256]; struct wlr_ext_workspace_group_handle_v1 *ext_group; @@ -848,6 +850,8 @@ struct dvec2 *baked_points_open; struct dvec2 *baked_points_tag; struct dvec2 *baked_points_close; struct dvec2 *baked_points_focus; +struct dvec2 *baked_points_opafadein; +struct dvec2 *baked_points_opafadeout; static struct wl_event_source *hide_source; static bool cursor_hidden = false; @@ -1211,6 +1215,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) { APPLY_INT_PROP(c, r, isfullscreen); APPLY_INT_PROP(c, r, isnoborder); APPLY_INT_PROP(c, r, isnoshadow); + APPLY_INT_PROP(c, r, isnoradius); APPLY_INT_PROP(c, r, isnoanimation); APPLY_INT_PROP(c, r, isopensilent); APPLY_INT_PROP(c, r, istagsilent); @@ -1389,8 +1394,11 @@ void applyrules(Client *c) { // if no geom rule hit and is normal winodw, use the center pos and record // the hit size - if (!hit_rule_pos && (!client_is_x11(c) || !client_is_x11_popup(c))) { + if (!hit_rule_pos && + (!client_is_x11(c) || (c->geom.x == 0 && c->geom.y == 0))) { c->float_geom = c->geom = setclient_coordinate_center(c, c->geom, 0, 0); + } else { + c->float_geom = c->geom; } /*-----------------------apply rule action-------------------------*/ @@ -1708,10 +1716,11 @@ axisnotify(struct wl_listener *listener, void *data) { * implemented checking the event's orientation and the delta of the event */ /* Notify the client with pointer focus of the axis event. */ - wlr_seat_pointer_notify_axis(seat, // 滚轮事件发送给客户端也就是窗口 - event->time_msec, event->orientation, - event->delta, event->delta_discrete, - event->source, event->relative_direction); + wlr_seat_pointer_notify_axis( + seat, // 滚轮事件发送给客户端也就是窗口 + event->time_msec, event->orientation, event->delta * axis_scroll_factor, + roundf(event->delta_discrete * axis_scroll_factor), event->source, + event->relative_direction); } int ongesture(struct wlr_pointer_swipe_end_event *event) { @@ -1997,16 +2006,27 @@ buttonpress(struct wl_listener *listener, void *data) { } void checkidleinhibitor(struct wlr_surface *exclude) { - int inhibited = 0, unused_lx, unused_ly; + int inhibited = 0; + Client *c = NULL; + struct wlr_surface *surface = NULL; struct wlr_idle_inhibitor_v1 *inhibitor; + wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { - struct wlr_surface *surface = - wlr_surface_get_root_surface(inhibitor->surface); + surface = wlr_surface_get_root_surface(inhibitor->surface); + + if (exclude == surface) { + continue; + } + + toplevel_from_wlr_surface(inhibitor->surface, &c, NULL); + + if (idleinhibit_ignore_visible) { + inhibited = 1; + break; + } + struct wlr_scene_tree *tree = surface->data; - if (exclude != surface && - (inhibit_regardless_of_visibility || - (!tree || - wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) { + if (!tree || (tree->node.enabled && (!c || !c->animation.tagouting))) { inhibited = 1; break; } @@ -3431,8 +3451,12 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym, keycode == k->keysymcode.keycode.keycode3))) && k->func) { + if (!k->ispassapply) + handled = 1; + else + handled = 0; + isbreak = k->func(&k->arg); - handled = 1; if (isbreak) break; @@ -3699,18 +3723,24 @@ void init_client_properties(Client *c) { c->no_force_center = 0; c->isnoborder = 0; c->isnosizehint = 0; + c->isnoradius = 0; + c->isnoshadow = 0; c->ignore_maximize = 1; c->ignore_minimize = 1; c->iscustomsize = 0; c->master_mfact_per = 0.0f; c->master_inner_per = 0.0f; - c->stack_innder_per = 0.0f; + c->stack_inner_per = 0.0f; c->isterm = 0; c->allow_csd = 0; c->force_maximize = 0; c->force_tearing = 0; c->allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; c->scroller_proportion_single = 0.0f; + c->float_geom.width = 0; + c->float_geom.height = 0; + c->float_geom.x = 0; + c->float_geom.y = 0; } void // old fix to 0.5 @@ -4009,7 +4039,11 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, .y = grabc->geom.y, .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}; - resize(grabc, grabc->float_geom, 1); + if (last_apply_drap_time == 0 || + time - last_apply_drap_time > drag_refresh_interval) { + resize(grabc, grabc->float_geom, 1); + last_apply_drap_time = time; + } return; } else { resize_tile_client(grabc, true, 0, 0, time); @@ -4305,7 +4339,7 @@ void exchange_two_client(Client *c1, Client *c2) { uint32_t tmp_tags; double master_inner_per = 0.0f; double master_mfact_per = 0.0f; - double stack_innder_per = 0.0f; + double stack_inner_per = 0.0f; if (c1 == NULL || c2 == NULL || (!exchange_cross_monitor && c1->mon != c2->mon)) { @@ -4314,15 +4348,15 @@ void exchange_two_client(Client *c1, Client *c2) { master_inner_per = c1->master_inner_per; master_mfact_per = c1->master_mfact_per; - stack_innder_per = c1->stack_innder_per; + stack_inner_per = c1->stack_inner_per; c1->master_inner_per = c2->master_inner_per; c1->master_mfact_per = c2->master_mfact_per; - c1->stack_innder_per = c2->stack_innder_per; + c1->stack_inner_per = c2->stack_inner_per; c2->master_inner_per = master_inner_per; c2->master_mfact_per = master_mfact_per; - c2->stack_innder_per = stack_innder_per; + c2->stack_inner_per = stack_inner_per; struct wl_list *tmp1_prev = c1->link.prev; struct wl_list *tmp2_prev = c2->link.prev; @@ -4493,7 +4527,7 @@ setfloating(Client *c, int floating) { } // 重新计算居中的坐标 - if (!client_is_x11(c) || !client_is_x11_popup(c)) + if (!client_is_x11(c) || (c->geom.x == 0 && c->geom.y == 0)) target_box = setclient_coordinate_center(c, target_box, 0, 0); backup_box = c->geom; hit = applyrulesgeom(c); @@ -5700,8 +5734,15 @@ void handle_keyboard_shortcuts_inhibit_new_inhibitor( } // per-view, seat-agnostic config via criteria - Client *c = get_client_from_surface(inhibitor->surface); - if (c && !c->allow_shortcuts_inhibit) { + Client *c = NULL; + LayerSurface *l = NULL; + + int type = toplevel_from_wlr_surface(inhibitor->surface, &c, &l); + + if (type < 0) + return; + + if (type != LayerShell && c && !c->allow_shortcuts_inhibit) { return; }