Merge branch 'main' into wayland-protocol-improvements

This commit is contained in:
Vaxry 2023-08-21 19:35:53 +02:00 committed by GitHub
commit 3b935ccbf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 900 additions and 753 deletions

View File

@ -26,4 +26,6 @@ jobs:
name: Commit name: Commit
with: with:
commit_message: "[gha] build man pages" commit_message: "[gha] build man pages"
commit_author: Mihai Fufezan <fufexan@protonmail.com> commit_user_name: Mihai Fufezan
commit_user_email: fufexan@protonmail.com
commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

View File

@ -38,4 +38,6 @@ jobs:
- uses: stefanzweifel/git-auto-commit-action@v4 - uses: stefanzweifel/git-auto-commit-action@v4
with: with:
commit_message: "Nix: bump inputs" commit_message: "Nix: bump inputs"
commit_author: Mihai Fufezan <fufexan@protonmail.com> commit_user_name: Mihai Fufezan
commit_user_email: fufexan@protonmail.com
commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

View File

@ -33,4 +33,6 @@ jobs:
- uses: stefanzweifel/git-auto-commit-action@v4 - uses: stefanzweifel/git-auto-commit-action@v4
with: with:
commit_message: "Nix: bump wlroots" commit_message: "Nix: bump wlroots"
commit_author: Mihai Fufezan <fufexan@protonmail.com> commit_user_name: Mihai Fufezan
commit_user_email: fufexan@protonmail.com
commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

View File

