diff --git a/README.md b/README.md index 9780ac6..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 diff --git a/config.conf b/config.conf index e72ee09..ed7c7e0 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 @@ -76,7 +78,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 67f4c10..596336f 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -240,8 +240,9 @@ void buffer_set_effect(Client *c, BufferData data) { if (c == grabc) data.should_scale = false; - if (c->isfullscreen || (no_radius_when_single && c->mon && - c->mon->visible_tiling_clients == 1)) { + if (c->isnoradius || c->isfullscreen || + (no_radius_when_single && c->mon && + c->mon->visible_tiling_clients == 1)) { data.corner_location = CORNER_LOCATION_NONE; } @@ -354,11 +355,13 @@ 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->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->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) { @@ -630,6 +633,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 = @@ -650,7 +654,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, @@ -701,10 +711,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){ @@ -1109,8 +1119,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/config/parse_config.h b/src/config/parse_config.h index cd0d2d3..68133d3 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -64,6 +64,7 @@ typedef struct { const char *layer_animation_type_close; int isnoborder; int isnoshadow; + int isnoradius; int isnoanimation; int isopensilent; int istagsilent; @@ -194,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; @@ -237,7 +240,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; @@ -264,6 +267,8 @@ typedef struct { uint32_t send_events_mode; uint32_t button_map; + double axis_scroll_factor; + int blur; int blur_layer; int blur_optimized; @@ -1187,6 +1192,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) { @@ -1446,8 +1467,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) { @@ -1494,6 +1515,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) { @@ -1691,6 +1714,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; @@ -1780,6 +1804,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) { @@ -2406,6 +2432,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) { @@ -2719,8 +2753,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); @@ -2764,6 +2798,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); @@ -2820,6 +2855,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() { @@ -2888,6 +2927,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; @@ -2903,8 +2943,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 */ @@ -2969,6 +3009,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)); @@ -3171,9 +3215,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) { @@ -3293,5 +3365,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 8c52445..1f43f19 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; // 滚轮绑定动作的触发的时间间隔 @@ -79,7 +81,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 */ @@ -105,7 +107,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; @@ -177,6 +179,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 63ddfea..ad715b4 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -196,15 +196,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; } } @@ -212,10 +214,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); } 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/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 7195416..f779f88 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -389,30 +389,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 d6d6f0a..7344844 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, @@ -520,16 +521,16 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, if (VISIBLEON(c, m) && ISTILED(c)) { 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 = master_num > 0 ? 1.0f / master_num : 1.0f; - c->stack_innder_per = + 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++; @@ -541,11 +542,11 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, 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,15 +559,15 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_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; } @@ -580,7 +581,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; @@ -598,7 +599,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) { @@ -612,9 +612,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++; } @@ -640,17 +637,17 @@ arrange(Monitor *m, bool want_animation) { 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; } } @@ -671,7 +668,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) { diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index 4d9f4c4..c82e554 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -705,17 +705,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; } @@ -741,19 +741,19 @@ void center_tile(Monitor *m) { if ((stack_index % 2) ^ (n % 2 == 0)) { // 右侧堆叠窗口 - if (c->stack_innder_per > 0.0f) { - h = slave_right_surplus_height * 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_innder_per; + 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; @@ -770,19 +770,19 @@ void center_tile(Monitor *m) { ety += c->geom.height + cur_gappiv * ie; } else { // 左侧堆叠窗口 - if (c->stack_innder_per > 0.0f) { - h = slave_left_surplus_height * 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_innder_per; + 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; @@ -884,22 +884,22 @@ void tile(Monitor *m) { my += c->geom.height + cur_gappiv * ie; } else { r = n - i; - if (c->stack_innder_per > 0.0f) { - h = slave_surplus_height * 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_innder_per; + 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, @@ -995,22 +995,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 = slave_surplus_height * 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_innder_per; + 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, @@ -1047,3 +1047,14 @@ 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; + } +} diff --git a/src/layout/layout.h b/src/layout/layout.h index 1564e6d..9615cbc 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -12,6 +12,7 @@ static void vertical_grid(Monitor *m); static void vertical_scroller(Monitor *m); static void vertical_deck(Monitor *mon); static void dual_scroller(Monitor *mon); +static void tgmix(Monitor *m); /* layout(s) */ Layout overviewlayout = {"󰃇", overview, "overview"}; @@ -29,6 +30,7 @@ enum { VERTICAL_DECK, RIGHT_TILE, DUAL_SCROLLER, + TGMIX, }; Layout layouts[] = { @@ -47,4 +49,5 @@ Layout layouts[] = { {"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局 {"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局 {"DS", dual_scroller, "dual_scroller", DUAL_SCROLLER}, // 双行滚动布局 -}; \ No newline at end of file + {"TG", tgmix, "tgmix", TGMIX}, // 混合布局 +}; diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 3893a4c..b6dd27d 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -78,17 +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 = slave_surplus_width * 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_innder_per; + 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; } diff --git a/src/mango.c b/src/mango.c index 3d8b9fa..12a11b3 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 }; @@ -364,6 +364,7 @@ struct Client { int isglobal; int isnoborder; int isnoshadow; + int isnoradius; int isnoanimation; int isopensilent; int istagsilent; @@ -394,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; int dual_scroller_row; // 0 = top row, 1 = bottom row, -1 = not set @@ -509,7 +510,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; @@ -852,6 +852,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; @@ -1215,6 +1217,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); @@ -1393,8 +1396,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-------------------------*/ @@ -1712,10 +1718,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) { @@ -2001,16 +2008,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; } @@ -3436,13 +3454,13 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym, keycode == k->keysymcode.keycode.keycode3))) && k->func) { - isbreak = k->func(&k->arg); - if (!k->ispassapply) handled = 1; else handled = 0; + isbreak = k->func(&k->arg); + if (isbreak) break; } @@ -3708,18 +3726,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 @@ -4023,7 +4047,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); @@ -4319,7 +4347,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)) { @@ -4328,15 +4356,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; @@ -4507,7 +4535,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);