diff --git a/README.md b/README.md index 843780ba..b927b920 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ And then rebuild your system. ## Other ```bash -git clone -b 0.19.3 https://gitlab.freedesktop.org/wlroots/wlroots.git +git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git cd wlroots meson build -Dprefix=/usr sudo ninja -C build install diff --git a/assets/config.conf b/assets/config.conf index eb326d16..15b654c1 100644 --- a/assets/config.conf +++ b/assets/config.conf @@ -34,7 +34,7 @@ animation_type_close=slide animation_fade_in=1 animation_fade_out=1 tag_animation_direction=1 -zoom_initial_ratio=0.4 +zoom_initial_ratio=0.3 zoom_end_ratio=0.8 fadein_begin_opacity=0.5 fadeout_begin_opacity=0.8 diff --git a/docs/bindings/keys.md b/docs/bindings/keys.md index b3a4ab64..64ba64b7 100644 --- a/docs/bindings/keys.md +++ b/docs/bindings/keys.md @@ -90,7 +90,6 @@ bindr=Super,Super_L,spawn,rofi -show run | :--- | :--- | :--- | | `killclient` | - | Close the focused window. | | `togglefloating` | - | Toggle floating state. | -| `toggle_all_floating` | - | Toggle all visible clients floating state. | | `togglefullscreen` | - | Toggle fullscreen. | | `togglefakefullscreen` | - | Toggle "fake" fullscreen (remains constrained). | | `togglemaximizescreen` | - | Maximize window (keep decoration/bar). | @@ -195,16 +194,6 @@ bind=NONE,XF86AudioMute,spawn,wpctl set-mute @DEFAULT_SINK@ toggle bind=SHIFT,XF86AudioMute,spawn,wpctl set-mute @DEFAULT_SOURCE@ toggle ``` -#### Playback - -Requires: `playerctl` - -```ini -bind=NONE,XF86AudioNext,spawn,playerctl next -bind=NONE,XF86AudioPrev,spawn,playerctl previous -bind=NONE,XF86AudioPlay,spawn,playerctl play-pause -``` - ### Floating Window Movement | Command | Param | Description | @@ -212,4 +201,4 @@ bind=NONE,XF86AudioPlay,spawn,playerctl play-pause | `smartmovewin` | `left/right/up/down` | Move floating window by snap distance. | | `smartresizewin` | `left/right/up/down` | Resize floating window by snap distance. | | `movewin` | `(x,y)` | Move floating window. | -| `resizewin` | `(width,height)` | Resize window. | +| `resizewin` | `(width,height)` | Resize window. | \ No newline at end of file diff --git a/docs/configuration/input.md b/docs/configuration/input.md index ac30f179..6d5eefdb 100644 --- a/docs/configuration/input.md +++ b/docs/configuration/input.md @@ -45,7 +45,6 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t | `tap_to_click` | `1` | Tap to trigger a left click. | | `tap_and_drag` | `1` | Tap and hold to drag items. | | `trackpad_natural_scrolling` | `0` | Invert scrolling direction (natural scrolling). | -| `scroll_button` | `274` | The mouse button that use for scrolling(272 to 279). | `scroll_method` | `1` | `1` (Two-finger), `2` (Edge), `4` (Button). | | `click_method` | `1` | `1` (Button areas), `2` (Clickfinger). | | `drag_lock` | `1` | Lock dragging after tapping. | @@ -58,16 +57,6 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t **Detailed descriptions:** -- `scroll_button` values: - - `272` — Left button. - - `273` — Right button. - - `274` — Middle button. - - `275` — Side button. - - `276` — Extra button. - - `277` — Forward button. - - `278` — Back button. - - `279` — Task button. - - `scroll_method` values: - `0` — Never send scroll events (no scrolling). - `1` — Two-finger scrolling: send scroll events when two fingers are logically down on the device. diff --git a/docs/installation.md b/docs/installation.md index 6f3927a0..10d2bd47 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -185,7 +185,7 @@ mangowm is available in the **PikaOS package repository**. You can install it using the `pikman` package manager: ```bash -pikman install mangowm +pikman install mangowc ``` --- @@ -214,7 +214,7 @@ You will need to build `wlroots` and `scenefx` manually as well. 1. **Build wlroots** Clone and install the specific version required (check README for latest version). ```bash - git clone -b 0.19.3 https://gitlab.freedesktop.org/wlroots/wlroots.git + git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git cd wlroots meson build -Dprefix=/usr sudo ninja -C build install diff --git a/docs/visuals/animations.md b/docs/visuals/animations.md index 76477e05..b4b88816 100644 --- a/docs/visuals/animations.md +++ b/docs/visuals/animations.md @@ -46,7 +46,7 @@ fadeout_begin_opacity=0.5 Adjust the zoom ratios for zoom animations. ```ini -zoom_initial_ratio=0.4 +zoom_initial_ratio=0.3 zoom_end_ratio=0.8 ``` diff --git a/docs/window-management/rules.md b/docs/window-management/rules.md index 93e81eba..996c172f 100644 --- a/docs/window-management/rules.md +++ b/docs/window-management/rules.md @@ -27,7 +27,7 @@ windowrule=Parameter:Values,Parameter:Values,appid:Values,title:Values | `isoverlay` | integer | `0` / `1` | Make it always in top layer | | `isopensilent` | integer | `0` / `1` | Open without focus | | `istagsilent` | integer | `0` / `1` | Don't focus if client is not in current view tag | -| `force_fakemaximize` | integer | `0` / `1` (default 1) | The state of client set to fake maximized | +| `force_maximize` | integer | `0` / `1` (default 1) | The state of client default to maximized | | `ignore_maximize` | integer | `0` / `1` (default 1) | Don't handle maximize request from client | | `ignore_minimize` | integer | `0` / `1` (default 1) | Don't handle minimize request from client | | `force_tiled_state` | integer | `0` / `1` | Deceive the window into thinking it is tiling, so it better adheres to assigned dimensions | @@ -179,7 +179,6 @@ tagrule=id:Values,monitor_make:xxx,monitor_model:xxx,Parameter:Values | `monitor_serial` | string | monitor serial | Match by monitor serial number | | `layout_name` | string | layout name | Layout name to set | | `no_render_border` | integer | `0` / `1` | Disable render border | -| `open_as_floating` | integer | `0` / `1` | New open window will be floating| | `no_hide` | integer | `0` / `1` | Not hide even if the tag is empty | | `nmaster` | integer | 0, 99 | Number of master windows | | `mfact` | float | 0.1–0.9 | Master area factor | diff --git a/mangowm.scm b/mangowm.scm index 44031ed0..7d94166d 100644 --- a/mangowm.scm +++ b/mangowm.scm @@ -15,7 +15,7 @@ #:use-module (gnu packages ninja) #:use-module (gnu packages pkg-config) #:use-module (guix build-system meson) - #:use-module ((guix licenses) #:prefix license:)) + #:use-module (guix licenses)) (define-public mangowm-git @@ -36,13 +36,10 @@ (add-before 'configure 'patch-meson (lambda _ (substitute* "meson.build" - ;; MangoWM ignores sysconfdir handling for NixOS. - ;; We also need to skip that sysconfdir edits. - (("is_nixos = false") - "is_nixos = true") - ;; Unhardcode path. Fixes loading default config. (("'-DSYSCONFDIR=\\\"@0@\\\"'.format\\('/etc'\\)") - "'-DSYSCONFDIR=\"@0@\"'.format(sysconfdir)"))))))) + "'-DSYSCONFDIR=\"@0@\"'.format(sysconfdir)") + (("sysconfdir = sysconfdir.substring\\(prefix.length\\(\\)\\)") + ""))))))) (inputs (list wayland libinput libdrm @@ -55,17 +52,14 @@ pcre2 libxcb xcb-util-wm - wlroots-0.19 + wlroots scenefx)) (native-inputs (list pkg-config wayland-protocols)) - (home-page "https://github.com/mangowm/mango") + (home-page "https://github.com/DreamMaoMao/mangowm") (synopsis "Wayland compositor based on wlroots and scenefx") - (description - "MangoWM is a modern, lightweight, high-performance Wayland compositor -built on dwl — crafted for speed, flexibility, and a customizable desktop experience.") - (license (list license:gpl3 ;mangowm itself, dwl - license:expat ;dwm, sway, wlroots - license:cc0)))) ;tinywl + (description "A Wayland compositor based on wlroots and scenefx, +inspired by dwl but aiming to be more feature-rich.") + (license gpl3))) (define-deprecated-package mangowc mangowm-git) diff --git a/meson.build b/meson.build index 64394cd9..5d09d536 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mango', ['c', 'cpp'], - version : '0.12.8', + version : '0.12.7', ) subdir('protocols') diff --git a/mmsg/mmsg.c b/mmsg/mmsg.c index 0191a635..4e0e1d8c 100644 --- a/mmsg/mmsg.c +++ b/mmsg/mmsg.c @@ -569,12 +569,12 @@ int32_t main(int32_t argc, char *argv[]) { mode = WATCH; break; case 'o': - if (mode == GET || mode == WATCH) - oflag = 1; - else if (mode == SET) + if (mode == SET) output_name = EARGF(usage()); else output_name = ARGF(); + if (!output_name) + oflag = 1; break; case 't': tflag = 1; diff --git a/nix/default.nix b/nix/default.nix index cb6497b9..87d4bfd0 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -67,8 +67,8 @@ stdenv.mkDerivation { meta = { mainProgram = "mango"; - description = "Practical and Powerful wayland compositor (dwm but wayland)"; - homepage = "https://github.com/mangowm/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/nix/hm-modules.nix b/nix/hm-modules.nix index f00d9c68..85d57908 100644 --- a/nix/hm-modules.nix +++ b/nix/hm-modules.nix @@ -1,22 +1,18 @@ -self: -{ +self: { lib, config, pkgs, ... -}: -let +}: let cfg = config.wayland.windowManager.mango; - selflib = import ./lib.nix lib; variables = lib.concatStringsSep " " cfg.systemd.variables; extraCommands = lib.concatStringsSep " && " cfg.systemd.extraCommands; - systemdActivation = "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables}; ${extraCommands}"; + systemdActivation = ''${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables}; ${extraCommands}''; autostart_sh = pkgs.writeShellScript "autostart.sh" '' ${lib.optionalString cfg.systemd.enable systemdActivation} ${cfg.autostart_sh} ''; -in -{ +in { options = { wayland.windowManager.mango = with lib; { enable = mkOption { @@ -58,7 +54,7 @@ in "XCURSOR_THEME" "XCURSOR_SIZE" ]; - example = [ "--all" ]; + example = ["--all"]; description = '' Environment variables imported into the systemd and D-Bus user environment. ''; @@ -79,195 +75,50 @@ in ''; }; settings = mkOption { - type = - with lib.types; - let - valueType = - nullOr (oneOf [ - bool - int - float - str - path - (attrsOf valueType) - (listOf valueType) - ]) - // { - description = "Mango configuration value"; - }; - in - valueType; - default = { }; - description = '' - Mango configuration written in Nix. Entries with the same key - should be written as lists. Variables and colors names should be - quoted. See for more examples. - - ::: {.note} - This option uses a structured format that is converted to Mango's - configuration syntax. Nested attributes are flattened with underscore separators. - For example: `animation.duration_open = 400` becomes `animation_duration_open = 400` - - Keymodes (submaps) are supported via the special `keymode` attribute. Each keymode - is a nested attribute set under `keymode` that contains its own bindings. - ::: - ''; - example = lib.literalExpression '' - { - # Window effects - blur = 1; - blur_optimized = 1; - blur_params = { - radius = 5; - num_passes = 2; - }; - border_radius = 6; - focused_opacity = 1.0; - - # Animations - use underscores for multi-part keys - animations = 1; - animation_type_open = "slide"; - animation_type_close = "slide"; - animation_duration_open = 400; - animation_duration_close = 800; - - # Or use nested attrs (will be flattened with underscores) - animation_curve = { - open = "0.46,1.0,0.29,1"; - close = "0.08,0.92,0,1"; - }; - - # Use lists for duplicate keys like bind and tagrule - bind = [ - "SUPER,r,reload_config" - "Alt,space,spawn,rofi -show drun" - "Alt,Return,spawn,foot" - "ALT,R,setkeymode,resize" # Enter resize mode - ]; - - tagrule = [ - "id:1,layout_name:tile" - "id:2,layout_name:scroller" - ]; - - # Keymodes (submaps) for modal keybindings - keymode = { - resize = { - bind = [ - "NONE,Left,resizewin,-10,0" - "NONE,Escape,setkeymode,default" - ]; - }; - }; - } - ''; - }; - extraConfig = mkOption { + description = "mango config content"; type = types.lines; default = ""; - description = '' - Extra configuration lines to add to `~/.config/mango/config.conf`. - This is useful for advanced configurations that don't fit the structured - settings format, or for options that aren't yet supported by the module. - ''; example = '' - # Advanced config that doesn't fit structured format - special_option = 1 + # menu and terminal + bind=Alt,space,spawn,rofi -show drun + bind=Alt,Return,spawn,foot ''; }; - topPrefixes = mkOption { - type = with lib.types; listOf str; - default = [ ]; - description = '' - List of prefixes for attributes that should appear at the top of the config file. - Attributes starting with these prefixes will be sorted to the beginning. - ''; - example = [ "source" ]; - }; - bottomPrefixes = mkOption { - type = with lib.types; listOf str; - default = [ ]; - description = '' - List of prefixes for attributes that should appear at the bottom of the config file. - Attributes starting with these prefixes will be sorted to the end. - ''; - example = [ "source" ]; - }; autostart_sh = mkOption { - description = '' - Shell script to run on mango startup. No shebang needed. - - When this option is set, the script will be written to - `~/.config/mango/autostart.sh` and an `exec-once` line - will be automatically added to the config to execute it. - ''; + description = "WARRNING: This is a shell script, but no need to add shebang"; type = types.lines; default = ""; example = '' waybar & - dunst & ''; }; }; }; - config = lib.mkIf cfg.enable ( - let - finalConfigText = - # Support old string-based config during transition period - ( - if builtins.isString cfg.settings then - cfg.settings - else - lib.optionalString (cfg.settings != { }) ( - selflib.toMango { - topCommandsPrefixes = cfg.topPrefixes; - bottomCommandsPrefixes = cfg.bottomPrefixes; - } cfg.settings - ) - ) - + lib.optionalString (cfg.extraConfig != "") cfg.extraConfig - + lib.optionalString (cfg.autostart_sh != "") "\nexec-once=~/.config/mango/autostart.sh\n"; - - validatedConfig = pkgs.runCommand "mango-config.conf" { } '' - cp ${pkgs.writeText "mango-config.conf" finalConfigText} "$out" - ${cfg.package}/bin/mango -c "$out" -p || exit 1 - ''; - in - { - # Backwards compatibility warning for old string-based config - warnings = lib.optional (builtins.isString cfg.settings) '' - wayland.windowManager.mango.settings: Using a string for settings is deprecated. - Please migrate to the new structured attribute set format. - See the module documentation for examples, or use the 'extraConfig' option for raw config strings. - The old string format will be removed in a future release. - ''; - - home.packages = [ cfg.package ]; - xdg.configFile = { - "mango/config.conf" = - lib.mkIf (cfg.settings != { } || cfg.extraConfig != "" || cfg.autostart_sh != "") - { - source = validatedConfig; - }; - "mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") { - source = autostart_sh; - executable = true; - }; + config = lib.mkIf cfg.enable { + home.packages = [cfg.package]; + xdg.configFile = { + "mango/config.conf" = lib.mkIf (cfg.settings != "") { + text = cfg.settings; }; - systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable { - Unit = { - Description = "mango compositor session"; - Documentation = [ "man:systemd.special(7)" ]; - BindsTo = [ "graphical-session.target" ]; - Wants = [ + "mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") { + source = autostart_sh; + executable = true; + }; + }; + systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable { + Unit = { + Description = "mango compositor session"; + Documentation = ["man:systemd.special(7)"]; + BindsTo = ["graphical-session.target"]; + Wants = + [ "graphical-session-pre.target" ] ++ lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target"; - After = [ "graphical-session-pre.target" ]; - Before = lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target"; - }; + After = ["graphical-session-pre.target"]; + Before = lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target"; }; - } - ); + }; + }; } diff --git a/nix/lib.nix b/nix/lib.nix deleted file mode 100644 index 9dfd2ff6..00000000 --- a/nix/lib.nix +++ /dev/null @@ -1,312 +0,0 @@ -lib: -let - inherit (lib) - attrNames - filterAttrs - foldl - generators - partition - removeAttrs - ; - - inherit (lib.strings) - concatMapStrings - hasPrefix - ; - - /** - Convert a structured Nix attribute set into Mango's configuration format. - - This function takes a nested attribute set and converts it into Mango-compatible - configuration syntax, supporting top, bottom, and regular command sections. - - Commands are flattened using the `flattenAttrs` function, and attributes are formatted as - `key = value` pairs. Lists are expanded as duplicate keys to match Mango's expected format. - - Configuration: - - * `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `[]`). - * `bottomCommandsPrefixes` - A list of prefixes to define **bottom** commands (default: `[]`). - - Attention: - - - The function ensures top commands appear **first** and bottom commands **last**. - - The generated configuration is a **single string**, suitable for writing to a config file. - - Lists are converted into multiple entries, ensuring compatibility with Mango. - - # Inputs - - Structured function argument: - - : topCommandsPrefixes (optional, default: `[]`) - : A list of prefixes that define **top** commands. Any key starting with one of these - prefixes will be placed at the beginning of the configuration. - : bottomCommandsPrefixes (optional, default: `[]`) - : A list of prefixes that define **bottom** commands. Any key starting with one of these - prefixes will be placed at the end of the configuration. - - Value: - - : The attribute set to be converted to Hyprland configuration format. - - # Type - - ``` - toMango :: AttrSet -> AttrSet -> String - ``` - - # Examples - :::{.example} - - ## Basic mangowc configuration - - ```nix - let - config = { - blur = 1; - blur_params_radius = 5; - border_radius = 6; - animations = 1; - animation_duration_open = 400; - }; - in lib.toMango {} config - ``` - - **Output:** - ``` - animations = 1 - animation_duration_open = 400 - blur = 1 - blur_params_radius = 5 - border_radius = 6 - ``` - - ## Using nested attributes - - ```nix - let - config = { - blur = 1; - blur_params = { - radius = 5; - num_passes = 2; - noise = 0.02; - }; - animation_curve = { - open = "0.46,1.0,0.29,1"; - close = "0.08,0.92,0,1"; - }; - }; - in lib.toMango {} config - ``` - - **Output:** - ``` - animation_curve_close = 0.08,0.92,0,1 - animation_curve_open = 0.46,1.0,0.29,1 - blur = 1 - blur_params_noise = 0.02 - blur_params_num_passes = 2 - blur_params_radius = 5 - ``` - - ## Using lists for duplicate keys - - ```nix - let - config = { - bind = [ - "SUPER,r,reload_config" - "Alt,space,spawn,rofi -show drun" - "Alt,Return,spawn,foot" - ]; - tagrule = [ - "id:1,layout_name:tile" - "id:2,layout_name:scroller" - ]; - }; - in lib.toMango {} config - ``` - - **Output:** - ``` - bind = SUPER,r,reload_config - bind = Alt,space,spawn,rofi -show drun - bind = Alt,Return,spawn,foot - tagrule = id:1,layout_name:tile - tagrule = id:2,layout_name:scroller - ``` - - ## Using keymodes (submaps) - - ```nix - let - config = { - bind = [ - "SUPER,Q,killclient" - "ALT,R,setkeymode,resize" - ]; - keymode = { - resize = { - bind = [ - "NONE,Left,resizewin,-10,0" - "NONE,Right,resizewin,10,0" - "NONE,Escape,setkeymode,default" - ]; - }; - }; - }; - in lib.toMango {} config - ``` - - **Output:** - ``` - bind = SUPER,Q,killclient - bind = ALT,R,setkeymode,resize - - keymode = resize - bind = NONE,Left,resizewin,-10,0 - bind = NONE,Right,resizewin,10,0 - bind = NONE,Escape,setkeymode,default - ``` - - ::: - */ - toMango = - { - topCommandsPrefixes ? [ ], - bottomCommandsPrefixes ? [ ], - }: - attrs: - let - toMango' = - attrs: - let - # Specially configured `toKeyValue` generator with support for duplicate keys - # and a legible key-value separator. - mkCommands = generators.toKeyValue { - mkKeyValue = generators.mkKeyValueDefault { } " = "; - listsAsDuplicateKeys = true; - indent = ""; # No indent, since we don't have nesting - }; - - # Extract keymode definitions if they exist - keymodes = attrs.keymode or { }; - attrsWithoutKeymodes = removeAttrs attrs [ "keymode" ]; - - # Generate keymode blocks - # Format: keymode=name\nbind=...\nbind=...\n - mkKeymodeBlock = - name: modeAttrs: - let - modeCommands = flattenAttrs (p: k: "${p}_${k}") modeAttrs; - in - "keymode = ${name}\n${mkCommands modeCommands}"; - - keymodeBlocks = - if keymodes == { } then - "" - else - "\n" + concatMapStrings (name: mkKeymodeBlock name keymodes.${name} + "\n") (attrNames keymodes); - - # Flatten the attrset, combining keys in a "path" like `"a_b_c" = "x"`. - # Uses `flattenAttrs` with an underscore separator. - commands = flattenAttrs (p: k: "${p}_${k}") attrsWithoutKeymodes; - - # General filtering function to check if a key starts with any prefix in a given list. - filterCommands = list: n: foldl (acc: prefix: acc || hasPrefix prefix n) false list; - - # Partition keys into top commands and the rest - result = partition (filterCommands topCommandsPrefixes) (attrNames commands); - topCommands = filterAttrs (n: _: builtins.elem n result.right) commands; - remainingCommands = removeAttrs commands result.right; - - # Partition remaining commands into bottom commands and regular commands - result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong; - bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands; - regularCommands = removeAttrs remainingCommands result2.right; - in - # Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands. - # Keymodes are appended at the end. - concatMapStrings mkCommands [ - topCommands - regularCommands - bottomCommands - ] - + keymodeBlocks; - in - toMango' attrs; - - /** - Flatten a nested attribute set into a flat attribute set, using a custom key separator function. - - This function recursively traverses a nested attribute set and produces a flat attribute set - where keys are joined using a user-defined function (`pred`). It allows transforming deeply - nested structures into a single-level attribute set while preserving key-value relationships. - - Configuration: - - * `pred` - A function `(string -> string -> string)` defining how keys should be concatenated. - - # Inputs - - Structured function argument: - - : pred (required) - : A function that determines how parent and child keys should be combined into a single key. - It takes a `prefix` (parent key) and `key` (current key) and returns the joined key. - - Value: - - : The nested attribute set to be flattened. - - # Type - - ``` - flattenAttrs :: (String -> String -> String) -> AttrSet -> AttrSet - ``` - - # Examples - :::{.example} - - ```nix - let - nested = { - a = "3"; - b = { c = "4"; d = "5"; }; - }; - - separator = (prefix: key: "${prefix}.${key}"); # Use dot notation - in lib.flattenAttrs separator nested - ``` - - **Output:** - ```nix - { - "a" = "3"; - "b.c" = "4"; - "b.d" = "5"; - } - ``` - - ::: - */ - flattenAttrs = - pred: attrs: - let - flattenAttrs' = - prefix: attrs: - builtins.foldl' ( - acc: key: - let - value = attrs.${key}; - newKey = if prefix == "" then key else pred prefix key; - in - acc // (if builtins.isAttrs value then flattenAttrs' newKey value else { "${newKey}" = value; }) - ) { } (builtins.attrNames attrs); - in - flattenAttrs' "" attrs; -in -{ - inherit flattenAttrs toMango; -} diff --git a/src/animation/client.h b/src/animation/client.h index e94f872a..8c9c3915 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -723,8 +723,6 @@ void client_animation_next_tick(Client *c) { c->is_pending_open_animation = false; - client_apply_clip(c, factor); - if (animation_passed >= 1.0) { // clear the open action state @@ -754,6 +752,8 @@ void client_animation_next_tick(Client *c) { // end flush in next frame, not the current frame c->need_output_flush = false; } + + client_apply_clip(c, factor); } void init_fadeout_client(Client *c) { diff --git a/src/client/client.h b/src/client/client.h index 965b4106..4788e448 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -294,8 +294,9 @@ static inline uint32_t client_set_size(Client *c, uint32_t width, uint32_t height) { #ifdef XWAYLAND if (client_is_x11(c)) { - struct wlr_xwayland_surface *surface = c->surface.xwayland; - struct wlr_surface_state *state = &surface->surface->current; + + struct wlr_surface_state *state = + &c->surface.xwayland->surface->current; if ((int32_t)c->geom.width - 2 * (int32_t)c->bw == (int32_t)state->width && @@ -308,22 +309,6 @@ static inline uint32_t client_set_size(Client *c, uint32_t width, return 0; } - xcb_size_hints_t *size_hints = surface->size_hints; - int32_t width = c->geom.width - 2 * c->bw; - int32_t height = c->geom.height - 2 * c->bw; - - if (c->mon && c->mon->isoverview && size_hints && - c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width && - c->geom.height - 2 * (int32_t)c->bw < size_hints->min_height) - return 0; - - if (size_hints && - c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width) - width = size_hints->min_width; - if (size_hints && - c->geom.height - 2 * (int32_t)c->bw < size_hints->min_height) - height = size_hints->min_height; - wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw, c->geom.y + c->bw, width, height); return 1; @@ -365,7 +350,7 @@ static inline void client_set_maximized(Client *c, bool maximized) { static inline void client_set_tiled(Client *c, uint32_t edges) { struct wlr_xdg_toplevel *toplevel; #ifdef XWAYLAND - if (client_is_x11(c) && c->force_fakemaximize) { + if (client_is_x11(c) && c->force_maximize) { wlr_xwayland_surface_set_maximized(c->surface.xwayland, edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE); @@ -380,7 +365,7 @@ static inline void client_set_tiled(Client *c, uint32_t edges) { wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); } - if (c->force_fakemaximize) { + if (c->force_maximize) { wlr_xdg_toplevel_set_maximized(toplevel, edges != WLR_EDGE_NONE); } } diff --git a/src/config/parse_config.h b/src/config/parse_config.h index e02b5017..6ae97406 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -90,7 +90,7 @@ typedef struct { int32_t no_force_center; int32_t isterm; int32_t allow_csd; - int32_t force_fakemaximize; + int32_t force_maximize; int32_t force_tiled_state; int32_t force_tearing; int32_t noswallow; @@ -168,7 +168,6 @@ typedef struct { float mfact; int32_t nmaster; int32_t no_render_border; - int32_t open_as_floating; int32_t no_hide; } ConfigTagRule; @@ -635,14 +634,9 @@ uint32_t parse_mod(const char *mod_str) { // 分割处理每个部分 token = strtok_r(input_copy, "+", &saveptr); while (token != NULL) { - // 去除前后空白 - trim_whitespace(token); - - // 如果 token 变成空字符串则跳过 - if (*token == '\0') { - token = strtok_r(NULL, "+", &saveptr); - continue; - } + // 去除空白 + while (*token == ' ' || *token == '\t') + token++; if (strncmp(token, "code:", 5) == 0) { // 处理 code: 形式 @@ -1202,8 +1196,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "scroller_stack") == 0) { func = scroller_stack; (*arg).i = parse_direction(arg_value); - } else if (strcmp(func_name, "toggle_all_floating") == 0) { - func = toggle_all_floating; } else { return NULL; } @@ -1907,7 +1899,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->nmaster = 0; rule->mfact = 0.0f; rule->no_render_border = 0; - rule->open_as_floating = 0; rule->no_hide = 0; bool parse_error = false; @@ -1936,8 +1927,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->monitor_serial = strdup(val); } else if (strcmp(key, "no_render_border") == 0) { rule->no_render_border = CLAMP_INT(atoi(val), 0, 1); - } else if (strcmp(key, "open_as_floating") == 0) { - rule->open_as_floating = CLAMP_INT(atoi(val), 0, 1); } else if (strcmp(key, "no_hide") == 0) { rule->no_hide = CLAMP_INT(atoi(val), 0, 1); } else if (strcmp(key, "nmaster") == 0) { @@ -2058,7 +2047,7 @@ bool parse_option(Config *config, char *key, char *value) { rule->indleinhibit_when_focus = -1; rule->isterm = -1; rule->allow_csd = -1; - rule->force_fakemaximize = -1; + rule->force_maximize = -1; rule->force_tiled_state = -1; rule->force_tearing = -1; rule->noswallow = -1; @@ -2172,8 +2161,8 @@ bool parse_option(Config *config, char *key, char *value) { rule->isterm = atoi(val); } else if (strcmp(key, "allow_csd") == 0) { rule->allow_csd = atoi(val); - } else if (strcmp(key, "force_fakemaximize") == 0) { - rule->force_fakemaximize = atoi(val); + } else if (strcmp(key, "force_maximize") == 0) { + rule->force_maximize = atoi(val); } else if (strcmp(key, "force_tiled_state") == 0) { rule->force_tiled_state = atoi(val); } else if (strcmp(key, "force_tearing") == 0) { @@ -3213,7 +3202,7 @@ void override_config(void) { config.accel_profile = CLAMP_INT(config.accel_profile, 0, 2); config.accel_speed = CLAMP_FLOAT(config.accel_speed, -1.0f, 1.0f); config.scroll_method = CLAMP_INT(config.scroll_method, 0, 4); - config.scroll_button = CLAMP_INT(config.scroll_button, 272, 279); + config.scroll_button = CLAMP_INT(config.scroll_button, 272, 276); config.click_method = CLAMP_INT(config.click_method, 0, 2); config.send_events_mode = CLAMP_INT(config.send_events_mode, 0, 2); config.button_map = CLAMP_INT(config.button_map, 0, 1); @@ -3263,7 +3252,7 @@ void set_value_default() { config.animation_fade_in = 1; config.animation_fade_out = 1; config.tag_animation_direction = HORIZONTAL; - config.zoom_initial_ratio = 0.4f; + config.zoom_initial_ratio = 0.3f; config.zoom_end_ratio = 0.8f; config.fadein_begin_opacity = 0.5f; config.fadeout_begin_opacity = 0.5f; @@ -3791,8 +3780,6 @@ void parse_tagrule(Monitor *m) { m->pertag->mfacts[tr.id] = tr.mfact; if (tr.no_render_border >= 0) m->pertag->no_render_border[tr.id] = tr.no_render_border; - if (tr.open_as_floating >= 0) - m->pertag->open_as_floating[tr.id] = tr.open_as_floating; } } diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index dbeebd33..7dced532 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -70,4 +70,3 @@ int32_t disable_monitor(const Arg *arg); int32_t enable_monitor(const Arg *arg); int32_t toggle_monitor(const Arg *arg); int32_t scroller_stack(const Arg *arg); -int32_t toggle_all_floating(const Arg *arg); \ No newline at end of file diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index f5992e29..449adf3b 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -376,11 +376,7 @@ int32_t moveresize(const Arg *arg) { /* Float the window and tell motionnotify to grab it */ if (grabc->isfloating == 0 && arg->ui == CurMove) { grabc->drag_to_tile = true; - exit_scroller_stack(grabc); setfloating(grabc, 1); - grabc->old_stack_inner_per = 0.0f; - grabc->old_master_inner_per = 0.0f; - set_size_per(grabc->mon, grabc); } switch (cursor_mode = arg->ui) { @@ -552,7 +548,7 @@ int32_t restore_minimized(const Arg *arg) { if (selmon && selmon->sel && selmon->sel->is_in_scratchpad && selmon->sel->is_scratchpad_show) { - client_pending_minimized_state(selmon->sel, 0); + selmon->sel->isminimized = 0; selmon->sel->is_scratchpad_show = 0; selmon->sel->is_in_scratchpad = 0; selmon->sel->isnamedscratchpad = 0; @@ -863,6 +859,7 @@ int32_t spawn_shell(const Arg *arg) { } int32_t spawn(const Arg *arg) { + if (!arg->v) return 0; @@ -875,21 +872,28 @@ int32_t spawn(const Arg *arg) { dup2(STDERR_FILENO, STDOUT_FILENO); setsid(); - // 2. 对整个参数字符串进行单词展开 - wordexp_t p; - if (wordexp(arg->v, &p, 0) != 0) { - wlr_log(WLR_DEBUG, "mango: wordexp failed for '%s'\n", arg->v); - _exit(EXIT_FAILURE); + // 2. 解析参数 + char *argv[64]; + int32_t argc = 0; + char *token = strtok((char *)arg->v, " "); + while (token != NULL && argc < 63) { + wordexp_t p; + if (wordexp(token, &p, 0) == 0) { + argv[argc++] = p.we_wordv[0]; + } else { + argv[argc++] = token; + } + token = strtok(NULL, " "); } + argv[argc] = NULL; - // 3. 执行命令(p.we_wordv 已经是 argv 数组) - execvp(p.we_wordv[0], p.we_wordv); + // 3. 执行命令 + execvp(argv[0], argv); - // 4. execvp 失败时:打印错误,释放 wordexp 资源,然后退出 - wlr_log(WLR_DEBUG, "mango: execvp '%s' failed: %s\n", p.we_wordv[0], + // 4. execvp 失败时:打印错误并直接退出(避免 coredump) + wlr_log(WLR_DEBUG, "mango: execvp '%s' failed: %s\n", argv[0], strerror(errno)); - wordfree(&p); // 释放 wordexp 分配的内存 - _exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); // 使用 _exit 避免缓冲区刷新等操作 } return 0; } @@ -1862,27 +1866,3 @@ int32_t scroller_stack(const Arg *arg) { arrange(selmon, false, false); return 0; } - -int32_t toggle_all_floating(const Arg *arg) { - if (!selmon || !selmon->sel) - return 0; - - Client *c = NULL; - bool should_floating = !selmon->sel->isfloating; - - wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, selmon)) { - - if (c->isfloating && !should_floating) { - c->old_master_inner_per = 0.0f; - c->old_stack_inner_per = 0.0f; - set_size_per(selmon, c); - } - - if (c->isfloating != should_floating) { - setfloating(c, should_floating); - } - } - } - return 0; -} diff --git a/src/fetch/client.h b/src/fetch/client.h index 8fe831be..0b142847 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -1,12 +1,15 @@ bool check_hit_no_border(Client *c) { + int32_t i; bool hit_no_border = false; if (!render_border) { hit_no_border = true; } - if (c->mon && !c->mon->isoverview && - c->mon->pertag->no_render_border[get_tags_first_tag_num(c->tags)]) { - hit_no_border = true; + for (i = 0; i < config.tag_rules_count; i++) { + if (c->tags & (1 << (config.tag_rules[i].id - 1)) && + config.tag_rules[i].no_render_border) { + hit_no_border = true; + } } if (config.no_border_when_single && c && c->mon && @@ -16,7 +19,6 @@ bool check_hit_no_border(Client *c) { } return hit_no_border; } - Client *termforwin(Client *w) { Client *c = NULL; diff --git a/src/mango.c b/src/mango.c index 8fdff709..df1315a1 100644 --- a/src/mango.c +++ b/src/mango.c @@ -391,7 +391,7 @@ struct Client { struct dwl_opacity_animation opacity_animation; int32_t isterm, noswallow; int32_t allow_csd; - int32_t force_fakemaximize; + int32_t force_maximize; int32_t force_tiled_state; pid_t pid; Client *swallowing, *swallowedby; @@ -806,10 +806,6 @@ static int32_t keep_idle_inhibit(void *data); static void check_keep_idle_inhibit(Client *c); static void pre_caculate_before_arrange(Monitor *m, bool want_animation, bool from_view, bool only_caculate); -static void client_pending_fullscreen_state(Client *c, int32_t isfullscreen); -static void client_pending_maximized_state(Client *c, int32_t ismaximized); -static void client_pending_minimized_state(Client *c, int32_t isminimized); - #include "data/static_keymap.h" #include "dispatch/bind_declare.h" #include "layout/layout.h" @@ -937,9 +933,8 @@ struct Pertag { uint32_t curtag, prevtag; /* current and previous tag */ int32_t nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ - int32_t no_hide[LENGTH(tags) + 1]; /* no_hide per tag */ - int32_t no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */ - int32_t open_as_floating[LENGTH(tags) + 1]; /* open_as_floating per tag */ + bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */ + bool no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */ const Layout *ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */ }; @@ -1067,33 +1062,11 @@ void clear_fullscreen_flag(Client *c) { } } -void client_pending_fullscreen_state(Client *c, int32_t isfullscreen) { - c->isfullscreen = isfullscreen; - - if (c->foreign_toplevel && !c->iskilling) - wlr_foreign_toplevel_handle_v1_set_fullscreen(c->foreign_toplevel, - isfullscreen); -} - -void client_pending_maximized_state(Client *c, int32_t ismaximized) { - c->ismaximizescreen = ismaximized; - if (c->foreign_toplevel && !c->iskilling) - wlr_foreign_toplevel_handle_v1_set_maximized(c->foreign_toplevel, - ismaximized); -} - -void client_pending_minimized_state(Client *c, int32_t isminimized) { - c->isminimized = isminimized; - if (c->foreign_toplevel && !c->iskilling) - wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, - isminimized); -} - void show_scratchpad(Client *c) { c->is_scratchpad_show = 1; if (c->isfullscreen || c->ismaximizescreen) { - client_pending_fullscreen_state(c, 0); - client_pending_maximized_state(c, 0); + c->isfullscreen = 0; // 清除窗口全屏标志 + c->ismaximizescreen = 0; c->bw = c->isnoborder ? 0 : config.borderpx; } @@ -1132,6 +1105,9 @@ void swallow(Client *c, Client *w) { c->bw = w->bw; c->isfloating = w->isfloating; c->isurgent = w->isurgent; + c->isfullscreen = w->isfullscreen; + c->ismaximizescreen = w->ismaximizescreen; + c->isminimized = w->isminimized; c->is_in_scratchpad = w->is_in_scratchpad; c->is_scratchpad_show = w->is_scratchpad_show; c->tags = w->tags; @@ -1143,7 +1119,6 @@ void swallow(Client *c, Client *w) { c->scroller_proportion = w->scroller_proportion; c->next_in_stack = w->next_in_stack; c->prev_in_stack = w->prev_in_stack; - if (w->next_in_stack) w->next_in_stack->prev_in_stack = c; if (w->prev_in_stack) @@ -1162,9 +1137,11 @@ void swallow(Client *c, Client *w) { if (!c->foreign_toplevel && c->mon) add_foreign_toplevel(c); - client_pending_fullscreen_state(c, w->isfullscreen); - client_pending_maximized_state(c, w->ismaximizescreen); - client_pending_minimized_state(c, w->isminimized); + if (c->isminimized && c->foreign_toplevel) { + wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, + false); + wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true); + } } bool switch_scratchpad_client_state(Client *c) { @@ -1347,7 +1324,7 @@ void toggle_hotarea(int32_t x_root, int32_t y_root) { static void apply_rule_properties(Client *c, const ConfigWinRule *r) { APPLY_INT_PROP(c, r, isterm); APPLY_INT_PROP(c, r, allow_csd); - APPLY_INT_PROP(c, r, force_fakemaximize); + APPLY_INT_PROP(c, r, force_maximize); APPLY_INT_PROP(c, r, force_tiled_state); APPLY_INT_PROP(c, r, force_tearing); APPLY_INT_PROP(c, r, noswallow); @@ -1425,25 +1402,6 @@ void set_float_malposition(Client *tc) { tc->float_geom.y = tc->geom.y = y; } -void client_reset_mon_tags(Client *c, Monitor *mon, uint32_t newtags) { - if (!newtags && mon && !mon->isoverview) { - c->tags = mon->tagset[mon->seltags]; - } else if (!newtags && mon && mon->isoverview) { - c->tags = mon->ovbk_current_tagset; - } else if (newtags) { - c->tags = newtags; - } else { - c->tags = mon->tagset[mon->seltags]; - } -} - -void check_match_tag_floating_rule(Client *c, Monitor *mon) { - if (c->tags && !c->isfloating && mon && !c->swallowedby && - mon->pertag->open_as_floating[get_tags_first_tag_num(c->tags)]) { - c->isfloating = 1; - } -} - void applyrules(Client *c) { /* rule matching */ const char *appid, *title; @@ -1568,7 +1526,6 @@ void applyrules(Client *c) { int32_t fullscreen_state_backup = c->isfullscreen || client_wants_fullscreen(c); - setmon(c, mon, newtags, !c->isopensilent && !(client_is_x11_popup(c) && client_should_ignore_focus(c)) && @@ -1576,11 +1533,6 @@ void applyrules(Client *c) { (!c->istagsilent || !newtags || newtags & mon->tagset[mon->seltags])); - if (!c->isfloating) { - c->old_stack_inner_per = c->stack_inner_per; - c->old_master_inner_per = c->master_inner_per; - } - if (c->mon && !(c->mon == selmon && c->tags & c->mon->tagset[c->mon->seltags]) && !c->isopensilent && !c->istagsilent) { @@ -4090,12 +4042,12 @@ void init_client_properties(Client *c) { c->master_mfact_per = 0.0f; c->master_inner_per = 0.0f; c->stack_inner_per = 0.0f; - c->old_stack_inner_per = 0.0f; - c->old_master_inner_per = 0.0f; - c->old_master_mfact_per = 0.0f; + c->old_stack_inner_per = 1.0f; + c->old_master_inner_per = 1.0f; + c->old_master_mfact_per = 1.0f; c->isterm = 0; c->allow_csd = 0; - c->force_fakemaximize = 0; + c->force_maximize = 0; c->force_tiled_state = 1; c->force_tearing = 0; c->allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; @@ -4253,7 +4205,7 @@ void maximizenotify(struct wl_listener *listener, void *data) { void unminimize(Client *c) { if (c && c->is_in_scratchpad && c->is_scratchpad_show) { - client_pending_minimized_state(c, 0); + c->isminimized = 0; c->is_scratchpad_show = 0; c->is_in_scratchpad = 0; c->isnamedscratchpad = 0; @@ -4281,12 +4233,13 @@ void set_minimized(Client *c) { c->oldtags = c->mon->tagset[c->mon->seltags]; c->mini_restore_tag = c->tags; c->tags = 0; - client_pending_minimized_state(c, 1); + c->isminimized = 1; c->is_in_scratchpad = 1; c->is_scratchpad_show = 0; focusclient(focustop(selmon), 1); arrange(c->mon, false, false); wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, false); + wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true); wl_list_remove(&c->link); // 从原来位置移除 wl_list_insert(clients.prev, &c->link); // 插入尾部 } @@ -5062,12 +5015,12 @@ setfloating(Client *c, int32_t floating) { if (floating == 1 && c != grabc) { - if (c->isfullscreen) { - client_pending_fullscreen_state(c, 0); - client_set_fullscreen(c, 0); + if (c->isfullscreen || c->ismaximizescreen) { + c->isfullscreen = 0; // 清除窗口全屏标志 + c->ismaximizescreen = 0; + c->bw = c->isnoborder ? 0 : config.borderpx; } - client_pending_maximized_state(c, 0); exit_scroller_stack(c); // 重新计算居中的坐标 @@ -5109,8 +5062,7 @@ setfloating(Client *c, int32_t floating) { // 让当前tag中的全屏窗口退出全屏参与平铺 wl_list_for_each(fc, &clients, link) if (fc && fc != c && VISIBLEON(fc, c->mon) && - c->tags & fc->tags && ISFULLSCREEN(fc) && - old_floating_state) { + c->tags & fc->tags && ISFULLSCREEN(fc)) { clear_fullscreen_flag(fc); } } @@ -5124,8 +5076,7 @@ setfloating(Client *c, int32_t floating) { layers[c->isfloating ? LyrTop : LyrTile]); } - if (!c->isfloating && old_floating_state && - (c->old_stack_inner_per > 0.0f || c->old_master_inner_per > 0.0f)) { + if (!c->isfloating && old_floating_state) { restore_size_per(c->mon, c); } @@ -5133,7 +5084,7 @@ setfloating(Client *c, int32_t floating) { save_old_size_per(c->mon); } - if (!c->force_fakemaximize) + if (!c->force_maximize) client_set_maximized(c, false); if (!c->isfloating || c->force_tiled_state) { @@ -5144,12 +5095,6 @@ setfloating(Client *c, int32_t floating) { } arrange(c->mon, false, false); - - if (!c->isfloating) { - c->old_master_inner_per = c->master_inner_per; - c->old_stack_inner_per = c->stack_inner_per; - } - setborder_color(c); printstatus(); } @@ -5192,17 +5137,18 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { return; int32_t old_maximizescreen_state = c->ismaximizescreen; - client_pending_maximized_state(c, maximizescreen); + c->ismaximizescreen = maximizescreen; if (maximizescreen) { - if (c->isfullscreen) { - client_pending_fullscreen_state(c, 0); - client_set_fullscreen(c, 0); - } + if (c->isfullscreen) + setfullscreen(c, 0); exit_scroller_stack(c); + if (c->isfloating) + c->float_geom = c->geom; + maximizescreen_box.x = c->mon->w.x + config.gappoh; maximizescreen_box.y = c->mon->w.y + config.gappov; maximizescreen_box.width = c->mon->w.width - 2 * config.gappoh; @@ -5210,8 +5156,10 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { wlr_scene_node_raise_to_top(&c->scene->node); if (!is_scroller_layout(c->mon) || c->isfloating) resize(c, maximizescreen_box, 0); + c->ismaximizescreen = 1; } else { c->bw = c->isnoborder ? 0 : config.borderpx; + c->ismaximizescreen = 0; if (c->isfloating) setfloating(c, 1); } @@ -5226,9 +5174,9 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { save_old_size_per(c->mon); } - if (!c->force_fakemaximize && !c->ismaximizescreen) { + if (!c->force_maximize && !c->ismaximizescreen) { client_set_maximized(c, false); - } else if (!c->force_fakemaximize && c->ismaximizescreen) { + } else if (!c->force_maximize && c->ismaximizescreen) { client_set_maximized(c, true); } @@ -5259,25 +5207,26 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自 c->isfullscreen = fullscreen; client_set_fullscreen(c, fullscreen); - client_pending_fullscreen_state(c, fullscreen); if (fullscreen) { - - if (c->ismaximizescreen && !c->force_fakemaximize) { - client_set_maximized(c, false); - } - - client_pending_maximized_state(c, 0); + if (c->ismaximizescreen) + setmaximizescreen(c, 0); exit_scroller_stack(c); + + if (c->isfloating) + c->float_geom = c->geom; + c->isfakefullscreen = 0; c->bw = 0; wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 if (!is_scroller_layout(c->mon) || c->isfloating) resize(c, c->mon->m, 1); + c->isfullscreen = 1; } else { c->bw = c->isnoborder ? 0 : config.borderpx; + c->isfullscreen = 0; if (c->isfloating) setfloating(c, 1); } @@ -5426,8 +5375,15 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) { /* Make sure window actually overlaps with the monitor */ reset_foreign_tolevel(c); resize(c, c->geom, 0); - client_reset_mon_tags(c, m, newtags); - check_match_tag_floating_rule(c, m); + if (!newtags && !m->isoverview) { + c->tags = m->tagset[m->seltags]; + } else if (!newtags && m->isoverview) { + c->tags = m->ovbk_current_tagset; + } else if (newtags) { + c->tags = newtags; + } else { + c->tags = m->tagset[m->seltags]; + } setfloating(c, c->isfloating); setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ } @@ -5469,7 +5425,8 @@ void show_hide_client(Client *c) { c->tags = c->oldtags; arrange(c->mon, false, false); } - client_pending_minimized_state(c, 0); + c->isminimized = 0; + wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, false); focusclient(c, 1); wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); } @@ -5893,8 +5850,8 @@ void overview_backup(Client *c) { c->isfloating = 0; } if (c->isfullscreen || c->ismaximizescreen) { - client_pending_fullscreen_state(c, 0); // 清除窗口全屏标志 - client_pending_maximized_state(c, 0); + c->isfullscreen = 0; // 清除窗口全屏标志 + c->ismaximizescreen = 0; } c->bw = c->isnoborder ? 0 : config.borderpx; @@ -5924,8 +5881,8 @@ void overview_restore(Client *c, const Arg *arg) { } else if (want_restore_fullscreen(c) && c->isfullscreen) { setfullscreen(c, 1); } else { - client_pending_fullscreen_state(c, 0); - client_pending_maximized_state(c, 0); + c->isfullscreen = 0; + c->ismaximizescreen = 0; setfullscreen(c, false); } } else { @@ -6498,11 +6455,13 @@ void activatex11(struct wl_listener *listener, void *data) { return; if (c->isminimized) { - client_pending_minimized_state(c, 0); + c->isminimized = 0; c->tags = c->mini_restore_tag; c->is_scratchpad_show = 0; c->is_in_scratchpad = 0; c->isnamedscratchpad = 0; + wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, + false); setborder_color(c); if (VISIBLEON(c, c->mon)) { need_arrange = true;