@ -4,14 +4,17 @@
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
],
"systems": [
"systems"
] ]
}, },
"locked": { "locked": {
"lastModified": 1684265364, "lastModified": 1691753796,
"narHash": "sha256-AxNnWbthsuNx73HDQr0eBxrcE3+yfl/WsaXZqUFmkpQ=", "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-protocols", "repo": "hyprland-protocols",
"rev": "8c279b9fb0f2b031427dc5ef4eab53f2ed835530", "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -22,11 +25,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1690179384, "lastModified": 1691654369,
"narHash": "sha256-+arbgqFTAtoeKtepW9wCnA0njCOyoiDFyl0Q0SBSOtE=", "narHash": "sha256-gSILTEx1jRaJjwZxRlnu3ZwMn1FVNk80qlwiCX8kmpo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b12803b6d90e2e583429bb79b859ca53c348b39a", "rev": "ce5e4a6ef2e59d89a971bc434ca8ca222b9c7f5e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -40,10 +43,26 @@
"inputs": { "inputs": {
"hyprland-protocols": "hyprland-protocols", "hyprland-protocols": "hyprland-protocols",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"systems": "systems",
"wlroots": "wlroots", "wlroots": "wlroots",
"xdph": "xdph" "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": { "wlroots": {
"flake": false, "flake": false,
"locked": { "locked": {
@ -70,14 +89,17 @@
], ],
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
],
"systems": [
"systems"
] ]
}, },
"locked": { "locked": {
"lastModified": 1691082525, "lastModified": 1691841170,
"narHash": "sha256-C5AO0KnyAFJaCkOn+5nJfWm0kyiPn/Awh0lKTjhgr7Y=", "narHash": "sha256-RCTm1/MVWYPnReMgyp7tr2ogGYo/pvw38jZaFwemgPU=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland", "repo": "xdg-desktop-portal-hyprland",
"rev": "42747d267ab4345c4ceb78cd4a4fe99f072d80fc", "rev": "57a3a41ba6b358109e4fc25c6a4706b5f7d93c6b",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -4,6 +4,9 @@
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# <https://github.com/nix-systems/nix-systems>
systems.url = "github:nix-systems/default-linux";
wlroots = { wlroots = {
type = "gitlab"; type = "gitlab";
host = "gitlab.freedesktop.org"; host = "gitlab.freedesktop.org";
@ -16,11 +19,13 @@
hyprland-protocols = { hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols"; url = "github:hyprwm/hyprland-protocols";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
}; };
xdph = { xdph = {
url = "github:hyprwm/xdg-desktop-portal-hyprland"; url = "github:hyprwm/xdg-desktop-portal-hyprland";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
inputs.hyprland-protocols.follows = "hyprland-protocols"; inputs.hyprland-protocols.follows = "hyprland-protocols";
}; };
}; };
@ -28,39 +33,23 @@
outputs = inputs @ { outputs = inputs @ {
self, self,
nixpkgs, nixpkgs,
systems,
... ...
}: let }: let
lib = nixpkgs.lib.extend (import ./nix/lib.nix); inherit (nixpkgs) lib;
genSystems = lib.genAttrs [ eachSystem = lib.genAttrs (import systems);
# Add more systems if they are supported pkgsFor = eachSystem (system:
"aarch64-linux"
"x86_64-linux"
];
pkgsFor = genSystems (system:
import nixpkgs { import nixpkgs {
inherit system; localSystem = system;
overlays = [ overlays = with self.overlays; [
self.overlays.hyprland-packages hyprland-packages
self.overlays.wlroots-hyprland hyprland-extras
inputs.hyprland-protocols.overlays.default
]; ];
}); });
in { in {
overlays = overlays = import ./nix/overlays.nix {inherit self lib inputs;};
(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
]);
};
checks = genSystems (system: checks = eachSystem (system:
(lib.filterAttrs (lib.filterAttrs
(n: _: (lib.hasPrefix "hyprland" n) && !(lib.hasSuffix "debug" n)) (n: _: (lib.hasPrefix "hyprland" n) && !(lib.hasSuffix "debug" n))
self.packages.${system}) self.packages.${system})
@ -68,16 +57,29 @@
inherit (self.packages.${system}) xdg-desktop-portal-hyprland; inherit (self.packages.${system}) xdg-desktop-portal-hyprland;
}); });
packages = genSystems (system: packages = eachSystem (system: {
(self.overlays.default pkgsFor.${system} pkgsFor.${system}) default = self.packages.${system}.hyprland;
// { inherit
default = self.packages.${system}.hyprland; (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 { default = pkgsFor.${system}.mkShell {
name = "hyprland-shell"; name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [ cmake python3 ]; nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
buildInputs = [self.packages.${system}.wlroots-hyprland]; buildInputs = [self.packages.${system}.wlroots-hyprland];
inputsFrom = [ inputsFrom = [
self.packages.${system}.wlroots-hyprland 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; nixosModules.default = import ./nix/module.nix inputs;
homeManagerModules.default = import ./nix/hm-module.nix self; homeManagerModules.default = import ./nix/hm-module.nix self;

View File

@ -193,20 +193,15 @@ void requestHyprpaper(std::string arg) {
return; return;
} }
// get the instance signature if (instanceSignature.empty()) {
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!instanceSig) {
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)"; std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
return; return;
} }
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0}; sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX; 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); strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
@ -215,6 +210,9 @@ void requestHyprpaper(std::string arg) {
return; 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()); auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
if (sizeWritten < 0) { if (sizeWritten < 0) {
@ -430,7 +428,7 @@ int main(int argc, char** argv) {
else if (fullRequest.contains("/keyword")) else if (fullRequest.contains("/keyword"))
request(fullRequest, 2); request(fullRequest, 2);
else if (fullRequest.contains("/hyprpaper")) else if (fullRequest.contains("/hyprpaper"))
request(fullRequest, 2); requestHyprpaper(fullRequest);
else if (fullRequest.contains("/--help")) else if (fullRequest.contains("/--help"))
printf("%s", USAGE.c_str()); printf("%s", USAGE.c_str());
else { else {

View File

@ -26,114 +26,111 @@
xcbutilwm, xcbutilwm,
xwayland, xwayland,
debug ? false, debug ? false,
enableNvidiaPatches ? false,
enableXWayland ? true, enableXWayland ? true,
hidpiXWayland ? false,
legacyRenderer ? false, legacyRenderer ? false,
nvidiaPatches ? false,
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
wrapRuntimeDeps ? true, wrapRuntimeDeps ? true,
version ? "git", version ? "git",
commit, commit,
}: let # deprecated flags
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) '' nvidiaPatches ? false,
Hyprland: cannot have hidpiXWayland when enableXWayland is false. hidpiXWayland ? false,
''; }:
in assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been renamed `enableNvidiaPatches`";
assert assertXWayland; assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
stdenv.mkDerivation { stdenv.mkDerivation {
pname = "hyprland" + lib.optionalString debug "-debug"; pname = "hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}${lib.optionalString debug "-debug"}";
inherit version; inherit version;
src = lib.cleanSourceWith { src = lib.cleanSourceWith {
filter = name: type: let filter = name: type: let
baseName = baseNameOf (toString name); baseName = baseNameOf (toString name);
in in
! ( ! (lib.hasSuffix ".nix" baseName);
lib.hasSuffix ".nix" baseName src = lib.cleanSource ../.;
); };
src = lib.cleanSource ../.;
};
nativeBuildInputs = [ nativeBuildInputs = [
jq jq
meson meson
ninja ninja
pkg-config pkg-config
makeWrapper makeWrapper
wayland-scanner wayland-scanner
]; ];
outputs = [ outputs = [
"out" "out"
"man" "man"
"dev" "dev"
]; ];
buildInputs = buildInputs =
[ [
git git
cairo cairo
hyprland-protocols hyprland-protocols
libdrm libdrm
libinput libinput
libxkbcommon libxkbcommon
mesa mesa
pango pango
udis86 udis86
wayland wayland
wayland-protocols wayland-protocols
pciutils pciutils
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;}) (wlroots.override {inherit enableNvidiaPatches;})
] ]
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland] ++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
++ lib.optionals withSystemd [systemd]; ++ lib.optionals withSystemd [systemd];
mesonBuildType = mesonBuildType =
if debug if debug
then "debug" then "debug"
else "release"; else "release";
mesonFlags = builtins.concatLists [ mesonFlags = builtins.concatLists [
["-Dauto_features=disabled"] ["-Dauto_features=disabled"]
(lib.optional enableXWayland "-Dxwayland=enabled") (lib.optional enableXWayland "-Dxwayland=enabled")
(lib.optional legacyRenderer "-Dlegacy_renderer=enabled") (lib.optional legacyRenderer "-Dlegacy_renderer=enabled")
(lib.optional withSystemd "-Dsystemd=enabled") (lib.optional withSystemd "-Dsystemd=enabled")
]; ];
patches = [ patches = [
# make meson use the provided wlroots instead of the git submodule # make meson use the provided wlroots instead of the git submodule
./patches/meson-build.patch ./patches/meson-build.patch
# fixes portals search path to be picked up from $XDG_DESKTOP_PORTAL_DIR # fixes portals search path to be picked up from $XDG_DESKTOP_PORTAL_DIR
./patches/portals.patch ./patches/portals.patch
]; ];
postPatch = '' postPatch = ''
# Fix hardcoded paths to /usr installation # Fix hardcoded paths to /usr installation
sed -i "s#/usr#$out#" src/render/OpenGL.cpp sed -i "s#/usr#$out#" src/render/OpenGL.cpp
substituteInPlace meson.build \ substituteInPlace meson.build \
--replace "@GIT_COMMIT_HASH@" '${commit}' \ --replace "@GIT_COMMIT_HASH@" '${commit}' \
--replace "@GIT_DIRTY@" '${ --replace "@GIT_DIRTY@" '${
if commit == "" if commit == ""
then "dirty" then "dirty"
else "" else ""
}' }'
''; '';
postInstall = '' postInstall = ''
ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots
${lib.optionalString wrapRuntimeDeps '' ${lib.optionalString wrapRuntimeDeps ''
wrapProgram $out/bin/Hyprland \ wrapProgram $out/bin/Hyprland \
--suffix PATH : ${lib.makeBinPath [ binutils pciutils ]} --suffix PATH : ${lib.makeBinPath [binutils pciutils]}
''} ''}
''; '';
passthru.providedSessions = ["hyprland"]; passthru.providedSessions = ["hyprland"];
meta = with lib; { meta = with lib; {
homepage = "https://github.com/vaxerski/Hyprland"; homepage = "https://github.com/vaxerski/Hyprland";
description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
license = licenses.bsd3; license = licenses.bsd3;
platforms = platforms.linux; platforms = platforms.linux;
mainProgram = "Hyprland"; mainProgram = "Hyprland";
}; };
} }

View File

@ -7,8 +7,7 @@ self: {
cfg = config.wayland.windowManager.hyprland; cfg = config.wayland.windowManager.hyprland;
defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override { defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
enableXWayland = cfg.xwayland.enable; enableXWayland = cfg.xwayland.enable;
hidpiXWayland = cfg.xwayland.hidpi; inherit (cfg) enableNvidiaPatches;
inherit (cfg) nvidiaPatches;
}; };
in { in {
disabledModules = ["services/window-managers/hyprland.nix"]; disabledModules = ["services/window-managers/hyprland.nix"];
@ -36,13 +35,12 @@ in {
defaultText = lib.literalExpression '' defaultText = lib.literalExpression ''
hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override { hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override {
enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable; enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable;
hidpiXWayland = config.wayland.windowManager.hyprland.xwayland.hidpi; inherit (config.wayland.windowManager.hyprland) enableNvidiaPatches;
inherit (config.wayland.windowManager.hyprland) nvidiaPatches;
} }
''; '';
description = lib.mdDoc '' description = lib.mdDoc ''
Hyprland package to use. Will override the 'xwayland' and Hyprland package to use. Will override the 'xwayland' and
'nvidiaPatches' options. 'enableNvidiaPatches' options.
Defaults to the one provided by the flake. Set it to Defaults to the one provided by the flake. Set it to
{package}`pkgs.hyprland` to use the one provided by nixpkgs or {package}`pkgs.hyprland` to use the one provided by nixpkgs or
@ -86,19 +84,9 @@ in {
''; '';
}; };
xwayland = { xwayland.enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;};
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 <https://wiki.hyprland.org/Nix/Options-Overrides/#xwayland-hidpi> for more info.
'';
};
};
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 { extraConfig = lib.mkOption {
type = lib.types.nullOr lib.types.lines; type = lib.types.nullOr lib.types.lines;
@ -119,10 +107,14 @@ in {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
warnings = warnings =
if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null then if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null
[ ''You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins. then [
Your Hyprland config will be linked by home manager. ''
Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning.'' ] 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 []; else [];
home.packages = 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 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 + lib.concatStrings (builtins.map (entry: let
plugin = if lib.types.package.check entry then "${entry}/lib/lib${entry.pname}.so" else entry; plugin =
in "plugin = ${plugin}\n") cfg.plugins) if lib.types.package.check entry
+ (if cfg.extraConfig != null then cfg.extraConfig else ""); 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 onChange = let
hyprlandPackage = 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")
];
} }

View File

@ -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;
}

View File

@ -6,11 +6,12 @@ inputs: {
}: }:
with lib; let with lib; let
cfg = config.programs.hyprland; cfg = config.programs.hyprland;
inherit (pkgs.stdenv.hostPlatform) system;
defaultHyprlandPackage = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.default.override { finalPortalPackage = cfg.portalPackage.override {
enableXWayland = cfg.xwayland.enable; hyprland-share-picker = inputs.xdph.packages.${system}.hyprland-share-picker.override {
hidpiXWayland = cfg.xwayland.hidpi; hyprland = cfg.finalPackage;
inherit (cfg) nvidiaPatches; };
}; };
in { in {
# disables Nixpkgs Hyprland module to avoid conflicts # disables Nixpkgs Hyprland module to avoid conflicts
@ -30,47 +31,36 @@ in {
''; '';
}; };
package = mkOption { package = mkPackageOptionMD inputs.self.packages.${system} "hyprland" { };
type = types.path;
default = defaultHyprlandPackage; finalPackage = mkOption {
defaultText = literalExpression '' type = types.package;
hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override { readOnly = true;
enableXWayland = config.programs.hyprland.xwayland.enable; default = cfg.package.override {
hidpiXWayland = config.programs.hyprland.xwayland.hidpi; enableXWayland = cfg.xwayland.enable;
inherit (config.programs.hyprland) nvidiaPatches; enableNvidiaPatches = cfg.enableNvidiaPatches;
} };
''; defaultText =
example = literalExpression "pkgs.hyprland"; literalExpression
"`programs.hyprland.package` with applied configuration";
description = mdDoc '' description = mdDoc ''
The Hyprland package to use. The Hyprland package after applying configuration.
Setting this option will make {option}`programs.hyprland.xwayland` and
{option}`programs.hyprland.nvidiaPatches` not work.
''; '';
}; };
xwayland = { portalPackage = mkPackageOptionMD inputs.xdph.packages.${system} "xdg-desktop-portal-hyprland" {};
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 <https://wiki.hyprland.org/Nix/Options-Overrides/#xwayland-hidpi> for more info.
'';
};
};
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 { config = mkIf cfg.enable {
environment = { environment.systemPackages = [cfg.finalPackage];
systemPackages = [cfg.package];
sessionVariables = {
NIXOS_OZONE_WL = mkDefault "1";
};
};
fonts = fonts =
if versionOlder config.system.stateVersion "23.11" if versionOlder config.system.stateVersion "23.11"
@ -81,22 +71,29 @@ in {
programs = { programs = {
dconf.enable = mkDefault true; dconf.enable = mkDefault true;
xwayland.enable = mkDefault true; xwayland.enable = mkDefault cfg.xwayland.enable;
}; };
security.polkit.enable = true; security.polkit.enable = true;
services.xserver.displayManager.sessionPackages = [cfg.package]; services.xserver.displayManager.sessionPackages = [cfg.finalPackage];
xdg.portal = { xdg.portal = {
enable = mkDefault true; enable = mkDefault true;
extraPortals = lib.mkIf (cfg.package != null) [ extraPortals = [finalPortalPackage];
(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;
};
})
];
}; };
}; };
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"]
)
];
} }

