diff --git a/.github/workflows/man-update.yaml b/.github/workflows/man-update.yaml index 224d81a4..931e1d62 100644 --- a/.github/workflows/man-update.yaml +++ b/.github/workflows/man-update.yaml @@ -26,4 +26,6 @@ jobs: name: Commit with: commit_message: "[gha] build man pages" - commit_author: Mihai Fufezan + commit_user_name: Mihai Fufezan + commit_user_email: fufexan@protonmail.com + commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> diff --git a/.github/workflows/nix-update-inputs.yaml b/.github/workflows/nix-update-inputs.yaml index 13dc499c..005f8a4f 100644 --- a/.github/workflows/nix-update-inputs.yaml +++ b/.github/workflows/nix-update-inputs.yaml @@ -38,4 +38,6 @@ jobs: - uses: stefanzweifel/git-auto-commit-action@v4 with: commit_message: "Nix: bump inputs" - commit_author: Mihai Fufezan + commit_user_name: Mihai Fufezan + commit_user_email: fufexan@protonmail.com + commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> diff --git a/.github/workflows/nix-update-wlroots.yaml b/.github/workflows/nix-update-wlroots.yaml index 3a9f6998..2867ba89 100644 --- a/.github/workflows/nix-update-wlroots.yaml +++ b/.github/workflows/nix-update-wlroots.yaml @@ -33,4 +33,6 @@ jobs: - uses: stefanzweifel/git-auto-commit-action@v4 with: commit_message: "Nix: bump wlroots" - commit_author: Mihai Fufezan + commit_user_name: Mihai Fufezan + commit_user_email: fufexan@protonmail.com + commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> diff --git a/flake.lock b/flake.lock index 45fa8010..8e0488da 100644 --- a/flake.lock +++ b/flake.lock @@ -4,14 +4,17 @@ "inputs": { "nixpkgs": [ "nixpkgs" + ], + "systems": [ + "systems" ] }, "locked": { - "lastModified": 1684265364, - "narHash": "sha256-AxNnWbthsuNx73HDQr0eBxrcE3+yfl/WsaXZqUFmkpQ=", + "lastModified": 1691753796, + "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "8c279b9fb0f2b031427dc5ef4eab53f2ed835530", + "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", "type": "github" }, "original": { @@ -22,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1690179384, - "narHash": "sha256-+arbgqFTAtoeKtepW9wCnA0njCOyoiDFyl0Q0SBSOtE=", + "lastModified": 1691654369, + "narHash": "sha256-gSILTEx1jRaJjwZxRlnu3ZwMn1FVNk80qlwiCX8kmpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b12803b6d90e2e583429bb79b859ca53c348b39a", + "rev": "ce5e4a6ef2e59d89a971bc434ca8ca222b9c7f5e", "type": "github" }, "original": { @@ -40,10 +43,26 @@ "inputs": { "hyprland-protocols": "hyprland-protocols", "nixpkgs": "nixpkgs", + "systems": "systems", "wlroots": "wlroots", "xdph": "xdph" } }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, "wlroots": { "flake": false, "locked": { @@ -70,14 +89,17 @@ ], "nixpkgs": [ "nixpkgs" + ], + "systems": [ + "systems" ] }, "locked": { - "lastModified": 1691082525, - "narHash": "sha256-C5AO0KnyAFJaCkOn+5nJfWm0kyiPn/Awh0lKTjhgr7Y=", + "lastModified": 1691841170, + "narHash": "sha256-RCTm1/MVWYPnReMgyp7tr2ogGYo/pvw38jZaFwemgPU=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "42747d267ab4345c4ceb78cd4a4fe99f072d80fc", + "rev": "57a3a41ba6b358109e4fc25c6a4706b5f7d93c6b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 5908f8c4..e9d5a5d9 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,9 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + # + systems.url = "github:nix-systems/default-linux"; + wlroots = { type = "gitlab"; host = "gitlab.freedesktop.org"; @@ -16,11 +19,13 @@ hyprland-protocols = { url = "github:hyprwm/hyprland-protocols"; inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; }; xdph = { url = "github:hyprwm/xdg-desktop-portal-hyprland"; inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; inputs.hyprland-protocols.follows = "hyprland-protocols"; }; }; @@ -28,39 +33,23 @@ outputs = inputs @ { self, nixpkgs, + systems, ... }: let - lib = nixpkgs.lib.extend (import ./nix/lib.nix); - genSystems = lib.genAttrs [ - # Add more systems if they are supported - "aarch64-linux" - "x86_64-linux" - ]; - - pkgsFor = genSystems (system: + inherit (nixpkgs) lib; + eachSystem = lib.genAttrs (import systems); + pkgsFor = eachSystem (system: import nixpkgs { - inherit system; - overlays = [ - self.overlays.hyprland-packages - self.overlays.wlroots-hyprland - inputs.hyprland-protocols.overlays.default + localSystem = system; + overlays = with self.overlays; [ + hyprland-packages + hyprland-extras ]; }); in { - overlays = - (import ./nix/overlays.nix {inherit self lib inputs;}) - // { - default = - lib.mkJoinedOverlays - (with self.overlays; [ - hyprland-packages - hyprland-extras - wlroots-hyprland - inputs.hyprland-protocols.overlays.default - ]); - }; + overlays = import ./nix/overlays.nix {inherit self lib inputs;}; - checks = genSystems (system: + checks = eachSystem (system: (lib.filterAttrs (n: _: (lib.hasPrefix "hyprland" n) && !(lib.hasSuffix "debug" n)) self.packages.${system}) @@ -68,16 +57,29 @@ inherit (self.packages.${system}) xdg-desktop-portal-hyprland; }); - packages = genSystems (system: - (self.overlays.default pkgsFor.${system} pkgsFor.${system}) - // { - default = self.packages.${system}.hyprland; - }); + packages = eachSystem (system: { + default = self.packages.${system}.hyprland; + inherit + (pkgsFor.${system}) + # hyprland-packages + hyprland + hyprland-unwrapped + hyprland-debug + hyprland-nvidia + # hyprland-extras + xdg-desktop-portal-hyprland + hyprland-share-picker + # dependencies + hyprland-protocols + wlroots-hyprland + udis86 + ; + }); - devShells = genSystems (system: { + devShells = eachSystem (system: { default = pkgsFor.${system}.mkShell { name = "hyprland-shell"; - nativeBuildInputs = with pkgsFor.${system}; [ cmake python3 ]; + nativeBuildInputs = with pkgsFor.${system}; [cmake python3]; buildInputs = [self.packages.${system}.wlroots-hyprland]; inputsFrom = [ self.packages.${system}.wlroots-hyprland @@ -86,7 +88,7 @@ }; }); - formatter = genSystems (system: pkgsFor.${system}.alejandra); + formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra); nixosModules.default = import ./nix/module.nix inputs; homeManagerModules.default = import ./nix/hm-module.nix self; diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 431f309d..6f418c05 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -193,20 +193,15 @@ void requestHyprpaper(std::string arg) { return; } - // get the instance signature - auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE"); - - if (!instanceSig) { + if (instanceSignature.empty()) { std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)"; return; } - std::string instanceSigStr = std::string(instanceSig); - sockaddr_un serverAddress = {0}; serverAddress.sun_family = AF_UNIX; - std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock"; + std::string socketPath = "/tmp/hypr/" + instanceSignature + "/.hyprpaper.sock"; strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1); @@ -215,6 +210,9 @@ void requestHyprpaper(std::string arg) { return; } + arg = arg.substr(arg.find_first_of('/') + 1); // strip flags + arg = arg.substr(arg.find_first_of(' ') + 1); // strip "hyprpaper" + auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length()); if (sizeWritten < 0) { @@ -430,7 +428,7 @@ int main(int argc, char** argv) { else if (fullRequest.contains("/keyword")) request(fullRequest, 2); else if (fullRequest.contains("/hyprpaper")) - request(fullRequest, 2); + requestHyprpaper(fullRequest); else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str()); else { diff --git a/nix/default.nix b/nix/default.nix index 8c3c6364..663d5429 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -26,114 +26,111 @@ xcbutilwm, xwayland, debug ? false, + enableNvidiaPatches ? false, enableXWayland ? true, - hidpiXWayland ? false, legacyRenderer ? false, - nvidiaPatches ? false, withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, wrapRuntimeDeps ? true, version ? "git", commit, -}: let - assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) '' - Hyprland: cannot have hidpiXWayland when enableXWayland is false. - ''; -in - assert assertXWayland; - stdenv.mkDerivation { - pname = "hyprland" + lib.optionalString debug "-debug"; - inherit version; + # deprecated flags + nvidiaPatches ? false, + hidpiXWayland ? false, +}: +assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been renamed `enableNvidiaPatches`"; +assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; + stdenv.mkDerivation { + pname = "hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}${lib.optionalString debug "-debug"}"; + inherit version; - src = lib.cleanSourceWith { - filter = name: type: let - baseName = baseNameOf (toString name); - in - ! ( - lib.hasSuffix ".nix" baseName - ); - src = lib.cleanSource ../.; - }; + src = lib.cleanSourceWith { + filter = name: type: let + baseName = baseNameOf (toString name); + in + ! (lib.hasSuffix ".nix" baseName); + src = lib.cleanSource ../.; + }; - nativeBuildInputs = [ - jq - meson - ninja - pkg-config - makeWrapper - wayland-scanner - ]; + nativeBuildInputs = [ + jq + meson + ninja + pkg-config + makeWrapper + wayland-scanner + ]; - outputs = [ - "out" - "man" - "dev" - ]; + outputs = [ + "out" + "man" + "dev" + ]; - buildInputs = - [ - git - cairo - hyprland-protocols - libdrm - libinput - libxkbcommon - mesa - pango - udis86 - wayland - wayland-protocols - pciutils - (wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;}) - ] - ++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland] - ++ lib.optionals withSystemd [systemd]; + buildInputs = + [ + git + cairo + hyprland-protocols + libdrm + libinput + libxkbcommon + mesa + pango + udis86 + wayland + wayland-protocols + pciutils + (wlroots.override {inherit enableNvidiaPatches;}) + ] + ++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland] + ++ lib.optionals withSystemd [systemd]; - mesonBuildType = - if debug - then "debug" - else "release"; + mesonBuildType = + if debug + then "debug" + else "release"; - mesonFlags = builtins.concatLists [ - ["-Dauto_features=disabled"] - (lib.optional enableXWayland "-Dxwayland=enabled") - (lib.optional legacyRenderer "-Dlegacy_renderer=enabled") - (lib.optional withSystemd "-Dsystemd=enabled") - ]; + mesonFlags = builtins.concatLists [ + ["-Dauto_features=disabled"] + (lib.optional enableXWayland "-Dxwayland=enabled") + (lib.optional legacyRenderer "-Dlegacy_renderer=enabled") + (lib.optional withSystemd "-Dsystemd=enabled") + ]; - patches = [ - # make meson use the provided wlroots instead of the git submodule - ./patches/meson-build.patch - # fixes portals search path to be picked up from $XDG_DESKTOP_PORTAL_DIR - ./patches/portals.patch - ]; + patches = [ + # make meson use the provided wlroots instead of the git submodule + ./patches/meson-build.patch + # fixes portals search path to be picked up from $XDG_DESKTOP_PORTAL_DIR + ./patches/portals.patch + ]; - postPatch = '' - # Fix hardcoded paths to /usr installation - sed -i "s#/usr#$out#" src/render/OpenGL.cpp - substituteInPlace meson.build \ - --replace "@GIT_COMMIT_HASH@" '${commit}' \ - --replace "@GIT_DIRTY@" '${ - if commit == "" - then "dirty" - else "" - }' - ''; + postPatch = '' + # Fix hardcoded paths to /usr installation + sed -i "s#/usr#$out#" src/render/OpenGL.cpp + substituteInPlace meson.build \ + --replace "@GIT_COMMIT_HASH@" '${commit}' \ + --replace "@GIT_DIRTY@" '${ + if commit == "" + then "dirty" + else "" + }' + ''; - postInstall = '' - ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots - ${lib.optionalString wrapRuntimeDeps '' - wrapProgram $out/bin/Hyprland \ - --suffix PATH : ${lib.makeBinPath [ binutils pciutils ]} - ''} - ''; + postInstall = '' + ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots + ${lib.optionalString wrapRuntimeDeps '' + wrapProgram $out/bin/Hyprland \ + --suffix PATH : ${lib.makeBinPath [binutils pciutils]} + ''} + ''; - passthru.providedSessions = ["hyprland"]; + passthru.providedSessions = ["hyprland"]; - meta = with lib; { - homepage = "https://github.com/vaxerski/Hyprland"; - description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; - license = licenses.bsd3; - platforms = platforms.linux; - mainProgram = "Hyprland"; - }; - } + meta = with lib; { + homepage = "https://github.com/vaxerski/Hyprland"; + description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; + license = licenses.bsd3; + platforms = platforms.linux; + mainProgram = "Hyprland"; + }; + } diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 133c0ef6..123bceb3 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -7,8 +7,7 @@ self: { cfg = config.wayland.windowManager.hyprland; defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override { enableXWayland = cfg.xwayland.enable; - hidpiXWayland = cfg.xwayland.hidpi; - inherit (cfg) nvidiaPatches; + inherit (cfg) enableNvidiaPatches; }; in { disabledModules = ["services/window-managers/hyprland.nix"]; @@ -36,13 +35,12 @@ in { defaultText = lib.literalExpression '' hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override { enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable; - hidpiXWayland = config.wayland.windowManager.hyprland.xwayland.hidpi; - inherit (config.wayland.windowManager.hyprland) nvidiaPatches; + inherit (config.wayland.windowManager.hyprland) enableNvidiaPatches; } ''; description = lib.mdDoc '' Hyprland package to use. Will override the 'xwayland' and - 'nvidiaPatches' options. + 'enableNvidiaPatches' options. Defaults to the one provided by the flake. Set it to {package}`pkgs.hyprland` to use the one provided by nixpkgs or @@ -86,19 +84,9 @@ in { ''; }; - xwayland = { - enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;}; - hidpi = - lib.mkEnableOption null - // { - description = lib.mdDoc '' - Enable HiDPI XWayland, based on [XWayland MR 733](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733). - See for more info. - ''; - }; - }; + xwayland.enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;}; - nvidiaPatches = lib.mkEnableOption (lib.mdDoc "patching wlroots for better Nvidia support."); + enableNvidiaPatches = lib.mkEnableOption (lib.mdDoc "patching wlroots for better Nvidia support."); extraConfig = lib.mkOption { type = lib.types.nullOr lib.types.lines; @@ -119,10 +107,14 @@ in { config = lib.mkIf cfg.enable { warnings = - if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null then - [ ''You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins. - Your Hyprland config will be linked by home manager. - Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning.'' ] + if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null + then [ + '' + You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins. + Your Hyprland config will be linked by home manager. + Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning. + '' + ] else []; home.packages = @@ -138,9 +130,17 @@ in { exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && systemctl --user start hyprland-session.target '') + lib.concatStrings (builtins.map (entry: let - plugin = if lib.types.package.check entry then "${entry}/lib/lib${entry.pname}.so" else entry; - in "plugin = ${plugin}\n") cfg.plugins) - + (if cfg.extraConfig != null then cfg.extraConfig else ""); + plugin = + if lib.types.package.check entry + then "${entry}/lib/lib${entry.pname}.so" + else entry; + in "plugin = ${plugin}\n") + cfg.plugins) + + ( + if cfg.extraConfig != null + then cfg.extraConfig + else "" + ); onChange = let hyprlandPackage = @@ -169,4 +169,9 @@ in { }; }; }; + + imports = [ + (lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "hidpi"] + "Support for this option has been removed. Refer to https://wiki.hyprland.org/Configuring/XWayland for more info") + ]; } diff --git a/nix/lib.nix b/nix/lib.nix deleted file mode 100644 index 1a413352..00000000 --- a/nix/lib.nix +++ /dev/null @@ -1,8 +0,0 @@ -final: prev: let - lib = final; - - mkJoinedOverlays = overlays: final: prev: - lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays; -in prev // { - inherit mkJoinedOverlays; -} diff --git a/nix/module.nix b/nix/module.nix index 04f48fcd..2dd173c3 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -6,11 +6,12 @@ inputs: { }: with lib; let cfg = config.programs.hyprland; + inherit (pkgs.stdenv.hostPlatform) system; - defaultHyprlandPackage = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.default.override { - enableXWayland = cfg.xwayland.enable; - hidpiXWayland = cfg.xwayland.hidpi; - inherit (cfg) nvidiaPatches; + finalPortalPackage = cfg.portalPackage.override { + hyprland-share-picker = inputs.xdph.packages.${system}.hyprland-share-picker.override { + hyprland = cfg.finalPackage; + }; }; in { # disables Nixpkgs Hyprland module to avoid conflicts @@ -30,47 +31,36 @@ in { ''; }; - package = mkOption { - type = types.path; - default = defaultHyprlandPackage; - defaultText = literalExpression '' - hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override { - enableXWayland = config.programs.hyprland.xwayland.enable; - hidpiXWayland = config.programs.hyprland.xwayland.hidpi; - inherit (config.programs.hyprland) nvidiaPatches; - } - ''; - example = literalExpression "pkgs.hyprland"; + package = mkPackageOptionMD inputs.self.packages.${system} "hyprland" { }; + + finalPackage = mkOption { + type = types.package; + readOnly = true; + default = cfg.package.override { + enableXWayland = cfg.xwayland.enable; + enableNvidiaPatches = cfg.enableNvidiaPatches; + }; + defaultText = + literalExpression + "`programs.hyprland.package` with applied configuration"; description = mdDoc '' - The Hyprland package to use. - Setting this option will make {option}`programs.hyprland.xwayland` and - {option}`programs.hyprland.nvidiaPatches` not work. + The Hyprland package after applying configuration. ''; }; - xwayland = { - enable = mkEnableOption (mdDoc "XWayland") // {default = true;}; - hidpi = - mkEnableOption null - // { - description = mdDoc '' - Enable HiDPI XWayland, based on [XWayland MR 733](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733). - See for more info. - ''; - }; - }; + portalPackage = mkPackageOptionMD inputs.xdph.packages.${system} "xdg-desktop-portal-hyprland" {}; - nvidiaPatches = mkEnableOption (mdDoc "patching wlroots for better Nvidia support"); + xwayland.enable = mkEnableOption (mdDoc "support for XWayland") // {default = true;}; + + enableNvidiaPatches = + mkEnableOption null + // { + description = mdDoc "Whether to apply patches to wlroots for better Nvidia support."; + }; }; config = mkIf cfg.enable { - environment = { - systemPackages = [cfg.package]; - - sessionVariables = { - NIXOS_OZONE_WL = mkDefault "1"; - }; - }; + environment.systemPackages = [cfg.finalPackage]; fonts = if versionOlder config.system.stateVersion "23.11" @@ -81,22 +71,29 @@ in { programs = { dconf.enable = mkDefault true; - xwayland.enable = mkDefault true; + xwayland.enable = mkDefault cfg.xwayland.enable; }; security.polkit.enable = true; - services.xserver.displayManager.sessionPackages = [cfg.package]; + services.xserver.displayManager.sessionPackages = [cfg.finalPackage]; xdg.portal = { enable = mkDefault true; - extraPortals = lib.mkIf (cfg.package != null) [ - (inputs.xdph.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland.override { - hyprland-share-picker = inputs.xdph.packages.${pkgs.stdenv.hostPlatform.system}.hyprland-share-picker.override { - hyprland = cfg.package; - }; - }) - ]; + extraPortals = [finalPortalPackage]; }; }; + + imports = with lib; [ + ( + mkRemovedOptionModule + ["programs" "hyprland" "xwayland" "hidpi"] + "XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland" + ) + ( + mkRenamedOptionModule + ["programs" "hyprland" "nvidiaPatches"] + ["programs" "hyprland" "enableNvidiaPatches"] + ) + ]; } diff --git a/nix/overlays.nix b/nix/overlays.nix index 8a61fa10..ddd8b2e6 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -10,71 +10,62 @@ (builtins.substring 4 2 longDate) (builtins.substring 6 2 longDate) ]); + + mkJoinedOverlays = overlays: final: prev: + lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays; in { - # Packages for variations of Hyprland, and its dependencies. - hyprland-packages = final: prev: { - hyprland = final.callPackage ./default.nix { - version = - props.version - + "+date=" - + (mkDate (self.lastModifiedDate or "19700101")) - + "_" - + (self.shortRev or "dirty"); - wlroots = final.wlroots-hyprland; - commit = self.rev or ""; - inherit (final) udis86 hyprland-protocols; - }; + # Contains what a user is most likely to care about: + # Hyprland itself, XDPH and the Share Picker. + default = mkJoinedOverlays (with self.overlays; [ + hyprland-packages + hyprland-extras + ]); - hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; - hyprland-debug = final.hyprland.override {debug = true;}; - hyprland-hidpi = final.hyprland.override {hidpiXWayland = true;}; - hyprland-nvidia = final.hyprland.override {nvidiaPatches = true;}; - hyprland-no-hidpi = - builtins.trace - "hyprland-no-hidpi was removed. Please use the default package." - final.hyprland; - - udis86 = final.callPackage ./udis86.nix {}; - }; + # Packages for variations of Hyprland, dependencies included. + hyprland-packages = mkJoinedOverlays [ + # Dependencies + inputs.hyprland-protocols.overlays.default + self.overlays.wlroots-hyprland + self.overlays.udis86 + # Hyprland packages themselves + (final: prev: { + hyprland = final.callPackage ./default.nix { + version = "${props.version}+date=${mkDate (self.lastModifiedDate or "19700101")}_${self.shortRev or "dirty"}"; + wlroots = final.wlroots-hyprland; + commit = self.rev or ""; + inherit (final) udis86 hyprland-protocols; + }; + hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; + hyprland-debug = final.hyprland.override {debug = true;}; + hyprland-nvidia = final.hyprland.override {enableNvidiaPatches = true;}; + hyprland-hidpi = + builtins.trace '' + hyprland-hidpi was removed. Please use the hyprland package. + For more information, refer to https://wiki.hyprland.org/Configuring/XWayland. + '' + final.hyprland; + }) + ]; # Packages for extra software recommended for usage with Hyprland, # including forked or patched packages for compatibility. - hyprland-extras = lib.mkJoinedOverlays [ - # Include any inputs' specific overlays whose attributes should - # be re-exported by the Hyprland flake. - # - inputs.xdph.overlays.default - # Provides: - # - xdg-desktop-portal-hyprland - # - hyprland-share-picker - # - # Attributes for `hyprland-extras` defined by this flake can - # go in the oberlay below. - (final: prev: { - waybar-hyprland = prev.waybar.overrideAttrs (old: { - postPatch = '' - # use hyprctl to switch workspaces - sed -i 's/zext_workspace_handle_v1_activate(workspace_handle_);/const std::string command = "hyprctl dispatch workspace " + name_;\n\tsystem(command.c_str());/g' src/modules/wlr/workspace_manager.cpp - ''; - postFixup = '' - wrapProgram $out/bin/waybar \ - --suffix PATH : ${lib.makeBinPath [final.hyprland]} - ''; - mesonFlags = old.mesonFlags ++ ["-Dexperimental=true"]; - }); - }) + hyprland-extras = mkJoinedOverlays [ + inputs.xdph.overlays.xdg-desktop-portal-hyprland + inputs.xdph.overlays.hyprland-share-picker ]; + udis86 = final: prev: { + udis86 = final.callPackage ./udis86.nix {}; + }; + # Patched version of wlroots for Hyprland. # It is under a new package name so as to not conflict with # the standard version in nixpkgs. wlroots-hyprland = final: prev: { wlroots-hyprland = final.callPackage ./wlroots.nix { - version = - mkDate (inputs.wlroots.lastModifiedDate or "19700101") - + "_" - + (inputs.wlroots.shortRev or "dirty"); + version = "${mkDate (inputs.wlroots.lastModifiedDate or "19700101")}_${inputs.wlroots.shortRev or "dirty"}"; src = inputs.wlroots; + libdisplay-info = prev.libdisplay-info.overrideAttrs (old: { version = "0.1.1+date=2023-03-02"; src = final.fetchFromGitLab { @@ -85,6 +76,7 @@ in { sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4="; }; }); + libliftoff = prev.libliftoff.overrideAttrs (old: { version = "0.5.0-dev"; src = final.fetchFromGitLab { diff --git a/nix/patches/portals.patch b/nix/patches/portals.patch index 4d426dd5..cb3d97c3 100644 --- a/nix/patches/portals.patch +++ b/nix/patches/portals.patch @@ -1,8 +1,8 @@ diff --git a/src/Compositor.cpp b/src/Compositor.cpp -index a9d95f39..069a03ca 100644 +index 1d978aed..56665389 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp -@@ -2340,14 +2340,18 @@ void CCompositor::performUserChecks() { +@@ -2365,17 +2365,16 @@ void CCompositor::performUserChecks() { static auto* const PSUPPRESSPORTAL = &g_pConfigManager->getConfigValuePtr("misc:suppress_portal_warnings")->intValue; @@ -18,9 +18,11 @@ index a9d95f39..069a03ca 100644 g_pHyprNotificationOverlay->addNotification("You have one or more incompatible xdg-desktop-portal impls installed. Please remove incompatible ones to avoid issues.", CColor(0), 15000, ICON_ERROR); } - +- - if (std::filesystem::exists("/usr/share/xdg-desktop-portal/portals/hyprland.portal") && std::filesystem::exists("/usr/share/xdg-desktop-portal/portals/wlr.portal")) { -+ if (std::filesystem::exists(PORTALDIR + "/hyprland.portal") && std::filesystem::exists(PORTALDIR + "/wlr.portal")) { - g_pHyprNotificationOverlay->addNotification("You have xdg-desktop-portal-hyprland and -wlr installed simultaneously. Please uninstall one to avoid issues.", CColor(0), - 15000, ICON_ERROR); - } +- g_pHyprNotificationOverlay->addNotification("You have xdg-desktop-portal-hyprland and -wlr installed simultaneously. Please uninstall one to avoid issues.", CColor(0), +- 15000, ICON_ERROR); +- } + } + } + diff --git a/nix/wlroots.nix b/nix/wlroots.nix index 794bb959..c1aa27de 100644 --- a/nix/wlroots.nix +++ b/nix/wlroots.nix @@ -1,64 +1,28 @@ { + lib, version, src, - # wlroots, - xwayland, - fetchpatch, - lib, hwdata, - libliftoff, libdisplay-info, - hidpiXWayland ? true, + libliftoff, enableXWayland ? true, - nvidiaPatches ? false, + enableNvidiaPatches ? false, }: -assert (lib.assertMsg (hidpiXWayland -> enableXWayland) '' - wlroots-hyprland: cannot have hidpiXWayland when enableXWayland is false. -''); - (wlroots.overrideAttrs - (old: { - inherit version src; - pname = - old.pname - + "-hyprland" - + ( - if hidpiXWayland - then "-hidpi" - else "" - ) - + ( - if nvidiaPatches - then "-nvidia" - else "" - ); - patches = - (old.patches or []) - ++ (lib.optionals (enableXWayland && hidpiXWayland) [ - # adapted from https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7 - ./patches/wlroots-hidpi.patch - (fetchpatch { - url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff"; - sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI="; - revert = true; - }) - ]) - ++ (lib.optionals nvidiaPatches [ - ./patches/wlroots-nvidia.patch - ]); - buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info]; +wlroots.overrideAttrs (old: { + inherit version src enableXWayland; - NIX_CFLAGS_COMPILE = toString [ - "-Wno-error=maybe-uninitialized" - ]; - })) - .override { - xwayland = xwayland.overrideAttrs (old: { - patches = - (old.patches or []) - ++ (lib.optionals hidpiXWayland [ - ./patches/xwayland-vsync.patch - ./patches/xwayland-hidpi.patch - ]); - }); - } + pname = "${old.pname}-hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}"; + + patches = + (old.patches or []) + ++ (lib.optionals enableNvidiaPatches [ + ./patches/wlroots-nvidia.patch + ]); + + buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info]; + + NIX_CFLAGS_COMPILE = toString [ + "-Wno-error=maybe-uninitialized" + ]; +}) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9d32d9df..d6cd019f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -12,11 +12,10 @@ int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal %d", signo); - if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) { + if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) g_pCompositor->cleanup(); - } - return 0; // everything went fine + return 0; } void handleUnrecoverableSignal(int sig) { @@ -112,20 +111,20 @@ void CCompositor::initServer() { if (!m_sWLRBackend) { Debug::log(CRIT, "m_sWLRBackend was NULL!"); - throw std::runtime_error("wlr_backend_autocreate() failed!"); + throwError("wlr_backend_autocreate() failed!"); } m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); if (m_iDRMFD < 0) { Debug::log(CRIT, "Couldn't query the DRM FD!"); - throw std::runtime_error("wlr_backend_get_drm_fd() failed!"); + throwError("wlr_backend_get_drm_fd() failed!"); } m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); if (!m_sWLRRenderer) { Debug::log(CRIT, "m_sWLRRenderer was NULL!"); - throw std::runtime_error("wlr_gles2_renderer_create_with_drm_fd() failed!"); + throwError("wlr_gles2_renderer_create_with_drm_fd() failed!"); } wlr_renderer_init_wl_shm(m_sWLRRenderer, m_sWLDisplay); @@ -141,14 +140,14 @@ void CCompositor::initServer() { if (!m_sWLRAllocator) { Debug::log(CRIT, "m_sWLRAllocator was NULL!"); - throw std::runtime_error("wlr_allocator_autocreate() failed!"); + throwError("wlr_allocator_autocreate() failed!"); } m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer); if (!m_sWLREGL) { Debug::log(CRIT, "m_sWLREGL was NULL!"); - throw std::runtime_error("wlr_gles2_renderer_get_egl() failed!"); + throwError("wlr_gles2_renderer_get_egl() failed!"); } m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, 6, m_sWLRRenderer); @@ -247,7 +246,7 @@ void CCompositor::initServer() { if (!m_sWLRHeadlessBackend) { Debug::log(CRIT, "Couldn't create the headless backend"); - throw std::runtime_error("wlr_headless_backend_create() failed!"); + throwError("wlr_headless_backend_create() failed!"); } wlr_single_pixel_buffer_manager_v1_create(m_sWLDisplay); @@ -464,7 +463,7 @@ void CCompositor::startCompositor() { if (m_szWLDisplaySocket.empty()) { Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); wlr_backend_destroy(m_sWLRBackend); - throw std::runtime_error("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); + throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); } setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); @@ -486,7 +485,7 @@ void CCompositor::startCompositor() { Debug::log(CRIT, "Backend did not start!"); wlr_backend_destroy(m_sWLRBackend); wl_display_destroy(m_sWLDisplay); - throw std::runtime_error("The backend could not start!"); + throwError("The backend could not start!"); } wlr_cursor_set_xcursor(m_sWLRCursor, m_sWLRXCursorMgr, "left_ptr"); @@ -2488,3 +2487,51 @@ void CCompositor::setIdleActivityInhibit(bool enabled) { wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, enabled); wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled); } + +void CCompositor::arrangeMonitors() { + static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; + + std::vector toArrange; + std::vector arranged; + + for (auto& m : m_vMonitors) + toArrange.push_back(m.get()); + + for (auto it = toArrange.begin(); it != toArrange.end();) { + auto m = *it; + + if (m->activeMonitorRule.offset != Vector2D{-INT32_MAX, -INT32_MAX}) { + // explicit. + m->moveTo(m->activeMonitorRule.offset); + arranged.push_back(m); + it = toArrange.erase(it); + + if (it == toArrange.end()) + break; + + continue; + } + + ++it; + } + + // auto left + int maxOffset = 0; + for (auto& m : arranged) { + if (m->vecPosition.x + m->vecSize.x > maxOffset) + maxOffset = m->vecPosition.x + m->vecSize.x; + } + + for (auto& m : toArrange) { + m->moveTo({maxOffset, 0}); + maxOffset += m->vecPosition.x + m->vecSize.x; + } + + // reset maxOffset (reuse) + // and set xwayland positions aka auto for all + maxOffset = 0; + for (auto& m : m_vMonitors) { + m->vecXWaylandPosition = {maxOffset, 0}; + maxOffset += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x); + } +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 971b0fa2..6101aa5e 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -202,6 +202,7 @@ class CCompositor { CWindow* getForceFocus(); void notifyIdleActivity(); void setIdleActivityInhibit(bool inhibit); + void arrangeMonitors(); std::string explicitConfigPath; diff --git a/src/Window.cpp b/src/Window.cpp index 7350f74c..2c6781f4 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -26,17 +26,7 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { if (m_bFadingOut) return m_eOriginalClosedExtents; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; - - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); - - const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; - - auto borderSize = m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE); - if (m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - borderSize = m_sAdditionalConfigData.borderSize.toUnderlying(); - - borderSize *= m_sSpecialRenderData.border && !m_sAdditionalConfigData.forceNoBorder; + const int BORDERSIZE = getRealBorderSize(); if (m_sAdditionalConfigData.dimAround) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); @@ -44,7 +34,7 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { {PMONITOR->vecSize.x - (m_vRealPosition.vec().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.vec().y - PMONITOR->vecPosition.y)}}; } - SWindowDecorationExtents maxExtents = {{borderSize + 2, borderSize + 2}, {borderSize + 2, borderSize + 2}}; + SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; for (auto& wd : m_dWindowDecorations) { @@ -144,14 +134,14 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() { } wlr_box CWindow::getWindowInputBox() { - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + const int BORDERSIZE = getRealBorderSize(); if (m_sAdditionalConfigData.dimAround) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } - SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}}; + SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; for (auto& wd : m_dWindowDecorations) { @@ -347,6 +337,8 @@ void CWindow::moveToWorkspace(int workspaceID) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); + updateSpecialRenderData(); + if (PWORKSPACE) { g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%lx,%s", this, PWORKSPACE->m_szName.c_str())}); EMIT_HOOK_EVENT("moveWindow", (std::vector{this, PWORKSPACE})); @@ -356,6 +348,9 @@ void CWindow::moveToWorkspace(int workspaceID) { m_pSwallowed->moveToWorkspace(workspaceID); m_pSwallowed->m_iMonitorID = m_iMonitorID; } + + // update xwayland coords + g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec()); } CWindow* CWindow::X11TransientFor() { @@ -589,29 +584,27 @@ void CWindow::updateDynamicRules() { // it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize) // otherwise behaviour is undefined bool CWindow::isInCurvedCorner(double x, double y) { - static auto* const ROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; - static auto* const BORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; - - if (BORDERSIZE >= ROUNDING || ROUNDING == 0) + const int ROUNDING = rounding(); + if (getRealBorderSize() >= ROUNDING) return false; // (x0, y0), (x0, y1), ... are the center point of rounding at each corner - double x0 = m_vRealPosition.vec().x + *ROUNDING; - double y0 = m_vRealPosition.vec().y + *ROUNDING; - double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - *ROUNDING; - double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - *ROUNDING; + double x0 = m_vRealPosition.vec().x + ROUNDING; + double y0 = m_vRealPosition.vec().y + ROUNDING; + double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - ROUNDING; + double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - ROUNDING; if (x < x0 && y < y0) { - return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING; + return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; } if (x > x1 && y < y0) { - return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING; + return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; } if (x < x0 && y > y1) { - return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING; + return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; } if (x > x1 && y > y1) { - return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING; + return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; } return false; @@ -687,7 +680,7 @@ void CWindow::setGroupCurrent(CWindow* pWindow) { g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode); PCURRENT->setHidden(true); - pWindow->setHidden(false); // can remove m_pLastWindow + pWindow->setHidden(false); // can remove m_pLastWindow g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow); @@ -810,3 +803,31 @@ float CWindow::rounding() { return rounding; } + +void CWindow::updateSpecialRenderData() { + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); + const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; + bool border = true; + + if (m_bIsFloating && g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue == 1) + border = false; + + m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(border); + m_sSpecialRenderData.borderSize = WORKSPACERULE.borderSize.value_or(-1); + m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); + m_sSpecialRenderData.rounding = WORKSPACERULE.rounding.value_or(true); + m_sSpecialRenderData.shadow = WORKSPACERULE.shadow.value_or(true); +} + +int CWindow::getRealBorderSize() { + if (!m_sSpecialRenderData.border || m_sAdditionalConfigData.forceNoBorder) + return 0; + + if (m_sAdditionalConfigData.borderSize.toUnderlying() != -1) + return m_sAdditionalConfigData.borderSize.toUnderlying(); + + if (m_sSpecialRenderData.borderSize.toUnderlying() != -1) + return m_sSpecialRenderData.borderSize.toUnderlying(); + + return g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; +} diff --git a/src/Window.hpp b/src/Window.hpp index 3d1c69ac..307ff1de 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -104,6 +104,7 @@ struct SWindowSpecialRenderData { bool rounding = true; bool border = true; bool decorate = true; + bool shadow = true; }; struct SWindowAdditionalConfigData { @@ -333,6 +334,9 @@ class CWindow { bool opaque(); float rounding(); + int getRealBorderSize(); + void updateSpecialRenderData(); + void onBorderAngleAnimEnd(void* ptr); bool isInCurvedCorner(double x, double y); bool hasPopupAt(const Vector2D& pos); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index bb582039..fffa61a0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -125,6 +125,7 @@ void CConfigManager::setDefaultVars() { configValues["debug:enable_stdout_logs"].intValue = 0; configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; configValues["debug:manual_crash"].intValue = 0; + configValues["debug:suppress_errors"].intValue = 0; configValues["decoration:rounding"].intValue = 0; configValues["decoration:blur:enabled"].intValue = 1; @@ -626,15 +627,10 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string } if (ARGS[2].find("auto") == 0) { - newrule.offset = Vector2D(-1, -1); + newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX); } else { newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x'))); newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1)); - - if (newrule.offset.x < 0 || newrule.offset.y < 0) { - parseError = "invalid offset. Offset cannot be negative."; - newrule.offset = Vector2D(); - } } if (ARGS[3].find("auto") == 0) { @@ -1144,6 +1140,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: wsRule.borderSize = std::stoi(rule.substr(delim + 11)); else if ((delim = rule.find("border:")) != std::string::npos) wsRule.border = configStringToInt(rule.substr(delim + 7)); + else if ((delim = rule.find("shadow:")) != std::string::npos) + wsRule.shadow = configStringToInt(rule.substr(delim + 7)); else if ((delim = rule.find("rounding:")) != std::string::npos) wsRule.rounding = configStringToInt(rule.substr(delim + 9)); else if ((delim = rule.find("decorate:")) != std::string::npos) @@ -1569,7 +1567,7 @@ void CConfigManager::loadConfigLoadVars() { g_pHyprOpenGL->m_bReloadScreenShader = true; // parseError will be displayed next frame - if (parseError != "") + if (parseError != "" && !configValues["debug:suppress_errors"].intValue) g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); else if (configValues["autogenerated"].intValue == 1) g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + mainConfigPath + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", @@ -1588,12 +1586,13 @@ void CConfigManager::loadConfigLoadVars() { ensureVRR(); } - // Updates dynamic window rules + // Updates dynamic window and workspace rules for (auto& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped) continue; w->updateDynamicRules(); + w->updateSpecialRenderData(); } // Update window border colors @@ -1778,7 +1777,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st Debug::log(WARN, "No rules configured. Using the default hardcoded one."); - return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-1, -1), .scale = -1}; // 0, 0 is preferred and -1, -1 is auto + return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-INT32_MAX, -INT32_MAX), .scale = -1}; // 0, 0 is preferred and -1, -1 is auto } SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index b2b9c38c..a14f5470 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -48,6 +48,7 @@ struct SWorkspaceRule { std::optional border; std::optional rounding; std::optional decorate; + std::optional shadow; }; struct SMonitorAdditionalReservedArea { diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index 4b8eeea8..7a836edd 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -122,19 +122,8 @@ void Events::listener_destroyConstraint(void* owner, void* data) { const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse); - if (PWINDOW && PCONSTRAINT->positionHint != Vector2D{-1, -1}) { - if (PWINDOW->m_bIsX11) { - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PCONSTRAINT->positionHint.x + PWINDOW->m_uSurface.xwayland->x, - PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->positionHint.y); - - wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y); - } else { - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PCONSTRAINT->positionHint.x + PWINDOW->m_vRealPosition.vec().x, - PCONSTRAINT->positionHint.y + PWINDOW->m_vRealPosition.vec().y); - - wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y); - } - } + if (PWINDOW && PCONSTRAINT->positionHint != Vector2D{-1, -1}) + g_pInputManager->warpMouseToConstraintMiddle(PCONSTRAINT); PCONSTRAINT->pMouse->currentConstraint = nullptr; } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index e7d6e2ad..f89032ea 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -39,6 +39,7 @@ namespace Events { DYNLISTENFUNC(destroyPopupXDG); DYNLISTENFUNC(commitPopupXDG); DYNLISTENFUNC(newPopupFromPopupXDG); + DYNLISTENFUNC(repositionPopupXDG); // Surface XDG (window) LISTENER(newXDGSurface); diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index 01849867..4fec9041 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -142,8 +142,11 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output); - if (layersurface->layerSurface->current.keyboard_interactive && - (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained + const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive && + // don't focus if constrained + (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint); + + if (GRABSFOCUS) { g_pCompositor->focusSurface(layersurface->layerSurface->surface); const auto LOCAL = @@ -161,7 +164,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; layersurface->alpha.setValue(0); - layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN) ? 0.f : 1.f); + layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS) ? 0.f : 1.f); layersurface->readyToDelete = false; layersurface->fadingOut = false; diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp index b76c70af..0c1594a5 100644 --- a/src/events/Popups.cpp +++ b/src/events/Popups.cpp @@ -60,6 +60,7 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) { pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->surface->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup"); pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup"); pHyprPopup->hyprListener_commitPopupXDG.initCallback(&popup->base->surface->events.commit, &Events::listener_commitPopupXDG, pHyprPopup, "HyprPopup"); + pHyprPopup->hyprListener_repositionPopupXDG.initCallback(&popup->events.reposition, &Events::listener_repositionPopupXDG, pHyprPopup, "HyprPopup"); const auto PMONITOR = g_pCompositor->m_pLastMonitor; @@ -170,6 +171,21 @@ void Events::listener_mapPopupXDG(void* owner, void* data) { Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %lx", PPOPUP->pSurfaceTree); } +void Events::listener_repositionPopupXDG(void* owner, void* data) { + SXDGPopup* PPOPUP = (SXDGPopup*)owner; + + Debug::log(LOG, "XDG Popup %lx asks for a reposition", PPOPUP); + + int lx = 0, ly = 0; + addPopupGlobalCoords(PPOPUP, &lx, &ly); + + wlr_box extents; + wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents); + + PPOPUP->lastPos = {lx - extents.x, ly - extents.y}; + PPOPUP->repositionRequested = true; +} + void Events::listener_unmapPopupXDG(void* owner, void* data) { SXDGPopup* PPOPUP = (SXDGPopup*)owner; Debug::log(LOG, "XDG Popup unmapped"); @@ -207,9 +223,17 @@ void Events::listener_commitPopupXDG(void* owner, void* data) { PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y; } - int lx = 0, ly = 0; + int lx = 0, ly = 0; addPopupGlobalCoords(PPOPUP, &lx, &ly); + wlr_box extents; + wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents); + + if (PPOPUP->repositionRequested) + g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2); + + PPOPUP->repositionRequested = false; + g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index a45aa91e..02ccd950 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -223,6 +223,8 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode); } + PWINDOW->updateSpecialRenderData(); + // disallow tiled pinned if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating) PWINDOW->m_bPinned = false; @@ -413,8 +415,8 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); } } else if (r.szRule.find("center") == 0) { - auto RESERVEDOFFSET = Vector2D(); - const auto ARGS = CVarList(r.szRule, 2, ' '); + auto RESERVEDOFFSET = Vector2D(); + const auto ARGS = CVarList(r.szRule, 2, ' '); if (ARGS[1] == "1") RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; @@ -994,7 +996,9 @@ void Events::listener_configureX11(void* owner, void* data) { else PWINDOW->setHidden(true); - PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(E->x, E->y)); + const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({E->x, E->y}); + + PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS); PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height)); static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; @@ -1044,13 +1048,15 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; - if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || - abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) { - Debug::log(LOG, "Unmanaged window %lx requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, - (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height); + const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y}); + + if (abs(std::floor(POS.x) - LOGICALPOS.x) > 2 || abs(std::floor(POS.y) - LOGICALPOS.y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || + abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) { + Debug::log(LOG, "Unmanaged window %lx requests geometry update to %i %i %i %i", PWINDOW, (int)LOGICALPOS.x, (int)LOGICALPOS.y, (int)PWINDOW->m_uSurface.xwayland->width, + (int)PWINDOW->m_uSurface.xwayland->height); g_pHyprRenderer->damageWindow(PWINDOW); - PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y)); + PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y)); if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height)); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index acda2abd..7bf254ea 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -714,3 +714,8 @@ std::vector getBacktrace() { return callstack; } + +void throwError(const std::string& err) { + Debug::log(CRIT, "Critical error thrown: %s", err.c_str()); + throw std::runtime_error(err); +} diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index c9e1f1b3..88598390 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -29,4 +29,5 @@ float getPlusMinusKeywordResult(std::string in, float void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); double normalizeAngleRad(double ang); std::string replaceInString(std::string subject, const std::string& search, const std::string& replace); -std::vector getBacktrace(); \ No newline at end of file +std::vector getBacktrace(); +void throwError(const std::string& err); \ No newline at end of file diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a860585d..3839115a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -489,6 +489,8 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // remove from mvmonitors std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; }); + g_pCompositor->arrangeMonitors(); + g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get()); g_pCompositor->sanityCheckWorkspaces(); @@ -622,3 +624,10 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { void CMonitor::setSpecialWorkspace(const int& id) { setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id)); } + +void CMonitor::moveTo(const Vector2D& pos) { + vecPosition = pos; + + if (!isMirror()) + wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y); +} diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index e4bf6251..d24ca162 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -30,10 +30,11 @@ class CMonitor { CMonitor(); ~CMonitor(); - Vector2D vecPosition = Vector2D(-1, -1); // means unset - Vector2D vecSize = Vector2D(0, 0); - Vector2D vecPixelSize = Vector2D(0, 0); - Vector2D vecTransformedSize = Vector2D(0, 0); + Vector2D vecPosition = Vector2D(-1, -1); // means unset + Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset + Vector2D vecSize = Vector2D(0, 0); + Vector2D vecPixelSize = Vector2D(0, 0); + Vector2D vecTransformedSize = Vector2D(0, 0); bool primary = false; @@ -109,6 +110,7 @@ class CMonitor { void changeWorkspace(const int& id, bool internal = false); void setSpecialWorkspace(CWorkspace* const pWorkspace); void setSpecialWorkspace(const int& id); + void moveTo(const Vector2D& pos); std::shared_ptr* m_pThisWrap = nullptr; bool m_bEnabled = false; diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index d23b3fbe..a5fcc72a 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -43,6 +43,14 @@ class Vector2D { return Vector2D(this->x / a.x, this->y / a.y); } + bool operator>(const Vector2D& a) const { + return this->x > a.x && this->y > a.y; + } + + bool operator<(const Vector2D& a) const { + return this->x < a.x && this->y < a.y; + } + double distance(const Vector2D& other) const; Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index e43a00ff..b84c9657 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -191,10 +191,14 @@ struct SXDGPopup { DYNLISTENER(mapPopupXDG); DYNLISTENER(unmapPopupXDG); DYNLISTENER(commitPopupXDG); + DYNLISTENER(repositionPopupXDG); double lx; double ly; + Vector2D lastPos = {}; + bool repositionRequested = false; + SSurfaceTreeNode* pSurfaceTree = nullptr; // For the list lookup @@ -242,8 +246,9 @@ struct STablet { std::string name = ""; - bool operator==(const STablet& b) const { - return wlrDevice == b.wlrDevice; + // + bool operator==(const STablet& b) const { + return wlrDevice == b.wlrDevice; } }; diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp index a71dd55d..eddd2143 100644 --- a/src/helpers/Workspace.cpp +++ b/src/helpers/Workspace.cpp @@ -58,7 +58,46 @@ CWorkspace::~CWorkspace() { void CWorkspace::startAnim(bool in, bool left, bool instant) { const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; - if (ANIMSTYLE == "fade") { + if (ANIMSTYLE.find("slidefade") == 0) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + float movePerc = 100.f; + + if (ANIMSTYLE.find("%") != std::string::npos) { + try { + auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1); + movePerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { + Debug::log(ERR, "Error in startAnim: invalid percentage"); + } + } + + m_fAlpha.setValueAndWarp(1.f); + m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); + + if (ANIMSTYLE.find("slidefadevert") == 0) { + if (in) { + m_fAlpha.setValueAndWarp(0.f); + m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); + m_fAlpha = 1.f; + m_vRenderOffset = Vector2D(0, 0); + } else { + m_fAlpha.setValueAndWarp(1.f); + m_fAlpha = 0.f; + m_vRenderOffset = Vector2D(0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); + } + } else { + if (in) { + m_fAlpha.setValueAndWarp(0.f); + m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0)); + m_fAlpha = 1.f; + m_vRenderOffset = Vector2D(0, 0); + } else { + m_fAlpha.setValueAndWarp(1.f); + m_fAlpha = 0.f; + m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0); + } + } + } else if (ANIMSTYLE == "fade") { m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. if (in) { diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index cbf1cb99..62a5522f 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -117,21 +117,16 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for const auto PWINDOW = pNode->pWindow; // get specific gaps and rules for this workspace, // if user specified them in config - const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); - static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue; - static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + PWINDOW->updateSpecialRenderData(); + + static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue; + static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue; + static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue; auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); - auto borderSize = - PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE); - - if (PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - borderSize = PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying(); - - borderSize *= PWINDOW->m_sSpecialRenderData.border && !PWINDOW->m_sAdditionalConfigData.forceNoBorder; if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) { Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW); @@ -142,36 +137,32 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->m_vSize = pNode->size; PWINDOW->m_vPosition = pNode->position; - static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue; - - const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID); + const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID); if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) && (NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { - PWINDOW->m_sSpecialRenderData.rounding = false; - PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2); + PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); + PWINDOW->m_sSpecialRenderData.rounding = false; + PWINDOW->m_sSpecialRenderData.shadow = false; const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - borderSize *= PWINDOW->m_sSpecialRenderData.border; + const int BORDERSIZE = PWINDOW->getRealBorderSize(); - PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize) + RESERVED.topLeft; - PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize) - (RESERVED.topLeft + RESERVED.bottomRight); + PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE) + RESERVED.topLeft; + PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE) - (RESERVED.topLeft + RESERVED.bottomRight); PWINDOW->updateWindowDecos(); return; } - PWINDOW->m_sSpecialRenderData.rounding = WORKSPACERULE.rounding.value_or(true); - PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); - PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(true); - PWINDOW->m_sSpecialRenderData.borderSize = WORKSPACERULE.borderSize.value_or(-1); + const int BORDERSIZE = PWINDOW->getRealBorderSize(); - auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize); - auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize); + auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE); + auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE); const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); @@ -491,9 +482,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) { return; } - pWindow->m_sSpecialRenderData.rounding = true; - pWindow->m_sSpecialRenderData.border = true; - pWindow->m_sSpecialRenderData.decorate = true; + pWindow->updateSpecialRenderData(); if (pWindow->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); @@ -818,9 +807,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; - pWindow->m_sSpecialRenderData.rounding = true; - pWindow->m_sSpecialRenderData.border = true; - pWindow->m_sSpecialRenderData.decorate = true; + pWindow->updateSpecialRenderData(); } } else { // if it now got fullscreen, make it fullscreen diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f39b190a..fd40e979 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -75,9 +75,17 @@ void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) { } void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { + wlr_box desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + + if (pWindow->m_bIsX11) { + Vector2D xy = {desiredGeometry.x, desiredGeometry.y}; + xy = g_pXWaylandManager->xwaylandToWaylandCoords(xy); + desiredGeometry.x = xy.x; + desiredGeometry.y = xy.y; + } static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; @@ -103,7 +111,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { if (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) { if (pWindow->m_uSurface.xwayland->x != 0 && pWindow->m_uSurface.xwayland->y != 0) - pWindow->m_vRealPosition = Vector2D{pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y}; + pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords({pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y}); else pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f); @@ -153,10 +161,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { } } - if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) { - pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale; - pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() / PMONITOR->scale; - } + if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) + pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale; if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) { pWindow->m_vRealPosition.warp(); @@ -296,7 +302,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) || (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - TIMER).count() < 1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate && - *PANIMATEMOUSE)) + (*PANIMATEMOUSE || *PANIMATE))) return; TIMER = std::chrono::high_resolution_clock::now(); @@ -460,9 +466,7 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); - pWindow->m_sSpecialRenderData.rounding = true; - pWindow->m_sSpecialRenderData.border = true; - pWindow->m_sSpecialRenderData.decorate = true; + pWindow->updateSpecialRenderData(); if (pWindow == m_pLastTiledWindow) m_pLastTiledWindow = nullptr; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index ebe7f4b7..f272f012 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -177,9 +177,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue; - pWindow->m_sSpecialRenderData.rounding = true; - pWindow->m_sSpecialRenderData.border = true; - pWindow->m_sSpecialRenderData.decorate = true; + pWindow->updateSpecialRenderData(); if (pWindow->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); @@ -268,9 +266,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { return; const auto PWORKSPACEDATA = getMasterWorkspaceData(ws); - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); - const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID); if (!PMASTERNODE) @@ -279,200 +275,192 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { eOrientation orientation = PWORKSPACEDATA->orientation; bool centerMasterWindow = false; static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; + + const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); + const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); + const auto STACKWINDOWS = WINDOWS - MASTERS; + const auto WSSIZE = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + if (orientation == ORIENTATION_CENTER) { - if (getNodesOnWorkspace(PWORKSPACE->m_iID) > 2 || (*ALWAYSCENTER == 1)) { + if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) { centerMasterWindow = true; } else { orientation = ORIENTATION_LEFT; } } - const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); - const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); - const auto STACKWINDOWS = WINDOWS - MASTERS; - //compute placement of master window(s) - if ((WINDOWS < 2) && !centerMasterWindow) { - PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition; - PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, - PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); + // compute placement of master window(s) + if (WINDOWS == 1 && !centerMasterWindow) { + PMASTERNODE->size = WSSIZE; + PMASTERNODE->position = WSPOS; + applyNodeDataToWindow(PMASTERNODE); return; - } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { - float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; - int nodesLeft = MASTERS; - float nextY = 0; - float WIDTH = 0; - - if (STACKWINDOWS == 0 && MASTERS > 0) - WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x); - else - WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster; - - for (auto& n : m_lMasterNodesData) { - if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { - if (orientation == ORIENTATION_RIGHT) { - n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + - Vector2D(PMONITOR->vecSize.x - WIDTH - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x, nextY); - } else { - n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY); - } - float HEIGHT = nodesLeft > 1 ? heightLeft / nodesLeft * n.percSize : heightLeft; - if (HEIGHT > heightLeft * 0.9f && nodesLeft > 1) - HEIGHT = heightLeft * 0.9f; - n.size = Vector2D(WIDTH, HEIGHT); - - nodesLeft--; - heightLeft -= HEIGHT; - nextY += HEIGHT; - - applyNodeDataToWindow(&n); - } - } } else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) { - float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x; - int nodesLeft = MASTERS; - float nextX = 0; - const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster; + const float HEIGHT = WSSIZE.y * PMASTERNODE->percMaster; + float widthLeft = WSSIZE.x; + int mastersLeft = MASTERS; + float nextX = 0; + float nextY = 0; - for (auto& n : m_lMasterNodesData) { - if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { - if (orientation == ORIENTATION_BOTTOM) { - n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + - Vector2D(nextX, PMONITOR->vecSize.y - HEIGHT - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); - } else { - n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0); - } - float WIDTH = nodesLeft > 1 ? widthLeft / nodesLeft * n.percSize : widthLeft; - if (WIDTH > widthLeft * 0.9f && nodesLeft > 1) - WIDTH = widthLeft * 0.9f; - n.size = Vector2D(WIDTH, HEIGHT); + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID || !nd.isMaster) + continue; - nodesLeft--; - widthLeft -= WIDTH; - nextX += WIDTH; + if (orientation == ORIENTATION_BOTTOM) + nextY = WSSIZE.y - HEIGHT; - applyNodeDataToWindow(&n); - } + float WIDTH = mastersLeft > 1 ? widthLeft / mastersLeft * nd.percSize : widthLeft; + if (WIDTH > widthLeft * 0.9f && mastersLeft > 1) + WIDTH = widthLeft * 0.9f; + + nd.size = Vector2D(WIDTH, HEIGHT); + nd.position = WSPOS + Vector2D(nextX, nextY); + applyNodeDataToWindow(&nd); + + mastersLeft--; + widthLeft -= WIDTH; + nextX += WIDTH; } - } else if (orientation == ORIENTATION_CENTER && STACKWINDOWS >= 2) { - float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; - int nodesLeft = MASTERS; - float nextY = 0; - const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster; + } else { // orientation left, right or center + float WIDTH = WSSIZE.x; + float heightLeft = WSSIZE.y; + int mastersLeft = MASTERS; + float nextX = 0; + float nextY = 0; - for (auto& n : m_lMasterNodesData) { - if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { - float CENTER_OFFSET = (PMONITOR->vecSize.x - WIDTH) / 2; - n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(CENTER_OFFSET, nextY); - float HEIGHT = nodesLeft > 1 ? heightLeft / nodesLeft * n.percSize : heightLeft; - if (HEIGHT > heightLeft * 0.9f && nodesLeft > 1) - HEIGHT = heightLeft * 0.9f; - n.size = Vector2D(WIDTH, HEIGHT); + if (STACKWINDOWS > 0 || centerMasterWindow) + WIDTH *= PMASTERNODE->percMaster; - nodesLeft--; - heightLeft -= HEIGHT; - nextY += HEIGHT; + if (orientation == ORIENTATION_RIGHT) { + nextX = WSSIZE.x - WIDTH; + } else if (centerMasterWindow) { + nextX = (WSSIZE.x - WIDTH) / 2; + } - applyNodeDataToWindow(&n); - } + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID || !nd.isMaster) + continue; + + float HEIGHT = mastersLeft > 1 ? heightLeft / mastersLeft * nd.percSize : heightLeft; + if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1) + HEIGHT = heightLeft * 0.9f; + + nd.size = Vector2D(WIDTH, HEIGHT); + nd.position = WSPOS + Vector2D(nextX, nextY); + applyNodeDataToWindow(&nd); + + mastersLeft--; + heightLeft -= HEIGHT; + nextY += HEIGHT; } } - //compute placement of slave window(s) - int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS; - if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { - float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; - float nextY = 0; - const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x; + if (STACKWINDOWS == 0) + return; - for (auto& nd : m_lMasterNodesData) { - if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) - continue; - - if (orientation == ORIENTATION_LEFT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + - Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY); - } else { - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY); - } - float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft; - if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) - HEIGHT = heightLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); - - slavesLeft--; - heightLeft -= HEIGHT; - nextY += HEIGHT; - - applyNodeDataToWindow(&nd); - } - } else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) { - float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x; + // compute placement of slave window(s) + int slavesLeft = STACKWINDOWS; + if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) { + const float HEIGHT = WSSIZE.y - PMASTERNODE->size.y; + float widthLeft = WSSIZE.x; float nextX = 0; - const float HEIGHT = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y - PMASTERNODE->size.y; + float nextY = 0; + + if (orientation == ORIENTATION_TOP) + nextY = PMASTERNODE->size.y; for (auto& nd : m_lMasterNodesData) { if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) continue; - if (orientation == ORIENTATION_TOP) { - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + - Vector2D(nextX, PMASTERNODE->percMaster * (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y)); - } else { - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0); - } + float WIDTH = slavesLeft > 1 ? widthLeft / slavesLeft * nd.percSize : widthLeft; if (WIDTH > widthLeft * 0.9f && slavesLeft > 1) WIDTH = widthLeft * 0.9f; + nd.size = Vector2D(WIDTH, HEIGHT); + nd.position = WSPOS + Vector2D(nextX, nextY); + applyNodeDataToWindow(&nd); slavesLeft--; widthLeft -= WIDTH; nextX += WIDTH; - - applyNodeDataToWindow(&nd); } - } else if (orientation == ORIENTATION_CENTER && STACKWINDOWS >= 2) { - float heightLeftL = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; - float heightLeftR = heightLeftL; - float heightLeft = 0; - float nextYL = 0; - float nextYR = 0; - const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x) / 2.0; - bool on_left = true; + } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) { + const float WIDTH = WSSIZE.x - PMASTERNODE->size.x; + float heightLeft = WSSIZE.y; + float nextY = 0; + float nextX = 0; - int slavesLeftL = 1 + (slavesLeft - 1) / 2; - int slavesLeftR = slavesLeft - slavesLeftL; + if (orientation == ORIENTATION_LEFT) + nextX = PMASTERNODE->size.x; for (auto& nd : m_lMasterNodesData) { if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) continue; - if (on_left) { - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextYL); - heightLeft = heightLeftL; - slavesLeft = slavesLeftL; - } else { - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(WIDTH + PMASTERNODE->size.x, nextYR); - heightLeft = heightLeftR; - slavesLeft = slavesLeftR; - } float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft; if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); - if (on_left) { - heightLeftL -= HEIGHT; - nextYL += HEIGHT; - slavesLeftL--; + nd.size = Vector2D(WIDTH, HEIGHT); + nd.position = WSPOS + Vector2D(nextX, nextY); + applyNodeDataToWindow(&nd); + + slavesLeft--; + heightLeft -= HEIGHT; + nextY += HEIGHT; + } + } else { // slaves for centered master window(s) + const float WIDTH = (WSSIZE.x - PMASTERNODE->size.x) / 2.0; + float heightLeft = 0; + float heightLeftL = WSSIZE.y; + float heightLeftR = WSSIZE.y; + float nextX = 0; + float nextY = 0; + float nextYL = 0; + float nextYR = 0; + bool onRight = true; + + int slavesLeftR = 1 + (slavesLeft - 1) / 2; + int slavesLeftL = slavesLeft - slavesLeftR; + + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) + continue; + + if (onRight) { + nextX = WIDTH + PMASTERNODE->size.x; + nextY = nextYR; + heightLeft = heightLeftR; + slavesLeft = slavesLeftR; } else { + nextX = 0; + nextY = nextYL; + heightLeft = heightLeftL; + slavesLeft = slavesLeftL; + } + + float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft; + if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) + HEIGHT = heightLeft * 0.9f; + + nd.size = Vector2D(WIDTH, HEIGHT); + nd.position = WSPOS + Vector2D(nextX, nextY); + applyNodeDataToWindow(&nd); + + if (onRight) { heightLeftR -= HEIGHT; nextYR += HEIGHT; slavesLeftR--; + } else { + heightLeftL -= HEIGHT; + nextYL += HEIGHT; + slavesLeftL--; } - applyNodeDataToWindow(&nd); - on_left = !on_left; + onRight = !onRight; } } } @@ -505,28 +493,22 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { const auto PWINDOW = pNode->pWindow; // get specific gaps and rules for this workspace, // if user specified them in config - const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); - static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue; - static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + PWINDOW->updateSpecialRenderData(); + + static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue; + static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue; + static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue; auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); - auto borderSize = - PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE); - if (PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - borderSize = PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying(); - - borderSize *= PWINDOW->m_sSpecialRenderData.border && !PWINDOW->m_sAdditionalConfigData.forceNoBorder; if (!g_pCompositor->windowValidMapped(PWINDOW)) { Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW); return; } - static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue; - PWINDOW->m_vSize = pNode->size; PWINDOW->m_vPosition = pNode->position; @@ -534,29 +516,27 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { - PWINDOW->m_sSpecialRenderData.rounding = false; - PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2); + PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); + PWINDOW->m_sSpecialRenderData.rounding = false; + PWINDOW->m_sSpecialRenderData.shadow = false; const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - borderSize *= PWINDOW->m_sSpecialRenderData.border; + const int BORDERSIZE = PWINDOW->getRealBorderSize(); - PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize) + RESERVED.topLeft; - PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize) - (RESERVED.topLeft + RESERVED.bottomRight); + PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE) + RESERVED.topLeft; + PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE) - (RESERVED.topLeft + RESERVED.bottomRight); PWINDOW->updateWindowDecos(); return; } - PWINDOW->m_sSpecialRenderData.rounding = WORKSPACERULE.rounding.value_or(true); - PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); - PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(true); - PWINDOW->m_sSpecialRenderData.borderSize = WORKSPACERULE.borderSize.value_or(-1); + const int BORDERSIZE = PWINDOW->getRealBorderSize(); - auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize); - auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize); + auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE); + auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE); const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); @@ -613,19 +593,20 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne return; } - // get monitor - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); + static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; - if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) < 2) + eOrientation orientation = PWORKSPACEDATA->orientation; + bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1); + double delta = 0; + + if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 && !centered) return; m_bForceWarps = true; - const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); - - double delta = 0; - - switch (PWORKSPACEDATA->orientation) { + switch (orientation) { case ORIENTATION_LEFT: delta = pixResize.x / PMONITOR->vecSize.x; break; case ORIENTATION_RIGHT: delta = -pixResize.x / PMONITOR->vecSize.x; break; case ORIENTATION_BOTTOM: delta = -pixResize.y / PMONITOR->vecSize.y; break; @@ -695,9 +676,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; - pWindow->m_sSpecialRenderData.rounding = true; - pWindow->m_sSpecialRenderData.border = true; - pWindow->m_sSpecialRenderData.decorate = true; + pWindow->updateSpecialRenderData(); } } else { // if it now got fullscreen, make it fullscreen diff --git a/src/main.cpp b/src/main.cpp index fbd3da47..35080439 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,7 +22,7 @@ void help() { int main(int argc, char** argv) { if (!getenv("XDG_RUNTIME_DIR")) - throw std::runtime_error("XDG_RUNTIME_DIR is not set!"); + throwError("XDG_RUNTIME_DIR is not set!"); // export HYPRLAND_CMD std::string cmd = ""; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index c37c89b8..f4e845c3 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -55,7 +55,6 @@ void CAnimationManager::tick() { if (!*PANIMENABLED) animGlobalDisabled = true; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static auto* const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); @@ -217,7 +216,7 @@ void CAnimationManager::tick() { // damage only the border. static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; const auto ROUNDINGSIZE = *PROUNDING + 1; - const auto BORDERSIZE = *PBORDERSIZE; + const auto BORDERSIZE = PWINDOW->getRealBorderSize(); // damage for old box g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top @@ -486,6 +485,22 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config, } else if (config == "workspaces" || config == "specialWorkspace") { if (style == "slide" || style == "slidevert" || style == "fade") return ""; + else if (style.find("slidefade") == 0) { + // try parsing + float movePerc = 0.f; + if (style.find("%") != std::string::npos) { + try { + auto percstr = style.substr(style.find_last_of(' ') + 1); + movePerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { return "invalid movePerc"; } + + return ""; + } + + movePerc; // fix warning + + return ""; + } return "unknown style"; } else if (config == "borderangle") { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 6956c697..2a44137e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -3,6 +3,7 @@ #include #include +#include #if defined(__linux__) #include #elif defined(__NetBSD__) || defined(__OpenBSD__) @@ -518,15 +519,19 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // vtnr is bugged for some reason. unsigned int ttynum = 0; + int fd; + if ((fd = open("/dev/tty", O_RDONLY | O_NOCTTY)) >= 0) { #if defined(VT_GETSTATE) - struct vt_stat st; - if (!ioctl(0, VT_GETSTATE, &st)) - ttynum = st.v_active; + struct vt_stat st; + if (!ioctl(fd, VT_GETSTATE, &st)) + ttynum = st.v_active; #elif defined(VT_GETACTIVE) - int vt; - if (!ioctl(0, VT_GETACTIVE, &vt)) - ttynum = vt; + int vt; + if (!ioctl(fd, VT_GETACTIVE, &vt)) + ttynum = vt; #endif + close(fd); + } if (ttynum == TTY) return true; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 556b40b7..76f979da 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -54,6 +54,7 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { if (pWindow->m_bIsX11) { + setWindowSize(pWindow, pWindow->m_vRealSize.vec()); // update xwayland output pos if (activate) { wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); @@ -142,14 +143,28 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) { void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) { - if (!force && - ((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))) + static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; + + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + if (!PMONITOR) return; - pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec(); - pWindow->m_vReportedSize = size; + // calculate pos + // TODO: this should be decoupled from setWindowSize IMO + Vector2D windowPos = pWindow->m_vRealPosition.vec(); - static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; + if (pWindow->m_bIsX11) { + windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor + if (*PXWLFORCESCALEZERO) + windowPos = windowPos * PMONITOR->scale; // scale if applicable + windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland + } + + if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))) + return; + + pWindow->m_vReportedPosition = windowPos; + pWindow->m_vReportedSize = size; pWindow->m_fX11SurfaceScaledBy = 1.f; @@ -160,10 +175,8 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f } } - const Vector2D POS = *PXWLFORCESCALEZERO && pWindow->m_bIsX11 ? pWindow->m_vRealPosition.vec() * pWindow->m_fX11SurfaceScaledBy : pWindow->m_vRealPosition.vec(); - if (pWindow->m_bIsX11) - wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, POS.x, POS.y, size.x, size.y); + wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y); else wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); } @@ -295,4 +308,31 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) { MAXSIZE.y = 99999; return MAXSIZE; -} \ No newline at end of file +} + +Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { + + static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; + + CMonitor* pMonitor = nullptr; + for (auto& m : g_pCompositor->m_vMonitors) { + const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; + if (VECINRECT(coord, m->vecXWaylandPosition.x, m->vecXWaylandPosition.y, m->vecXWaylandPosition.x + SIZ.x, m->vecXWaylandPosition.y + SIZ.y)) { + pMonitor = m.get(); + break; + } + } + + if (!pMonitor) + return Vector2D{}; + + // get local coords + Vector2D result = coord - pMonitor->vecXWaylandPosition; + // if scaled, unscale + if (*PXWLFORCESCALEZERO) + result = result / pMonitor->scale; + // add pos + result = result + pMonitor->vecPosition; + + return result; +} diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index 27bce17d..28ae67cc 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -26,6 +26,7 @@ class CHyprXWaylandManager { void moveXWaylandWindow(CWindow*, const Vector2D&); void checkBorders(CWindow*); Vector2D getMaxSizeForWindow(CWindow*); + Vector2D xwaylandToWaylandCoords(const Vector2D&); }; inline std::unique_ptr g_pXWaylandManager; \ No newline at end of file diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f4382838..bda2e5ee 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -85,6 +85,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) return; + if (time) + g_pCompositor->notifyIdleActivity(); + EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED); m_vLastCursorPosFloored = MOUSECOORDSFLOORED; @@ -319,9 +322,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bEmptyFocusCursorSet = false; - if (time) - g_pCompositor->notifyIdleActivity(); - Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos; if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) { @@ -1177,31 +1177,8 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co pMouse->hyprListener_commitConstraint.removeCallback(); if (pMouse->currentConstraint) { - if (!constraint) { - // warpe to hint - - if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { - if (PWINDOW) { - if (PWINDOW->m_bIsX11) { - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x, - constraint->current.cursor_hint.y + PWINDOW->m_uSurface.xwayland->y); - - wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y); - } else { - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x, - constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y); - - wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y); - } - } - - const auto PCONSTRAINT = constraintFromWlr(constraint); - if (PCONSTRAINT) { // should never be null but who knows - PCONSTRAINT->positionHint = Vector2D(constraint->current.cursor_hint.x, constraint->current.cursor_hint.y); - PCONSTRAINT->hintSet = true; - } - } - } + if (constraint && constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) + warpMouseToConstraintMiddle(constraintFromWlr(constraint)); wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint); } @@ -1224,6 +1201,27 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co Debug::log(LOG, "Constrained mouse to %lx", pMouse->currentConstraint); } +void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) { + + if (!pConstraint) + return; + + pConstraint->positionHint = Vector2D(pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); + pConstraint->hintSet = true; + + const auto PWINDOW = g_pCompositor->getWindowFromSurface(pConstraint->constraint->surface); + + if (PWINDOW) { + const auto RELATIVETO = PWINDOW->m_bIsX11 ? + g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y}) / PWINDOW->m_fX11SurfaceScaledBy : + PWINDOW->m_vRealPosition.goalv(); + const auto HINTSCALE = PWINDOW->m_fX11SurfaceScaledBy; + + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + pConstraint->positionHint.x / HINTSCALE, RELATIVETO.y + pConstraint->positionHint.y / HINTSCALE); + wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); + } +} + void CInputManager::unconstrainMouse() { if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) return; @@ -1531,14 +1529,16 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { } static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; - static const auto* PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static const auto* PEXTENDBORDERGRAB = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; + const int BORDERSIZE = w->getRealBorderSize(); + // give a small leeway (10 px) for corner icon - const auto CORNER = *PROUNDING + *PBORDERSIZE + 10; + const auto CORNER = *PROUNDING + BORDERSIZE + 10; const auto mouseCoords = getMouseCoordsInternal(); wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; - wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB, box.y - *PEXTENDBORDERGRAB, box.width + 2 * *PEXTENDBORDERGRAB, box.height + 2 * *PEXTENDBORDERGRAB}; + wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 1a3eac0c..a5f38947 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -79,6 +79,7 @@ class CInputManager { void destroySwitch(SSwitchDevice*); void constrainMouse(SMouse*, wlr_pointer_constraint_v1*); + void warpMouseToConstraintMiddle(SConstraint*); void recheckConstraint(SMouse*); void unconstrainMouse(); SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*); diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 906d5d9b..5fe91b65 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -50,7 +50,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue; static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue; static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert"; + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.find("slidefadevert") == 0; // commit std::string wsname = ""; @@ -194,7 +195,8 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue; static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert"; + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.find("slidefadevert") == 0; m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx); diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 43b758ae..8d9bbd84 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -110,14 +110,15 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; - + if (!pOutput->resource->good()) return; - zxdg_output_v1_send_logical_position(pOutput->resource->resource(), pOutput->monitor->vecPosition.x, pOutput->monitor->vecPosition.y); + const auto POS = pOutput->isXWayland ? pOutput->monitor->vecXWaylandPosition : pOutput->monitor->vecPosition; + zxdg_output_v1_send_logical_position(pOutput->resource->resource(), POS.x, POS.y); if (*PXWLFORCESCALEZERO && pOutput->isXWayland) - zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecPixelSize.x, pOutput->monitor->vecPixelSize.y); + zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecTransformedSize.x, pOutput->monitor->vecTransformedSize.y); else zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecSize.x, pOutput->monitor->vecSize.y); diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 13b7029c..2469e600 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -1,6 +1,7 @@ #pragma once #include "WaylandProtocol.hpp" +#include class CMonitor; @@ -8,6 +9,8 @@ struct SXDGOutput { CMonitor* monitor = nullptr; std::unique_ptr resource; + std::optional overridePosition; + wl_client* client = nullptr; bool isXWayland = false; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1f75fd4f..2a1df02d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -261,11 +261,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* TRACY_GPU_ZONE("RenderWindow"); - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); - static auto* const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue; - static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); + const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); + static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; + static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; if (ignorePosition) { @@ -282,11 +281,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding); renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl()); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl(); - renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && - (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); - renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; - renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later - renderdata.pWindow = pWindow; + renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); + renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; + renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later + renderdata.pWindow = pWindow; if (ignoreAllGeometry) { renderdata.alpha = 1.f; @@ -1593,7 +1591,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || - pMonitorRule->offset == Vector2D(-1, -1)) && + pMonitorRule->offset == Vector2D(-INT32_MAX, -INT32_MAX)) && pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit && !memcmp(&pMonitor->customDrmMode, &pMonitorRule->drmMode, sizeof(pMonitor->customDrmMode))) { @@ -1879,32 +1877,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } - if (pMonitorRule->offset == Vector2D(-1, -1) && pMonitor->vecPosition == Vector2D(-1, -1)) { - // let's find manually a sensible position for it, to the right. - Vector2D finalPos; - - for (auto& m : g_pCompositor->m_vMonitors) { - if (m->ID == pMonitor->ID) - continue; - - if (m->vecPosition.x + std::ceil(m->vecSize.x) > finalPos.x) { - finalPos.x = m->vecPosition.x + std::ceil(m->vecSize.x); - } - } - - pMonitor->vecPosition = finalPos; - } else if (pMonitorRule->offset != Vector2D(-1, -1)) { - pMonitor->vecPosition = pMonitorRule->offset; - } - wlr_output_enable(pMonitor->output, 1); // update renderer (here because it will call rollback, so we cannot do this before committing) g_pHyprOpenGL->destroyMonitorResources(pMonitor); // updato wlroots - if (!pMonitor->isMirror()) - wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y); + g_pCompositor->arrangeMonitors(); wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 62e07e14..15f993c9 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -59,6 +59,9 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (!m_pWindow->m_sSpecialRenderData.decorate) return; + if (!m_pWindow->m_sSpecialRenderData.shadow) + return; + if (m_pWindow->m_sAdditionalConfigData.forceNoShadow) return; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 07abdbe5..2414357e 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -39,18 +39,10 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) { if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) { // we draw 3px above the window's border with 3px - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; - const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)); + const int BORDERSIZE = pWindow->getRealBorderSize(); - auto borderSize = pWindow->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? pWindow->m_sSpecialRenderData.borderSize.toUnderlying() : - WORKSPACERULE.borderSize.value_or(*PBORDERSIZE); - if (pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - borderSize = pWindow->m_sAdditionalConfigData.borderSize.toUnderlying(); - - borderSize *= pWindow->m_sSpecialRenderData.border && !pWindow->m_sAdditionalConfigData.forceNoBorder; - - m_seExtents.topLeft = Vector2D(0, borderSize + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2); + m_seExtents.topLeft = Vector2D(0, BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2); m_seExtents.bottomRight = Vector2D(); m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET; @@ -99,17 +91,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("misc:render_titles_in_groupbar")->intValue; static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("misc:groupbar_titles_font_size")->intValue; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("misc:groupbar_gradients")->intValue; - const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID)); - - auto borderSize = m_pWindow->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? m_pWindow->m_sSpecialRenderData.borderSize.toUnderlying() : - WORKSPACERULE.borderSize.value_or(*PBORDERSIZE); - if (m_pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - borderSize = m_pWindow->m_sAdditionalConfigData.borderSize.toUnderlying(); - - borderSize *= m_pWindow->m_sSpecialRenderData.border && !m_pWindow->m_sAdditionalConfigData.forceNoBorder; + const int BORDERSIZE = m_pWindow->getRealBorderSize(); if (!m_pWindow->m_sSpecialRenderData.decorate) return; @@ -122,7 +106,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& for (int i = 0; i < barsToDraw; ++i) { wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, - m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - borderSize - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, BARW, BAR_INDICATOR_HEIGHT}; + m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, BARW, BAR_INDICATOR_HEIGHT}; if (rect.width <= 0 || rect.height <= 0) break; diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index d881dc5b..4e2d485d 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -109,11 +109,14 @@ void main() { discard; } - if (pixColor[3] == 0.0) + if (additionalAlpha == 0.0) discard; pixColor = getColorForCoord(v_texcoord); + pixColor.rgb *= pixColor[3]; - gl_FragColor = pixColor * alpha * additionalAlpha; + pixColor *= alpha * additionalAlpha; + + gl_FragColor = pixColor; } )#"; diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp index 49f548d7..2c7b07b2 100644 --- a/src/render/shaders/Shadow.hpp +++ b/src/render/shaders/Shadow.hpp @@ -79,9 +79,7 @@ void main() { } // premultiply - pixColor[0] *= pixColor[3]; - pixColor[1] *= pixColor[3]; - pixColor[2] *= pixColor[3]; + pixColor.rgb *= pixColor[3]; gl_FragColor = pixColor; })#";