diff --git a/home/pc/common/home.nix b/home/pc/common/home.nix index 9f6a92d..e4bf599 100644 --- a/home/pc/common/home.nix +++ b/home/pc/common/home.nix @@ -8,12 +8,16 @@ ./clangd.nix ./packages.nix ./xdg.nix + + ./river ]; home.username = "autumn"; home.homeDirectory = "/home/autumn"; home.stateVersion = "25.05"; + # programs.ghostty.enable = true; + # programs.ghostty.settings.font-size = 24; programs.foot = { enable = true; settings.main.font = lib.mkForce "Caskaydia Cove Mono:size=24"; diff --git a/home/pc/common/programs/default.nix b/home/pc/common/programs/default.nix index 8c08b20..d4d70d5 100644 --- a/home/pc/common/programs/default.nix +++ b/home/pc/common/programs/default.nix @@ -6,8 +6,9 @@ ./btop.nix ./carapace.nix # ./fastfetch.nix - ./fish.nix + #./fish.nix ./git.nix + ./havoc.nix # ./hyfetch.nix ./mako.nix # ./ncspot.nix @@ -15,6 +16,7 @@ ./vesktop.nix ./waybar.nix # ./yazi.nix + ./yash.nix ./zathura.nix ./zen.nix ./zoxide.nix diff --git a/home/pc/common/programs/havoc.nix b/home/pc/common/programs/havoc.nix new file mode 100644 index 0000000..dc0c8d1 --- /dev/null +++ b/home/pc/common/programs/havoc.nix @@ -0,0 +1,57 @@ +{ pkgs, ... }: +{ + home.packages = [ pkgs.havoc ]; + xdg.configFile."havoc/havoc.cfg".text = '' + [child] + program=yash + + [window] + margin=yes + + [bind] + C-S-c=copy + C-S-v=paste + C-S-j=scroll down + C-S-k=scroll up + + [font] + size=30 + path=${pkgs.nerd-fonts.caskaydia-cove}/share/fonts/truetype/NerdFonts/CaskaydiaCove/CaskaydiaCoveNerdFontMono-Regular.ttf + + [colors] + foreground=#cdd6f7 + background=#11111b + + # black + color0 = #45475a + color8 = #585b70 + + # red + color1 = #f38ba8 + color9 = #f38ba8 + + # green + color2 = #a6e3a1 + color10 = #a6e3a1 + + # yellow + color3 = #f9e2af + color11 = #f9e2af + + # blue + color4 = #89b4fa + color12 = #89b4fa + + # magenta + color5 = #f5c2e7 + color13 = #f5c2e7 + + # cyan + color6 = #94e2d5 + color14 = #94e2d5 + + # white + color7 = #bac2de + color15 = #a6adc8 + ''; +} diff --git a/home/pc/common/programs/nvim/config.lua b/home/pc/common/programs/nvim/config.lua index bea3147..91c1c33 100644 --- a/home/pc/common/programs/nvim/config.lua +++ b/home/pc/common/programs/nvim/config.lua @@ -10,7 +10,7 @@ vim.opt.softtabstop = 4 vim.opt.wildmenu = true vim.opt.undofile = true vim.opt.termguicolors = true -vim.opt.shell = "fish" +vim.opt.shell = "yash" vim.opt.splitbelow = true vim.opt.splitright = true vim.opt.winborder = "rounded" @@ -29,6 +29,7 @@ vim.keymap.set("n", "q", function() vim.cmd("hori term") vim.cmd("startinsert") end, {}) + vim.keymap.set("t", "", "", {}) vim.pack.add({ @@ -45,7 +46,12 @@ vim.pack.add({ "https://github.com/ej-shafran/compile-mode.nvim", "https://github.com/m00qek/baleia.nvim", "https://github.com/nvim-lualine/lualine.nvim", - "https://github.com/stevearc/oil.nvim" + "https://github.com/stevearc/oil.nvim", + "https://github.com/folke/lazydev.nvim", +}) + +require("lazydev").setup({ + ft = "lua", }) require("oil").setup({ @@ -69,7 +75,7 @@ vim.g.compile_mode = { buffer_name = "*compile*", baleia_setup = true, } -vim.keymap.set("n", "c", "Recompile", {silent = true}) +vim.keymap.set("n", "c", "Recompile", { silent = true }) local file_types = { "rust", "zig", "haskell", "c", "cpp" } require("nvim-treesitter").install(file_types) @@ -117,7 +123,7 @@ cmp.setup({ { name = "emoji" }, { keywordLength = 3, name = "buffer", option = { get_bufnrs = vim.api.nvim_list_bufs } }, { keywordLength = 3, name = "path" }, - { keywordLength = 3, name = "luasnip" }, + { name = "lazydev" }, }, window = { completion = cmp.config.window.bordered(), @@ -157,8 +163,10 @@ vim.lsp.config("nil_ls", { cmd = { "nil" }, filetypes = { "nix" } }) vim.lsp.enable("nil_ls") vim.lsp.config("nixd", { cmd = { "nixd" }, filetypes = { "nix" } }) vim.lsp.enable("nixd") -vim.lsp.config("pyright", { cmd = { "pyright" }, filetypes = { "python" } }) +vim.lsp.config("pyright", { cmd = { "pyright-langserver", "--stdio" }, filetypes = { "python" } }) vim.lsp.enable("pyright") +vim.lsp.config("rust-analyzer", { cmd = { "rust-analyzer" }, filetypes = { "rust" } }) +vim.lsp.enable("rust-analyzer") vim.lsp.config("zls", { cmd = { "zls" }, filetypes = { "zig" } }) vim.lsp.enable("zls") diff --git a/home/pc/common/programs/rofi/config.nix b/home/pc/common/programs/rofi/config.nix index de283cc..83b49dc 100644 --- a/home/pc/common/programs/rofi/config.nix +++ b/home/pc/common/programs/rofi/config.nix @@ -1,27 +1,47 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { home.packages = [ pkgs.libnotify ]; xdg.configFile."rofi/config.rasi".text = '' configuration{ - modi: "run,drun,window"; + modi: "run"; lines: 5; cycle: false; - font: "${config.stylix.fonts.serif.name} 14"; - show-icons: true; - icon-theme: "Papirus-dark"; + font: "CaskaydiaCove Nerd Font 14"; + show-icons: false; terminal: "foot"; - drun-display-format: "{icon} {name}"; + run-display-format: "{name}"; location: 0; disable-history: true; hide-scrollbar: true; - display-drun: " Apps "; display-run: " Run "; - display-window: " Window "; - /* display-Network: " Network"; */ sidebar-mode: true; sorting-method: "fzf"; } + + @theme "theme" + ''; - @theme "theme"''; + # xdg.configFile."rofi/config.rasi".text = '' + # configuration{ + # modi: "run,drun,window"; + # lines: 5; + # cycle: false; + # font: "${config.stylix.fonts.serif.name} 14"; + # show-icons: true; + # icon-theme: "Papirus-dark"; + # terminal: "foot"; + # drun-display-format: "{icon} {name}"; + # location: 0; + # disable-history: true; + # hide-scrollbar: true; + # display-drun: " Apps "; + # display-run: " Run "; + # display-window: " Window "; + # /* display-Network: " Network"; */ + # sidebar-mode: true; + # sorting-method: "fzf"; + # } + # + # @theme "theme"''; } diff --git a/home/pc/common/programs/yash.nix b/home/pc/common/programs/yash.nix new file mode 100644 index 0000000..5bd8cf2 --- /dev/null +++ b/home/pc/common/programs/yash.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: +{ + home.packages = [ pkgs.yash ]; + xdg.configFile."yash/rc".text = + " + . --autoload --no-alias initialization/common + YASH_PS1='\\fm\${PWD} λ \\fD' + YASH_PS1R='' + bindkey --emacs '\\^L' clear-and-redraw-all + bindkey --vi-insert '\\^L' clear-and-redraw-all + bindkey --vi-command '\\^L' clear-and-redraw-all + "; +} diff --git a/home/pc/common/river/default.nix b/home/pc/common/river/default.nix new file mode 100644 index 0000000..2262c9a --- /dev/null +++ b/home/pc/common/river/default.nix @@ -0,0 +1,11 @@ +{ pkgs, wallpaper, ... }: +{ + home.packages = [ pkgs.rivercarro ]; + + xdg.configFile."river/init" = { + source = pkgs.replaceVars ./init.sh { + inherit wallpaper; + }; + executable = true; + }; +} diff --git a/home/pc/common/river/init.sh b/home/pc/common/river/init.sh new file mode 100644 index 0000000..c653ed5 --- /dev/null +++ b/home/pc/common/river/init.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +# https://codeberg.org/river/river-classic/src/branch/main/example/init + +riverctl map normal Super Q spawn havoc +riverctl map normal Super D spawn "rofi -show run" + +riverctl map normal Super C close +riverctl map normal Super+Shift M exit + +riverctl map normal Super Up focus-view up +riverctl map normal Super Right focus-view right +riverctl map normal Super Left focus-view left +riverctl map normal Super Down focus-view down + +riverctl map normal Super k focus-view up +riverctl map normal Super l focus-view right +riverctl map normal Super h focus-view left +riverctl map normal Super j focus-view down + +riverctl map normal Super+Control Up focus-output up +riverctl map normal Super+Control Right focus-output right +riverctl map normal Super+Control Left focus-output left +riverctl map normal Super+Control Down focus-output down + +riverctl map normal Super+Control k focus-output up +riverctl map normal Super+Control l focus-output right +riverctl map normal Super+Control h focus-output left +riverctl map normal Super+Control j focus-output down + +riverctl map normal Super+Shift Up swap up +riverctl map normal Super+Shift Right swap right +riverctl map normal Super+Shift Left swap left +riverctl map normal Super+Shift Down swap down + +riverctl map normal Super+Shift k swap up +riverctl map normal Super+Shift l swap right +riverctl map normal Super+Shift h swap left +riverctl map normal Super+Shift j swap down + +riverctl map normal Super+Shift+Control Up send-to-output up +riverctl map normal Super+Shift+Control Right send-to-output right +riverctl map normal Super+Shift+Control Left send-to-output left +riverctl map normal Super+Shift+Control Down send-to-output down + +riverctl map normal Super+Shift+Control k send-to-output up +riverctl map normal Super+Shift+Control l send-to-output right +riverctl map normal Super+Shift+Control h send-to-output left +riverctl map normal Super+Shift+Control j send-to-output down + +riverctl map-pointer normal Super BTN_RIGHT resize-view + +for i in $(seq 1 9) +do + tags=$((1 << ($i - 1))) + riverctl map normal Super $i set-focused-tags $tags + riverctl map normal Super+Shift $i set-view-tags $tags +done + +riverctl map normal Super F toggle-fullscreen + +#TODO: stylix it +riverctl border-color-focused 0xf5c2e7 +riverctl border-color-unfocused 0x313244 + +riverctl set-repeat 30 300 + +riverctl default-layout rivercarro +rivercarro -inner-gaps 6 -outer-gaps 0 & + +riverctl rule-add ssd +riverctl rule-add -app-id "vesktop" output HDMI-A-2 + +wlr-randr --output DP-2 --mode 2560x1440@180Hz + +dbus-update-activation-environment --systemd WAYLAND_DISPLAY "XDG_CURRENT_DESKTOP=sway" + +awww-daemon & +awww img @wallpaper@ -t none + +vesktop & +riverctl focus-output left diff --git a/host/pc/common/dwl/config.h b/host/pc/common/dwl/config.h deleted file mode 100644 index da57229..0000000 --- a/host/pc/common/dwl/config.h +++ /dev/null @@ -1,255 +0,0 @@ -#define BASE_00 "@base00@" -#define BASE_01 "@base01@" -#define BASE_02 "@base02@" -#define BASE_03 "@base03@" -#define BASE_04 "@base04@" -#define BASE_05 "@base05@" -#define BASE_06 "@base06@" -#define BASE_07 "@base07@" -#define BASE_08 "@base08@" -#define BASE_09 "@base09@" -#define BASE_0A "@base0A@" -#define BASE_0B "@base0B@" -#define BASE_0C "@base0C@" -#define BASE_0D "@base0D@" -#define BASE_0E "@base0E@" -#define BASE_0F "@base0F@" - -#define WALLPAPER "@wallpaper@" - -/* Taken from https://github.com/jt0w/.dotfiles/blob/a6db8ad08ce834bb8ba9d15b999281d6635f5169/modules/nixos/dwl/config.def.h */ -#define HEX(c) \ - ((c) >= '0' && (c) <= '9' ? (c) - '0' \ - : (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 \ - : (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 \ - : 0) - -#define HEXBYTE(s, i) ((HEX((s)[i]) << 4) | HEX((s)[(i) + 1])) - -#define RGB_HEX_TO_RGBA(s) \ - ((uint32_t)((HEXBYTE(s, 0) << 24) | (HEXBYTE(s, 2) << 16) | \ - (HEXBYTE(s, 4) << 8) | 0xFF)) - -/* Taken from https://github.com/djpohly/dwl/issues/466 */ -#define COLOR(hex) \ - {((hex >> 24) & 0xFF) / 255.0f, ((hex >> 16) & 0xFF) / 255.0f, \ - ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f} - -/* appearance */ -static const int sloppyfocus = 1; /* focus follows mouse */ -static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ -static const unsigned int borderpx = 2; /* border pixel of windows */ - -static const float rootcolor[] = COLOR(RGB_HEX_TO_RGBA(BASE_00)); -static const float bordercolor[] = COLOR(RGB_HEX_TO_RGBA(BASE_02)); -static const float focuscolor[] = COLOR(RGB_HEX_TO_RGBA(BASE_0D)); -static const float urgentcolor[] = COLOR(RGB_HEX_TO_RGBA(BASE_08)); - -// gaps patch -static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ -static int gaps = 1; /* 1 means gaps between windows are added */ -static const unsigned int gappx = 10; /* gap pixel between windows */ - -/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ -static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ - -enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN }; - -static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */ -static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */ - -/* tagging - TAGCOUNT must be no greater than 31 */ -#define TAGCOUNT (9) - -/* logging */ -static int log_level = WLR_ERROR; - -/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ -static const Rule rules[] = { - /* app_id title tags mask isfloating monitor */ - /* examples: */ - { "mpv", NULL, 0, 1, 0 }, -}; - -/* layout(s) */ -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, - { "|w|", btrtile }, - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -}; - -#define CONFIG_BTRTILE_LAYOUT &layouts[1] - -/* monitors */ -/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator - * WARNING: negative values other than (-1, -1) cause problems with Xwayland clients - * https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 -*/ -/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ -static const MonitorRule monrules[] = { - /* name mfact nmaster scale layout rotate/reflect x y */ - /* example of a HiDPI laptop monitor: - { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, - */ - /* defaults */ - - // https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/monitorconfig/monitorconfig.patch - { "DP-2", 0.55f, 1, 1, CONFIG_BTRTILE_LAYOUT, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1, 2560, 1440, 180.0f, 0, 1}, - { "HDMI-A-2", 0.55f, 1, 1, CONFIG_BTRTILE_LAYOUT, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1, 1920, 1080, 60.0f, 0, 1}, -}; - -// https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/autostart/autostart.patch -static const char *const autostart[] = { - // Set the resolution - "wlr-randr", "--output", "DP-2", "--mode", "2560x1440@180Hz", NULL, - // Start the wallpaper daemon - "awww-daemon", NULL, - // Include the wallpaper - "awww", "img", WALLPAPER, "-t", "none", NULL, - // Start waybar - "waybar", NULL, - // Needed for screencasting - "dbus-update-activation-environment", "--systemd", "WAYLAND_DISPLAY", "XDG_CURRENT_DESKTOP=sway", NULL, - NULL, -}; - -/* keyboard */ -static const struct xkb_rule_names xkb_rules = { - /* can specify fields: rules, model, layout, variant, options */ - /* example: - .options = "ctrl:nocaps", - */ - .layout = "us", -}; - -static const int repeat_rate = 25; -static const int repeat_delay = 600; - -/* Trackpad */ -static const int tap_to_click = 1; -static const int tap_and_drag = 1; -static const int drag_lock = 1; -static const int natural_scrolling = 0; -static const int disable_while_typing = 1; -static const int left_handed = 0; -static const int middle_button_emulation = 0; -/* You can choose between: -LIBINPUT_CONFIG_SCROLL_NO_SCROLL -LIBINPUT_CONFIG_SCROLL_2FG -LIBINPUT_CONFIG_SCROLL_EDGE -LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN -*/ -static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; - -/* You can choose between: -LIBINPUT_CONFIG_CLICK_METHOD_NONE -LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS -LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER -*/ -static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - -/* You can choose between: -LIBINPUT_CONFIG_SEND_EVENTS_ENABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE -*/ -static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - -/* You can choose between: -LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT -LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE -*/ -static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; -static const double accel_speed = 1.0; - -/* You can choose between: -LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle -LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right -*/ -static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; - -/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ -#define MODKEY WLR_MODIFIER_LOGO - -#define TAGKEYS(KEY,SKEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static const char *termcmd[] = { "foot", NULL }; -static const char *menucmd[] = { "rofi", "-show", "drun", NULL }; -static const char *powrcmd[] = { "rofi", "-show", "pm", "-modi", "pm:rofi-power-menu", "--choices", "suspend/reboot/shutdown", NULL }; -static const char *emjicmd[] = { "rofimoji", "--action", "copy", NULL }; -static const char *scshcmd[] = { "gscreenshot", "-c", "-s", NULL }; -static const char *brsrcmd[] = { "zen-beta", NULL }; - -static const Key keys[] = { - /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ - /* modifier key function argument */ - { MODKEY, XKB_KEY_d, spawn, {.v = menucmd} }, - { MODKEY, XKB_KEY_q, spawn, {.v = termcmd} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_P, spawn, {.v = powrcmd} }, - { MODKEY, XKB_KEY_e, spawn, {.v = emjicmd} }, - { MODKEY, XKB_KEY_s, spawn, {.v = scshcmd} }, - { MODKEY, XKB_KEY_w, spawn, {.v = brsrcmd} }, - - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_k, swapclients, {.i = DIR_UP} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_j, swapclients, {.i = DIR_DOWN} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_h, swapclients, {.i = DIR_RIGHT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_l, swapclients, {.i = DIR_LEFT} }, - - { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, focusmon, {.i = WLR_DIRECTION_LEFT} }, - { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, focusmon, {.i = WLR_DIRECTION_RIGHT} }, - { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_h, focusmon, {.i = WLR_DIRECTION_LEFT} }, - { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_l, focusmon, {.i = WLR_DIRECTION_RIGHT} }, - - { MODKEY, XKB_KEY_Left, focusdir, {.ui = 0} }, - { MODKEY, XKB_KEY_Right, focusdir, {.ui = 1} }, - { MODKEY, XKB_KEY_Up, focusdir, {.ui = 2} }, - { MODKEY, XKB_KEY_Down, focusdir, {.ui = 3} }, - { MODKEY, XKB_KEY_h, focusdir, {.ui = 0} }, - { MODKEY, XKB_KEY_l, focusdir, {.ui = 1} }, - { MODKEY, XKB_KEY_k, focusdir, {.ui = 2} }, - { MODKEY, XKB_KEY_j, focusdir, {.ui = 3} }, - - { MODKEY, XKB_KEY_Return, zoom, {0} }, - { MODKEY, XKB_KEY_c, killclient, {0} }, - // { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XKB_KEY_v, togglefloating, {0} }, - { MODKEY, XKB_KEY_f, togglefullscreen, {0} }, - TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), - TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), - TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), - TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), - TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), - TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), - TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), - TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), - TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_M, quit, {0} }, - - /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ - { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, - /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is - * do not remove them. - */ -#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } - CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), - CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), -}; - -static const Button buttons[] = { - { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, - { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, -}; diff --git a/host/pc/common/dwl/dwl.nix b/host/pc/common/dwl/dwl.nix deleted file mode 100644 index f2d4dbf..0000000 --- a/host/pc/common/dwl/dwl.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ config, pkgs, ... }: -{ - environment.systemPackages = [ - pkgs.gscreenshot - pkgs.wlr-randr - pkgs.awww - ]; - programs.dwl = { - enable = true; - package = - (pkgs.dwl.override { - configH = pkgs.replaceVars ./config.h { - base00 = config.lib.stylix.colors.base00; - base01 = config.lib.stylix.colors.base01; - base02 = config.lib.stylix.colors.base02; - base03 = config.lib.stylix.colors.base03; - base04 = config.lib.stylix.colors.base04; - base05 = config.lib.stylix.colors.base05; - base06 = config.lib.stylix.colors.base06; - base07 = config.lib.stylix.colors.base07; - base08 = config.lib.stylix.colors.base08; - base09 = config.lib.stylix.colors.base09; - base0A = config.lib.stylix.colors.base0A; - base0B = config.lib.stylix.colors.base0B; - base0C = config.lib.stylix.colors.base0C; - base0D = config.lib.stylix.colors.base0D; - base0E = config.lib.stylix.colors.base0E; - base0F = config.lib.stylix.colors.base0F; - - wallpaper = config.stylix.image; - }; - }).overrideAttrs - (oldAttrs: { - buildInputs = oldAttrs.buildInputs or [ ] ++ [ - pkgs.libdrm - pkgs.fcft - ]; - patches = oldAttrs.patches or [ ] ++ [ - ./patches/autostart-0.7.patch - ./patches/btrtile-v0.7-gaps.patch - ./patches/focusdir.patch - ./patches/gaps.patch - ./patches/ipc.patch - ./patches/monitorconfig.patch - ]; - }); - }; -} diff --git a/host/pc/common/dwl/patches/autostart-0.7.patch b/host/pc/common/dwl/patches/autostart-0.7.patch deleted file mode 100644 index 12e6d7e..0000000 --- a/host/pc/common/dwl/patches/autostart-0.7.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 787f7252d63945996f009828aff3c44afd0f7781 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= - -Date: Sat, 8 Jul 2023 17:11:36 -0600 -Subject: [PATCH] port autostart patch from dwm -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://dwm.suckless.org/patches/cool_autostart/ -Signed-off-by: Leonardo Hernández Hernández ---- - config.def.h | 7 +++++++ - dwl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 61 insertions(+), 5 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 22d2171..8dc6502 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -20,6 +20,13 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca - /* logging */ - static int log_level = WLR_ERROR; - -+/* Autostart */ -+static const char *const autostart[] = { -+ "wbg", "/path/to/your/image", NULL, -+ NULL /* terminate */ -+}; -+ -+ - /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ - static const Rule rules[] = { - /* app_id title tags mask isfloating monitor */ -diff --git a/dwl.c b/dwl.c -index 5bf995e..e8b8727 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -249,6 +249,7 @@ static void arrange(Monitor *m); - static void arrangelayer(Monitor *m, struct wl_list *list, - struct wlr_box *usable_area, int exclusive); - static void arrangelayers(Monitor *m); -+static void autostartexec(void); - static void axisnotify(struct wl_listener *listener, void *data); - static void buttonpress(struct wl_listener *listener, void *data); - static void chvt(const Arg *arg); -@@ -432,6 +433,9 @@ static xcb_atom_t netatom[NetLast]; - /* attempt to encapsulate suck into one file */ - #include "client.h" - -+static pid_t *autostart_pids; -+static size_t autostart_len; -+ - /* function implementations */ - void - applybounds(Client *c, struct wlr_box *bbox) -@@ -580,6 +584,27 @@ arrangelayers(Monitor *m) - } - } - -+void -+autostartexec(void) { -+ const char *const *p; -+ size_t i = 0; -+ -+ /* count entries */ -+ for (p = autostart; *p; autostart_len++, p++) -+ while (*++p); -+ -+ autostart_pids = calloc(autostart_len, sizeof(pid_t)); -+ for (p = autostart; *p; i++, p++) { -+ if ((autostart_pids[i] = fork()) == 0) { -+ setsid(); -+ execvp(*p, (char *const *)p); -+ die("dwl: execvp %s:", *p); -+ } -+ /* skip arguments */ -+ while (*++p); -+ } -+} -+ - void - axisnotify(struct wl_listener *listener, void *data) - { -@@ -676,11 +701,21 @@ checkidleinhibitor(struct wlr_surface *exclude) - void - cleanup(void) - { -+ size_t i; - #ifdef XWAYLAND - wlr_xwayland_destroy(xwayland); - xwayland = NULL; - #endif - wl_display_destroy_clients(dpy); -+ -+ /* kill child processes */ -+ for (i = 0; i < autostart_len; i++) { -+ if (0 < autostart_pids[i]) { -+ kill(autostart_pids[i], SIGTERM); -+ waitpid(autostart_pids[i], NULL, 0); -+ } -+ } -+ - if (child_pid > 0) { - kill(-child_pid, SIGTERM); - waitpid(child_pid, NULL, 0); -@@ -1497,18 +1532,31 @@ void - handlesig(int signo) - { - if (signo == SIGCHLD) { --#ifdef XWAYLAND - siginfo_t in; - /* wlroots expects to reap the XWayland process itself, so we - * use WNOWAIT to keep the child waitable until we know it's not - * XWayland. - */ - while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid -- && (!xwayland || in.si_pid != xwayland->server->pid)) -- waitpid(in.si_pid, NULL, 0); --#else -- while (waitpid(-1, NULL, WNOHANG) > 0); -+#ifdef XWAYLAND -+ && (!xwayland || in.si_pid != xwayland->server->pid) - #endif -+ ) { -+ pid_t *p, *lim; -+ waitpid(in.si_pid, NULL, 0); -+ if (in.si_pid == child_pid) -+ child_pid = -1; -+ if (!(p = autostart_pids)) -+ continue; -+ lim = &p[autostart_len]; -+ -+ for (; p < lim; p++) { -+ if (*p == in.si_pid) { -+ *p = -1; -+ break; -+ } -+ } -+ } - } else if (signo == SIGINT || signo == SIGTERM) { - quit(NULL); - } -@@ -2224,6 +2272,7 @@ run(char *startup_cmd) - die("startup: backend_start"); - - /* Now that the socket exists and the backend is started, run the startup command */ -+ autostartexec(); - if (startup_cmd) { - int piperw[2]; - if (pipe(piperw) < 0) --- -2.45.2 - diff --git a/host/pc/common/dwl/patches/btrtile-v0.7-gaps.patch b/host/pc/common/dwl/patches/btrtile-v0.7-gaps.patch deleted file mode 100644 index e81b60d..0000000 --- a/host/pc/common/dwl/patches/btrtile-v0.7-gaps.patch +++ /dev/null @@ -1,1074 +0,0 @@ -From d56f0b61d6b611a977c065d0834f76b42c0aa038 Mon Sep 17 00:00:00 2001 -From: julmajustus -Date: Sat, 8 Feb 2025 05:41:12 +0200 -Subject: [PATCH] btrtile-gaps init - ---- - btrtile.c | 716 +++++++++++++++++++++++++++++++++++++++++++++++++++ - config.def.h | 12 + - dwl.c | 173 +++++++++++-- - 3 files changed, 874 insertions(+), 27 deletions(-) - create mode 100644 btrtile.c - -diff --git a/btrtile.c b/btrtile.c -new file mode 100644 -index 0000000..3ff3e20 ---- /dev/null -+++ b/btrtile.c -@@ -0,0 +1,716 @@ -+/* ************************************************************************** */ -+/* */ -+/* ::: :::::::: */ -+/* btrtile.c :+: :+: :+: */ -+/* +:+ +:+ +:+ */ -+/* By: jmakkone +#+ +:+ +#+ */ -+/* +#+#+#+#+#+ +#+ */ -+/* Created: 2024/12/15 00:26:07 by jmakkone #+# #+# */ -+/* Updated: 2025/02/08 04:52:00 by jmakkone ### ########.fr */ -+/* */ -+/* ************************************************************************** */ -+ -+typedef enum { -+ COORD_X, -+ COORD_Y -+} CoordType; -+ -+typedef struct LayoutNode { -+ unsigned int is_client_node; -+ unsigned int split_vertically; -+ float split_ratio; -+ struct LayoutNode *left; -+ struct LayoutNode *right; -+ struct LayoutNode *split_node; -+ Client *client; -+} LayoutNode; -+ -+struct TreeLayout { -+ LayoutNode *root[TAGCOUNT + 1]; -+ struct wl_list tiled_clients[TAGCOUNT + 1]; -+}; -+ -+static void add_client_to_tiled_list(Client *c, struct wl_list *tiled_clients); -+static void apply_layout(Monitor *m, LayoutNode *node, -+ struct wlr_box area, unsigned int is_root); -+static void btrtile(Monitor *m); -+static LayoutNode *create_client_node(Client *c); -+static LayoutNode *create_split_node(unsigned int split_vertically, -+ LayoutNode *left, LayoutNode *right); -+static void destroy_node_tree(LayoutNode *node); -+static void destroy_tree_layout(Monitor *m); -+static LayoutNode *find_client_node(LayoutNode *node, Client *c); -+static LayoutNode *find_split_node(LayoutNode *root, LayoutNode *child); -+static LayoutNode *find_suitable_split_node(LayoutNode *client_node, -+ unsigned int need_vertical); -+static LayoutNode *find_closest_client_node(LayoutNode *split_node, -+ enum Direction dir, int current_x, -+ int current_y, LayoutNode **closest, -+ int *closest_dist); -+static unsigned int get_client_center(LayoutNode *node, CoordType type); -+static unsigned int get_current_tag(Monitor *m); -+static void init_tree_layout(Monitor *m); -+static void insert_client(Monitor *m, Client *focused, Client *new_client, -+ LayoutNode **root, struct wl_list *tiled_clients); -+static unsigned int is_client_tiled(Client *c, struct wl_list *tiled_clients); -+static LayoutNode *remove_client_node(LayoutNode *node, Client *c); -+static void remove_client(Monitor *m, Client *c, -+ LayoutNode **root, struct wl_list *tiled_clients); -+static void setratio_h(const Arg *arg); -+static void setratio_v(const Arg *arg); -+static void swapclients(const Arg *arg); -+static Client *xytoclient(double x, double y, uint32_t tag); -+ -+static int resizing_from_mouse = 0; -+static double resize_last_update_x, resize_last_update_y; -+static uint32_t last_resize_time = 0; -+ -+void -+add_client_to_tiled_list(Client *c, struct wl_list *tiled_clients) -+{ -+ if (!is_client_tiled(c, tiled_clients)) -+ wl_list_insert(tiled_clients, &c->link_tiled); -+} -+ -+void -+apply_layout(Monitor *m, LayoutNode *node, -+ struct wlr_box area, unsigned int is_root) -+{ -+ float ratio; -+ int mid; -+ unsigned int e = m->gaps; -+ struct wlr_box left_area, right_area; -+ -+ if (!node) -+ return; -+ -+ if (is_root && e) { -+ area.x += gappx; -+ area.y += gappx; -+ area.width -= 2 * gappx; -+ area.height -= 2 * gappx; -+ } -+ -+ if (node->is_client_node) { -+ resize(node->client, area, 0); -+ node->client->old_geom = area; -+ return; -+ } -+ -+ ratio = node->split_ratio; -+ if (ratio == 0.0f) -+ ratio = 0.5f; -+ if (ratio < 0.05f) -+ ratio = 0.05f; -+ if (ratio > 0.95f) -+ ratio = 0.95f; -+ -+ if (node->split_vertically) { -+ mid = (int)(area.width * ratio); -+ left_area = (struct wlr_box){ area.x, area.y, mid, area.height}; -+ right_area = (struct wlr_box){ area.x + mid, area.y, -+ area.width - mid, area.height}; -+ -+ if (e) { -+ left_area.width -= gappx / 2; -+ right_area.x += gappx / 2; -+ right_area.width -= gappx / 2; -+ } -+ } else { -+ mid = (int)(area.height * ratio); -+ left_area = (struct wlr_box){ area.x, area.y, area.width, mid }; -+ right_area = (struct wlr_box){ area.x, area.y + mid, -+ area.width, area.height - mid }; -+ -+ if (e) { -+ left_area.height -= gappx / 2; -+ right_area.y += gappx / 2; -+ right_area.height -= gappx / 2; -+ } -+ } -+ -+ apply_layout(m, node->left, left_area, 0); -+ apply_layout(m, node->right, right_area, 0); -+} -+ -+void btrtile(Monitor *m) -+{ -+ uint32_t active_tags = m->tagset[m->seltags]; -+ unsigned int n = 0, found = 0, curtag; -+ Client *c, *cc, *tmp, *cur, *focused_client = NULL; -+ LayoutNode **root_ptr; -+ struct wl_list current_clients, *tiled_clients; -+ struct wlr_box full_area = m->w; -+ -+ /* We skip handling clients in btrtile if multiple tags are selected */ -+ if (!m->tree_layout || (active_tags && (active_tags & (active_tags - 1)))) -+ return; -+ curtag = get_current_tag(m); -+ root_ptr = &m->tree_layout->root[curtag]; -+ tiled_clients = &m->tree_layout->tiled_clients[curtag]; -+ wl_list_for_each_reverse(c, &clients, link) { -+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) -+ n++; -+ } -+ -+ /* If no visible clients, clear the node tree and tiled_clients list. */ -+ if (n == 0) { -+ destroy_node_tree(*root_ptr); -+ *root_ptr = NULL; -+ wl_list_init(tiled_clients); -+ return; -+ } -+ -+ focused_client = xytoclient(cursor->x, cursor->y, curtag); -+ /* If no focused client found, pick the first visible */ -+ if (!focused_client) { -+ wl_list_for_each_reverse(c, &clients, link) { -+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) { -+ focused_client = c; -+ break; -+ } -+ } -+ } -+ -+ /* Build a temporary list of currently visible tiled clients. -+ * If new clients are found add them to tree.*/ -+ wl_list_init(¤t_clients); -+ wl_list_for_each_reverse(c, &clients, link) { -+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) { -+ found = 0; -+ /* If client has multiple tags set, we might create infinite -+ * point to self loops by adding the same client to multiple -+ * tiled_clients lists, so hacky way to prevent that is to revert -+ * clients active tags to current active tag if multiple -+ * tags are selected. */ -+ if (c->tags != 1u << curtag) -+ c->tags = 1u << curtag; -+ wl_list_for_each(cc, tiled_clients, link_tiled) { -+ if (cc == c) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ insert_client(m, focused_client, c, root_ptr, tiled_clients); -+ /* Recursion failsafe to handle inserted clients individually -+ * if a batch of new clients is added. */ -+ apply_layout(m, *root_ptr, full_area, 1); -+ btrtile(m); -+ return; -+ } -+ wl_list_insert(¤t_clients, &c->link_temp); -+ } -+ } -+ -+ /* Compare the current list of clients to the previous one and remove -+ * clients that no longer exist on the current tag. -+ * This handles cases where user moves clients to other tags. -+ * When client is closed or killed we manage the list and tree clean up in -+ * destroynotify. */ -+ wl_list_for_each_safe(cc, tmp, tiled_clients, link_tiled) { -+ found = 0; -+ wl_list_for_each(cur, ¤t_clients, link_temp) { -+ if (cur == cc) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) -+ remove_client(m, cc, root_ptr, tiled_clients); -+ } -+ -+ /* Rebuild the updated client list */ -+ wl_list_init(tiled_clients); -+ wl_list_for_each(cur, ¤t_clients, link_temp) { -+ wl_list_insert(tiled_clients, &cur->link_tiled); -+ } -+ -+ /* Tile visible clients. */ -+ apply_layout(m, *root_ptr, full_area, 1); -+} -+ -+LayoutNode * -+create_client_node(Client *c) -+{ -+ LayoutNode *node = calloc(1, sizeof(LayoutNode)); -+ -+ if (!node) -+ return NULL; -+ node->is_client_node = 1; -+ node->split_ratio = 0.5f; -+ node->client = c; -+ return node; -+} -+ -+LayoutNode * -+create_split_node(unsigned int split_vertically, -+ LayoutNode *left, LayoutNode *right) -+{ -+ LayoutNode *node = calloc(1, sizeof(LayoutNode)); -+ -+ if (!node) -+ return NULL; -+ node->is_client_node = 0; -+ node->split_ratio = 0.5f; -+ node->split_vertically = split_vertically; -+ node->left = left; -+ node->right = right; -+ if (left) -+ left->split_node = node; -+ if (right) -+ right->split_node = node; -+ return node; -+} -+ -+unsigned int -+is_client_tiled(Client *c, struct wl_list *tiled_clients) -+{ -+ Client *cc; -+ wl_list_for_each(cc, tiled_clients, link_tiled) { -+ if (cc == c) -+ return 1; -+ } -+ return 0; -+} -+ -+void -+destroy_node_tree(LayoutNode *node) -+{ -+ if (!node) -+ return; -+ if (!node->is_client_node) { -+ destroy_node_tree(node->left); -+ destroy_node_tree(node->right); -+ } -+ free(node); -+} -+ -+void -+destroy_tree_layout(Monitor *m) -+{ -+ if (!m) -+ return; -+ for (int i = 0; i <= TAGCOUNT; i++) { -+ destroy_node_tree(m->tree_layout->root[i]); -+ } -+} -+ -+LayoutNode * -+find_client_node(LayoutNode *node, Client *c) -+{ -+ LayoutNode *res; -+ -+ if (!node) -+ return NULL; -+ if (node->is_client_node) -+ return (node->client == c) ? node : NULL; -+ res = find_client_node(node->left, c); -+ return res ? res : find_client_node(node->right, c); -+} -+ -+LayoutNode * -+find_split_node(LayoutNode *root, LayoutNode *child) -+{ -+ LayoutNode *res; -+ -+ if (!root || root->is_client_node) -+ return NULL; -+ if (root->left == child || root->right == child) -+ return root; -+ res = find_split_node(root->left, child); -+ return res ? res : find_split_node(root->right, child); -+} -+ -+LayoutNode * -+find_suitable_split_node(LayoutNode *client_node, unsigned int need_vertical) -+{ -+ LayoutNode *node = client_node; -+ unsigned int curtag; -+ -+ curtag = get_current_tag(selmon); -+ /* If we're starting from a client_node, go up one level first */ -+ if (node->is_client_node) { -+ node = node->split_node ? node->split_node : -+ find_split_node(selmon->tree_layout->root[curtag], node); -+ } -+ -+ /* Climb the tree until we find a node that is not client_node and -+ * match needed orientation. */ -+ while (node && (node->is_client_node || -+ node->split_vertically != need_vertical)) { -+ node = node->split_node ? node->split_node : -+ find_split_node(selmon->tree_layout->root[curtag], node); -+ } -+ -+ return node; -+} -+ -+LayoutNode * -+find_closest_client_node(LayoutNode *split_node, enum Direction dir, -+ int current_x, int current_y, LayoutNode **closest, -+ int *closest_dist) -+{ -+ int client_center_x, client_center_y, dist, is_candidate; -+ if (!split_node) -+ return NULL; -+ -+ if (split_node->is_client_node && split_node->client) { -+ client_center_x = get_client_center(split_node, COORD_X); -+ client_center_y = get_client_center(split_node, COORD_Y); -+ dist = 0; -+ is_candidate = 0; -+ -+ switch (dir) { -+ case DIR_LEFT: -+ if (client_center_x < current_x) { -+ dist = current_x - client_center_x; -+ is_candidate = 1; -+ } -+ break; -+ case DIR_RIGHT: -+ if (client_center_x > current_x) { -+ dist = client_center_x - current_x; -+ is_candidate = 1; -+ } -+ break; -+ case DIR_UP: -+ if (client_center_y < current_y) { -+ dist = current_y - client_center_y; -+ is_candidate = 1; -+ } -+ break; -+ case DIR_DOWN: -+ if (client_center_y > current_y) { -+ dist = client_center_y - current_y; -+ is_candidate = 1; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (is_candidate && dist < *closest_dist) { -+ *closest_dist = dist; -+ *closest = split_node; -+ } -+ } -+ -+ /* Recursively search in left and right split_nodes */ -+ find_closest_client_node(split_node->left, dir, current_x, current_y, -+ closest, closest_dist); -+ find_closest_client_node(split_node->right, dir, current_x, current_y, -+ closest, closest_dist); -+ -+ return *closest; -+} -+ -+unsigned int -+get_client_center(LayoutNode *node, CoordType type) -+{ -+ if (!node || !node->is_client_node || !node->client) -+ return 0; -+ -+ switch (type) { -+ case COORD_X: -+ return node->client->old_geom.x + node->client->old_geom.width / 2; -+ case COORD_Y: -+ return node->client->old_geom.y + node->client->old_geom.height / 2; -+ default: -+ return 0; -+ } -+} -+ -+unsigned int -+get_current_tag(Monitor *m) -+{ -+ uint32_t active; -+ -+ if (!m) -+ return 0; -+ -+ active = m->tagset[m->seltags]; -+ for (int i = 0; i < TAGCOUNT; i++) { -+ if (active & (1u << i)) -+ return i; -+ } -+ return 0; -+} -+ -+void -+init_tree_layout(Monitor *m) -+{ -+ if (!m) -+ return; -+ m->tree_layout = calloc(1, sizeof(TreeLayout)); -+ for (int i = 0; i <= TAGCOUNT; i++) { -+ m->tree_layout->root[i] = NULL; -+ wl_list_init(&m->tree_layout->tiled_clients[i]); -+ } -+} -+ -+void -+insert_client(Monitor *m, Client *focused, Client *new_client, -+ LayoutNode **root, struct wl_list *tiled_clients) -+{ -+ int mid_x, mid_y; -+ LayoutNode *old_root, *client_node, *old_client_node, *new_client_node; -+ unsigned int wider; -+ -+ /* If there is no root node, inserted client must be the first one. -+ * If there's no focused client we treat the inserted client as a new root node.*/ -+ if (!*root) { -+ *root = create_client_node(new_client); -+ add_client_to_tiled_list(new_client, tiled_clients); -+ return; -+ } -+ if (!focused || !(client_node = find_client_node(*root, focused))) { -+ old_root = *root; -+ *root = create_split_node(1, old_root, create_client_node(new_client)); -+ add_client_to_tiled_list(new_client, tiled_clients); -+ return; -+ } -+ /* We check the cursor location on splittable area and choose -+ * the new client's position. On horizontal splits left node represent -+ * the upper node and vice versa.*/ -+ mid_x = focused->old_geom.x + focused->old_geom.width / 2; -+ mid_y = focused->old_geom.y + focused->old_geom.height / 2; -+ old_client_node = create_client_node(client_node->client); -+ new_client_node = create_client_node(new_client); -+ -+ wider = focused->old_geom.width >= focused->old_geom.height; -+ if (wider) { -+ /* Vertical split */ -+ client_node->split_vertically = 1; -+ if (cursor->x <= mid_x) { -+ client_node->left = new_client_node; -+ client_node->right = old_client_node; -+ } else { -+ client_node->left = old_client_node; -+ client_node->right = new_client_node; -+ } -+ } else { -+ /* Horizontal split */ -+ client_node->split_vertically = 0; -+ if (cursor->y <= mid_y) { -+ client_node->left = new_client_node; -+ client_node->right = old_client_node; -+ } else { -+ client_node->left = old_client_node; -+ client_node->right = new_client_node; -+ } -+ } -+ /* The old client node becomes the splitnode for the old and new client -+ * nodes.*/ -+ client_node->is_client_node = 0; -+ client_node->client = NULL; -+ add_client_to_tiled_list(new_client, tiled_clients); -+} -+ -+LayoutNode * -+remove_client_node(LayoutNode *node, Client *c) -+{ -+ LayoutNode *tmp; -+ if (!node) -+ return NULL; -+ if (node->is_client_node) { -+ /* If this client_node is the client we're removing, -+ * return NULL to remove it */ -+ if (node->client == c) { -+ free(node); -+ return NULL; -+ } -+ return node; -+ } -+ -+ node->left = remove_client_node(node->left, c); -+ node->right = remove_client_node(node->right, c); -+ -+ /* If one of the client node is NULL after removal and the other is not, -+ * we "lift" the other client node up to replace this split node. */ -+ if (!node->left && node->right) { -+ tmp = node->right; -+ -+ /* Save pointer to split node */ -+ if (tmp) -+ tmp->split_node = node->split_node; -+ -+ free(node); -+ return tmp; -+ } -+ -+ if (!node->right && node->left) { -+ tmp = node->left; -+ -+ /* Save pointer to split node */ -+ if (tmp) -+ tmp->split_node = node->split_node; -+ -+ free(node); -+ return tmp; -+ } -+ -+ /* If both children exist or both are NULL (empty tree), -+ * return node as is. */ -+ return node; -+} -+ -+void -+remove_client(Monitor *m, Client *c, LayoutNode **root, -+ struct wl_list *tiled_clients) -+{ -+ Client *cc, *tmp; -+ -+ *root = remove_client_node(*root, c); -+ wl_list_for_each_safe(cc, tmp, tiled_clients, link_tiled) { -+ if (cc == c) { -+ wl_list_remove(&cc->link_tiled); -+ break; -+ } -+ } -+} -+ -+void -+setratio_h(const Arg *arg) -+{ -+ Client *sel = focustop(selmon); -+ LayoutNode *client_node, *node; -+ float new_ratio; -+ -+ if (!arg || !sel || !selmon->lt[selmon->sellt]->arrange) -+ return; -+ -+ client_node = find_client_node(selmon->tree_layout->root[get_current_tag(selmon)], sel); -+ if (!client_node) -+ return; -+ -+ /* Find a suitable vertical node */ -+ node = find_suitable_split_node(client_node, 1); -+ if (!node) -+ return; -+ -+ new_ratio = arg->f ? (node->split_ratio + arg->f) : 0.5f; -+ if (new_ratio < 0.05f) -+ new_ratio = 0.05f; -+ if (new_ratio > 0.95f) -+ new_ratio = 0.95f; -+ -+ node->split_ratio = new_ratio; -+ /* Skip the arrange if done resizing by mouse, -+ * we call arrange from motionotify */ -+ if (!resizing_from_mouse) { -+ arrange(selmon); -+ } -+} -+ -+void -+setratio_v(const Arg *arg) -+{ -+ float new_ratio; -+ Client *sel = focustop(selmon); -+ LayoutNode *client_node, *node; -+ -+ if (!arg || !sel || !selmon->lt[selmon->sellt]->arrange) -+ return; -+ -+ client_node = find_client_node(selmon->tree_layout->root[get_current_tag(selmon)], sel); -+ if (!client_node) -+ return; -+ -+ /* Find a suitable horizontal node */ -+ node = find_suitable_split_node(client_node, 0); -+ if (!node) -+ return; -+ -+ new_ratio = arg->f ? (node->split_ratio + arg->f) : 0.5f; -+ if (new_ratio < 0.05f) new_ratio = 0.5f; -+ if (new_ratio > 0.95f) new_ratio = 0.95f; -+ -+ node->split_ratio = new_ratio; -+ /* Skip the arrange if done resizing by mouse, -+ * we call arrange from motionotify */ -+ if (!resizing_from_mouse) { -+ arrange(selmon); -+ } -+} -+ -+void -+swapclients(const Arg *arg) -+{ -+ Client *tmp, *sel = focustop(selmon); -+ enum Direction dir = (enum Direction)arg->i; -+ LayoutNode *client_node, *target = NULL, *split_node = NULL; -+ unsigned int current_x, current_y, curtag = get_current_tag(selmon); -+ int closest_dist = INT_MAX; -+ -+ if (!arg || !sel || !selmon->lt[selmon->sellt]->arrange) -+ return; -+ -+ client_node = find_client_node(selmon->tree_layout->root[curtag], sel); -+ if (!client_node) -+ return; -+ -+ current_x = get_client_center(client_node, COORD_X); -+ current_y = get_client_center(client_node, COORD_Y); -+ -+ /* For up/down swaps, restrict search within the current horizontal split -+ * node if no suitable horizontal split node is found, default to vertical */ -+ if (dir == DIR_UP || dir == DIR_DOWN) { -+ split_node = find_suitable_split_node(client_node, 0); -+ if (!split_node) -+ return; -+ } else { -+ split_node = selmon->tree_layout->root[curtag]; -+ } -+ -+ /* Find the closest client node in the specified direction and swap -+ * the clients */ -+ find_closest_client_node(split_node, dir, current_x, current_y, -+ &target, &closest_dist); -+ -+ if (target && target->is_client_node && target->client) { -+ tmp = client_node->client; -+ client_node->client = target->client; -+ target->client = tmp; -+ -+ arrange(selmon); -+ } -+} -+ -+Client * -+xytoclient(double x, double y, uint32_t tag) { -+ Client *c, *closest = NULL; -+ double dist, mindist = INT_MAX, dx, dy; -+ -+ wl_list_for_each_reverse(c, &selmon->tree_layout->tiled_clients[tag], link_tiled) { -+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen && -+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) && -+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){ -+ return c; -+ } -+ } -+ -+ /* If no client was found at cursor position fallback to closest. */ -+ wl_list_for_each_reverse(c, &selmon->tree_layout->tiled_clients[tag], link_tiled) { -+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) { -+ dx = 0, dy = 0; -+ -+ if (x < c->geom.x) -+ dx = c->geom.x - x; -+ else if (x > (c->geom.x + c->geom.width)) -+ dx = x - (c->geom.x + c->geom.width); -+ -+ if (y < c->geom.y) -+ dy = c->geom.y - y; -+ else if (y > (c->geom.y + c->geom.height)) -+ dy = y - (c->geom.y + c->geom.height); -+ -+ dist = sqrt(dx * dx + dy * dy); -+ if (dist < mindist) { -+ mindist = dist; -+ closest = c; -+ } -+ } -+ } -+ return closest; -+} -diff --git a/config.def.h b/config.def.h -index 22d2171..92f3ad6 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -13,7 +13,10 @@ static const float focuscolor[] = COLOR(0x005577ff); - static const float urgentcolor[] = COLOR(0xff0000ff); - /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ - static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ -+static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */ -+static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */ - -+enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN }; - /* tagging - TAGCOUNT must be no greater than 31 */ - #define TAGCOUNT (9) - -@@ -31,6 +34,7 @@ static const Rule rules[] = { - /* layout(s) */ - static const Layout layouts[] = { - /* symbol arrange function */ -+ { "|w|", btrtile }, - { "[]=", tile }, - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -@@ -148,6 +152,14 @@ static const Key keys[] = { - { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, -+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} }, -+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} }, -+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} }, -+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, setratio_h, {.f = +0.025f} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, setratio_h, {.f = -0.025f} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, setratio_v, {.f = -0.025f} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, setratio_v, {.f = +0.025f} }, - TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), - TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), - TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), -diff --git a/dwl.c b/dwl.c -index a2711f6..7682366 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -1,6 +1,7 @@ - /* - * See LICENSE file for copyright and license details. - */ -+#include - #include - #include - #include -@@ -103,6 +104,7 @@ typedef struct { - const Arg arg; - } Button; - -+typedef struct TreeLayout TreeLayout; - typedef struct Monitor Monitor; - typedef struct { - /* Must keep these three elements in this order */ -@@ -139,8 +141,11 @@ typedef struct { - #endif - unsigned int bw; - uint32_t tags; -- int isfloating, isurgent, isfullscreen; -+ int isfloating, isurgent, isfullscreen, was_tiled; - uint32_t resize; /* configure serial of a pending resize */ -+ struct wlr_box old_geom; -+ struct wl_list link_tiled; -+ struct wl_list link_temp; - } Client; - - typedef struct { -@@ -208,6 +213,7 @@ struct Monitor { - int nmaster; - char ltsymbol[16]; - int asleep; -+ TreeLayout *tree_layout; - }; - - typedef struct { -@@ -250,6 +256,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, - struct wlr_box *usable_area, int exclusive); - static void arrangelayers(Monitor *m); - static void axisnotify(struct wl_listener *listener, void *data); -+static void btrtile(Monitor *m); - static void buttonpress(struct wl_listener *listener, void *data); - static void chvt(const Arg *arg); - static void checkidleinhibitor(struct wlr_surface *exclude); -@@ -333,6 +340,9 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); - static void setpsel(struct wl_listener *listener, void *data); - static void setsel(struct wl_listener *listener, void *data); - static void setup(void); -+static void setratio_h(const Arg *arg); -+static void setratio_v(const Arg *arg); -+static void swapclients(const Arg *arg); - static void spawn(const Arg *arg); - static void startdrag(struct wl_listener *listener, void *data); - static void tag(const Arg *arg); -@@ -431,6 +441,7 @@ static xcb_atom_t netatom[NetLast]; - - /* attempt to encapsulate suck into one file */ - #include "client.h" -+#include "btrtile.c" - - /* function implementations */ - void -@@ -600,10 +611,15 @@ buttonpress(struct wl_listener *listener, void *data) - { - struct wlr_pointer_button_event *event = data; - struct wlr_keyboard *keyboard; -- uint32_t mods; -- Client *c; -+ struct wl_list *tiled_clients; -+ LayoutNode **root, *old_root; -+ uint32_t mods, curtag, active_tags = selmon->tagset[selmon->seltags]; -+ Client *c, *target = NULL; - const Button *b; - -+ curtag = get_current_tag(selmon); -+ root = &selmon->tree_layout->root[curtag]; -+ tiled_clients = &selmon->tree_layout->tiled_clients[curtag]; - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); - - switch (event->state) { -@@ -632,15 +648,47 @@ buttonpress(struct wl_listener *listener, void *data) - /* If you released any buttons, we exit interactive move/resize mode. */ - /* TODO should reset to the pointer focus's current setcursor */ - if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { -+ c = grabc; -+ if (c && c->was_tiled && !strcmp(selmon->ltsymbol, "|w|")) { -+ /* Check if more than one tag is active, if so we escape */ -+ if (active_tags && (active_tags & (active_tags - 1))) -+ break; -+ if (cursor_mode == CurMove && c->isfloating) { -+ target = xytoclient(cursor->x, cursor->y, curtag); -+ -+ if (target && !target->isfloating && !target->isfullscreen) { -+ insert_client(selmon, target, c, root, tiled_clients); -+ } else { -+ if (!root) { -+ *root = create_client_node(c); -+ add_client_to_tiled_list(c, tiled_clients); -+ } else { -+ old_root = *root; -+ *root = create_split_node(1, old_root, create_client_node(c)); -+ add_client_to_tiled_list(c, tiled_clients); -+ } -+ } -+ -+ setfloating(c, 0); -+ arrange(selmon); -+ -+ } else if (cursor_mode == CurResize && !c->isfloating) { -+ resizing_from_mouse = 0; -+ } -+ } else { -+ if (cursor_mode == CurResize && resizing_from_mouse) -+ resizing_from_mouse = 0; -+ } -+ /* Default behaviour */ - wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - cursor_mode = CurNormal; - /* Drop the window off on its new monitor */ - selmon = xytomon(cursor->x, cursor->y); - setmon(grabc, selmon, 0); -+ grabc = NULL; - return; -- } else { -- cursor_mode = CurNormal; - } -+ cursor_mode = CurNormal; - break; - } - /* If the event wasn't handled by the compositor, notify the client with -@@ -720,6 +768,9 @@ cleanupmon(struct wl_listener *listener, void *data) - wlr_output_layout_remove(output_layout, m->wlr_output); - wlr_scene_output_destroy(m->scene_output); - -+ destroy_tree_layout(m); -+ free(m->tree_layout); -+ m->tree_layout = NULL; - closemon(m); - wlr_scene_node_destroy(&m->fullscreen_bg->node); - free(m); -@@ -1024,6 +1075,7 @@ createmon(struct wl_listener *listener, void *data) - - wl_list_insert(&mons, &m->link); - printstatus(); -+ init_tree_layout(m); - - /* The xdg-protocol specifies: - * -@@ -1263,6 +1315,15 @@ destroynotify(struct wl_listener *listener, void *data) - wl_list_remove(&c->destroy.link); - wl_list_remove(&c->set_title.link); - wl_list_remove(&c->fullscreen.link); -+ /* We check if the destroyed client was part of any tiled_list, to catch -+ * client removals even if they would not be currently managed by btrtile */ -+ if (selmon && selmon->tree_layout) { -+ for (int i = 0; i < TAGCOUNT; i++) { -+ remove_client(selmon, c, -+ &selmon->tree_layout->root[i], -+ &selmon->tree_layout->tiled_clients[i]); -+ } -+ } - #ifdef XWAYLAND - if (c->type != XDGShell) { - wl_list_remove(&c->activate.link); -@@ -1809,7 +1870,8 @@ void - motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, - double dx_unaccel, double dy_unaccel) - { -- double sx = 0, sy = 0, sx_confined, sy_confined; -+ int tiled = 0; -+ double sx = 0, sy = 0, sx_confined, sy_confined, dx_total, dy_total; - Client *c = NULL, *w = NULL; - LayerSurface *l = NULL; - struct wlr_surface *surface = NULL; -@@ -1863,18 +1925,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d - /* Update drag icon's position */ - wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); - -- /* If we are currently grabbing the mouse, handle and return */ -+ /* Skip if internal call or already resizing */ -+ if (time == 0 && resizing_from_mouse) -+ goto focus; -+ -+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen; - if (cursor_mode == CurMove) { - /* Move the grabbed client to the new position. */ -- resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, -- .width = grabc->geom.width, .height = grabc->geom.height}, 1); -- return; -+ if (grabc && grabc->isfloating) { -+ resize(grabc, (struct wlr_box){ -+ .x = (int)round(cursor->x) - grabcx, -+ .y = (int)round(cursor->y) - grabcy, -+ .width = grabc->geom.width, -+ .height = grabc->geom.height -+ }, 1); -+ return; -+ } - } else if (cursor_mode == CurResize) { -- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, -- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); -- return; -+ if (tiled && resizing_from_mouse) { -+ dx_total = cursor->x - resize_last_update_x; -+ dy_total = cursor->y - resize_last_update_y; -+ -+ if (time - last_resize_time >= resize_interval_ms) { -+ Arg a = {0}; -+ if (fabs(dx_total) > fabs(dy_total)) { -+ a.f = (float)(dx_total * resize_factor); -+ setratio_h(&a); -+ } else { -+ a.f = (float)(dy_total * resize_factor); -+ setratio_v(&a); -+ } -+ arrange(selmon); -+ -+ last_resize_time = time; -+ resize_last_update_x = cursor->x; -+ resize_last_update_y = cursor->y; -+ } -+ -+ } else if (grabc && grabc->isfloating) { -+ /* Floating resize as original */ -+ resize(grabc, (struct wlr_box){ -+ .x = grabc->geom.x, -+ .y = grabc->geom.y, -+ .width = (int)round(cursor->x) - grabc->geom.x, -+ .height = (int)round(cursor->y) - grabc->geom.y -+ }, 1); -+ return; -+ } - } - -+focus: - /* If there's no client surface under the cursor, set the cursor image to a - * default. This is what makes the cursor image appear when you move it - * off of a client or over its border. */ -@@ -1908,22 +2008,41 @@ moveresize(const Arg *arg) - if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) - return; - -- /* Float the window and tell motionnotify to grab it */ -- setfloating(grabc, 1); -- switch (cursor_mode = arg->ui) { -- case CurMove: -- grabcx = (int)round(cursor->x) - grabc->geom.x; -- grabcy = (int)round(cursor->y) - grabc->geom.y; -- wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); -- break; -- case CurResize: -- /* Doesn't work for X11 output - the next absolute motion event -- * returns the cursor to where it started */ -- wlr_cursor_warp_closest(cursor, NULL, -+ cursor_mode = arg->ui; -+ grabc->was_tiled = (!grabc->isfloating && !grabc->isfullscreen); -+ -+ if (grabc->was_tiled) { -+ switch (cursor_mode) { -+ case CurMove: -+ setfloating(grabc, 1); -+ grabcx = (int)round(cursor->x) - grabc->geom.x; -+ grabcy = (int)round(cursor->y) - grabc->geom.y; -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); -+ break; -+ case CurResize: -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); -+ resize_last_update_x = cursor->x; -+ resize_last_update_y = cursor->y; -+ resizing_from_mouse = 1; -+ break; -+ } -+ } else { -+ /* Default floating logic */ -+ /* Float the window and tell motionnotify to grab it */ -+ setfloating(grabc, 1); -+ switch (cursor_mode) { -+ case CurMove: -+ grabcx = (int)round(cursor->x) - grabc->geom.x; -+ grabcy = (int)round(cursor->y) - grabc->geom.y; -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); -+ break; -+ case CurResize: -+ wlr_cursor_warp_closest(cursor, NULL, - grabc->geom.x + grabc->geom.width, - grabc->geom.y + grabc->geom.height); -- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); -- break; -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); -+ break; -+ } - } - } - --- -2.45.3 - diff --git a/host/pc/common/dwl/patches/focusdir.patch b/host/pc/common/dwl/patches/focusdir.patch deleted file mode 100644 index b74fd3e..0000000 --- a/host/pc/common/dwl/patches/focusdir.patch +++ /dev/null @@ -1,90 +0,0 @@ -From a0e71a687b7fcaebdaf1da80c09bf5563bff46b1 Mon Sep 17 00:00:00 2001 -From: ldev -Date: Mon, 12 Feb 2024 21:50:24 +0100 -Subject: [PATCH] focusdir - ---- - config.def.h | 4 ++++ - dwl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 49 insertions(+) - -diff --git a/config.def.h b/config.def.h -index 9009517..2a1a82e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -124,6 +124,10 @@ static const Key keys[] = { - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, - { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, - { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_h, focusdir, {.ui = 0} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_l, focusdir, {.ui = 1} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_k, focusdir, {.ui = 2} }, -+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_j, focusdir, {.ui = 3} }, - { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, - { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, - { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, -diff --git a/dwl.c b/dwl.c -index bf02a6d..64d5de7 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -268,6 +269,7 @@ static Monitor *dirtomon(enum wlr_direction dir); - static void focusclient(Client *c, int lift); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -+static void focusdir(const Arg *arg); - static Client *focustop(Monitor *m); - static void fullscreennotify(struct wl_listener *listener, void *data); - static void handlesig(int signo); -@@ -1271,6 +1273,49 @@ focusstack(const Arg *arg) - focusclient(c, 1); - } - -+void focusdir(const Arg *arg) -+{ -+ /* Focus the left, right, up, down client relative to the current focused client on selmon */ -+ Client *c, *sel = focustop(selmon); -+ if (!sel || sel->isfullscreen) -+ return; -+ -+ int dist=INT_MAX; -+ Client *newsel = NULL; -+ int newdist=INT_MAX; -+ wl_list_for_each(c, &clients, link) { -+ if (!VISIBLEON(c, selmon)) -+ continue; /* skip non visible windows */ -+ -+ if (arg->ui == 0 && sel->geom.x <= c->geom.x) { -+ /* Client isn't on our left */ -+ continue; -+ } -+ if (arg->ui == 1 && sel->geom.x >= c->geom.x) { -+ /* Client isn't on our right */ -+ continue; -+ } -+ if (arg->ui == 2 && sel->geom.y <= c->geom.y) { -+ /* Client isn't above us */ -+ continue; -+ } -+ if (arg->ui == 3 && sel->geom.y >= c->geom.y) { -+ /* Client isn't below us */ -+ continue; -+ } -+ -+ dist=abs(sel->geom.x-c->geom.x)+abs(sel->geom.y-c->geom.y); -+ if (dist < newdist){ -+ newdist = dist; -+ newsel=c; -+ } -+ } -+ if (newsel != NULL){ -+ focusclient(newsel, 1); -+ } -+} -+ -+ - /* We probably should change the name of this, it sounds like - * will focus the topmost client of this mon, when actually will - * only return that client */ --- -2.43.0 - diff --git a/host/pc/common/dwl/patches/gaps.patch b/host/pc/common/dwl/patches/gaps.patch deleted file mode 100644 index c025baf..0000000 --- a/host/pc/common/dwl/patches/gaps.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 50e3dd4746b6cb719efb9f8213b94ac52a5320d9 Mon Sep 17 00:00:00 2001 -From: peesock -Date: Mon, 24 Jun 2024 20:06:42 -0700 -Subject: [PATCH] gaps! - -Co-authored-by: sewn -Co-authored-by: serenevoid ---- - config.def.h | 4 ++++ - dwl.c | 34 ++++++++++++++++++++++++++-------- - 2 files changed, 30 insertions(+), 8 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 22d2171..b388b4e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -6,6 +6,9 @@ - /* appearance */ - static const int sloppyfocus = 1; /* focus follows mouse */ - static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ -+static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ -+static int gaps = 1; /* 1 means gaps between windows are added */ -+static const unsigned int gappx = 10; /* gap pixel between windows */ - static const unsigned int borderpx = 1; /* border pixel of windows */ - static const float rootcolor[] = COLOR(0x222222ff); - static const float bordercolor[] = COLOR(0x444444ff); -@@ -135,6 +138,7 @@ static const Key keys[] = { - { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, - { MODKEY, XKB_KEY_Return, zoom, {0} }, - { MODKEY, XKB_KEY_Tab, view, {0} }, -+ { MODKEY, XKB_KEY_g, togglegaps, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, - { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, -diff --git a/dwl.c b/dwl.c -index dc0437e..dc851df 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -199,6 +199,7 @@ struct Monitor { - struct wlr_box w; /* window area, layout-relative */ - struct wl_list layers[4]; /* LayerSurface.link */ - const Layout *lt[2]; -+ int gaps; - unsigned int seltags; - unsigned int sellt; - uint32_t tagset[2]; -@@ -336,6 +337,7 @@ static void tagmon(const Arg *arg); - static void tile(Monitor *m); - static void togglefloating(const Arg *arg); - static void togglefullscreen(const Arg *arg); -+static void togglegaps(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); - static void unlocksession(struct wl_listener *listener, void *data); -@@ -949,6 +951,8 @@ createmon(struct wl_listener *listener, void *data) - - wlr_output_state_init(&state); - /* Initialize monitor state using configured rules */ -+ m->gaps = gaps; -+ - m->tagset[0] = m->tagset[1] = 1; - for (r = monrules; r < END(monrules); r++) { - if (!r->name || strstr(wlr_output->name, r->name)) { -@@ -2638,7 +2642,7 @@ tagmon(const Arg *arg) - void - tile(Monitor *m) - { -- unsigned int mw, my, ty; -+ unsigned int h, r, e = m->gaps, mw, my, ty; - int i, n = 0; - Client *c; - -@@ -2647,23 +2651,30 @@ tile(Monitor *m) - n++; - if (n == 0) - return; -+ if (smartgaps == n) -+ e = 0; - - if (n > m->nmaster) -- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; -+ mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0; - else - mw = m->w.width; -- i = my = ty = 0; -+ i = 0; -+ my = ty = gappx*e; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) - continue; - if (i < m->nmaster) { -- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, -- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); -- my += c->geom.height; -+ r = MIN(n, m->nmaster) - i; -+ h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r; -+ resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my, -+ .width = mw - 2*gappx*e, .height = h}, 0); -+ my += c->geom.height + gappx*e; - } else { -+ r = n - i; -+ h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r; - resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, -- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); -- ty += c->geom.height; -+ .width = m->w.width - mw - gappx*e, .height = h}, 0); -+ ty += c->geom.height + gappx*e; - } - i++; - } -@@ -2686,6 +2697,13 @@ togglefullscreen(const Arg *arg) - setfullscreen(sel, !sel->isfullscreen); - } - -+void -+togglegaps(const Arg *arg) -+{ -+ selmon->gaps = !selmon->gaps; -+ arrange(selmon); -+} -+ - void - toggletag(const Arg *arg) - { --- -2.45.2 - diff --git a/host/pc/common/dwl/patches/ipc.patch b/host/pc/common/dwl/patches/ipc.patch deleted file mode 100644 index fd51b84..0000000 --- a/host/pc/common/dwl/patches/ipc.patch +++ /dev/null @@ -1,601 +0,0 @@ -From 6c6d655b68770ce82a24fde9b58c4d97b672553a Mon Sep 17 00:00:00 2001 -From: choc -Date: Mon, 23 Oct 2023 10:35:17 +0800 -Subject: [PATCH] implement dwl-ipc-unstable-v2 - https://codeberg.org/dwl/dwl-patches/wiki/ipc - ---- - Makefile | 14 +- - config.def.h | 1 + - dwl.c | 261 ++++++++++++++++++++++++++---- - protocols/dwl-ipc-unstable-v2.xml | 181 +++++++++++++++++++++ - 4 files changed, 419 insertions(+), 38 deletions(-) - create mode 100644 protocols/dwl-ipc-unstable-v2.xml - -diff --git a/Makefile b/Makefile -index 3358bae..28ed034 100644 ---- a/Makefile -+++ b/Makefile -@@ -17,12 +17,14 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CF - LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) - - all: dwl --dwl: dwl.o util.o -- $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ -+dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o -+ $(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ - dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ - pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ -- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h -+ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ -+ dwl-ipc-unstable-v2-protocol.h - util.o: util.c util.h -+dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.c dwl-ipc-unstable-v2-protocol.h - - # wayland-scanner is a tool which generates C headers and rigging for Wayland - # protocols, which are specified in XML. wlroots requires you to rig these up -@@ -45,6 +47,12 @@ wlr-output-power-management-unstable-v1-protocol.h: - xdg-shell-protocol.h: - $(WAYLAND_SCANNER) server-header \ - $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ -+dwl-ipc-unstable-v2-protocol.h: -+ $(WAYLAND_SCANNER) server-header \ -+ protocols/dwl-ipc-unstable-v2.xml $@ -+dwl-ipc-unstable-v2-protocol.c: -+ $(WAYLAND_SCANNER) private-code \ -+ protocols/dwl-ipc-unstable-v2.xml $@ - - config.h: - cp config.def.h $@ -diff --git a/config.def.h b/config.def.h -index 22d2171..1593033 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -127,6 +127,7 @@ static const Key keys[] = { - /* modifier key function argument */ - { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, -+ { MODKEY, XKB_KEY_b, togglebar, {0} }, - { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, - { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, - { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, -diff --git a/dwl.c b/dwl.c -index a2711f6..d9b8bae 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -67,6 +67,7 @@ - #include - #endif - -+#include "dwl-ipc-unstable-v2-protocol.h" - #include "util.h" - - /* macros */ -@@ -143,6 +144,12 @@ typedef struct { - uint32_t resize; /* configure serial of a pending resize */ - } Client; - -+typedef struct { -+ struct wl_list link; -+ struct wl_resource *resource; -+ Monitor *mon; -+} DwlIpcOutput; -+ - typedef struct { - uint32_t mod; - xkb_keysym_t keysym; -@@ -188,6 +195,7 @@ typedef struct { - - struct Monitor { - struct wl_list link; -+ struct wl_list dwl_ipc_outputs; - struct wlr_output *wlr_output; - struct wlr_scene_output *scene_output; - struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ -@@ -285,6 +293,17 @@ static void destroysessionlock(struct wl_listener *listener, void *data); - static void destroysessionmgr(struct wl_listener *listener, void *data); - static void destroykeyboardgroup(struct wl_listener *listener, void *data); - static Monitor *dirtomon(enum wlr_direction dir); -+static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); -+static void dwl_ipc_manager_destroy(struct wl_resource *resource); -+static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output); -+static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource); -+static void dwl_ipc_output_destroy(struct wl_resource *resource); -+static void dwl_ipc_output_printstatus(Monitor *monitor); -+static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output); -+static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags); -+static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index); -+static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset); -+static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource); - static void focusclient(Client *c, int lift); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -@@ -338,6 +357,7 @@ static void startdrag(struct wl_listener *listener, void *data); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *m); -+static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); - static void togglefullscreen(const Arg *arg); - static void toggletag(const Arg *arg); -@@ -413,6 +433,9 @@ static struct wlr_box sgeom; - static struct wl_list mons; - static Monitor *selmon; - -+static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output}; -+static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags}; -+ - #ifdef XWAYLAND - static void activatex11(struct wl_listener *listener, void *data); - static void associatex11(struct wl_listener *listener, void *data); -@@ -706,6 +729,10 @@ cleanupmon(struct wl_listener *listener, void *data) - LayerSurface *l, *tmp; - size_t i; - -+ DwlIpcOutput *ipc_output, *ipc_output_tmp; -+ wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link) -+ wl_resource_destroy(ipc_output->resource); -+ - /* m->layers[i] are intentionally not unlinked */ - for (i = 0; i < LENGTH(m->layers); i++) { - wl_list_for_each_safe(l, tmp, &m->layers[i], link) -@@ -986,6 +1013,8 @@ createmon(struct wl_listener *listener, void *data) - m = wlr_output->data = ecalloc(1, sizeof(*m)); - m->wlr_output = wlr_output; - -+ wl_list_init(&m->dwl_ipc_outputs); -+ - for (i = 0; i < LENGTH(m->layers); i++) - wl_list_init(&m->layers[i]); - -@@ -1336,6 +1365,192 @@ dirtomon(enum wlr_direction dir) - return selmon; - } - -+void -+dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) -+{ -+ struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id); -+ if (!manager_resource) { -+ wl_client_post_no_memory(client); -+ return; -+ } -+ wl_resource_set_implementation(manager_resource, &dwl_manager_implementation, NULL, dwl_ipc_manager_destroy); -+ -+ zdwl_ipc_manager_v2_send_tags(manager_resource, TAGCOUNT); -+ -+ for (unsigned int i = 0; i < LENGTH(layouts); i++) -+ zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol); -+} -+ -+void -+dwl_ipc_manager_destroy(struct wl_resource *resource) -+{ -+ /* No state to destroy */ -+} -+ -+void -+dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output) -+{ -+ DwlIpcOutput *ipc_output; -+ Monitor *monitor = wlr_output_from_resource(output)->data; -+ struct wl_resource *output_resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id); -+ if (!output_resource) -+ return; -+ -+ ipc_output = ecalloc(1, sizeof(*ipc_output)); -+ ipc_output->resource = output_resource; -+ ipc_output->mon = monitor; -+ wl_resource_set_implementation(output_resource, &dwl_output_implementation, ipc_output, dwl_ipc_output_destroy); -+ wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link); -+ dwl_ipc_output_printstatus_to(ipc_output); -+} -+ -+void -+dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource) -+{ -+ wl_resource_destroy(resource); -+} -+ -+static void -+dwl_ipc_output_destroy(struct wl_resource *resource) -+{ -+ DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource); -+ wl_list_remove(&ipc_output->link); -+ free(ipc_output); -+} -+ -+void -+dwl_ipc_output_printstatus(Monitor *monitor) -+{ -+ DwlIpcOutput *ipc_output; -+ wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link) -+ dwl_ipc_output_printstatus_to(ipc_output); -+} -+ -+void -+dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) -+{ -+ Monitor *monitor = ipc_output->mon; -+ Client *c, *focused; -+ int tagmask, state, numclients, focused_client, tag; -+ const char *title, *appid; -+ focused = focustop(monitor); -+ zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon); -+ -+ for (tag = 0 ; tag < TAGCOUNT; tag++) { -+ numclients = state = focused_client = 0; -+ tagmask = 1 << tag; -+ if ((tagmask & monitor->tagset[monitor->seltags]) != 0) -+ state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE; -+ -+ wl_list_for_each(c, &clients, link) { -+ if (c->mon != monitor) -+ continue; -+ if (!(c->tags & tagmask)) -+ continue; -+ if (c == focused) -+ focused_client = 1; -+ if (c->isurgent) -+ state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT; -+ -+ numclients++; -+ } -+ zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state, numclients, focused_client); -+ } -+ title = focused ? client_get_title(focused) : ""; -+ appid = focused ? client_get_appid(focused) : ""; -+ -+ zdwl_ipc_output_v2_send_layout(ipc_output->resource, monitor->lt[monitor->sellt] - layouts); -+ zdwl_ipc_output_v2_send_title(ipc_output->resource, title); -+ zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid); -+ zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol); -+ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) { -+ zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0); -+ } -+ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) { -+ zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0); -+ } -+ zdwl_ipc_output_v2_send_frame(ipc_output->resource); -+} -+ -+void -+dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags) -+{ -+ DwlIpcOutput *ipc_output; -+ Monitor *monitor; -+ Client *selected_client; -+ unsigned int newtags = 0; -+ -+ ipc_output = wl_resource_get_user_data(resource); -+ if (!ipc_output) -+ return; -+ -+ monitor = ipc_output->mon; -+ selected_client = focustop(monitor); -+ if (!selected_client) -+ return; -+ -+ newtags = (selected_client->tags & and_tags) ^ xor_tags; -+ if (!newtags) -+ return; -+ -+ selected_client->tags = newtags; -+ if (selmon == monitor) -+ focusclient(focustop(monitor), 1); -+ arrange(selmon); -+ printstatus(); -+} -+ -+void -+dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index) -+{ -+ DwlIpcOutput *ipc_output; -+ Monitor *monitor; -+ -+ ipc_output = wl_resource_get_user_data(resource); -+ if (!ipc_output) -+ return; -+ -+ monitor = ipc_output->mon; -+ if (index >= LENGTH(layouts)) -+ return; -+ if (index != monitor->lt[monitor->sellt] - layouts) -+ monitor->sellt ^= 1; -+ -+ monitor->lt[monitor->sellt] = &layouts[index]; -+ arrange(monitor); -+ printstatus(); -+} -+ -+void -+dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset) -+{ -+ DwlIpcOutput *ipc_output; -+ Monitor *monitor; -+ unsigned int newtags = tagmask & TAGMASK; -+ -+ ipc_output = wl_resource_get_user_data(resource); -+ if (!ipc_output) -+ return; -+ monitor = ipc_output->mon; -+ -+ if (!newtags || newtags == monitor->tagset[monitor->seltags]) -+ return; -+ if (toggle_tagset) -+ monitor->seltags ^= 1; -+ -+ monitor->tagset[monitor->seltags] = newtags; -+ if (selmon == monitor) -+ focusclient(focustop(monitor), 1); -+ arrange(monitor); -+ printstatus(); -+} -+ -+void -+dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource) -+{ -+ wl_resource_destroy(resource); -+} -+ - void - focusclient(Client *c, int lift) - { -@@ -2036,41 +2251,8 @@ void - printstatus(void) - { - Monitor *m = NULL; -- Client *c; -- uint32_t occ, urg, sel; -- const char *appid, *title; -- -- wl_list_for_each(m, &mons, link) { -- occ = urg = 0; -- wl_list_for_each(c, &clients, link) { -- if (c->mon != m) -- continue; -- occ |= c->tags; -- if (c->isurgent) -- urg |= c->tags; -- } -- if ((c = focustop(m))) { -- title = client_get_title(c); -- appid = client_get_appid(c); -- printf("%s title %s\n", m->wlr_output->name, title ? title : broken); -- printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken); -- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); -- printf("%s floating %d\n", m->wlr_output->name, c->isfloating); -- sel = c->tags; -- } else { -- printf("%s title \n", m->wlr_output->name); -- printf("%s appid \n", m->wlr_output->name); -- printf("%s fullscreen \n", m->wlr_output->name); -- printf("%s floating \n", m->wlr_output->name); -- sel = 0; -- } -- -- printf("%s selmon %u\n", m->wlr_output->name, m == selmon); -- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", -- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); -- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); -- } -- fflush(stdout); -+ wl_list_for_each(m, &mons, link) -+ dwl_ipc_output_printstatus(m); - } - - void -@@ -2625,6 +2807,8 @@ setup(void) - LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); - LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); - -+ wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind); -+ - /* Make sure XWayland clients don't connect to the parent X server, - * e.g when running in the x11 backend or the wayland backend and the - * compositor has Xwayland support */ -@@ -2722,6 +2906,13 @@ tile(Monitor *m) - } - } - -+void -+togglebar(const Arg *arg) { -+ DwlIpcOutput *ipc_output; -+ wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link) -+ zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource); -+} -+ - void - togglefloating(const Arg *arg) - { -diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml -new file mode 100644 -index 0000000..0a6e7e5 ---- /dev/null -+++ b/protocols/dwl-ipc-unstable-v2.xml -@@ -0,0 +1,181 @@ -+ -+ -+ -+ -+ This protocol allows clients to update and get updates from dwl. -+ -+ Warning! The protocol described in this file is experimental and -+ backward incompatible changes may be made. Backward compatible -+ changes may be added together with the corresponding interface -+ version bump. -+ Backward incompatible changes are done by bumping the version -+ number in the protocol and interface names and resetting the -+ interface version. Once the protocol is to be declared stable, -+ the 'z' prefix and the version number in the protocol and -+ interface names are removed and the interface version number is -+ reset. -+ -+ -+ -+ -+ This interface is exposed as a global in wl_registry. -+ -+ Clients can use this interface to get a dwl_ipc_output. -+ After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events. -+ The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client. -+ -+ -+ -+ -+ Indicates that the client will not the dwl_ipc_manager object anymore. -+ Objects created through this instance are not affected. -+ -+ -+ -+ -+ -+ Get a dwl_ipc_outout for the specified wl_output. -+ -+ -+ -+ -+ -+ -+ -+ This event is sent after binding. -+ A roundtrip after binding guarantees the client recieved all tags. -+ -+ -+ -+ -+ -+ -+ This event is sent after binding. -+ A roundtrip after binding guarantees the client recieved all layouts. -+ -+ -+ -+ -+ -+ -+ -+ Observe and control a dwl output. -+ -+ Events are double-buffered: -+ Clients should cache events and redraw when a dwl_ipc_output.frame event is sent. -+ -+ Request are not double-buffered: -+ The compositor will update immediately upon request. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Indicates to that the client no longer needs this dwl_ipc_output. -+ -+ -+ -+ -+ -+ Indicates the client should hide or show themselves. -+ If the client is visible then hide, if hidden then show. -+ -+ -+ -+ -+ -+ Indicates if the output is active. Zero is invalid, nonzero is valid. -+ -+ -+ -+ -+ -+ -+ Indicates that a tag has been updated. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Indicates a new layout is selected. -+ -+ -+ -+ -+ -+ -+ Indicates the title has changed. -+ -+ -+ -+ -+ -+ -+ Indicates the appid has changed. -+ -+ -+ -+ -+ -+ -+ Indicates the layout has changed. Since layout symbols are dynamic. -+ As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying. -+ You can ignore the zdwl_ipc_output.layout event. -+ -+ -+ -+ -+ -+ -+ Indicates that a sequence of status updates have finished and the client should redraw. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ The tags are updated as follows: -+ new_tags = (current_tags AND and_tags) XOR xor_tags -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Indicates if the selected client on this output is fullscreen. -+ -+ -+ -+ -+ -+ -+ Indicates if the selected client on this output is floating. -+ -+ -+ -+ -+ --- -2.51.2 - - diff --git a/host/pc/common/dwl/patches/monitorconfig.patch b/host/pc/common/dwl/patches/monitorconfig.patch deleted file mode 100644 index 4922f8d..0000000 --- a/host/pc/common/dwl/patches/monitorconfig.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 73f70cd9d817a307030f360f6c8a2500046b8b76 Mon Sep 17 00:00:00 2001 -From: Palanix -Date: Mon, 4 Apr 2022 16:08:29 +0200 -Subject: [PATCH] Updated patch now allowing setting x and y -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Co-authored-by: Leonardo Hernández Hernández ---- - config.def.h | 11 +++++++---- - dwl.c | 25 +++++++++++++++++++------ - 2 files changed, 26 insertions(+), 10 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 8f498d2..4ccacd2 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -38,12 +38,15 @@ static const Layout layouts[] = { - /* monitors */ - /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ - static const MonitorRule monrules[] = { -- /* name mfact nmaster scale layout rotate/reflect x y */ -- /* example of a HiDPI laptop monitor: -- { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, -+ /* name mfact nmaster scale layout rotate/reflect x y resx resy rate mode adaptive*/ -+ /* example of a HiDPI laptop monitor at 120Hz: -+ { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, 0, 0, 120.000f, 1, 1}, -+ * mode let's the user decide on how dwl should implement the modes: -+ * -1 Sets a custom mode following the users choice -+ * All other number's set the mode at the index n, 0 is the standard mode; see wlr-randr - */ - /* defaults */ -- { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, -+ { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1, 0, 0, 0.0f, 0 ,1}, - }; - - /* keyboard */ -diff --git a/dwl.c b/dwl.c -index 52bfbc8..9609b6d 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -215,6 +215,11 @@ typedef struct { - const Layout *lt; - enum wl_output_transform rr; - int x, y; -+ int resx; -+ int resy; -+ float rate; -+ int mode; -+ int adaptive; - } MonitorRule; - - typedef struct { -@@ -865,6 +870,7 @@ createmon(struct wl_listener *listener, void *data) - /* This event is raised by the backend when a new output (aka a display or - * monitor) becomes available. */ - struct wlr_output *wlr_output = data; -+ struct wlr_output_mode *mode = wl_container_of(wlr_output->modes.next, mode, link); - const MonitorRule *r; - size_t i; - struct wlr_output_state state; -@@ -893,16 +899,23 @@ createmon(struct wl_listener *listener, void *data) - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); - wlr_output_state_set_scale(&state, r->scale); - wlr_output_state_set_transform(&state, r->rr); -+ -+ wlr_output_state_set_adaptive_sync_enabled(&state, r->adaptive); -+ -+ if(r->mode == -1) -+ wlr_output_state_set_custom_mode(&state, r->resx, r->resy, -+ (int) (r->rate > 0 ? r->rate * 1000 : 0)); -+ else if (!wl_list_empty(&wlr_output->modes)) { -+ for (int j = 0; j < r->mode; j++) { -+ mode = wl_container_of(mode->link.next, mode, link); -+ } -+ wlr_output_state_set_mode(&state, mode); -+ } -+ - break; - } - } - -- /* The mode is a tuple of (width, height, refresh rate), and each -- * monitor supports only a specific set of modes. We just pick the -- * monitor's preferred mode; a more sophisticated compositor would let -- * the user configure it. */ -- wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); -- - /* Set up event listeners */ - LISTEN(&wlr_output->events.frame, &m->frame, rendermon); - LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); --- -2.45.1 - diff --git a/host/pc/common/dwl/patches/relative-mouse-resize.patch b/host/pc/common/dwl/patches/relative-mouse-resize.patch deleted file mode 100644 index e1dfc57..0000000 --- a/host/pc/common/dwl/patches/relative-mouse-resize.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 5c75c67fe49e5ab89e4a61dfb2fe74c768477b90 Mon Sep 17 00:00:00 2001 -From: wochap -Date: Fri, 5 Jul 2024 11:13:53 -0500 -Subject: [PATCH] implement relative-muse-resize - ---- - dwl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 59 insertions(+), 7 deletions(-) - -diff --git a/dwl.c b/dwl.c -index dc0437e..ebf9ef1 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -401,7 +401,8 @@ static struct wlr_seat *seat; - static KeyboardGroup *kb_group; - static unsigned int cursor_mode; - static Client *grabc; --static int grabcx, grabcy; /* client-relative */ -+static Client initial_grabc; -+static int grabcx, grabcy, grabx, graby, grabcenterx, grabcentery; /* client-relative */ - - static struct wlr_output_layout *output_layout; - static struct wlr_box sgeom; -@@ -1821,8 +1822,27 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d - .width = grabc->geom.width, .height = grabc->geom.height}, 1); - return; - } else if (cursor_mode == CurResize) { -- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, -- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); -+ if (grabcenterx < grabx) { -+ if (grabcentery < graby) { -+ /* bottom-right */ -+ resize(grabc, (struct wlr_box){.x = initial_grabc.geom.x, .y = initial_grabc.geom.y, -+ .width = (int)round(cursor->x) - initial_grabc.geom.x, .height = (int)round(cursor->y) - initial_grabc.geom.y}, 1); -+ } else { -+ /* top-right */ -+ resize(grabc, (struct wlr_box){.x = initial_grabc.geom.x, .y = (int)round(cursor->y), -+ .width = (int)round(cursor->x) - initial_grabc.geom.x, .height = initial_grabc.geom.y + initial_grabc.geom.height - (int)round(cursor->y)}, 1); -+ } -+ } else { -+ if (grabcentery < graby) { -+ /* bottom-left */ -+ resize(grabc, (struct wlr_box){.x = (int)round(cursor->x), .y = initial_grabc.geom.y, -+ .width = initial_grabc.geom.x + initial_grabc.geom.width - (int)round(cursor->x), .height = (int)round(cursor->y) - initial_grabc.geom.y}, 1); -+ } else { -+ /* top-left */ -+ resize(grabc, (struct wlr_box){.x = (int)round(cursor->x), .y = (int)round(cursor->y), -+ .width = initial_grabc.geom.x + initial_grabc.geom.width - (int)round(cursor->x), .height = initial_grabc.geom.y + initial_grabc.geom.height - (int)round(cursor->y)}, 1); -+ } -+ } - return; - } - -@@ -1870,10 +1890,42 @@ moveresize(const Arg *arg) - case CurResize: - /* Doesn't work for X11 output - the next absolute motion event - * returns the cursor to where it started */ -- wlr_cursor_warp_closest(cursor, NULL, -- grabc->geom.x + grabc->geom.width, -- grabc->geom.y + grabc->geom.height); -- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); -+ initial_grabc = *grabc; -+ grabx = (int)round(cursor->x); -+ graby = (int)round(cursor->y); -+ grabcx = (int)round(cursor->x) - grabc->geom.x; -+ grabcy = (int)round(cursor->y) - grabc->geom.y; -+ grabcenterx = grabc->geom.width / 2 + grabc->geom.x; -+ grabcentery = grabc->geom.height / 2 + grabc->geom.y; -+ if (grabcenterx < grabx) { -+ if (grabcentery < graby) { -+ /* bottom-right */ -+ wlr_cursor_warp_closest(cursor, NULL, -+ grabc->geom.x + grabc->geom.width, -+ grabc->geom.y + grabc->geom.height); -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); -+ } else { -+ /* top-right */ -+ wlr_cursor_warp_closest(cursor, NULL, -+ grabc->geom.x + grabc->geom.width, -+ grabc->geom.y); -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "ne-resize"); -+ } -+ } else { -+ if (grabcentery < graby) { -+ /* bottom-left */ -+ wlr_cursor_warp_closest(cursor, NULL, -+ grabc->geom.x, -+ grabc->geom.y + grabc->geom.height); -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "sw-resize"); -+ } else { -+ /* top-left */ -+ wlr_cursor_warp_closest(cursor, NULL, -+ grabc->geom.x, -+ grabc->geom.y); -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "nw-resize"); -+ } -+ } - break; - } - } --- -2.45.1 \ No newline at end of file diff --git a/host/pc/common/river.nix b/host/pc/common/river.nix new file mode 100644 index 0000000..baa4eaa --- /dev/null +++ b/host/pc/common/river.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + programs.river-classic = { + enable = true; + xwayland.enable = true; + }; +} diff --git a/screenshots/preview.png b/screenshots/preview.png index 982cad8..c774e57 100644 Binary files a/screenshots/preview.png and b/screenshots/preview.png differ