View File

@ -10,71 +10,62 @@
(builtins.substring 4 2 longDate) (builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate) (builtins.substring 6 2 longDate)
]); ]);
mkJoinedOverlays = overlays: final: prev:
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
in { in {
# Packages for variations of Hyprland, and its dependencies. # Contains what a user is most likely to care about:
hyprland-packages = final: prev: { # Hyprland itself, XDPH and the Share Picker.
hyprland = final.callPackage ./default.nix { default = mkJoinedOverlays (with self.overlays; [
version = hyprland-packages
props.version hyprland-extras
+ "+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;}; # Packages for variations of Hyprland, dependencies included.
hyprland-debug = final.hyprland.override {debug = true;}; hyprland-packages = mkJoinedOverlays [
hyprland-hidpi = final.hyprland.override {hidpiXWayland = true;}; # Dependencies
hyprland-nvidia = final.hyprland.override {nvidiaPatches = true;}; inputs.hyprland-protocols.overlays.default
hyprland-no-hidpi = self.overlays.wlroots-hyprland
builtins.trace self.overlays.udis86
"hyprland-no-hidpi was removed. Please use the default package." # Hyprland packages themselves
final.hyprland; (final: prev: {
hyprland = final.callPackage ./default.nix {
udis86 = final.callPackage ./udis86.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, # Packages for extra software recommended for usage with Hyprland,
# including forked or patched packages for compatibility. # including forked or patched packages for compatibility.
hyprland-extras = lib.mkJoinedOverlays [ hyprland-extras = mkJoinedOverlays [
# Include any inputs' specific overlays whose attributes should inputs.xdph.overlays.xdg-desktop-portal-hyprland
# be re-exported by the Hyprland flake. inputs.xdph.overlays.hyprland-share-picker
#
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"];
});
})
]; ];
udis86 = final: prev: {
udis86 = final.callPackage ./udis86.nix {};
};
# Patched version of wlroots for Hyprland. # Patched version of wlroots for Hyprland.
# It is under a new package name so as to not conflict with # It is under a new package name so as to not conflict with
# the standard version in nixpkgs. # the standard version in nixpkgs.
wlroots-hyprland = final: prev: { wlroots-hyprland = final: prev: {
wlroots-hyprland = final.callPackage ./wlroots.nix { wlroots-hyprland = final.callPackage ./wlroots.nix {
version = version = "${mkDate (inputs.wlroots.lastModifiedDate or "19700101")}_${inputs.wlroots.shortRev or "dirty"}";
mkDate (inputs.wlroots.lastModifiedDate or "19700101")
+ "_"
+ (inputs.wlroots.shortRev or "dirty");
src = inputs.wlroots; src = inputs.wlroots;
libdisplay-info = prev.libdisplay-info.overrideAttrs (old: { libdisplay-info = prev.libdisplay-info.overrideAttrs (old: {
version = "0.1.1+date=2023-03-02"; version = "0.1.1+date=2023-03-02";
src = final.fetchFromGitLab { src = final.fetchFromGitLab {
@ -85,6 +76,7 @@ in {
sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4="; sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4=";
}; };
}); });
libliftoff = prev.libliftoff.overrideAttrs (old: { libliftoff = prev.libliftoff.overrideAttrs (old: {
version = "0.5.0-dev"; version = "0.5.0-dev";
src = final.fetchFromGitLab { src = final.fetchFromGitLab {

View File

@ -1,8 +1,8 @@
diff --git a/src/Compositor.cpp b/src/Compositor.cpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index a9d95f39..069a03ca 100644 index 1d978aed..56665389 100644
--- a/src/Compositor.cpp --- a/src/Compositor.cpp
+++ b/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; 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.", 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); 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("/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),
g_pHyprNotificationOverlay->addNotification("You have xdg-desktop-portal-hyprland and -wlr installed simultaneously. Please uninstall one to avoid issues.", CColor(0), - 15000, ICON_ERROR);
15000, ICON_ERROR); - }
} }
}

View File

@ -1,64 +1,28 @@
{ {
lib,
version, version,
src, src,
#
wlroots, wlroots,
xwayland,
fetchpatch,
lib,
hwdata, hwdata,
libliftoff,
libdisplay-info, libdisplay-info,
hidpiXWayland ? true, libliftoff,
enableXWayland ? true, enableXWayland ? true,
nvidiaPatches ? false, enableNvidiaPatches ? false,
}: }:
assert (lib.assertMsg (hidpiXWayland -> enableXWayland) '' wlroots.overrideAttrs (old: {
wlroots-hyprland: cannot have hidpiXWayland when enableXWayland is false. inherit version src enableXWayland;
'');
(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];
NIX_CFLAGS_COMPILE = toString [ pname = "${old.pname}-hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}";
"-Wno-error=maybe-uninitialized"
]; patches =
})) (old.patches or [])
.override { ++ (lib.optionals enableNvidiaPatches [
xwayland = xwayland.overrideAttrs (old: { ./patches/wlroots-nvidia.patch
patches = ]);
(old.patches or [])
++ (lib.optionals hidpiXWayland [ buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info];
./patches/xwayland-vsync.patch
./patches/xwayland-hidpi.patch NIX_CFLAGS_COMPILE = toString [
]); "-Wno-error=maybe-uninitialized"
}); ];
} })

View File

@ -12,11 +12,10 @@
int handleCritSignal(int signo, void* data) { int handleCritSignal(int signo, void* data) {
Debug::log(LOG, "Hyprland received signal %d", signo); 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(); g_pCompositor->cleanup();
}
return 0; // everything went fine return 0;
} }
void handleUnrecoverableSignal(int sig) { void handleUnrecoverableSignal(int sig) {
@ -112,20 +111,20 @@ void CCompositor::initServer() {
if (!m_sWLRBackend) { if (!m_sWLRBackend) {
Debug::log(CRIT, "m_sWLRBackend was NULL!"); 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); m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend);
if (m_iDRMFD < 0) { if (m_iDRMFD < 0) {
Debug::log(CRIT, "Couldn't query the DRM FD!"); 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); m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
if (!m_sWLRRenderer) { if (!m_sWLRRenderer) {
Debug::log(CRIT, "m_sWLRRenderer was NULL!"); 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); wlr_renderer_init_wl_shm(m_sWLRRenderer, m_sWLDisplay);
@ -141,14 +140,14 @@ void CCompositor::initServer() {
if (!m_sWLRAllocator) { if (!m_sWLRAllocator) {
Debug::log(CRIT, "m_sWLRAllocator was NULL!"); 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); m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer);
if (!m_sWLREGL) { if (!m_sWLREGL) {
Debug::log(CRIT, "m_sWLREGL was NULL!"); 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); m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, 6, m_sWLRRenderer);
@ -247,7 +246,7 @@ void CCompositor::initServer() {
if (!m_sWLRHeadlessBackend) { if (!m_sWLRHeadlessBackend) {
Debug::log(CRIT, "Couldn't create the headless backend"); 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); wlr_single_pixel_buffer_manager_v1_create(m_sWLDisplay);
@ -464,7 +463,7 @@ void CCompositor::startCompositor() {
if (m_szWLDisplaySocket.empty()) { if (m_szWLDisplaySocket.empty()) {
Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
wlr_backend_destroy(m_sWLRBackend); 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); setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1);
@ -486,7 +485,7 @@ void CCompositor::startCompositor() {
Debug::log(CRIT, "Backend did not start!"); Debug::log(CRIT, "Backend did not start!");
wlr_backend_destroy(m_sWLRBackend); wlr_backend_destroy(m_sWLRBackend);
wl_display_destroy(m_sWLDisplay); 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"); 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_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, enabled);
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !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<CMonitor*> toArrange;
std::vector<CMonitor*> 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);
}
}

View File

@ -202,6 +202,7 @@ class CCompositor {
CWindow* getForceFocus(); CWindow* getForceFocus();
void notifyIdleActivity(); void notifyIdleActivity();
void setIdleActivityInhibit(bool inhibit); void setIdleActivityInhibit(bool inhibit);
void arrangeMonitors();
std::string explicitConfigPath; std::string explicitConfigPath;

View File

@ -26,17 +26,7 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
if (m_bFadingOut) if (m_bFadingOut)
return m_eOriginalClosedExtents; return m_eOriginalClosedExtents;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; const int BORDERSIZE = getRealBorderSize();
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;
if (m_sAdditionalConfigData.dimAround) { if (m_sAdditionalConfigData.dimAround) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); 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)}}; {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) { for (auto& wd : m_dWindowDecorations) {
@ -144,14 +134,14 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
} }
wlr_box CWindow::getWindowInputBox() { wlr_box CWindow::getWindowInputBox() {
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; const int BORDERSIZE = getRealBorderSize();
if (m_sAdditionalConfigData.dimAround) { if (m_sAdditionalConfigData.dimAround) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; 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) { for (auto& wd : m_dWindowDecorations) {
@ -347,6 +337,8 @@ void CWindow::moveToWorkspace(int workspaceID) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
updateSpecialRenderData();
if (PWORKSPACE) { if (PWORKSPACE) {
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%lx,%s", this, PWORKSPACE->m_szName.c_str())}); g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%lx,%s", this, PWORKSPACE->m_szName.c_str())});
EMIT_HOOK_EVENT("moveWindow", (std::vector<void*>{this, PWORKSPACE})); EMIT_HOOK_EVENT("moveWindow", (std::vector<void*>{this, PWORKSPACE}));
@ -356,6 +348,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
m_pSwallowed->moveToWorkspace(workspaceID); m_pSwallowed->moveToWorkspace(workspaceID);
m_pSwallowed->m_iMonitorID = m_iMonitorID; m_pSwallowed->m_iMonitorID = m_iMonitorID;
} }
// update xwayland coords
g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec());
} }
CWindow* CWindow::X11TransientFor() { 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) // it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
// otherwise behaviour is undefined // otherwise behaviour is undefined
bool CWindow::isInCurvedCorner(double x, double y) { bool CWindow::isInCurvedCorner(double x, double y) {
static auto* const ROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; const int ROUNDING = rounding();
static auto* const BORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; if (getRealBorderSize() >= ROUNDING)
if (BORDERSIZE >= ROUNDING || ROUNDING == 0)
return false; return false;
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner // (x0, y0), (x0, y1), ... are the center point of rounding at each corner
double x0 = m_vRealPosition.vec().x + *ROUNDING; double x0 = m_vRealPosition.vec().x + ROUNDING;
double y0 = m_vRealPosition.vec().y + *ROUNDING; double y0 = m_vRealPosition.vec().y + ROUNDING;
double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - *ROUNDING; double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - ROUNDING;
double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - *ROUNDING; double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - ROUNDING;
if (x < x0 && y < y0) { 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) { 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) { 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) { 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; return false;
@ -687,7 +680,7 @@ void CWindow::setGroupCurrent(CWindow* pWindow) {
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode); g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
PCURRENT->setHidden(true); PCURRENT->setHidden(true);
pWindow->setHidden(false); // can remove m_pLastWindow pWindow->setHidden(false); // can remove m_pLastWindow
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow); g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
@ -810,3 +803,31 @@ float CWindow::rounding() {
return 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;
}

View File

@ -104,6 +104,7 @@ struct SWindowSpecialRenderData {
bool rounding = true; bool rounding = true;
bool border = true; bool border = true;
bool decorate = true; bool decorate = true;
bool shadow = true;
}; };
struct SWindowAdditionalConfigData { struct SWindowAdditionalConfigData {
@ -333,6 +334,9 @@ class CWindow {
bool opaque(); bool opaque();
float rounding(); float rounding();
int getRealBorderSize();
void updateSpecialRenderData();
void onBorderAngleAnimEnd(void* ptr); void onBorderAngleAnimEnd(void* ptr);
bool isInCurvedCorner(double x, double y); bool isInCurvedCorner(double x, double y);
bool hasPopupAt(const Vector2D& pos); bool hasPopupAt(const Vector2D& pos);

View File

@ -125,6 +125,7 @@ void CConfigManager::setDefaultVars() {
configValues["debug:enable_stdout_logs"].intValue = 0; configValues["debug:enable_stdout_logs"].intValue = 0;
configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL;
configValues["debug:manual_crash"].intValue = 0; configValues["debug:manual_crash"].intValue = 0;
configValues["debug:suppress_errors"].intValue = 0;
configValues["decoration:rounding"].intValue = 0; configValues["decoration:rounding"].intValue = 0;
configValues["decoration:blur:enabled"].intValue = 1; 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) { if (ARGS[2].find("auto") == 0) {
newrule.offset = Vector2D(-1, -1); newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX);
} else { } else {
newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x'))); 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)); 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) { 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)); wsRule.borderSize = std::stoi(rule.substr(delim + 11));
else if ((delim = rule.find("border:")) != std::string::npos) else if ((delim = rule.find("border:")) != std::string::npos)
wsRule.border = configStringToInt(rule.substr(delim + 7)); 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) else if ((delim = rule.find("rounding:")) != std::string::npos)
wsRule.rounding = configStringToInt(rule.substr(delim + 9)); wsRule.rounding = configStringToInt(rule.substr(delim + 9));
else if ((delim = rule.find("decorate:")) != std::string::npos) else if ((delim = rule.find("decorate:")) != std::string::npos)
@ -1569,7 +1567,7 @@ void CConfigManager::loadConfigLoadVars() {
g_pHyprOpenGL->m_bReloadScreenShader = true; g_pHyprOpenGL->m_bReloadScreenShader = true;
// parseError will be displayed next frame // 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)); 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) 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", 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(); ensureVRR();
} }
// Updates dynamic window rules // Updates dynamic window and workspace rules
for (auto& w : g_pCompositor->m_vWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped) if (!w->m_bIsMapped)
continue; continue;
w->updateDynamicRules(); w->updateDynamicRules();
w->updateSpecialRenderData();
} }
// Update window border colors // 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."); 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) { SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) {

View File

@ -48,6 +48,7 @@ struct SWorkspaceRule {
std::optional<int> border; std::optional<int> border;
std::optional<int> rounding; std::optional<int> rounding;
std::optional<int> decorate; std::optional<int> decorate;
std::optional<int> shadow;
}; };
struct SMonitorAdditionalReservedArea { struct SMonitorAdditionalReservedArea {

View File

@ -122,19 +122,8 @@ void Events::listener_destroyConstraint(void* owner, void* data) {
const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse); const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
if (PWINDOW && PCONSTRAINT->positionHint != Vector2D{-1, -1}) { if (PWINDOW && PCONSTRAINT->positionHint != Vector2D{-1, -1})
if (PWINDOW->m_bIsX11) { g_pInputManager->warpMouseToConstraintMiddle(PCONSTRAINT);
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);
}
}
PCONSTRAINT->pMouse->currentConstraint = nullptr; PCONSTRAINT->pMouse->currentConstraint = nullptr;
} }

View File

@ -39,6 +39,7 @@ namespace Events {
DYNLISTENFUNC(destroyPopupXDG); DYNLISTENFUNC(destroyPopupXDG);
DYNLISTENFUNC(commitPopupXDG); DYNLISTENFUNC(commitPopupXDG);
DYNLISTENFUNC(newPopupFromPopupXDG); DYNLISTENFUNC(newPopupFromPopupXDG);
DYNLISTENFUNC(repositionPopupXDG);
// Surface XDG (window) // Surface XDG (window)
LISTENER(newXDGSurface); LISTENER(newXDGSurface);

View File

@ -142,8 +142,11 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output); wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
if (layersurface->layerSurface->current.keyboard_interactive && const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive &&
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained // don't focus if constrained
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
if (GRABSFOCUS) {
g_pCompositor->focusSurface(layersurface->layerSurface->surface); g_pCompositor->focusSurface(layersurface->layerSurface->surface);
const auto LOCAL = 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; const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
layersurface->alpha.setValue(0); 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->readyToDelete = false;
layersurface->fadingOut = false; layersurface->fadingOut = false;

View File

@ -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_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_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_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; 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); 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) { void Events::listener_unmapPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner; SXDGPopup* PPOPUP = (SXDGPopup*)owner;
Debug::log(LOG, "XDG Popup unmapped"); 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; PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y;
} }
int lx = 0, ly = 0; int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly); 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); g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly);
} }

View File

@ -223,6 +223,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode); g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode);
} }
PWINDOW->updateSpecialRenderData();
// disallow tiled pinned // disallow tiled pinned
if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating) if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating)
PWINDOW->m_bPinned = false; PWINDOW->m_bPinned = false;
@ -413,8 +415,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
} catch (...) { Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); } } 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) { } else if (r.szRule.find("center") == 0) {
auto RESERVEDOFFSET = Vector2D(); auto RESERVEDOFFSET = Vector2D();
const auto ARGS = CVarList(r.szRule, 2, ' '); const auto ARGS = CVarList(r.szRule, 2, ' ');
if (ARGS[1] == "1") if (ARGS[1] == "1")
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
@ -994,7 +996,9 @@ void Events::listener_configureX11(void* owner, void* data) {
else else
PWINDOW->setHidden(true); 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)); PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; 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; 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 || const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y});
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, 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 ||
(int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height); 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); 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) 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)); PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));

