diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 914c1a4..0000000 --- a/.clang-format +++ /dev/null @@ -1,4 +0,0 @@ -BasedOnStyle: LLVM -UseTab: Always -TabWidth: 4 -IndentWidth: 4 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 5576f63..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug report -about: Something in mango isn't working correctly -title: "" -labels: "A: bug" -assignees: "" ---- - -## Info - - - - -mango version: -wlroots version: - -## Crash track -1.you need to build mango by enable asan flag. -```bash -meson build -Dprefix=/usr -Dasan=true -`` -2.run mango in tty. -```bash -export ASAN_OPTIONS="detect_leaks=1:halt_on_error=0:log_path=/home/xxx/asan.log" -mango - -``` - -3.after mango crash,paste the log file `/home/xxx/asan.log` here. - -## Description - - diff --git a/.github/ISSUE_TEMPLATE/enhancement-idea.md b/.github/ISSUE_TEMPLATE/enhancement-idea.md deleted file mode 100644 index 0ac096d..0000000 --- a/.github/ISSUE_TEMPLATE/enhancement-idea.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Enhancement idea -about: Suggest a feature or improvement -title: '' -labels: 'A: enhancement' -assignees: '' - ---- - - diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml deleted file mode 100644 index ad1080a..0000000 --- a/.github/workflows/lock.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Lock Threads - -on: - schedule: - - cron: "30 12 * * *" - workflow_dispatch: - -concurrency: - group: lock - -jobs: - lock: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - discussions: write - steps: - - uses: dessant/lock-threads@v5 - with: - issue-inactive-days: "30" - issue-comment: > - I'm going to lock this issue because it has been closed for _30 days_. ⏳ - - This helps our maintainers find and focus on the active issues. - If you have found a problem that seems similar to this, please file a new - issue and complete the issue template so we can capture all the details - necessary to investigate further. - pr-inactive-days: "30" - discussion-inactive-days: "30" - process-only: "issues,prs,discussions" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 43e8bad..0000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Close manually marked stale issues -on: - schedule: - - cron: "30 12 * * *" # 每天 UTC 12:30 运行 - -jobs: - close-issues: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/stale@v9 - with: - # 禁用自动标记 stale(仅手动标记的 issue 会被处理) - days-before-issue-stale: -1 - # 手动标记后,14 天后关闭 - days-before-issue-close: 7 - # 使用的标签(必须和你手动添加的标签一致) - stale-issue-label: "stale" - # 自动关闭时自动加上的标签 - close-issue-label: "automatic-closing" - # 关闭时的提示信息 - close-issue-message: "Sorry,this issue was closed because it was marked as stale and had no activity for 7 days." - # 禁用 PR 处理 - days-before-pr-stale: -1 - days-before-pr-close: -1 - repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 7681f94..0000000 --- a/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/.cache -/.vscode -/result -config.h -mango -mango.o -util.o -*-protocol.h -*-protocol.c -*-protocol.o diff --git a/README.md b/README.md index d512f39..d1370b3 100644 --- a/README.md +++ b/README.md @@ -1,299 +1,18 @@ -# Mango Wayland Compositor -
- MangoWC Logo -
+# Mango Wayland Compositor Nixpup Fork +![MangoWC Logo](https://codeberg.org/nixpup/MangoWC/raw/branch/main/mangowc_logo.png) -This project's development is based on [dwl](https://codeberg.org/dwl/dwl/). - - -1. **Lightweight & Fast Build** - - - _Mango_ is as lightweight as _dwl_, and can be built completely within a few seconds. Despite this, _Mango_ does not compromise on functionality. - -2. **Feature Highlights** - - In addition to basic WM functionality, Mango provides: - - Excellent xwayland support. - - Base tags not workspaces (supports separate window layouts for each tag) - - Smooth and customizable complete animations (window open/move/close, tag enter/leave,layer open/close/move) - - Excellent input method support (text input v2/v3) - - Flexible window layouts with easy switching (scroller, master-stack, monocle,center-master, etc.) - - Rich window states (swallow, minimize, maximize, unglobal, global, fakefullscreen, overlay, etc.) - - Simple yet powerful external configuration(support shortcuts hot-reload) - - Sway-like scratchpad and named scratchpad - - Ipc support(get/send message from/to compositor by external program) - - Hycov-like overview - - Window effects from scenefx (blur, shadow, corner radius, opacity) - -Master-Stack Layout - -https://github.com/user-attachments/assets/a9d4776e-b50b-48fb-94ce-651d8a749b8a - -Scroller Layout - -https://github.com/user-attachments/assets/c9bf9415-fad1-4400-bcdc-3ad2d76de85a - -Layer animation - -https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0 - - -# Our discord -[mangowc](https://discord.gg/CPjbDxesh5) - -# Supported layouts - -- tile -- scroller -- monocle -- grid -- deck -- center_tile -- vertical_tile -- vertical_grid -- vertical_scroller - -# Installation - -## Dependencies - -- glibc -- wayland -- wayland-protocols -- libinput -- libdrm -- libxkbcommon -- pixman -- git -- meson -- ninja -- libdisplay-info -- libliftoff -- hwdata -- seatd -- pcre2 -- xorg-xwayland -- libxcb - -## Arch Linux -The package is in the Arch User Repository and is availble for manual download [here](https://aur.archlinux.org/packages/mangowc-git) or through a AUR helper like yay: -```bash -yay -S mangowc-git +# Demo + +# New Features +This build of MangoWC supports *vertical stacking* within the *scroller* layout, similar to how the Niri Wayland Compositor and Window Manager works. This means by binding the following actions in your `~/.config/mango/config.conf`: ``` - -## Gentoo Linux -The package is in the community-maintained repository called GURU. -First, add GURU repository: - -```bash -emerge --ask --verbose eselect-repository -eselect repository enable guru -emerge --sync guru +bind=Alt,comma,stack_with_left +bind=Alt,period,unstack +bind=Alt,t,revert_size ``` +You can automatically split/resize the window to the left of the currently selected window, and then move/tile the currently selected window below the window to its left via the `stack_with_left` option. Removing a window from a stack is triggered by the `unstack` action, and with the `revert_size` action you can revert a window to its original size, meaning it gets resized back to using the full vertical screen size, and gets re-integrated into the scroller layout. -Then, add `gui-libs/scenefx` and `gui-wm/mangowc` to the `package.accept_keywords`. - -Finally, install the package: - -```bash -emerge --ask --verbose gui-wm/mangowc -``` - -## Fedora Linux -The package is in the third-party Terra repository. -First, add the [Terra Repository](https://terra.fyralabs.com/). - -Then, install the package: - -```bash -dnf install mangowc -``` - -## Other - -```bash -git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git -cd wlroots -meson build -Dprefix=/usr -sudo ninja -C build install - -git clone -b 0.4.1 https://github.com/wlrfx/scenefx.git -cd scenefx -meson build -Dprefix=/usr -sudo ninja -C build install - -git clone https://github.com/DreamMaoMao/mangowc.git -cd mangowc -meson build -Dprefix=/usr -sudo ninja -C build install -``` - -## Suggested Tools - -### Hybrid component -- [dms-shell](https://github.com/AvengeMedia/DankMaterialShell) - -### Independent component -- Application launcher (rofi, bemenu, wmenu, fuzzel) -- Terminal emulator (foot, wezterm, alacritty, kitty, ghostty) -- Status bar (waybar, eww, quickshell, ags), waybar is preferred -- Wallpaper setup (swww, swaybg) -- Notification daemon (swaync, dunst,mako) -- Desktop portal (xdg-desktop-portal, xdg-desktop-portal-wlr, xdg-desktop-portal-gtk) -- Clipboard (wl-clipboard, wl-clip-persist, cliphist) -- Gamma control/night light (wlsunset, gammastep) -- Miscellaneous (xfce-polkit, wlogout) - -## Some Common Default Keybindings - -- alt+return: open foot terminal -- alt+space: open rofi launcher -- alt+q: kill client -- alt+left/right/up/down: focus direction -- super+m: quit mango - -## My Dotfiles - -### Daily -- Dependencies - -```bash -yay -S rofi foot xdg-desktop-portal-wlr swaybg waybar wl-clip-persist cliphist wl-clipboard wlsunset xfce-polkit swaync pamixer wlr-dpms sway-audio-idle-inhibit-git swayidle dimland-git brightnessctl swayosd wlr-randr grim slurp satty swaylock-effects-git wlogout sox -``` - -### Dms -- Dependencies -```bash -yay -S foot xdg-desktop-portal-wlr swaybg wl-clip-persist cliphist wl-clipboard sway-audio-idle-inhibit-git brightnessctl grim slurp satty matugen-bin dms-shell-git - -``` -- use my dms config - -```bash -git clone -b dms https://github.com/DreamMaoMao/mango-config.git ~/.config/mango -``` -- use my daily config - -```bash -git clone https://github.com/DreamMaoMao/mango-config.git ~/.config/mango -``` - - -## Config Documentation - -Refer to the repo wiki [wiki](https://github.com/DreamMaoMao/mango/wiki/) - -or the website docs [docs](https://mangowc.vercel.app/docs) - -# NixOS + Home-manager - -The repo contains a flake that provides a NixOS module and a home-manager module for mango. -Use the NixOS module to install mango with other necessary components of a working Wayland environment. -Use the home-manager module to declare configuration and autostart for mango. - -Here's an example of using the modules in a flake: - -```nix -{ - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - home-manager = { - url = "github:nix-community/home-manager"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - flake-parts.url = "github:hercules-ci/flake-parts"; - mango = { - url = "github:DreamMaoMao/mango"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - }; - outputs = - inputs@{ self, flake-parts, ... }: - flake-parts.lib.mkFlake { inherit inputs; } { - debug = true; - systems = [ "x86_64-linux" ]; - flake = { - nixosConfigurations = { - hostname = inputs.nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - inputs.home-manager.nixosModules.home-manager - - # Add mango nixos module - inputs.mango.nixosModules.mango - { - programs.mango.enable = true; - } - { - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - backupFileExtension = "backup"; - users."username".imports = - [ - ( - { ... }: - { - wayland.windowManager.mango = { - enable = true; - settings = '' - # see config.conf - ''; - autostart_sh = '' - # see autostart.sh - # Note: here no need to add shebang - ''; - }; - } - ) - ] - ++ [ - # Add mango hm module - inputs.mango.hmModules.mango - ]; - }; - } - ]; - }; - }; - }; - }; -} -``` - -# Packaging mango - -To package mango for other distributions, you can check the reference setup for: - -- [nix](https://github.com/DreamMaoMao/mangowc/blob/main/nix/default.nix) -- [arch](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=mangowc-git). -- [gentoo](https://data.gpo.zugaina.org/guru/gui-wm/mangowc) - -You might need to package `scenefx` for your distribution, check availability [here](https://github.com/wlrfx/scenefx.git). - -If you encounter build errors when packaging `mango`, feel free to create an issue and ask a question, but -Read The Friendly Manual on packaging software in your distribution first. - -# Thanks to These Reference Repositories - -- https://gitlab.freedesktop.org/wlroots/wlroots - Implementation of Wayland protocol - -- https://github.com/dqrk0jeste/owl - Basal window animation - -- https://codeberg.org/dwl/dwl - Basal dwl feature - -- https://github.com/swaywm/sway - Sample of Wayland protocol - -- https://github.com/wlrfx/scenefx - Make it simple to add window effect. - - -# Sponsor -At present, I can only accept sponsorship through an encrypted connection. -If you find this project helpful to you, you can offer sponsorship in the following ways. - -image - - -Thanks to the following friends for their sponsorship of this project - -[@tonybanters](https://github.com/tonybanters) +## [Original MangoWC Repository](https://github.com/DreamMaoMao/mangowc) \ No newline at end of file diff --git a/config.conf b/config.conf index 6cbb3a2..2413b3b 100644 --- a/config.conf +++ b/config.conf @@ -1,7 +1,38 @@ -# More option see https://github.com/DreamMaoMao/mango/wiki/ +# Autostart +exec-once=wl-paste --watch cliphist store +exec-once=dex --autostart environment mango +exec-once=swaybg -i /home/puppy/Pictures/gruvbox_pokemon_marnie_wp_dark.png -m fill +exec-once=gammastep -l 52.520008:13.404954 -t 4000:4000 +exec-once=dunst +exec-once=noctalia-shell +exec-once=vicinae server + +# Environment +env=GBM_BACKEND,nvidia-drm +env=__GLX_VENDOR_LIBRARY_NAME,nvidia +env=DISPLAY,:0 +env=XDG_CURRENT_DESKTOP,mango +env=XDG_SESSION_TYPE,wayland +env=QT_QPA_PLATFORM,wayland +env=QT_QPA_PLATFORMTHEME,qt5ct +env=QT_WAYLAND_DISABLE_WINDOWDECORATION,1 +env=MOZ_ENABLE_WAYLAND,1 +env=NIXOS_OZONE_WL,1 +env=ELECTRON_OZONE_PLATFORM_HINT,wayland +env=OZONE_PLATFORM,wayland +env=GDK_BACKEND,wayland +env=WINDOW_MANAGER,mango +env=SDL_VIDEODRIVER,wayland + +# Input +xkb_rules_layout=us +xkb_rules_options=caps:ctrl_modifier,ctrl:swapcaps +repeat_rate=25 +repeat_delay=600 +numlockon=0 # Window effect -blur=0 +blur=1 blur_layer=0 blur_optimized=1 blur_params_num_passes = 2 @@ -11,7 +42,7 @@ blur_params_brightness = 0.9 blur_params_contrast = 0.9 blur_params_saturation = 1.2 -shadows = 0 +shadows = 1 layer_shadows = 0 shadow_only_floating = 1 shadows_size = 10 @@ -23,7 +54,7 @@ shadowscolor= 0x000000ff border_radius=6 no_radius_when_single=0 focused_opacity=1.0 -unfocused_opacity=1.0 +unfocused_opacity=0.8 # Animation Configuration(support type:zoom,slide) # tag_animation_direction: 1-horizontal,0-vertical @@ -87,19 +118,13 @@ snap_distance=30 cursor_size=24 drag_tile_to_tile=1 -# keyboard -repeat_rate=25 -repeat_delay=600 -numlockon=0 -xkb_rules_layout=us - # Trackpad # need relogin to make it apply disable_trackpad=0 tap_to_click=1 tap_and_drag=1 drag_lock=1 -trackpad_natural_scrolling=0 +trackpad_natural_scrolling=1 disable_while_typing=1 left_handed=0 middle_button_emulation=0 @@ -108,6 +133,7 @@ swipe_min_threshold=1 # mouse # need relogin to make it apply mouse_natural_scrolling=0 +sloppyfocus=1 # Appearance gappih=5 @@ -118,8 +144,8 @@ scratchpad_width_ratio=0.8 scratchpad_height_ratio=0.9 borderpx=4 rootcolor=0x201b14ff -bordercolor=0x444444ff -focuscolor=0xc9b890ff +bordercolor=0x1d1f21ff +focuscolor=0xff2a54ff maximizescreencolor=0x89aa61ff urgentcolor=0xad401fff scratchpadcolor=0x516c93ff @@ -128,51 +154,53 @@ overlaycolor=0x14a57cff # layout support: # tile,scroller,grid,deck,monocle,center_tile,vertical_tile,vertical_scroller -tagrule=id:1,layout_name:tile +tagrule=id:1,layout_name:scroller tagrule=id:2,layout_name:tile -tagrule=id:3,layout_name:tile -tagrule=id:4,layout_name:tile -tagrule=id:5,layout_name:tile -tagrule=id:6,layout_name:tile -tagrule=id:7,layout_name:tile +tagrule=id:3,layout_name:monocle +tagrule=id:4,layout_name:deck +tagrule=id:5,layout_name:grid +tagrule=id:6,layout_name:center_tile +tagrule=id:7,layout_name:vertical_tile tagrule=id:8,layout_name:tile tagrule=id:9,layout_name:tile -# Key Bindings -# key name refer to `xev` or `wev` command output, -# mod keys name: super,ctrl,alt,shift,none - # reload config -bind=SUPER,r,reload_config +bind=Alt+Shift,r,reload_config # menu and terminal -bind=Alt,space,spawn,rofi -show drun -bind=Alt,Return,spawn,foot +bind=Alt,f,spawn,vicinae open +bind=Alt+Shift,Return,spawn,kitty # exit -bind=SUPER,m,quit -bind=ALT,q,killclient, +#bind=Alt+Shift,x,quit +bind=Alt+Shift,x,spawn,~/.scripts/mango-exit.sh +bind=ALT+Shift,q,killclient, # switch window focus -bind=SUPER,Tab,focusstack,next +bind=Alt,Tab,focusstack,next bind=ALT,Left,focusdir,left bind=ALT,Right,focusdir,right bind=ALT,Up,focusdir,up bind=ALT,Down,focusdir,down # swap window -bind=SUPER+SHIFT,Up,exchange_client,up -bind=SUPER+SHIFT,Down,exchange_client,down -bind=SUPER+SHIFT,Left,exchange_client,left -bind=SUPER+SHIFT,Right,exchange_client,right +bind=Alt+SHIFT,Up,exchange_client,up +bind=Alt+SHIFT,Down,exchange_client,down +bind=Alt+SHIFT,Left,exchange_client,left +bind=Alt+SHIFT,Right,exchange_client,right + +# scroller stack operations +bind=Alt,comma,stack_with_left +bind=Alt,period,unstack +bind=Alt,t,revert_size # switch window status -bind=SUPER,g,toggleglobal, -bind=ALT,Tab,toggleoverview, -bind=ALT,backslash,togglefloating, -bind=ALT,a,togglemaximizescreen, -bind=ALT,f,togglefullscreen, -bind=ALT+SHIFT,f,togglefakefullscreen, +bind=ALT,g,toggleglobal, +bind=SUPER,Space,toggleoverview, +bind=Super,Space,togglefloating +bind=Alt+Shift,a,togglemaximizescreen, +bind=Alt+Shift,f,togglefullscreen, +bind=SUPER+Shift,f,togglefakefullscreen, bind=SUPER,i,minimized, bind=SUPER,o,toggleoverlay, bind=SUPER+SHIFT,I,restore_minimized @@ -180,52 +208,60 @@ bind=ALT,z,toggle_scratchpad # scroller layout bind=ALT,e,set_proportion,1.0 -bind=ALT,x,switch_proportion_preset, + +# Applications +bind=ALT+Shift,e,spawn,emacs-wayland +bind=Alt,d,spawn,firefox +bind=SUPER,e,spawn,thunar +bind=SUPER,t,spawn,marker +bind=SUPER,l,spawn,hyprlock +bind=SUPER,f,spawn,sherlock +bind=Alt,a,spawn,hyprshot -m region --clipboard-only # switch layout -bind=SUPER,n,switch_layout +bind=Alt,space,switch_layout # tag switch bind=SUPER,Left,viewtoleft,0 -bind=CTRL,Left,viewtoleft_have_client,0 +bind=CTRL+Super+Shift,Left,viewtoleft_have_client,0 bind=SUPER,Right,viewtoright,0 -bind=CTRL,Right,viewtoright_have_client,0 +bind=CTRL+SUPER+Shift,Right,viewtoright_have_client,0 bind=CTRL+SUPER,Left,tagtoleft,0 bind=CTRL+SUPER,Right,tagtoright,0 -bind=Ctrl,1,view,1,0 -bind=Ctrl,2,view,2,0 -bind=Ctrl,3,view,3,0 -bind=Ctrl,4,view,4,0 -bind=Ctrl,5,view,5,0 -bind=Ctrl,6,view,6,0 -bind=Ctrl,7,view,7,0 -bind=Ctrl,8,view,8,0 -bind=Ctrl,9,view,9,0 +bind=Alt,1,view,1,0 +bind=Alt,2,view,2,0 +bind=Alt,3,view,3,0 +bind=Alt,4,view,4,0 +bind=Alt,5,view,5,0 +bind=Alt,6,view,6,0 +bind=Alt,7,view,7,0 +bind=Alt,8,view,8,0 +bind=Alt,9,view,9,0 # tag: move client to the tag and focus it # tagsilent: move client to the tag and not focus it # bind=Alt,1,tagsilent,1 -bind=Alt,1,tag,1,0 -bind=Alt,2,tag,2,0 -bind=Alt,3,tag,3,0 -bind=Alt,4,tag,4,0 -bind=Alt,5,tag,5,0 -bind=Alt,6,tag,6,0 -bind=Alt,7,tag,7,0 -bind=Alt,8,tag,8,0 -bind=Alt,9,tag,9,0 +bind=Alt+Shift,1,tag,1,0 +bind=Alt+Shift,2,tag,2,0 +bind=Alt+Shift,3,tag,3,0 +bind=Alt+Shift,4,tag,4,0 +bind=Alt+Shift,5,tag,5,0 +bind=Alt+Shift,6,tag,6,0 +bind=Alt+Shift,7,tag,7,0 +bind=Alt+Shift,8,tag,8,0 +bind=Alt+Shift,9,tag,9,0 # monitor switch -bind=alt+shift,Left,focusmon,left -bind=alt+shift,Right,focusmon,right +bind=alt+shift,ctrl,Left,focusmon,left +bind=alt+shift,ctrl,Right,focusmon,right bind=SUPER+Alt,Left,tagmon,left bind=SUPER+Alt,Right,tagmon,right # gaps bind=ALT+SHIFT,X,incgaps,1 bind=ALT+SHIFT,Z,incgaps,-1 -bind=ALT+SHIFT,R,togglegaps +bind=ALT+SHIFT,G,togglegaps # movewin bind=CTRL+SHIFT,Up,movewin,+0,-50 @@ -241,9 +277,9 @@ bind=CTRL+ALT,Right,resizewin,+50,+0 # Mouse Button Bindings # NONE mode key only work in ov mode -mousebind=SUPER,btn_left,moveresize,curmove +mousebind=ALT,btn_left,moveresize,curmove mousebind=NONE,btn_middle,togglemaximizescreen,0 -mousebind=SUPER,btn_right,moveresize,curresize +mousebind=ALT,btn_right,moveresize,curresize mousebind=NONE,btn_left,toggleoverview,1 mousebind=NONE,btn_right,killclient,0 @@ -251,7 +287,9 @@ mousebind=NONE,btn_right,killclient,0 axisbind=SUPER,UP,viewtoleft_have_client axisbind=SUPER,DOWN,viewtoright_have_client - # layer rule layerrule=animation_type_open:zoom,layer_name:rofi layerrule=animation_type_close:zoom,layer_name:rofi + +# Window Rules +windowrule=tags:2,appid:vesktop diff --git a/demo.mp4 b/demo.mp4 new file mode 100644 index 0000000..2d44799 Binary files /dev/null and b/demo.mp4 differ diff --git a/mangowc_logo.png b/mangowc_logo.png new file mode 100644 index 0000000..974ab3f Binary files /dev/null and b/mangowc_logo.png differ diff --git a/nix/default.nix b/nix/default.nix index 6085565..52b2627 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -35,6 +35,10 @@ stdenv.mkDerivation { (lib.mesonBool "asan" debug) ]; + preConfigure = '' + rm -rf build + ''; + nativeBuildInputs = [ meson ninja diff --git a/result b/result new file mode 120000 index 0000000..479baac --- /dev/null +++ b/result @@ -0,0 +1 @@ +/nix/store/znxl3gxcqpx3bh1wdhhv7w5n2xxq05w2-mango-nightly \ No newline at end of file diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 9c27872..a90e337 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1080,6 +1080,26 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "toggle_monitor") == 0) { func = toggle_monitor; (*arg).v = strdup(arg_value); + } else if (strcmp(func_name, "expand_client_left") == 0) { + func = expand_client_left; + if (arg_value && *arg_value) { + (*arg).f = atof(arg_value); + } else { + (*arg).f = 0.05; + } + } else if (strcmp(func_name, "collapse_client_right") == 0) { + func = collapse_client_right; + if (arg_value && *arg_value) { + (*arg).f = atof(arg_value); + } else { + (*arg).f = -0.05; + } + } else if (strcmp(func_name, "stack_with_left") == 0) { + func = stack_with_left; + } else if (strcmp(func_name, "unstack") == 0) { + func = unstack; + } else if (strcmp(func_name, "revert_size") == 0) { + func = revert_size; } else { return NULL; } diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index b197778..a19a57c 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -68,4 +68,10 @@ int32_t toggle_trackpad_enable(const Arg *arg); int32_t setoption(const Arg *arg); int32_t disable_monitor(const Arg *arg); int32_t enable_monitor(const Arg *arg); +int32_t expand_client_left(const Arg *arg); +int32_t collapse_client_right(const Arg *arg); +int32_t stack_with_left(const Arg *arg); +int32_t unstack(const Arg *arg); +int32_t revert_size(const Arg *arg); + int32_t toggle_monitor(const Arg *arg); \ No newline at end of file diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 19d743e..21cdfea 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -1585,3 +1585,130 @@ int32_t toggle_monitor(const Arg *arg) { } return 0; } + +int32_t expand_client_left(const Arg *arg) { + Client *c = selmon->sel; + if (selmon && c && is_scroller_layout(selmon)) { + c->scroller_proportion += arg->f; + if (c->scroller_proportion > 1.0) + c->scroller_proportion = 1.0; + arrange(selmon, false, false); + } else { + setmfact(arg); + } + return 0; +} + +int32_t collapse_client_right(const Arg *arg) { + Client *c = selmon->sel; + if (selmon && c && is_scroller_layout(selmon)) { + c->scroller_proportion += arg->f; + if (c->scroller_proportion < 0.1) + c->scroller_proportion = 0.1; + arrange(selmon, false, false); + } else { + setmfact(arg); + } + return 0; +} + +int32_t stack_with_left(const Arg *arg) { + Client *c = selmon->sel; + if (!c || c->isfloating || !is_scroller_layout(selmon)) + return 0; + + Client *left_c = get_next_stack_client(c, true); + if (!left_c) + return 0; + + // If c is already in a stack, remove it. + if (c->prev_in_stack) { + c->prev_in_stack->next_in_stack = c->next_in_stack; + } + if (c->next_in_stack) { + c->next_in_stack->prev_in_stack = c->prev_in_stack; + } + // If c was a stack head, its next client becomes the new head. + if (c->next_in_stack) { + c->next_in_stack->prev_in_stack = NULL; + } + + + // Find the tail of left_c's stack + Client *stack_tail = left_c; + while (stack_tail->next_in_stack) { + stack_tail = stack_tail->next_in_stack; + } + + // Add c to the stack + stack_tail->next_in_stack = c; + c->prev_in_stack = stack_tail; + c->next_in_stack = NULL; + + arrange(selmon, false, false); + return 0; +} + +int32_t unstack(const Arg *arg) { + Client *c = selmon->sel; + if (!c || !c->prev_in_stack) { + // Not in a stack or is the head of a stack, do nothing. + return 0; + } + + Client *stack_head = c; + while(stack_head->prev_in_stack) { + stack_head = stack_head->prev_in_stack; + } + + // Remove c from its current stack + if (c->prev_in_stack) { + c->prev_in_stack->next_in_stack = c->next_in_stack; + } + if (c->next_in_stack) { + c->next_in_stack->prev_in_stack = c->prev_in_stack; + } + + c->next_in_stack = NULL; + c->prev_in_stack = NULL; + + // Insert c after the stack it was in + wl_list_remove(&c->link); + wl_list_insert(&stack_head->link, &c->link); + + focusclient(c, 1); + arrange(selmon, false, false); + return 0; +} + +int32_t revert_size(const Arg *arg) { + Client *c = selmon->sel; + if (!c) { + return 0; + } + + // Ensure the client is not floating and its size is managed by the layout + if (c->isfloating) { + setfloating(c, false); + } + c->iscustomsize = 0; // Let the layout manage its size + + // Explicitly remove the client from any stack it might be in + if (c->prev_in_stack) { + c->prev_in_stack->next_in_stack = c->next_in_stack; + } + if (c->next_in_stack) { + c->next_in_stack->prev_in_stack = c->prev_in_stack; + } + c->prev_in_stack = NULL; + c->next_in_stack = NULL; + + // Explicitly reset float_geom to ensure arrange recalculates geometry + c->float_geom = (struct wlr_box){0}; + + // The arrange function will now correctly size and position the window + // within the scroller layout, giving it full vertical size and preventing overlaps. + arrange(selmon, false, false); + + return 0; +} diff --git a/src/layout/arrange.h b/src/layout/arrange.h index d668f30..13141d9 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -627,7 +627,7 @@ arrange(Monitor *m, bool want_animation, bool from_view) { m->visible_tiling_clients++; } - if (ISSCROLLTILED(c)) { + if (ISSCROLLTILED(c) && !c->prev_in_stack) { m->visible_scroll_tiling_clients++; } } diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index a2f5e5c..6126574 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -212,6 +212,33 @@ void horizontal_scroll_adjust_fullandmax(Client *c, target_geom->y = m->w.y + (m->w.height - target_geom->height) / 2; } +void arrange_stack(Client *stack_head, struct wlr_box geometry, int32_t gappiv) { + int32_t stack_size = 0; + Client *iter = stack_head; + while (iter) { + stack_size++; + iter = iter->next_in_stack; + } + + if (stack_size == 0) return; + + int32_t client_height = (geometry.height - (stack_size - 1) * gappiv) / stack_size; + int32_t current_y = geometry.y; + + iter = stack_head; + while (iter) { + struct wlr_box client_geom = { + .x = geometry.x, + .y = current_y, + .width = geometry.width, + .height = client_height + }; + resize(iter, client_geom, 0); + current_y += client_height + gappiv; + iter = iter->next_in_stack; + } +} + // 滚动布局 void scroller(Monitor *m) { int32_t i, n, j; @@ -225,6 +252,8 @@ void scroller(Monitor *m) { int32_t cur_gappih = enablegaps ? m->gappih : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0; + int32_t cur_gappiv = enablegaps ? m->gappiv : 0; + cur_gappih = smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih; @@ -251,7 +280,7 @@ void scroller(Monitor *m) { // 第二次遍历,填充 tempClients j = 0; wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISSCROLLTILED(c)) { + if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) { tempClients[j] = c; j++; } @@ -269,7 +298,7 @@ void scroller(Monitor *m) { target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; - resize(c, target_geom, 0); + arrange_stack(c, target_geom, cur_gappiv); free(tempClients); // 释放内存 return; } @@ -283,6 +312,14 @@ void scroller(Monitor *m) { root_client = center_tiled_select(m); } + // root_client might be in a stack, find the stack head + if (root_client) { + while(root_client->prev_in_stack) { + root_client = root_client->prev_in_stack; + } + } + + if (!root_client) { free(tempClients); // 释放内存 return; @@ -317,10 +354,10 @@ void scroller(Monitor *m) { &target_geom); if (tempClients[focus_client_index]->isfullscreen) { target_geom.x = m->m.x; - resize(tempClients[focus_client_index], target_geom, 0); + arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); } else if (tempClients[focus_client_index]->ismaximizescreen) { target_geom.x = m->w.x + cur_gappoh; - resize(tempClients[focus_client_index], target_geom, 0); + arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); } else if (need_scroller) { if (scroller_focus_center || ((!m->prevsel || @@ -338,10 +375,10 @@ void scroller(Monitor *m) { scroller_structs) : m->w.x + scroller_structs; } - resize(tempClients[focus_client_index], target_geom, 0); + arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); } else { target_geom.x = c->geom.x; - resize(tempClients[focus_client_index], target_geom, 0); + arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); } for (i = 1; i <= focus_client_index; i++) { @@ -351,7 +388,7 @@ void scroller(Monitor *m) { target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - cur_gappih - target_geom.width; - resize(c, target_geom, 0); + arrange_stack(c, target_geom, cur_gappiv); } for (i = 1; i < n - focus_client_index; i++) { @@ -361,7 +398,7 @@ void scroller(Monitor *m) { target_geom.x = tempClients[focus_client_index + i - 1]->geom.x + cur_gappih + tempClients[focus_client_index + i - 1]->geom.width; - resize(c, target_geom, 0); + arrange_stack(c, target_geom, cur_gappiv); } free(tempClients); // 最后释放内存 diff --git a/src/mango.c b/src/mango.c index ac5edf9..57e4326 100644 --- a/src/mango.c +++ b/src/mango.c @@ -407,6 +407,8 @@ struct Client { int32_t allow_shortcuts_inhibit; float scroller_proportion_single; bool isfocusing; + struct Client *next_in_stack; + struct Client *prev_in_stack; }; typedef struct { diff --git a/thumbnail.png b/thumbnail.png new file mode 100644 index 0000000..987ddd4 Binary files /dev/null and b/thumbnail.png differ