View File

@ -714,3 +714,8 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
return callstack; return callstack;
} }
void throwError(const std::string& err) {
Debug::log(CRIT, "Critical error thrown: %s", err.c_str());
throw std::runtime_error(err);
}

View File

@ -29,4 +29,5 @@ float getPlusMinusKeywordResult(std::string in, float
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
double normalizeAngleRad(double ang); double normalizeAngleRad(double ang);
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace); std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
std::vector<SCallstackFrameInfo> getBacktrace(); std::vector<SCallstackFrameInfo> getBacktrace();
void throwError(const std::string& err);

View File

@ -489,6 +489,8 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
// remove from mvmonitors // remove from mvmonitors
std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; }); 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->setActiveMonitor(g_pCompositor->m_vMonitors.front().get());
g_pCompositor->sanityCheckWorkspaces(); g_pCompositor->sanityCheckWorkspaces();
@ -622,3 +624,10 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
void CMonitor::setSpecialWorkspace(const int& id) { void CMonitor::setSpecialWorkspace(const int& id) {
setSpecialWorkspace(g_pCompositor->getWorkspaceByID(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);
}

View File

@ -30,10 +30,11 @@ class CMonitor {
CMonitor(); CMonitor();
~CMonitor(); ~CMonitor();
Vector2D vecPosition = Vector2D(-1, -1); // means unset Vector2D vecPosition = Vector2D(-1, -1); // means unset
Vector2D vecSize = Vector2D(0, 0); Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset
Vector2D vecPixelSize = Vector2D(0, 0); Vector2D vecSize = Vector2D(0, 0);
Vector2D vecTransformedSize = Vector2D(0, 0); Vector2D vecPixelSize = Vector2D(0, 0);
Vector2D vecTransformedSize = Vector2D(0, 0);
bool primary = false; bool primary = false;
@ -109,6 +110,7 @@ class CMonitor {
void changeWorkspace(const int& id, bool internal = false); void changeWorkspace(const int& id, bool internal = false);
void setSpecialWorkspace(CWorkspace* const pWorkspace); void setSpecialWorkspace(CWorkspace* const pWorkspace);
void setSpecialWorkspace(const int& id); void setSpecialWorkspace(const int& id);
void moveTo(const Vector2D& pos);
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr; std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
bool m_bEnabled = false; bool m_bEnabled = false;

View File

@ -43,6 +43,14 @@ class Vector2D {
return Vector2D(this->x / a.x, this->y / a.y); 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; double distance(const Vector2D& other) const;
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const; Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;

View File

@ -191,10 +191,14 @@ struct SXDGPopup {
DYNLISTENER(mapPopupXDG); DYNLISTENER(mapPopupXDG);
DYNLISTENER(unmapPopupXDG); DYNLISTENER(unmapPopupXDG);
DYNLISTENER(commitPopupXDG); DYNLISTENER(commitPopupXDG);
DYNLISTENER(repositionPopupXDG);
double lx; double lx;
double ly; double ly;
Vector2D lastPos = {};
bool repositionRequested = false;
SSurfaceTreeNode* pSurfaceTree = nullptr; SSurfaceTreeNode* pSurfaceTree = nullptr;
// For the list lookup // For the list lookup
@ -242,8 +246,9 @@ struct STablet {
std::string name = ""; std::string name = "";
bool operator==(const STablet& b) const { //
return wlrDevice == b.wlrDevice; bool operator==(const STablet& b) const {
return wlrDevice == b.wlrDevice;
} }
}; };

View File

@ -58,7 +58,46 @@ CWorkspace::~CWorkspace() {
void CWorkspace::startAnim(bool in, bool left, bool instant) { void CWorkspace::startAnim(bool in, bool left, bool instant) {
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; 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. m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade.
if (in) { if (in) {

View File

@ -117,21 +117,16 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
const auto PWINDOW = pNode->pWindow; const auto PWINDOW = pNode->pWindow;
// get specific gaps and rules for this workspace, // get specific gaps and rules for this workspace,
// if user specified them in config // 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; PWINDOW->updateSpecialRenderData();
static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; 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 gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); 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) { if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW); 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_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position; 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) && if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { (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.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(); 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_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_vRealSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE) - (RESERVED.topLeft + RESERVED.bottomRight);
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
return; return;
} }
PWINDOW->m_sSpecialRenderData.rounding = WORKSPACERULE.rounding.value_or(true); const int BORDERSIZE = PWINDOW->getRealBorderSize();
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);
auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize); auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize); auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
@ -491,9 +482,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
return; return;
} }
pWindow->m_sSpecialRenderData.rounding = true; pWindow->updateSpecialRenderData();
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow->m_bIsFullscreen) if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); 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_vRealPosition = pWindow->m_vLastFloatingPosition;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_sSpecialRenderData.rounding = true; pWindow->updateSpecialRenderData();
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
} }
} else { } else {
// if it now got fullscreen, make it fullscreen // if it now got fullscreen, make it fullscreen

View File

@ -75,9 +75,17 @@ void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
} }
void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
wlr_box desiredGeometry = {0}; wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); 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; 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_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) {
if (pWindow->m_uSurface.xwayland->x != 0 && pWindow->m_uSurface.xwayland->y != 0) 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 else
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, 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); 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) { if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale; pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale;
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() / PMONITOR->scale;
}
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) { if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
pWindow->m_vRealPosition.warp(); 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) || if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() < (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate && 1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate &&
*PANIMATEMOUSE)) (*PANIMATEMOUSE || *PANIMATE)))
return; return;
TIMER = std::chrono::high_resolution_clock::now(); 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)); g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
pWindow->m_sSpecialRenderData.rounding = true; pWindow->updateSpecialRenderData();
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow == m_pLastTiledWindow) if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr; m_pLastTiledWindow = nullptr;

View File

@ -177,9 +177,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID);
static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue; static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue;
pWindow->m_sSpecialRenderData.rounding = true; pWindow->updateSpecialRenderData();
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow->m_bIsFullscreen) if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
@ -268,9 +266,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
return; return;
const auto PWORKSPACEDATA = getMasterWorkspaceData(ws); const auto PWORKSPACEDATA = getMasterWorkspaceData(ws);
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID); const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID);
if (!PMASTERNODE) if (!PMASTERNODE)
@ -279,200 +275,192 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
eOrientation orientation = PWORKSPACEDATA->orientation; eOrientation orientation = PWORKSPACEDATA->orientation;
bool centerMasterWindow = false; bool centerMasterWindow = false;
static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; 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 (orientation == ORIENTATION_CENTER) {
if (getNodesOnWorkspace(PWORKSPACE->m_iID) > 2 || (*ALWAYSCENTER == 1)) { if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) {
centerMasterWindow = true; centerMasterWindow = true;
} else { } else {
orientation = ORIENTATION_LEFT; orientation = ORIENTATION_LEFT;
} }
} }
const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); // compute placement of master window(s)
const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); if (WINDOWS == 1 && !centerMasterWindow) {
const auto STACKWINDOWS = WINDOWS - MASTERS; PMASTERNODE->size = WSSIZE;
//compute placement of master window(s) PMASTERNODE->position = WSPOS;
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);
applyNodeDataToWindow(PMASTERNODE); applyNodeDataToWindow(PMASTERNODE);
return; 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) { } else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x; const float HEIGHT = WSSIZE.y * PMASTERNODE->percMaster;
int nodesLeft = MASTERS; float widthLeft = WSSIZE.x;
float nextX = 0; int mastersLeft = MASTERS;
const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster; float nextX = 0;
float nextY = 0;
for (auto& n : m_lMasterNodesData) { for (auto& nd : m_lMasterNodesData) {
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { if (nd.workspaceID != PWORKSPACE->m_iID || !nd.isMaster)
if (orientation == ORIENTATION_BOTTOM) { continue;
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);
nodesLeft--; if (orientation == ORIENTATION_BOTTOM)
widthLeft -= WIDTH; nextY = WSSIZE.y - HEIGHT;
nextX += WIDTH;
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) { } else { // orientation left, right or center
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; float WIDTH = WSSIZE.x;
int nodesLeft = MASTERS; float heightLeft = WSSIZE.y;
float nextY = 0; int mastersLeft = MASTERS;
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster; float nextX = 0;
float nextY = 0;
for (auto& n : m_lMasterNodesData) { if (STACKWINDOWS > 0 || centerMasterWindow)
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { WIDTH *= PMASTERNODE->percMaster;
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);
nodesLeft--; if (orientation == ORIENTATION_RIGHT) {
heightLeft -= HEIGHT; nextX = WSSIZE.x - WIDTH;
nextY += HEIGHT; } 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) if (STACKWINDOWS == 0)
int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS; return;
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;
for (auto& nd : m_lMasterNodesData) { // compute placement of slave window(s)
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) int slavesLeft = STACKWINDOWS;
continue; if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
const float HEIGHT = WSSIZE.y - PMASTERNODE->size.y;
if (orientation == ORIENTATION_LEFT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { float widthLeft = WSSIZE.x;
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;
float nextX = 0; 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) { for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue; 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; float WIDTH = slavesLeft > 1 ? widthLeft / slavesLeft * nd.percSize : widthLeft;
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1) if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
WIDTH = widthLeft * 0.9f; WIDTH = widthLeft * 0.9f;
nd.size = Vector2D(WIDTH, HEIGHT); nd.size = Vector2D(WIDTH, HEIGHT);
nd.position = WSPOS + Vector2D(nextX, nextY);
applyNodeDataToWindow(&nd);
slavesLeft--; slavesLeft--;
widthLeft -= WIDTH; widthLeft -= WIDTH;
nextX += WIDTH; nextX += WIDTH;
applyNodeDataToWindow(&nd);
} }
} else if (orientation == ORIENTATION_CENTER && STACKWINDOWS >= 2) { } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) {
float heightLeftL = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; const float WIDTH = WSSIZE.x - PMASTERNODE->size.x;
float heightLeftR = heightLeftL; float heightLeft = WSSIZE.y;
float heightLeft = 0; float nextY = 0;
float nextYL = 0; float nextX = 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;
int slavesLeftL = 1 + (slavesLeft - 1) / 2; if (orientation == ORIENTATION_LEFT)
int slavesLeftR = slavesLeft - slavesLeftL; nextX = PMASTERNODE->size.x;
for (auto& nd : m_lMasterNodesData) { for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue; 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; float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
HEIGHT = heightLeft * 0.9f; HEIGHT = heightLeft * 0.9f;
nd.size = Vector2D(WIDTH, HEIGHT);
if (on_left) { nd.size = Vector2D(WIDTH, HEIGHT);
heightLeftL -= HEIGHT; nd.position = WSPOS + Vector2D(nextX, nextY);
nextYL += HEIGHT; applyNodeDataToWindow(&nd);
slavesLeftL--;
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 { } 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; heightLeftR -= HEIGHT;
nextYR += HEIGHT; nextYR += HEIGHT;
slavesLeftR--; slavesLeftR--;
} else {
heightLeftL -= HEIGHT;
nextYL += HEIGHT;
slavesLeftL--;
} }
applyNodeDataToWindow(&nd); onRight = !onRight;
on_left = !on_left;
} }
} }
} }
@ -505,28 +493,22 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
const auto PWINDOW = pNode->pWindow; const auto PWINDOW = pNode->pWindow;
// get specific gaps and rules for this workspace, // get specific gaps and rules for this workspace,
// if user specified them in config // 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; PWINDOW->updateSpecialRenderData();
static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; 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 gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); 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)) { if (!g_pCompositor->windowValidMapped(PWINDOW)) {
Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW); Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW);
return; return;
} }
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
PWINDOW->m_vSize = pNode->size; PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position; PWINDOW->m_vPosition = pNode->position;
@ -534,29 +516,27 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
(getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 || (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 ||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { (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.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(); 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_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_vRealSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE) - (RESERVED.topLeft + RESERVED.bottomRight);
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
return; return;
} }
PWINDOW->m_sSpecialRenderData.rounding = WORKSPACERULE.rounding.value_or(true); const int BORDERSIZE = PWINDOW->getRealBorderSize();
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);
auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize); auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize); auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
@ -613,19 +593,20 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
return; 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; return;
m_bForceWarps = true; m_bForceWarps = true;
const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); switch (orientation) {
double delta = 0;
switch (PWORKSPACEDATA->orientation) {
case ORIENTATION_LEFT: delta = pixResize.x / PMONITOR->vecSize.x; break; case ORIENTATION_LEFT: delta = pixResize.x / PMONITOR->vecSize.x; break;
case ORIENTATION_RIGHT: 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; 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_vRealPosition = pWindow->m_vLastFloatingPosition;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_sSpecialRenderData.rounding = true; pWindow->updateSpecialRenderData();
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
} }
} else { } else {
// if it now got fullscreen, make it fullscreen // if it now got fullscreen, make it fullscreen

View File

@ -22,7 +22,7 @@ void help() {
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (!getenv("XDG_RUNTIME_DIR")) 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 // export HYPRLAND_CMD
std::string cmd = ""; std::string cmd = "";

View File

@ -55,7 +55,6 @@ void CAnimationManager::tick() {
if (!*PANIMENABLED) if (!*PANIMENABLED)
animGlobalDisabled = true; animGlobalDisabled = true;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; static auto* const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
@ -217,7 +216,7 @@ void CAnimationManager::tick() {
// damage only the border. // damage only the border.
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
const auto ROUNDINGSIZE = *PROUNDING + 1; const auto ROUNDINGSIZE = *PROUNDING + 1;
const auto BORDERSIZE = *PBORDERSIZE; const auto BORDERSIZE = PWINDOW->getRealBorderSize();
// damage for old box // damage for old box
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top 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") { } else if (config == "workspaces" || config == "specialWorkspace") {
if (style == "slide" || style == "slidevert" || style == "fade") if (style == "slide" || style == "slidevert" || style == "fade")
return ""; 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"; return "unknown style";
} else if (config == "borderangle") { } else if (config == "borderangle") {

View File

@ -3,6 +3,7 @@
#include <regex> #include <regex>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <fcntl.h>
#if defined(__linux__) #if defined(__linux__)
#include <linux/vt.h> #include <linux/vt.h>
#elif defined(__NetBSD__) || defined(__OpenBSD__) #elif defined(__NetBSD__) || defined(__OpenBSD__)
@ -518,15 +519,19 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
// vtnr is bugged for some reason. // vtnr is bugged for some reason.
unsigned int ttynum = 0; unsigned int ttynum = 0;
int fd;
if ((fd = open("/dev/tty", O_RDONLY | O_NOCTTY)) >= 0) {
#if defined(VT_GETSTATE) #if defined(VT_GETSTATE)
struct vt_stat st; struct vt_stat st;
if (!ioctl(0, VT_GETSTATE, &st)) if (!ioctl(fd, VT_GETSTATE, &st))
ttynum = st.v_active; ttynum = st.v_active;
#elif defined(VT_GETACTIVE) #elif defined(VT_GETACTIVE)
int vt; int vt;
if (!ioctl(0, VT_GETACTIVE, &vt)) if (!ioctl(fd, VT_GETACTIVE, &vt))
ttynum = vt; ttynum = vt;
#endif #endif
close(fd);
}
if (ttynum == TTY) if (ttynum == TTY)
return true; return true;

View File

@ -54,6 +54,7 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (pWindow->m_bIsX11) { if (pWindow->m_bIsX11) {
setWindowSize(pWindow, pWindow->m_vRealSize.vec()); // update xwayland output pos
if (activate) { if (activate) {
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); 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) { void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) {
if (!force && static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
if (!PMONITOR)
return; return;
pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec(); // calculate pos
pWindow->m_vReportedSize = size; // 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; 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) 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 else
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); 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; MAXSIZE.y = 99999;
return MAXSIZE; return MAXSIZE;
} }
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;
}

View File

@ -26,6 +26,7 @@ class CHyprXWaylandManager {
void moveXWaylandWindow(CWindow*, const Vector2D&); void moveXWaylandWindow(CWindow*, const Vector2D&);
void checkBorders(CWindow*); void checkBorders(CWindow*);
Vector2D getMaxSizeForWindow(CWindow*); Vector2D getMaxSizeForWindow(CWindow*);
Vector2D xwaylandToWaylandCoords(const Vector2D&);
}; };
inline std::unique_ptr<CHyprXWaylandManager> g_pXWaylandManager; inline std::unique_ptr<CHyprXWaylandManager> g_pXWaylandManager;

View File

@ -85,6 +85,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
return; return;
if (time)
g_pCompositor->notifyIdleActivity();
EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED); EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED);
m_vLastCursorPosFloored = MOUSECOORDSFLOORED; m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
@ -319,9 +322,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
m_bEmptyFocusCursorSet = false; m_bEmptyFocusCursorSet = false;
if (time)
g_pCompositor->notifyIdleActivity();
Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos; Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos;
if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) { 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(); pMouse->hyprListener_commitConstraint.removeCallback();
if (pMouse->currentConstraint) { if (pMouse->currentConstraint) {
if (!constraint) { if (constraint && constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT)
// warpe to hint warpMouseToConstraintMiddle(constraintFromWlr(constraint));
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;
}
}
}
wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint); 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); 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() { void CInputManager::unconstrainMouse() {
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)
return; return;
@ -1531,14 +1529,16 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) {
} }
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; 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; 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 // 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(); 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}; 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; 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)) { if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) {
direction = BORDERICON_NONE; direction = BORDERICON_NONE;

View File

@ -79,6 +79,7 @@ class CInputManager {
void destroySwitch(SSwitchDevice*); void destroySwitch(SSwitchDevice*);
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*); void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void warpMouseToConstraintMiddle(SConstraint*);
void recheckConstraint(SMouse*); void recheckConstraint(SMouse*);
void unconstrainMouse(); void unconstrainMouse();
SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*); SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*);

View File

@ -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 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 PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->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 // commit
std::string wsname = ""; 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 PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->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); m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx);

View File

@ -110,14 +110,15 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
if (!pOutput->resource->good()) if (!pOutput->resource->good())
return; 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) 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 else
zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecSize.x, pOutput->monitor->vecSize.y); zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecSize.x, pOutput->monitor->vecSize.y);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "WaylandProtocol.hpp" #include "WaylandProtocol.hpp"
#include <optional>
class CMonitor; class CMonitor;
@ -8,6 +9,8 @@ struct SXDGOutput {
CMonitor* monitor = nullptr; CMonitor* monitor = nullptr;
std::unique_ptr<CWaylandResource> resource; std::unique_ptr<CWaylandResource> resource;
std::optional<Vector2D> overridePosition;
wl_client* client = nullptr; wl_client* client = nullptr;
bool isXWayland = false; bool isXWayland = false;
}; };

View File

@ -261,11 +261,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
TRACY_GPU_ZONE("RenderWindow"); TRACY_GPU_ZONE("RenderWindow");
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); 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 PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y};
if (ignorePosition) { 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.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.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl());
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl(); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
(!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale;
renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later
renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later renderdata.pWindow = pWindow;
renderdata.pWindow = pWindow;
if (ignoreAllGeometry) { if (ignoreAllGeometry) {
renderdata.alpha = 1.f; 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) && 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->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale &&
((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || ((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 && pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit &&
!memcmp(&pMonitor->customDrmMode, &pMonitorRule->drmMode, sizeof(pMonitor->customDrmMode))) { !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); 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); wlr_output_enable(pMonitor->output, 1);
// update renderer (here because it will call rollback, so we cannot do this before committing) // update renderer (here because it will call rollback, so we cannot do this before committing)
g_pHyprOpenGL->destroyMonitorResources(pMonitor); g_pHyprOpenGL->destroyMonitorResources(pMonitor);
// updato wlroots // updato wlroots
if (!pMonitor->isMirror()) g_pCompositor->arrangeMonitors();
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);

View File

@ -59,6 +59,9 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
if (!m_pWindow->m_sSpecialRenderData.decorate) if (!m_pWindow->m_sSpecialRenderData.decorate)
return; return;
if (!m_pWindow->m_sSpecialRenderData.shadow)
return;
if (m_pWindow->m_sAdditionalConfigData.forceNoShadow) if (m_pWindow->m_sAdditionalConfigData.forceNoShadow)
return; return;

View File

@ -39,18 +39,10 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) { if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
// we draw 3px above the window's border with 3px // 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() : m_seExtents.topLeft = Vector2D(0, BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2);
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.bottomRight = Vector2D(); m_seExtents.bottomRight = Vector2D();
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET; 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 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 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; static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("misc:groupbar_gradients")->intValue;
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID)); const int BORDERSIZE = m_pWindow->getRealBorderSize();
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;
if (!m_pWindow->m_sSpecialRenderData.decorate) if (!m_pWindow->m_sSpecialRenderData.decorate)
return; return;
@ -122,7 +106,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
for (int i = 0; i < barsToDraw; ++i) { for (int i = 0; i < barsToDraw; ++i) {
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, 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) if (rect.width <= 0 || rect.height <= 0)
break; break;

View File

@ -109,11 +109,14 @@ void main() {
discard; discard;
} }
if (pixColor[3] == 0.0) if (additionalAlpha == 0.0)
discard; discard;
pixColor = getColorForCoord(v_texcoord); pixColor = getColorForCoord(v_texcoord);
pixColor.rgb *= pixColor[3];
gl_FragColor = pixColor * alpha * additionalAlpha; pixColor *= alpha * additionalAlpha;
gl_FragColor = pixColor;
} }
)#"; )#";

View File

@ -79,9 +79,7 @@ void main() {
} }
// premultiply // premultiply
pixColor[0] *= pixColor[3]; pixColor.rgb *= pixColor[3];
pixColor[1] *= pixColor[3];
pixColor[2] *= pixColor[3];
gl_FragColor = pixColor; gl_FragColor = pixColor;
})#"; })#";