diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index 8a33dd55..8598b5a3 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -12,6 +12,7 @@ runs: - name: Get required pacman pkgs shell: bash run: | + sed -i -e "1i [extra-testing]\nInclude = /etc/pacman.d/mirrorlist" "/etc/pacman.conf" sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf pacman --noconfirm --noprogressbar -Syyu pacman --noconfirm --noprogressbar -Sy \ @@ -51,7 +52,18 @@ runs: wayland-protocols \ xcb-util-errors \ xcb-util-renderutil \ - xcb-util-wm + xcb-util-wm \ + libzip \ + librsvg + + - name: Get hyprcursor-git + shell: bash + run: | + git clone https://github.com/hyprwm/hyprcursor --recursive + cd hyprcursor + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + cmake --install build - name: Get Xorg pacman pkgs shell: bash diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 01bb43d1..42dfcf9c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,6 +31,7 @@ jobs: cp ./LICENSE hyprland/ cp build/Hyprland hyprland/ cp build/hyprctl/hyprctl hyprland/ + cp build/hyprpm/hyprpm hyprland/ cp subprojects/wlroots/build/libwlroots.so.13032 hyprland/ cp build/Hyprland hyprland/ cp -r example/ hyprland/ diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 2c05d5e2..bb6d90ad 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -19,7 +19,7 @@ jobs: with: ref: ${{ github.ref }} - - uses: DeterminateSystems/nix-installer-action@main + - uses: cachix/install-nix-action@v25 - uses: DeterminateSystems/magic-nix-cache-action@main - uses: cachix/cachix-action@v12 with: diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 6a86f70e..564013cf 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -24,44 +24,3 @@ jobs: uses: github/codeql-action/upload-sarif@v2 with: sarif_file: ${{github.workspace}}/flawfinder_results.sarif - - codeql: - name: CodeQL - runs-on: ubuntu-latest - container: - image: archlinux - - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'cpp' ] - - steps: - - name: Checkout repository actions - uses: actions/checkout@v4 - with: - sparse-checkout: .github/actions - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - - - name: Setup base - uses: ./.github/actions/setup_base - with: - INSTALL_XORG_PKGS: true - - - name: Build Hyprland - run: | - make all - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" diff --git a/.gitmodules b/.gitmodules index b483fce1..4ab24838 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,6 @@ [submodule "wlroots"] path = subprojects/wlroots - url = https://github.com/DRAGONTOS/wlroots.git - branch = 0.18.0-dev + url = https://git.kaleyfischer.xyz/DRAGONTOS/wlroots [submodule "subprojects/hyprland-protocols"] path = subprojects/hyprland-protocols url = https://github.com/hyprwm/hyprland-protocols diff --git a/CMakeLists.txt b/CMakeLists.txt index 857e21de..71766a8c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ message(STATUS "Checking deps...") find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) find_package(OpenGL REQUIRED) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2) # we do not check for wlroots, as we provide it ourselves +pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2 hyprcursor) # we do not check for wlroots, as we provide it ourselves file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") diff --git a/Makefile b/Makefile index 9c5e94d5..c29f20a0 100644 --- a/Makefile +++ b/Makefile @@ -106,3 +106,24 @@ man: --variable=section:1 \ --from rst \ --to man > ./docs/hyprctl.1 + +asan: + @echo -en "!!WARNING!!\nOnly run this in the TTY.\n" + @pidof Hyprland > /dev/null && echo -ne "Refusing to run with Hyprland running.\n" || echo "" + @pidof Hyprland > /dev/null && exit 1 || echo "" + + rm -rf ./wayland + git reset --hard + + git clone --recursive https://gitlab.freedesktop.org/wayland/wayland + cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd .. + cp ./wayland/build/src/libwayland-server.a . + @echo "Wayland done" + + patch -p1 < ./scripts/hyprlandStaticAsan.diff + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DWITH_ASAN:STRING=True -DUSE_TRACY:STRING=False -DUSE_TRACY_GPU:STRING=False -S . -B ./build -G Ninja + cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + @echo "Hyprland done" + + ASAN_OPTIONS="detect_odr_violation=0,log_path=asan.log" HYPRLAND_NO_CRASHREPORTER=1 ./build/Hyprland -c ~/.config/hypr/hyprland.conf + diff --git a/README.md b/README.md index 9f4aa847..70cce21d 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... [Wayfire]: https://github.com/WayfireWM/wayfire [TinyWl]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/tinywl/tinywl.c [Sway]: https://github.com/swaywm/sway -[DWL]: https://github.com/djpohly/dwl +[DWL]: https://codeberg.org/dwl/dwl diff --git a/flake.lock b/flake.lock index d5e00c3b..9e6464f0 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,29 @@ { "nodes": { + "hyprcursor": { + "inputs": { + "hyprlang": "hyprlang", + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1710257359, + "narHash": "sha256-43re5pzE/cswFAgw92/ugsB3+d5ufDaCcLtl9ztKfBo=", + "owner": "hyprwm", + "repo": "hyprcursor", + "rev": "1761f6cefd77f4fcd2039d930c88d6716ddc4974", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprcursor", + "type": "github" + } + }, "hyprland-protocols": { "inputs": { "nixpkgs": [ @@ -24,6 +48,28 @@ } }, "hyprlang": { + "inputs": { + "nixpkgs": [ + "hyprcursor", + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1709914708, + "narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -33,11 +79,11 @@ ] }, "locked": { - "lastModified": 1708787654, - "narHash": "sha256-7ACgM3ZuAhPqurXHUvR2nWMRcnmzGGPjLK6q4DSTelI=", + "lastModified": 1709914708, + "narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "0fce791ba2334aca183f2ed42399518947550d0d", + "rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2", "type": "github" }, "original": { @@ -48,11 +94,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1708807242, - "narHash": "sha256-sRTRkhMD4delO/hPxxi+XwLqPn8BuUq6nnj4JqLwOu0=", + "lastModified": 1710272261, + "narHash": "sha256-g0bDwXFmTE7uGDOs9HcJsfLFhH7fOsASbAuOzDC+fhQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "73de017ef2d18a04ac4bfd0c02650007ccb31c2a", + "rev": "0ad13a6833440b8e238947e47bea7f11071dc2b2", "type": "github" }, "original": { @@ -64,10 +110,11 @@ }, "root": { "inputs": { + "hyprcursor": "hyprcursor", "hyprland-protocols": "hyprland-protocols", - "hyprlang": "hyprlang", + "hyprlang": "hyprlang_2", "nixpkgs": "nixpkgs", - "systems": "systems", + "systems": "systems_2", "wlroots": "wlroots", "xdph": "xdph" } @@ -87,22 +134,37 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, "wlroots": { "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1708558866, - "narHash": "sha256-Mz6hCtommq7RQfcPnxLINigO4RYSNt23HeJHC6mVmWI=", + "lastModified": 1709983277, + "narHash": "sha256-wXWIJLd4F2JZeMaihWVDW/yYXCLEC8OpeNJZg9a9ly8=", "owner": "wlroots", "repo": "wlroots", - "rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5", + "rev": "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5", + "rev": "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b", "type": "gitlab" } }, @@ -122,11 +184,11 @@ ] }, "locked": { - "lastModified": 1708696469, - "narHash": "sha256-shh5wmpeYy3MmsBfkm4f76yPsBDGk6OLYRVG+ARy2F0=", + "lastModified": 1709299639, + "narHash": "sha256-jYqJM5khksLIbqSxCLUUcqEgI+O2LdlSlcMEBs39CAU=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "1b713911c2f12b96c2574474686e4027ac4bf826", + "rev": "2d2fb547178ec025da643db57d40a971507b82fe", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 675a6d92..e419e3e3 100644 --- a/flake.nix +++ b/flake.nix @@ -12,10 +12,16 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5"; + rev = "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b"; flake = false; }; + hyprcursor = { + url = "github:hyprwm/hyprcursor"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + }; + hyprland-protocols = { url = "github:hyprwm/hyprland-protocols"; inputs.nixpkgs.follows = "nixpkgs"; @@ -71,9 +77,9 @@ # hyprland-packages hyprland - hyprland-unwrapped hyprland-debug hyprland-legacy-renderer + hyprland-unwrapped # hyprland-extras xdg-desktop-portal-hyprland @@ -91,7 +97,7 @@ stdenv = pkgsFor.${system}.gcc13Stdenv; } { name = "hyprland-shell"; - nativeBuildInputs = with pkgsFor.${system}; [cmake python3]; + nativeBuildInputs = with pkgsFor.${system}; [cmake python3 expat libxml2]; buildInputs = [self.packages.${system}.wlroots-hyprland]; hardeningDisable = ["fortify"]; inputsFrom = [ diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 11b571ac..880ed673 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -315,6 +315,8 @@ int main(int argc, char** argv) { json = true; } else if (ARGS[i] == "-r" && !fullArgs.contains("r")) { fullArgs += "r"; + } else if (ARGS[i] == "-a" && !fullArgs.contains("a")) { + fullArgs += "a"; } else if (ARGS[i] == "--batch") { fullRequest = "--batch "; } else if (ARGS[i] == "--instance" || ARGS[i] == "-i") { @@ -429,6 +431,8 @@ int main(int argc, char** argv) { request(fullRequest, 3); else if (fullRequest.contains("/plugin")) request(fullRequest, 1); + else if (fullRequest.contains("/dismissnotify")) + request(fullRequest, 0); else if (fullRequest.contains("/notify")) request(fullRequest, 2); else if (fullRequest.contains("/output")) diff --git a/hyprpm/src/core/DataState.cpp b/hyprpm/src/core/DataState.cpp index b4fc8dd5..9946db66 100644 --- a/hyprpm/src/core/DataState.cpp +++ b/hyprpm/src/core/DataState.cpp @@ -45,12 +45,14 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) { {"repository", toml::table{ {"name", repo.name}, {"hash", repo.hash}, - {"url", repo.url} + {"url", repo.url}, + {"rev", repo.rev} }} }; for (auto& p : repo.plugins) { // copy .so to the good place - std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so"); + if (std::filesystem::exists(p.filename)) + std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so"); DATA.emplace(p.name, toml::table{ {"filename", p.name + ".so"}, @@ -177,12 +179,14 @@ std::vector DataState::getAllRepositories() { const auto NAME = STATE["repository"]["name"].value_or(""); const auto URL = STATE["repository"]["url"].value_or(""); + const auto REV = STATE["repository"]["rev"].value_or(""); const auto HASH = STATE["repository"]["hash"].value_or(""); SPluginRepository repo; repo.hash = HASH; repo.name = NAME; repo.url = URL; + repo.rev = REV; for (const auto& [key, val] : STATE) { if (key == "repository") diff --git a/hyprpm/src/core/Plugin.hpp b/hyprpm/src/core/Plugin.hpp index edc7486a..dccc71b0 100644 --- a/hyprpm/src/core/Plugin.hpp +++ b/hyprpm/src/core/Plugin.hpp @@ -12,6 +12,7 @@ struct SPlugin { struct SPluginRepository { std::string url; + std::string rev; std::string name; std::vector plugins; std::string hash; diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 50f2d443..e9a9a9fa 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -77,8 +77,7 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { return ver; } -bool CPluginManager::addNewPluginRepo(const std::string& url) { - +bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& rev) { const auto HLVER = getHyprlandVersion(); if (DataState::pluginRepoExists(url)) { @@ -134,6 +133,14 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) { return false; } + if (!rev.empty()) { + std::string ret = execAndGet("git -C /tmp/hyprpm/new reset --hard --recurse-submodules " + rev); + if (ret.compare(0, 6, "fatal:") == 0) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n"; + return false; + } + } + progress.m_iSteps = 1; progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); progress.m_szCurrentMessage = "Reading the manifest"; @@ -240,6 +247,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) { repohash.pop_back(); repo.name = pManifest->m_sRepository.name.empty() ? url.substr(url.find_last_of('/') + 1) : pManifest->m_sRepository.name; repo.url = url; + repo.rev = rev; repo.hash = repohash; for (auto& p : pManifest->m_vPlugins) { repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed}); @@ -494,6 +502,16 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { return false; } + if (!repo.rev.empty()) { + progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev); + + std::string ret = execAndGet("git -C /tmp/hyprpm reset --hard --recurse-submodules " + repo.rev); + if (ret.compare(0, 6, "fatal:") == 0) { + std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret; + return false; + } + } + if (!update) { // check if git has updates std::string hash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD"); @@ -538,8 +556,8 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { continue; } - if (!pManifest->m_sRepository.commitPins.empty()) { - // check commit pins + if (repo.rev.empty() && !pManifest->m_sRepository.commitPins.empty()) { + // check commit pins unless a revision is specified progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index 5e1eb6fb..028e6357 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -36,7 +36,7 @@ struct SHyprlandVersion { class CPluginManager { public: - bool addNewPluginRepo(const std::string& url); + bool addNewPluginRepo(const std::string& url, const std::string& rev); bool removePluginRepo(const std::string& urlOrName); eHeadersErrors headersValid(); diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index c0697e29..af20e211 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -75,7 +75,12 @@ int main(int argc, char** argv, char** envp) { return 1; } - return g_pPluginManager->addNewPluginRepo(command[1]) ? 0 : 1; + std::string rev = ""; + if (command.size() >= 3) { + rev = command[2]; + } + + return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1; } else if (command[0] == "remove") { if (ARGS.size() < 2) { std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for remove.\n"; diff --git a/nix/default.nix b/nix/default.nix index 6062a215..a2a31818 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -8,6 +8,7 @@ binutils, cairo, git, + hyprcursor, hyprland-protocols, hyprlang, jq, @@ -75,6 +76,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov [ cairo git + hyprcursor.dev hyprland-protocols hyprlang libdrm @@ -132,6 +134,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov postInstall = '' ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots + ${lib.optionalString wrapRuntimeDeps '' wrapProgram $out/bin/Hyprland \ --suffix PATH : ${lib.makeBinPath [ diff --git a/nix/overlays.nix b/nix/overlays.nix index 0a84d93e..c216ff53 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -21,6 +21,7 @@ in { # Packages for variations of Hyprland, dependencies included. hyprland-packages = lib.composeManyExtensions [ # Dependencies + inputs.hyprcursor.overlays.default inputs.hyprland-protocols.overlays.default inputs.hyprlang.overlays.default self.overlays.wlroots-hyprland diff --git a/nix/patches/meson-build.patch b/nix/patches/meson-build.patch index aefbf1bc..7f372107 100644 --- a/nix/patches/meson-build.patch +++ b/nix/patches/meson-build.patch @@ -37,15 +37,16 @@ diff --git a/src/meson.build b/src/meson.build index 45701f5f..3505cefe 100644 --- a/src/meson.build +++ b/src/meson.build -@@ -9,17 +9,17 @@ executable('Hyprland', src, +@@ -9,7 +9,7 @@ executable('Hyprland', src, server_protos, dependency('wayland-server'), dependency('wayland-client'), - wlroots.get_variable('wlroots'), + dependency('wlroots'), dependency('cairo'), + dependency('hyprcursor'), dependency('hyprlang', version: '>= 0.3.2'), - dependency('libdrm'), +@@ -16,12 +16,12 @@ executable('Hyprland', src, dependency('egl'), dependency('xkbcommon'), dependency('libinput'), diff --git a/props.json b/props.json index 557042f5..b140a0f5 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.36.0" + "version": "0.37.1" } diff --git a/scripts/hyprlandStaticAsan.diff b/scripts/hyprlandStaticAsan.diff new file mode 100644 index 00000000..5499f793 --- /dev/null +++ b/scripts/hyprlandStaticAsan.diff @@ -0,0 +1,21 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 857e21de..122d6a78 100755 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -101,7 +101,7 @@ message(STATUS "Checking deps...") + find_package(Threads REQUIRED) + find_package(PkgConfig REQUIRED) + find_package(OpenGL REQUIRED) +-pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2) # we do not check for wlroots, as we provide it ourselves ++pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2 libffi) # we do not check for wlroots, as we provide it ourselves + + file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") + +@@ -121,6 +121,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) + message(STATUS "Enabling ASan") + + target_link_libraries(Hyprland asan) ++ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a) + target_compile_options(Hyprland PUBLIC -fsanitize=address) + endif() + \ No newline at end of file diff --git a/scripts/waylandStatic.diff b/scripts/waylandStatic.diff new file mode 100644 index 00000000..04aeda23 --- /dev/null +++ b/scripts/waylandStatic.diff @@ -0,0 +1,23 @@ +diff --git a/src/meson.build b/src/meson.build +index 5d04334..6645eec 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -170,7 +170,7 @@ if get_option('libraries') + error('We probably need to bump the SONAME of libwayland-server and -client') + endif + +- wayland_server = library( ++ wayland_server = static_library( + 'wayland-server', + sources: [ + wayland_server_protocol_core_h, +@@ -180,9 +180,6 @@ if get_option('libraries') + 'wayland-shm.c', + 'event-loop.c' + ], +- # To avoid an unnecessary SONAME bump, wayland 1.x.y produces +- # libwayland-server.so.0.x.y. +- version: '.'.join(['0', wayland_version[1], wayland_version[2]]), + dependencies: [ + epoll_dep, + ffi_dep, diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f0d7ca0f..42ba9b5f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1,5 +1,7 @@ #include "Compositor.hpp" #include "helpers/Splashes.hpp" +#include "config/ConfigValue.hpp" +#include "managers/CursorManager.hpp" #include #include #include "debug/HyprCtl.hpp" @@ -125,13 +127,26 @@ void CCompositor::initServer() { throwError("wlr_backend_autocreate() failed!"); } - m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); - if (m_iDRMFD < 0) { - Debug::log(CRIT, "Couldn't query the DRM FD!"); - throwError("wlr_backend_get_drm_fd() failed!"); - } + bool isHeadlessOnly = true; + wlr_multi_for_each_backend( + m_sWLRBackend, + [](wlr_backend* backend, void* isHeadlessOnly) { + if (!wlr_backend_is_headless(backend)) + *(bool*)isHeadlessOnly = false; + }, + &isHeadlessOnly); - m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); + if (isHeadlessOnly) { + m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend); + } else { + m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); + if (m_iDRMFD < 0) { + Debug::log(CRIT, "Couldn't query the DRM FD!"); + throwError("wlr_backend_get_drm_fd() failed!"); + } + + m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); + } if (!m_sWLRRenderer) { Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues."); @@ -181,18 +196,6 @@ void CCompositor::initServer() { m_sWLRCursor = wlr_cursor_create(); wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout); - if (const auto XCURSORENV = getenv("XCURSOR_SIZE"); !XCURSORENV || std::string(XCURSORENV).empty()) - setenv("XCURSOR_SIZE", "24", true); - - const auto XCURSORENV = getenv("XCURSOR_SIZE"); - int cursorSize = 24; - try { - cursorSize = std::stoi(XCURSORENV); - } catch (std::exception& e) { Debug::log(ERR, "XCURSOR_SIZE invalid in check #2? ({})", XCURSORENV); } - - m_sWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, cursorSize); - wlr_xcursor_manager_load(m_sWLRXCursorMgr, 1); - m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0"); m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend); @@ -421,6 +424,7 @@ void CCompositor::cleanup() { wl_display_destroy_clients(g_pCompositor->m_sWLDisplay); g_pDecorationPositioner.reset(); + g_pCursorManager.reset(); g_pPluginSystem.reset(); g_pHyprNotificationOverlay.reset(); g_pDebugOverlay.reset(); @@ -510,6 +514,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the DecorationPositioner!"); g_pDecorationPositioner = std::make_unique(); + + Debug::log(LOG, "Creating the CursorManager!"); + g_pCursorManager = std::make_unique(); } break; default: UNREACHABLE(); } @@ -707,12 +714,12 @@ bool CCompositor::monitorExists(CMonitor* pMonitor) { } CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, CWindow* pIgnoreWindow) { - const auto PMONITOR = getMonitorFromVector(pos); - static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border"); - static auto* const PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size"); - static auto* const PBORDERGRABEXTEND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area"); - static auto* const PSPECIALFALLTHRU = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:special_fallthrough"); - const auto BORDER_GRAB_AREA = **PRESIZEONBORDER ? **PBORDERSIZE + **PBORDERGRABEXTEND : 0; + const auto PMONITOR = getMonitorFromVector(pos); + static auto PRESIZEONBORDER = CConfigValue("general:resize_on_border"); + static auto PBORDERSIZE = CConfigValue("general:border_size"); + static auto PBORDERGRABEXTEND = CConfigValue("general:extend_border_grab_area"); + static auto PSPECIALFALLTHRU = CConfigValue("input:special_fallthrough"); + const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; // pinned windows on top of floating regardless if (properties & ALLOW_FLOATING) { @@ -739,8 +746,16 @@ CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t propert if (special && !isWorkspaceSpecial(w->m_iWorkspaceID)) // because special floating may creep up into regular continue; - const auto BB = w->getWindowBoxUnified(properties); - CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; + const auto BB = w->getWindowBoxUnified(properties); + const auto PWINDOWMONITOR = getMonitorFromID(w->m_iMonitorID); + + // to avoid focusing windows behind special workspaces from other monitors + if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->specialWorkspaceID && w->m_iWorkspaceID != PWINDOWMONITOR->specialWorkspaceID && + BB.x >= PWINDOWMONITOR->vecPosition.x && BB.y >= PWINDOWMONITOR->vecPosition.y && + BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y) + continue; + + CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent @@ -814,7 +829,7 @@ CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t propert }; // special workspace - if (PMONITOR->specialWorkspaceID && !**PSPECIALFALLTHRU) + if (PMONITOR->specialWorkspaceID && !*PSPECIALFALLTHRU) return windowForWorkspace(true); if (PMONITOR->specialWorkspaceID) { @@ -843,7 +858,8 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr()); geom.applyFromWlr(); - const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x + geom.x, pos.y - pWindow->m_vRealPosition.vec().y + geom.y, &subx, &suby); + const auto PFOUND = + wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.value().x + geom.x, pos.y - pWindow->m_vRealPosition.value().y + geom.y, &subx, &suby); if (PFOUND) { sl.x = subx; @@ -851,8 +867,8 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW return PFOUND; } - sl.x = pos.x - pWindow->m_vRealPosition.vec().x; - sl.y = pos.y - pWindow->m_vRealPosition.vec().y; + sl.x = pos.x - pWindow->m_vRealPosition.value().x; + sl.y = pos.y - pWindow->m_vRealPosition.value().y; sl.x += geom.x; sl.y += geom.y; @@ -865,7 +881,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow return {}; if (pWindow->m_bIsX11) - return vec - pWindow->m_vRealPosition.goalv(); + return vec - pWindow->m_vRealPosition.goal(); const auto PSURFACE = pWindow->m_uSurface.xdg; @@ -887,9 +903,9 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow geom.applyFromWlr(); if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337) - return vec - pWindow->m_vRealPosition.goalv(); + return vec - pWindow->m_vRealPosition.goal(); - return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y}; + return vec - pWindow->m_vRealPosition.goal() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y}; } CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { @@ -914,8 +930,8 @@ CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) { void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { - static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse"); - static auto* const PSPECIALFALLTHROUGH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:special_fallthrough"); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); if (g_pCompositor->m_sSeat.exclusiveClient) { Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer."); @@ -927,6 +943,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { return; } + if (pWindow && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(pWindow->m_uSurface.xwayland)) + return; + g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow); if (!pWindow || !windowValidMapped(pWindow)) { @@ -989,7 +1008,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { /* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which window focuses are "via keybinds" and which ones aren't. */ - if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID && !pWindow->m_bPinned && !**PSPECIALFALLTHROUGH) + if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH) PMONITOR->setSpecialWorkspace(nullptr); // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window @@ -1039,13 +1058,6 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { if (pWindow->m_phForeignToplevel) wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true); - if (!pWindow->m_bIsX11) { - const auto PCONSTRAINT = wlr_pointer_constraints_v1_constraint_for_surface(m_sWLRPointerConstraints, pWindow->m_uSurface.xdg->surface, m_sSeat.seat); - - if (PCONSTRAINT) - g_pInputManager->constrainMouse(m_sSeat.mouse, PCONSTRAINT); - } - g_pInputManager->recheckIdleInhibitorStatus(); // move to front of the window history @@ -1056,7 +1068,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); } - if (**PFOLLOWMOUSE == 0) + if (*PFOLLOWMOUSE == 0) g_pInputManager->sendMotionEventsToFocused(); } @@ -1068,6 +1080,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) return; + const auto PLASTSURF = m_pLastFocus; + // Unfocus last surface if should if (m_pLastFocus && !pWindowOwner) g_pXWaylandManager->activateSurface(m_pLastFocus, false); @@ -1102,6 +1116,15 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { m_pLastFocus = pSurface; EMIT_HOOK_EVENT("keyboardFocus", pSurface); + + const auto SURF = CWLSurface::surfaceFromWlr(pSurface); + const auto OLDSURF = CWLSurface::surfaceFromWlr(PLASTSURF); + + if (OLDSURF && OLDSURF->constraint()) + OLDSURF->constraint()->deactivate(); + + if (SURF && SURF->constraint()) + SURF->constraint()->activate(); } bool CCompositor::windowValidMapped(CWindow* pWindow) { @@ -1120,19 +1143,10 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) { return true; } -CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) { - for (auto& p : m_vXDGPopups) { - if (p->popup == popup) - return p->parentWindow; - } - - return nullptr; -} - wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) { for (auto& ls : *layerSurfaces | std::views::reverse) { - if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.fl() == 0.f) + if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f) continue; auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y); @@ -1250,7 +1264,7 @@ void CCompositor::sanityCheckWorkspaces() { if (!isWorkspaceVisible(WORKSPACE->m_iID)) { if (WORKSPACE->m_bIsSpecialWorkspace) { - if (WORKSPACE->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) { + if (WORKSPACE->m_fAlpha.value() > 0.f /* don't abruptly end the fadeout */) { ++it; continue; } @@ -1431,12 +1445,16 @@ void CCompositor::cleanupFadingOut(const int& monid) { bool valid = windowExists(w); - if (!valid || !w->m_bFadingOut || w->m_fAlpha.fl() == 0.f) { - if (valid && !w->m_bReadyToDelete) - continue; + if (!valid || !w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { + if (valid) { + w->m_bFadingOut = false; + + if (!w->m_bReadyToDelete) + continue; + + removeWindowFromVectorSafe(w); + } - w->m_bFadingOut = false; - removeWindowFromVectorSafe(w); std::erase(m_vWindowsFadingOut, w); Debug::log(LOG, "Cleanup: destroyed a window"); @@ -1480,7 +1498,7 @@ void CCompositor::cleanupFadingOut(const int& monid) { if (ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid)); - if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) { + if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) { for (auto& m : m_vMonitors) { for (auto& lsl : m->m_aLayerSurfaceLayers) { if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr& other) { return other.get() == ls; }) != lsl.end()) { @@ -1523,9 +1541,9 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { return nullptr; // 0 -> history, 1 -> shared length - static auto* const PMETHOD = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method"); + static auto PMETHOD = CConfigValue("binds:focus_preferred_method"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); if (!PMONITOR) return nullptr; // ?? @@ -1585,7 +1603,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { break; } - if (**PMETHOD == 0 /* history */) { + if (*PMETHOD == 0 /* history */) { if (intersectLength > 0) { // get idx @@ -1778,31 +1796,6 @@ void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) { pair->second = pair->second || pSurface == pair->first; } -CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) { - if (!pMouse->currentConstraint) - return nullptr; - - const auto PSURFACE = pMouse->currentConstraint->surface; - - for (auto& w : m_vWindows) { - if (w->isHidden() || !w->m_bIsMapped || !w->m_pWLSurface.exists()) - continue; - - if (w->m_bIsX11) { - if (PSURFACE == w->m_pWLSurface.wlr()) - return w.get(); - } else { - std::pair check = {PSURFACE, false}; - wlr_surface_for_each_surface(w->m_uSurface.xdg->surface, checkFocusSurfaceIter, &check); - - if (check.second) - return w.get(); - } - } - - return nullptr; -} - CMonitor* CCompositor::getMonitorInDirection(const char& dir) { return this->getMonitorInDirection(m_pLastMonitor, dir); } @@ -1891,32 +1884,32 @@ void CCompositor::updateWorkspaceWindows(const int64_t& id) { void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { // optimization - static auto* const PACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.active_border"); - static auto* const PINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border"); - static auto* const PNOGROUPACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active"); - static auto* const PNOGROUPINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border"); - static auto* const PGROUPACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_active"); - static auto* const PGROUPINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive"); - static auto* const PGROUPACTIVELOCKEDCOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active"); - static auto* const PGROUPINACTIVELOCKEDCOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive"); - static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity"); - static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity"); - static auto* const PFULLSCREENALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity"); - static auto* const PSHADOWCOL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:col.shadow"); - static auto* const PSHADOWCOLINACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive"); - static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength"); - static auto* const PDIMENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_inactive"); + static auto PACTIVECOL = CConfigValue("general:col.active_border"); + static auto PINACTIVECOL = CConfigValue("general:col.inactive_border"); + static auto PNOGROUPACTIVECOL = CConfigValue("general:col.nogroup_border_active"); + static auto PNOGROUPINACTIVECOL = CConfigValue("general:col.nogroup_border"); + static auto PGROUPACTIVECOL = CConfigValue("group:col.border_active"); + static auto PGROUPINACTIVECOL = CConfigValue("group:col.border_inactive"); + static auto PGROUPACTIVELOCKEDCOL = CConfigValue("group:col.border_locked_active"); + static auto PGROUPINACTIVELOCKEDCOL = CConfigValue("group:col.border_locked_inactive"); + static auto PINACTIVEALPHA = CConfigValue("decoration:inactive_opacity"); + static auto PACTIVEALPHA = CConfigValue("decoration:active_opacity"); + static auto PFULLSCREENALPHA = CConfigValue("decoration:fullscreen_opacity"); + static auto PSHADOWCOL = CConfigValue("decoration:col.shadow"); + static auto PSHADOWCOLINACTIVE = CConfigValue("decoration:col.shadow_inactive"); + static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); + static auto PDIMENABLED = CConfigValue("decoration:dim_inactive"); - auto* const ACTIVECOL = (CGradientValueData*)(*PACTIVECOL)->getData(); - auto* const INACTIVECOL = (CGradientValueData*)(*PINACTIVECOL)->getData(); - auto* const NOGROUPACTIVECOL = (CGradientValueData*)(*PNOGROUPACTIVECOL)->getData(); - auto* const NOGROUPINACTIVECOL = (CGradientValueData*)(*PNOGROUPINACTIVECOL)->getData(); - auto* const GROUPACTIVECOL = (CGradientValueData*)(*PGROUPACTIVECOL)->getData(); - auto* const GROUPINACTIVECOL = (CGradientValueData*)(*PGROUPINACTIVECOL)->getData(); - auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)(*PGROUPACTIVELOCKEDCOL)->getData(); - auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)(*PGROUPINACTIVELOCKEDCOL)->getData(); + auto* const ACTIVECOL = (CGradientValueData*)(PACTIVECOL.ptr())->getData(); + auto* const INACTIVECOL = (CGradientValueData*)(PINACTIVECOL.ptr())->getData(); + auto* const NOGROUPACTIVECOL = (CGradientValueData*)(PNOGROUPACTIVECOL.ptr())->getData(); + auto* const NOGROUPINACTIVECOL = (CGradientValueData*)(PNOGROUPINACTIVECOL.ptr())->getData(); + auto* const GROUPACTIVECOL = (CGradientValueData*)(PGROUPACTIVECOL.ptr())->getData(); + auto* const GROUPINACTIVECOL = (CGradientValueData*)(PGROUPINACTIVECOL.ptr())->getData(); + auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)(PGROUPACTIVELOCKEDCOL.ptr())->getData(); + auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)(PGROUPINACTIVELOCKEDCOL.ptr())->getData(); - auto setBorderColor = [&](CGradientValueData grad) -> void { + auto setBorderColor = [&](CGradientValueData grad) -> void { if (grad == pWindow->m_cRealBorderColor) return; @@ -1952,31 +1945,31 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { // opacity const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) { - pWindow->m_fActiveInactiveAlpha = **PFULLSCREENALPHA; + pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA; } else { if (pWindow == m_pLastWindow) pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alpha.toUnderlying() : - pWindow->m_sSpecialRenderData.alpha.toUnderlying() * **PACTIVEALPHA; + pWindow->m_sSpecialRenderData.alpha.toUnderlying() * *PACTIVEALPHA; else pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() != -1 ? (pWindow->m_sSpecialRenderData.alphaInactiveOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() : - pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * **PINACTIVEALPHA) : - **PINACTIVEALPHA; + pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * *PINACTIVEALPHA) : + *PINACTIVEALPHA; } // dim - if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !**PDIMENABLED) { + if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !*PDIMENABLED) { pWindow->m_fDimPercent = 0; } else { - pWindow->m_fDimPercent = **PDIMSTRENGTH; + pWindow->m_fDimPercent = *PDIMSTRENGTH; } // shadow if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) { if (pWindow == m_pLastWindow) { - pWindow->m_cRealShadowColor = CColor(**PSHADOWCOL); + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); } else { - pWindow->m_cRealShadowColor = CColor(**PSHADOWCOLINACTIVE != INT_MAX ? **PSHADOWCOLINACTIVE : **PSHADOWCOL); + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); } } else { pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow @@ -2023,7 +2016,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) // additionally, move floating and fs windows manually if (w->m_bIsFloating) - w->m_vRealPosition = w->m_vRealPosition.vec() - pMonitorA->vecPosition + pMonitorB->vecPosition; + w->m_vRealPosition = w->m_vRealPosition.value() - pMonitorA->vecPosition + pMonitorB->vecPosition; if (w->m_bIsFullscreen) { w->m_vRealPosition = pMonitorB->vecPosition; @@ -2048,7 +2041,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) // additionally, move floating and fs windows manually if (w->m_bIsFloating) - w->m_vRealPosition = w->m_vRealPosition.vec() - pMonitorB->vecPosition + pMonitorA->vecPosition; + w->m_vRealPosition = w->m_vRealPosition.value() - pMonitorB->vecPosition + pMonitorA->vecPosition; if (w->m_bIsFullscreen) { w->m_vRealPosition = pMonitorA->vecPosition; @@ -2062,6 +2055,9 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) pMonitorA->activeWorkspace = PWORKSPACEB->m_iID; pMonitorB->activeWorkspace = PWORKSPACEA->m_iID; + PWORKSPACEA->rememberPrevWorkspace(PWORKSPACEB); + PWORKSPACEB->rememberPrevWorkspace(PWORKSPACEA); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorA->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorB->ID); @@ -2076,8 +2072,10 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) // event g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName}); + g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEA->m_iID, PWORKSPACEA->m_szName, pMonitorB->szName)}); EMIT_HOOK_EVENT("moveWorkspace", (std::vector{PWORKSPACEA, pMonitorB})); g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEB->m_szName + "," + pMonitorA->szName}); + g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEB->m_iID, PWORKSPACEB->m_szName, pMonitorA->szName)}); EMIT_HOOK_EVENT("moveWorkspace", (std::vector{PWORKSPACEB, pMonitorA})); } @@ -2170,7 +2168,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni // fix old mon int nextWorkspaceOnMonitorID = -1; - if (!SWITCHINGISACTIVE || !POLDMON) + if (!SWITCHINGISACTIVE) nextWorkspaceOnMonitorID = pWorkspace->m_iID; else { for (auto& w : m_vWorkspaces) { @@ -2215,14 +2213,14 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni if (w->m_bIsMapped && !w->isHidden()) { if (POLDMON) { if (w->m_bIsFloating) - w->m_vRealPosition = w->m_vRealPosition.vec() - POLDMON->vecPosition + pMonitor->vecPosition; + w->m_vRealPosition = w->m_vRealPosition.value() - POLDMON->vecPosition + pMonitor->vecPosition; if (w->m_bIsFullscreen) { w->m_vRealPosition = pMonitor->vecPosition; w->m_vRealSize = pMonitor->vecSize; } } else { - w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goalv().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goalv().y % (int)pMonitor->vecSize.y}; + w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goal().y % (int)pMonitor->vecSize.y}; } } @@ -2258,6 +2256,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni // event g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName}); + g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", pWorkspace->m_iID, pWorkspace->m_szName, pMonitor->szName)}); EMIT_HOOK_EVENT("moveWorkspace", (std::vector{pWorkspace, pMonitor})); } @@ -2298,7 +2297,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(CWorkspace* pWorkspace) { const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID); - if (pWorkspace->m_iID == PMONITOR->activeWorkspace) { + if (pWorkspace->m_iID == PMONITOR->activeWorkspace || pWorkspace->m_iID == PMONITOR->specialWorkspaceID) { for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { if (!ls->fadingOut) ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f; @@ -2315,6 +2314,11 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode return; } + if (pWindow->m_bIsFullscreen == on) { + Debug::log(LOG, "Window is already in the required fullscreen state"); + return; + } + const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID); const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID); @@ -2339,7 +2343,7 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode } updateFullscreenFadeOnWorkspace(PWORKSPACE); - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true); + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal(), true); forceReportSizesToWindowsOnWorkspace(pWindow->m_iWorkspaceID); @@ -2462,9 +2466,9 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { // warpCursorTo should only be used for warps that // should be disabled with no_cursor_warps - static auto* const PNOWARPS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_cursor_warps"); + static auto PNOWARPS = CConfigValue("general:no_cursor_warps"); - if (**PNOWARPS && !force) + if (*PNOWARPS && !force) return; if (!m_sSeat.mouse) @@ -2578,7 +2582,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { for (auto& w : m_vWindows) { if (w->m_iWorkspaceID == wid && w->m_bIsMapped && !w->isHidden()) { - g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.vec(), true); + g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.value(), true); } } } @@ -2594,10 +2598,7 @@ CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, con const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2; - const auto PWORKSPACE = m_vWorkspaces.emplace_back(std::make_unique(monID, NAME, SPECIAL)).get(); - - PWORKSPACE->m_iID = id; - PWORKSPACE->m_iMonitorID = monID; + const auto PWORKSPACE = m_vWorkspaces.emplace_back(std::make_unique(id, monID, NAME, SPECIAL)).get(); PWORKSPACE->m_fAlpha.setValueAndWarp(0); @@ -2668,9 +2669,6 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); pWindow->moveToWorkspace(pWorkspace->m_iID); - pWindow->updateToplevel(); - pWindow->updateDynamicRules(); - pWindow->uncacheWindowDecos(); if (!pWindow->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); @@ -2679,7 +2677,7 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); } else { const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto POSTOMON = pWindow->m_vRealPosition.goalv() - PWINDOWMONITOR->vecPosition; + const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); @@ -2689,6 +2687,10 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; } + pWindow->updateToplevel(); + pWindow->updateDynamicRules(); + pWindow->uncacheWindowDecos(); + if (pWindow->m_sGroupData.pNextWindow) { CWindow* next = pWindow->m_sGroupData.pNextWindow; while (next != pWindow) { @@ -2776,9 +2778,9 @@ void CCompositor::arrangeMonitors() { for (auto& m : m_vMonitors) { Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {:.2f}]", m->szName, maxOffset, 0.f); m->vecXWaylandPosition = {maxOffset, 0}; - maxOffset += (**PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x); + maxOffset += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x); - if (**PXWLFORCESCALEZERO) + if (*PXWLFORCESCALEZERO) m->xwaylandScale = m->scale; else m->xwaylandScale = 1.f; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index c08a5931..84667656 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -21,7 +21,7 @@ #include "debug/HyprDebugOverlay.hpp" #include "debug/HyprNotificationOverlay.hpp" #include "helpers/Monitor.hpp" -#include "helpers/Workspace.hpp" +#include "desktop/Workspace.hpp" #include "Window.hpp" #include "render/Renderer.hpp" #include "render/OpenGL.hpp" @@ -57,7 +57,6 @@ class CCompositor { wlr_layer_shell_v1* m_sWLRLayerShell; wlr_xdg_shell* m_sWLRXDGShell; wlr_cursor* m_sWLRCursor; - wlr_xcursor_manager* m_sWLRXCursorMgr; wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr; wlr_output_manager_v1* m_sWLROutputMgr; wlr_presentation* m_sWLRPresentation; @@ -93,9 +92,7 @@ class CCompositor { std::vector> m_vMonitors; std::vector> m_vRealMonitors; // for all monitors, even those turned off std::vector> m_vWindows; - std::vector> m_vXDGPopups; std::vector> m_vWorkspaces; - std::vector> m_vSubsurfaces; std::vector m_vWindowsFadingOut; std::vector m_vSurfacesFadingOut; @@ -143,7 +140,6 @@ class CCompositor { Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*); CMonitor* getMonitorFromOutput(wlr_output*); CMonitor* getRealMonitorFromOutput(wlr_output*); - CWindow* getWindowForPopup(wlr_xdg_popup*); CWindow* getWindowFromSurface(wlr_surface*); CWindow* getWindowFromHandle(uint32_t); CWindow* getWindowFromZWLRHandle(wl_resource*); @@ -169,7 +165,6 @@ class CCompositor { int getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); - CWindow* getConstraintWindow(SMouse*); CMonitor* getMonitorInDirection(const char&); CMonitor* getMonitorInDirection(CMonitor*, const char&); void updateAllWindowsAnimatedDecorationValues(); @@ -180,7 +175,7 @@ class CCompositor { void swapActiveWorkspaces(CMonitor*, CMonitor*); CMonitor* getMonitorFromString(const std::string&); bool workspaceIDOutOfBounds(const int64_t&); - void setWindowFullscreen(CWindow*, bool, eFullscreenMode); + void setWindowFullscreen(CWindow*, bool, eFullscreenMode mode = FULLSCREEN_INVALID); void updateFullscreenFadeOnWorkspace(CWorkspace*); CWindow* getX11Parent(CWindow*); void scheduleFrameForMonitor(CMonitor*); @@ -237,4 +232,7 @@ inline std::map HYPRATOMS = {HYPRATOM("_NET_WM_WINDOW_T HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"), HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"), HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION"), - HYPRATOM("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE")}; + HYPRATOM("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"), + HYPRATOM("_NET_SUPPORTING_WM_CHECK"), + HYPRATOM("_NET_WM_NAME"), + HYPRATOM("UTF8_STRING")}; diff --git a/src/Window.cpp b/src/Window.cpp index ece5b658..06b71763 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -3,16 +3,17 @@ #include "render/decorations/CHyprDropShadowDecoration.hpp" #include "render/decorations/CHyprGroupBarDecoration.hpp" #include "render/decorations/CHyprBorderDecoration.hpp" +#include "config/ConfigValue.hpp" CWindow::CWindow() { - m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE); - m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE); - m_fBorderFadeAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER); - m_fBorderAngleAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER); - m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE); - m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE); - m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW); - m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE); + m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE); + m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE); + m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER); + m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER); + m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE); + m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE); + m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW); + m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE); addWindowDeco(std::make_unique(this)); addWindowDeco(std::make_unique(this)); @@ -39,8 +40,8 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { if (m_sAdditionalConfigData.dimAround) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - return {{m_vRealPosition.vec().x - PMONITOR->vecPosition.x, 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)}}; + return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y}, + {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; } SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; @@ -101,8 +102,8 @@ CBox CWindow::getFullWindowBoundingBox() { auto maxExtents = getFullWindowExtents(); - CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y, - m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; + CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y, + m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; return finalBox; } @@ -154,14 +155,14 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { if (properties & FULL_EXTENTS) EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(this, false)); - CBox box = {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y}; + CBox box = {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; box.addExtents(EXTENTS); return box; } CBox CWindow::getWindowMainSurfaceBox() { - return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y}; + return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; } SWindowDecorationExtents CWindow::getFullWindowReservedArea() { @@ -193,7 +194,14 @@ void CWindow::updateWindowDecos() { m_vDecosToRemove.clear(); + // make a copy because updateWindow can remove decos. + std::vector decos; + for (auto& wd : m_dWindowDecorations) { + decos.push_back(wd.get()); + } + + for (auto& wd : decos) { wd->updateWindow(this); } } @@ -239,13 +247,12 @@ bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoor pid_t CWindow::getPID() { pid_t PID = -1; if (!m_bIsX11) { - - if (!m_bIsMapped) + if (!m_uSurface.xdg) return -1; wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr); } else { - if (!m_bIsMapped) + if (!m_uSurface.xwayland) return -1; PID = m_uSurface.xwayland->pid; @@ -336,7 +343,7 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) { } void CWindow::updateSurfaceScaleTransformDetails() { - if (!m_bIsMapped || m_bHidden) + if (!m_bIsMapped || m_bHidden || g_pCompositor->m_bUnsafeState) return; const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID); @@ -345,6 +352,9 @@ void CWindow::updateSurfaceScaleTransformDetails() { const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + if (!PNEWMONITOR) + return; + if (PNEWMONITOR != PLASTMONITOR) { if (PLASTMONITOR && PLASTMONITOR->m_bEnabled) wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output); @@ -371,9 +381,9 @@ void CWindow::moveToWorkspace(int workspaceID) { if (m_iWorkspaceID == workspaceID) return; - static auto* const PCLOSEONLASTSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty"); + static auto PCLOSEONLASTSPECIAL = CConfigValue("misc:close_special_on_empty"); - const int OLDWORKSPACE = m_iWorkspaceID; + const int OLDWORKSPACE = m_iWorkspaceID; m_iWorkspaceID = workspaceID; @@ -383,6 +393,7 @@ void CWindow::moveToWorkspace(int workspaceID) { if (PWORKSPACE) { g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", std::format("{:x},{}", (uintptr_t)this, PWORKSPACE->m_szName)}); + g_pEventManager->postEvent(SHyprIPCEvent{"movewindowv2", std::format("{:x},{},{}", (uintptr_t)this, PWORKSPACE->m_iID, PWORKSPACE->m_szName)}); EMIT_HOOK_EVENT("moveWindow", (std::vector{this, PWORKSPACE})); } @@ -392,9 +403,9 @@ void CWindow::moveToWorkspace(int workspaceID) { } // update xwayland coords - g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec()); + g_pXWaylandManager->setWindowSize(this, m_vRealSize.value()); - if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && **PCLOSEONLASTSPECIAL) { + if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && *PCLOSEONLASTSPECIAL) { const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); if (PWS) { @@ -433,11 +444,11 @@ void CWindow::removeDecorationByType(eDecorationType type) { } void unregisterVar(void* ptr) { - ((CAnimatedVariable*)ptr)->unregister(); + ((CBaseAnimatedVariable*)ptr)->unregister(); } void CWindow::onUnmap() { - static auto* const PCLOSEONLASTSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty"); + static auto PCLOSEONLASTSPECIAL = CConfigValue("misc:close_special_on_empty"); if (g_pCompositor->m_pLastWindow == this) g_pCompositor->m_pLastWindow = nullptr; @@ -459,7 +470,7 @@ void CWindow::onUnmap() { hyprListener_unmapWindow.removeCallback(); - if (**PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(m_iWorkspaceID) == 0 && g_pCompositor->isWorkspaceSpecial(m_iWorkspaceID)) { + if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(m_iWorkspaceID) == 0 && g_pCompositor->isWorkspaceSpecial(m_iWorkspaceID)) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID) PMONITOR->setSpecialWorkspace(nullptr); @@ -471,12 +482,17 @@ void CWindow::onUnmap() { PMONITOR->solitaryClient = nullptr; g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); + + if (m_bIsX11) + return; + + m_pSubsurfaceHead.reset(); + m_pPopupHead.reset(); } void CWindow::onMap() { - m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this)); - m_pWLSurface.m_pOwner = this; + m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this), this); // JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped) m_vRealPosition.resetAllCallbacks(); @@ -516,10 +532,16 @@ void CWindow::onMap() { m_bTearingHint = ctrl->pWlrHint->current; break; } + + if (m_bIsX11) + return; + + m_pSubsurfaceHead = std::make_unique(this); + m_pPopupHead = std::make_unique(this); } void CWindow::onBorderAngleAnimEnd(void* ptr) { - const auto PANIMVAR = (CAnimatedVariable*)ptr; + const auto PANIMVAR = (CAnimatedVariable*)ptr; const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle; @@ -673,6 +695,38 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN; else Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE); + } else if (r.szRule.starts_with("maxsize")) { + try { + if (!m_bIsFloating) + return; + const auto VEC = configStringToVector2D(r.szRule.substr(8)); + if (VEC.x < 1 || VEC.y < 1) { + Debug::log(ERR, "Invalid size for maxsize"); + return; + } + + m_sAdditionalConfigData.maxSize = VEC; + m_vRealSize = Vector2D(std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().x, m_vRealSize.goal().x), + std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().y, m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(this, m_vRealSize.goal()); + setHidden(false); + } catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); } + } else if (r.szRule.starts_with("minsize")) { + try { + if (!m_bIsFloating) + return; + const auto VEC = configStringToVector2D(r.szRule.substr(8)); + if (VEC.x < 1 || VEC.y < 1) { + Debug::log(ERR, "Invalid size for minsize"); + return; + } + + m_sAdditionalConfigData.minSize = VEC; + m_vRealSize = Vector2D(std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().x, m_vRealSize.goal().x), + std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().y, m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(this, m_vRealSize.goal()); + setHidden(false); + } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } } } @@ -687,6 +741,8 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.forceNoDim = false; if (!m_sAdditionalConfigData.forceOpaqueOverridden) m_sAdditionalConfigData.forceOpaque = false; + m_sAdditionalConfigData.maxSize = Vector2D(std::numeric_limits::max(), std::numeric_limits::max()); + m_sAdditionalConfigData.minSize = Vector2D(20, 20); m_sAdditionalConfigData.forceNoAnims = false; m_sAdditionalConfigData.animationStyle = std::string(""); m_sAdditionalConfigData.rounding = -1; @@ -716,10 +772,10 @@ bool CWindow::isInCurvedCorner(double x, double y) { return false; // (x0, y0), (x0, y1), ... are the center point of rounding at each corner - double x0 = m_vRealPosition.vec().x + ROUNDING; - double y0 = m_vRealPosition.vec().y + ROUNDING; - double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - ROUNDING; - double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - ROUNDING; + double x0 = m_vRealPosition.value().x + ROUNDING; + double y0 = m_vRealPosition.value().y + ROUNDING; + double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING; + double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING; if (x < x0 && y < y0) { return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; @@ -752,7 +808,7 @@ bool CWindow::hasPopupAt(const Vector2D& pos) { return false; wlr_surface* resultSurf = nullptr; - Vector2D origin = m_vRealPosition.vec(); + Vector2D origin = m_vRealPosition.value(); SExtensionFindingData data = {origin, pos, &resultSurf}; wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data); @@ -891,8 +947,8 @@ void CWindow::setGroupCurrent(CWindow* pWindow) { const bool FULLSCREEN = PCURRENT->m_bIsFullscreen; const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENT->m_iWorkspaceID); - const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goalv(); - const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goalv(); + const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); + const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow; @@ -986,19 +1042,19 @@ void CWindow::updateGroupOutputs() { curr->m_iMonitorID = m_iMonitorID; curr->moveToWorkspace(m_iWorkspaceID); - curr->m_vRealPosition = m_vRealPosition.goalv(); - curr->m_vRealSize = m_vRealSize.goalv(); + curr->m_vRealPosition = m_vRealPosition.goal(); + curr->m_vRealSize = m_vRealSize.goal(); curr = curr->m_sGroupData.pNextWindow; } } Vector2D CWindow::middle() { - return m_vRealPosition.goalv() + m_vRealSize.goalv() / 2.f; + return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f; } bool CWindow::opaque() { - if (m_fAlpha.fl() != 1.f || m_fActiveInactiveAlpha.fl() != 1.f) + if (m_fAlpha.value() != 1.f || m_fActiveInactiveAlpha.value() != 1.f) return false; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); @@ -1006,7 +1062,7 @@ bool CWindow::opaque() { if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall) return false; - if (PWORKSPACE->m_fAlpha.fl() != 1.f) + if (PWORKSPACE->m_fAlpha.value() != 1.f) return false; if (m_bIsX11) @@ -1023,21 +1079,21 @@ bool CWindow::opaque() { } float CWindow::rounding() { - static auto* const PROUNDING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:rounding"); + static auto PROUNDING = CConfigValue("decoration:rounding"); - float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? **PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying(); + float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying(); return m_sSpecialRenderData.rounding ? rounding : 0; } void CWindow::updateSpecialRenderData() { - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); - const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; - bool border = true; + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); + const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; + bool border = true; - static auto* const* PNOBORDERONFLOATING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_border_on_floating"); + static auto PNOBORDERONFLOATING = CConfigValue("general:no_border_on_floating"); - if (m_bIsFloating && **PNOBORDERONFLOATING == 1) + if (m_bIsFloating && *PNOBORDERONFLOATING == 1) border = false; m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(border); @@ -1057,9 +1113,9 @@ int CWindow::getRealBorderSize() { if (m_sSpecialRenderData.borderSize.toUnderlying() != -1) return m_sSpecialRenderData.borderSize.toUnderlying(); - static auto* const* PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size"); + static auto PBORDERSIZE = CConfigValue("general:border_size"); - return **PBORDERSIZE; + return *PBORDERSIZE; } bool CWindow::canBeTorn() { @@ -1081,3 +1137,9 @@ void CWindow::setSuspended(bool suspend) { wlr_xdg_toplevel_set_suspended(m_uSurface.xdg->toplevel, suspend); m_bSuspended = suspend; } + +bool CWindow::visibleOnMonitor(CMonitor* pMonitor) { + CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()}; + + return wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, wbox.pWlr()); +} diff --git a/src/Window.hpp b/src/Window.hpp index f8ba4180..cb4fc057 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -1,13 +1,14 @@ #pragma once #include "defines.hpp" -#include "helpers/SubsurfaceTree.hpp" +#include "desktop/Subsurface.hpp" #include "helpers/AnimatedVariable.hpp" #include "render/decorations/IHyprWindowDecoration.hpp" #include #include "config/ConfigDataValues.hpp" #include "helpers/Vector2D.hpp" -#include "helpers/WLSurface.hpp" +#include "desktop/WLSurface.hpp" +#include "desktop/Popup.hpp" #include "macros.hpp" #include "managers/XWaylandManager.hpp" @@ -141,26 +142,28 @@ struct SWindowSpecialRenderData { }; struct SWindowAdditionalConfigData { - std::string animationStyle = std::string(""); - CWindowOverridableVar rounding = -1; // -1 means no - CWindowOverridableVar forceNoBlur = false; - CWindowOverridableVar forceOpaque = false; - CWindowOverridableVar forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher. - CWindowOverridableVar forceAllowsInput = false; - CWindowOverridableVar forceNoAnims = false; - CWindowOverridableVar forceNoBorder = false; - CWindowOverridableVar forceNoShadow = false; - CWindowOverridableVar forceNoDim = false; - CWindowOverridableVar noFocus = false; - CWindowOverridableVar windowDanceCompat = false; - CWindowOverridableVar noMaxSize = false; - CWindowOverridableVar dimAround = false; - CWindowOverridableVar forceRGBX = false; - CWindowOverridableVar keepAspectRatio = false; - CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one - CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one - CWindowOverridableVar forceTearing = false; - CWindowOverridableVar nearestNeighbor = false; + std::string animationStyle = std::string(""); + CWindowOverridableVar rounding = -1; // -1 means no + CWindowOverridableVar forceNoBlur = false; + CWindowOverridableVar forceOpaque = false; + CWindowOverridableVar forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher. + CWindowOverridableVar forceAllowsInput = false; + CWindowOverridableVar forceNoAnims = false; + CWindowOverridableVar forceNoBorder = false; + CWindowOverridableVar forceNoShadow = false; + CWindowOverridableVar forceNoDim = false; + CWindowOverridableVar noFocus = false; + CWindowOverridableVar windowDanceCompat = false; + CWindowOverridableVar noMaxSize = false; + CWindowOverridableVar maxSize = Vector2D(std::numeric_limits::max(), std::numeric_limits::max()); + CWindowOverridableVar minSize = Vector2D(20, 20); + CWindowOverridableVar dimAround = false; + CWindowOverridableVar forceRGBX = false; + CWindowOverridableVar keepAspectRatio = false; + CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one + CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one + CWindowOverridableVar forceTearing = false; + CWindowOverridableVar nearestNeighbor = false; }; struct SWindowRule { @@ -193,7 +196,6 @@ class CWindow { DYNLISTENER(setTitleWindow); DYNLISTENER(setGeometryX11U); DYNLISTENER(fullscreenWindow); - DYNLISTENER(newPopupXDG); DYNLISTENER(requestMove); DYNLISTENER(requestMinimize); DYNLISTENER(requestMaximize); @@ -209,8 +211,7 @@ class CWindow { DYNLISTENER(ackConfigure); // DYNLISTENER(newSubsurfaceWindow); - CWLSurface m_pWLSurface; - std::list m_lPopupSurfaces; + CWLSurface m_pWLSurface; union { wlr_xdg_surface* xdg; @@ -222,8 +223,8 @@ class CWindow { Vector2D m_vSize = Vector2D(0, 0); // this is the real position and size used to draw the thing - CAnimatedVariable m_vRealPosition; - CAnimatedVariable m_vRealSize; + CAnimatedVariable m_vRealPosition; + CAnimatedVariable m_vRealSize; // for not spamming the protocols Vector2D m_vReportedPosition; @@ -276,18 +277,20 @@ class CWindow { bool m_bWantsInitialFullscreen = false; // bitfield eSuppressEvents - uint64_t m_eSuppressedEvents = SUPPRESS_NONE; + uint64_t m_eSuppressedEvents = SUPPRESS_NONE; - SSurfaceTreeNode* m_pSurfaceTree = nullptr; + // desktop components + std::unique_ptr m_pSubsurfaceHead; + std::unique_ptr m_pPopupHead; // Animated border - CGradientValueData m_cRealBorderColor = {0}; - CGradientValueData m_cRealBorderColorPrevious = {0}; - CAnimatedVariable m_fBorderFadeAnimationProgress; - CAnimatedVariable m_fBorderAngleAnimationProgress; + CGradientValueData m_cRealBorderColor = {0}; + CGradientValueData m_cRealBorderColorPrevious = {0}; + CAnimatedVariable m_fBorderFadeAnimationProgress; + CAnimatedVariable m_fBorderAngleAnimationProgress; // Fade in-out - CAnimatedVariable m_fAlpha; + CAnimatedVariable m_fAlpha; bool m_bFadingOut = false; bool m_bReadyToDelete = false; Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in @@ -321,13 +324,13 @@ class CWindow { std::vector> m_vTransformers; // for alpha - CAnimatedVariable m_fActiveInactiveAlpha; + CAnimatedVariable m_fActiveInactiveAlpha; // animated shadow color - CAnimatedVariable m_cRealShadowColor; + CAnimatedVariable m_cRealShadowColor; // animated tint - CAnimatedVariable m_fDimPercent; + CAnimatedVariable m_fDimPercent; // swallowing CWindow* m_pSwallowed = nullptr; @@ -392,6 +395,7 @@ class CWindow { bool canBeTorn(); bool shouldSendFullscreenState(); void setSuspended(bool suspend); + bool visibleOnMonitor(CMonitor* pMonitor); int getRealBorderSize(); void updateSpecialRenderData(); diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index accc92ab..39c60a5a 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -14,6 +14,8 @@ class ICustomConfigValueData { virtual ~ICustomConfigValueData() = 0; virtual eConfigValueDataTypes getDataType() = 0; + + virtual std::string toString() = 0; }; class CGradientValueData : public ICustomConfigValueData { @@ -51,6 +53,15 @@ class CGradientValueData : public ICustomConfigValueData { return true; } + + virtual std::string toString() { + std::string result; + for (auto& c : m_vColors) { + result += std::format("{:x} ", c.getAsHex()); + } + + result += std::format("{}deg", (int)(m_fAngle * 180.0 / M_PI)); + } }; class CCssGapData : public ICustomConfigValueData { @@ -103,4 +114,8 @@ class CCssGapData : public ICustomConfigValueData { virtual eConfigValueDataTypes getDataType() { return CVD_TYPE_CSS_VALUE; } + + virtual std::string toString() { + return std::format("{} {} {} {}", top, right, bottom, left); + } }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5cb18e0f..89195a27 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -302,140 +302,142 @@ CConfigManager::CConfigManager() { m_pConfig = std::make_unique(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); m_pConfig->addConfigValue("general:sensitivity", {1.0f}); - m_pConfig->addConfigValue("general:apply_sens_to_raw", {0L}); - m_pConfig->addConfigValue("general:border_size", {1L}); - m_pConfig->addConfigValue("general:no_border_on_floating", {0L}); - m_pConfig->addConfigValue("general:border_part_of_window", {1L}); + m_pConfig->addConfigValue("general:apply_sens_to_raw", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); + m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:border_part_of_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"}); m_pConfig->addConfigValue("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"}); - m_pConfig->addConfigValue("general:gaps_workspaces", {0L}); - m_pConfig->addConfigValue("general:cursor_inactive_timeout", {0L}); - m_pConfig->addConfigValue("general:no_cursor_warps", {0L}); - m_pConfig->addConfigValue("general:no_focus_fallback", {0L}); - m_pConfig->addConfigValue("general:resize_on_border", {0L}); - m_pConfig->addConfigValue("general:extend_border_grab_area", {15L}); - m_pConfig->addConfigValue("general:hover_icon_on_border", {1L}); + m_pConfig->addConfigValue("general:gaps_workspaces", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:cursor_inactive_timeout", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:no_cursor_warps", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:no_focus_fallback", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:resize_on_border", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:extend_border_grab_area", Hyprlang::INT{15}); + m_pConfig->addConfigValue("general:hover_icon_on_border", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:layout", {"dwindle"}); - m_pConfig->addConfigValue("general:allow_tearing", {0L}); + m_pConfig->addConfigValue("general:allow_tearing", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:resize_corner", Hyprlang::INT{0}); - m_pConfig->addConfigValue("misc:disable_hyprland_logo", {0L}); - m_pConfig->addConfigValue("misc:disable_splash_rendering", {0L}); - m_pConfig->addConfigValue("misc:col.splash", {0x55ffffffL}); + m_pConfig->addConfigValue("misc:disable_hyprland_logo", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:disable_splash_rendering", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:col.splash", Hyprlang::INT{0x55ffffff}); m_pConfig->addConfigValue("misc:splash_font_family", {"Sans"}); - m_pConfig->addConfigValue("misc:force_default_wallpaper", {-1L}); - m_pConfig->addConfigValue("misc:vfr", {1L}); - m_pConfig->addConfigValue("misc:vrr", {0L}); - m_pConfig->addConfigValue("misc:mouse_move_enables_dpms", {0L}); - m_pConfig->addConfigValue("misc:key_press_enables_dpms", {0L}); - m_pConfig->addConfigValue("misc:always_follow_on_dnd", {1L}); - m_pConfig->addConfigValue("misc:layers_hog_keyboard_focus", {1L}); - m_pConfig->addConfigValue("misc:animate_manual_resizes", {0L}); - m_pConfig->addConfigValue("misc:animate_mouse_windowdragging", {0L}); - m_pConfig->addConfigValue("misc:disable_autoreload", {0L}); - m_pConfig->addConfigValue("misc:enable_swallow", {0L}); + m_pConfig->addConfigValue("misc:force_default_wallpaper", Hyprlang::INT{-1}); + m_pConfig->addConfigValue("misc:vfr", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:vrr", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:mouse_move_enables_dpms", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:key_press_enables_dpms", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:always_follow_on_dnd", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:layers_hog_keyboard_focus", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:animate_manual_resizes", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:animate_mouse_windowdragging", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:disable_autoreload", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:enable_swallow", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:swallow_regex", {STRVAL_EMPTY}); m_pConfig->addConfigValue("misc:swallow_exception_regex", {STRVAL_EMPTY}); - m_pConfig->addConfigValue("misc:focus_on_activate", {0L}); - m_pConfig->addConfigValue("misc:no_direct_scanout", {1L}); - m_pConfig->addConfigValue("misc:hide_cursor_on_touch", {1L}); - m_pConfig->addConfigValue("misc:mouse_move_focuses_monitor", {1L}); - m_pConfig->addConfigValue("misc:render_ahead_of_time", {0L}); - m_pConfig->addConfigValue("misc:render_ahead_safezone", {1L}); + m_pConfig->addConfigValue("misc:focus_on_activate", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:no_direct_scanout", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:hide_cursor_on_touch", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:mouse_move_focuses_monitor", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:render_ahead_of_time", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:render_ahead_safezone", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:cursor_zoom_factor", {1.f}); - m_pConfig->addConfigValue("misc:cursor_zoom_rigid", {0L}); - m_pConfig->addConfigValue("misc:allow_session_lock_restore", {0L}); - m_pConfig->addConfigValue("misc:close_special_on_empty", {1L}); - m_pConfig->addConfigValue("misc:background_color", {0xff111111L}); - m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", {0L}); + m_pConfig->addConfigValue("misc:cursor_zoom_rigid", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:allow_session_lock_restore", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:close_special_on_empty", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:background_color", Hyprlang::INT{0xff111111}); + m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:enable_hyprcursor", Hyprlang::INT{1}); - m_pConfig->addConfigValue("group:insert_after_current", {1L}); - m_pConfig->addConfigValue("group:focus_removed_window", {1L}); - m_pConfig->addConfigValue("group:groupbar:enabled", {1L}); + m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {"Sans"}); - m_pConfig->addConfigValue("group:groupbar:font_size", {8L}); - m_pConfig->addConfigValue("group:groupbar:gradients", {1L}); - m_pConfig->addConfigValue("group:groupbar:height", {14L}); - m_pConfig->addConfigValue("group:groupbar:priority", {3L}); - m_pConfig->addConfigValue("group:groupbar:render_titles", {1L}); - m_pConfig->addConfigValue("group:groupbar:scrolling", {1L}); - m_pConfig->addConfigValue("group:groupbar:text_color", {0xffffffffL}); + m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); + m_pConfig->addConfigValue("group:groupbar:gradients", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:height", Hyprlang::INT{14}); + m_pConfig->addConfigValue("group:groupbar:priority", Hyprlang::INT{3}); + m_pConfig->addConfigValue("group:groupbar:render_titles", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:scrolling", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:text_color", Hyprlang::INT{0xffffffff}); - m_pConfig->addConfigValue("debug:int", {0L}); - m_pConfig->addConfigValue("debug:log_damage", {0L}); - m_pConfig->addConfigValue("debug:overlay", {0L}); - m_pConfig->addConfigValue("debug:damage_blink", {0L}); - m_pConfig->addConfigValue("debug:disable_logs", {1L}); - m_pConfig->addConfigValue("debug:disable_time", {1L}); - m_pConfig->addConfigValue("debug:enable_stdout_logs", {0L}); + m_pConfig->addConfigValue("debug:int", Hyprlang::INT{0}); + m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0}); + m_pConfig->addConfigValue("debug:overlay", Hyprlang::INT{0}); + m_pConfig->addConfigValue("debug:damage_blink", Hyprlang::INT{0}); + m_pConfig->addConfigValue("debug:disable_logs", Hyprlang::INT{1}); + m_pConfig->addConfigValue("debug:disable_time", Hyprlang::INT{1}); + m_pConfig->addConfigValue("debug:enable_stdout_logs", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:damage_tracking", {(Hyprlang::INT)DAMAGE_TRACKING_FULL}); - m_pConfig->addConfigValue("debug:manual_crash", {0L}); - m_pConfig->addConfigValue("debug:suppress_errors", {0L}); - m_pConfig->addConfigValue("debug:watchdog_timeout", {5L}); - m_pConfig->addConfigValue("debug:disable_scale_checks", {0L}); + m_pConfig->addConfigValue("debug:manual_crash", Hyprlang::INT{0}); + m_pConfig->addConfigValue("debug:suppress_errors", Hyprlang::INT{0}); + m_pConfig->addConfigValue("debug:watchdog_timeout", Hyprlang::INT{5}); + m_pConfig->addConfigValue("debug:disable_scale_checks", Hyprlang::INT{0}); - m_pConfig->addConfigValue("decoration:rounding", {0L}); - m_pConfig->addConfigValue("decoration:blur:enabled", {1L}); - m_pConfig->addConfigValue("decoration:blur:size", {8L}); - m_pConfig->addConfigValue("decoration:blur:passes", {1L}); - m_pConfig->addConfigValue("decoration:blur:ignore_opacity", {0L}); - m_pConfig->addConfigValue("decoration:blur:new_optimizations", {1L}); - m_pConfig->addConfigValue("decoration:blur:xray", {0L}); + m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1}); + m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8}); + m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1}); + m_pConfig->addConfigValue("decoration:blur:ignore_opacity", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:blur:new_optimizations", Hyprlang::INT{1}); + m_pConfig->addConfigValue("decoration:blur:xray", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:blur:contrast", {0.8916F}); m_pConfig->addConfigValue("decoration:blur:brightness", {1.0F}); m_pConfig->addConfigValue("decoration:blur:vibrancy", {0.1696F}); m_pConfig->addConfigValue("decoration:blur:vibrancy_darkness", {0.0F}); m_pConfig->addConfigValue("decoration:blur:noise", {0.0117F}); - m_pConfig->addConfigValue("decoration:blur:special", {0L}); - m_pConfig->addConfigValue("decoration:blur:popups", {0L}); + m_pConfig->addConfigValue("decoration:blur:special", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:blur:popups", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:blur:popups_ignorealpha", {0.2F}); m_pConfig->addConfigValue("decoration:active_opacity", {1.F}); m_pConfig->addConfigValue("decoration:inactive_opacity", {1.F}); m_pConfig->addConfigValue("decoration:fullscreen_opacity", {1.F}); - m_pConfig->addConfigValue("decoration:no_blur_on_oversized", {0L}); - m_pConfig->addConfigValue("decoration:drop_shadow", {1L}); - m_pConfig->addConfigValue("decoration:shadow_range", {4L}); - m_pConfig->addConfigValue("decoration:shadow_render_power", {3L}); - m_pConfig->addConfigValue("decoration:shadow_ignore_window", {1L}); + m_pConfig->addConfigValue("decoration:no_blur_on_oversized", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:drop_shadow", Hyprlang::INT{1}); + m_pConfig->addConfigValue("decoration:shadow_range", Hyprlang::INT{4}); + m_pConfig->addConfigValue("decoration:shadow_render_power", Hyprlang::INT{3}); + m_pConfig->addConfigValue("decoration:shadow_ignore_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:shadow_offset", Hyprlang::VEC2{0, 0}); m_pConfig->addConfigValue("decoration:shadow_scale", {1.f}); - m_pConfig->addConfigValue("decoration:col.shadow", {0xee1a1a1aL}); + m_pConfig->addConfigValue("decoration:col.shadow", Hyprlang::INT{0xee1a1a1a}); m_pConfig->addConfigValue("decoration:col.shadow_inactive", {(Hyprlang::INT)INT_MAX}); - m_pConfig->addConfigValue("decoration:dim_inactive", {0L}); + m_pConfig->addConfigValue("decoration:dim_inactive", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:dim_strength", {0.5f}); m_pConfig->addConfigValue("decoration:dim_special", {0.2f}); m_pConfig->addConfigValue("decoration:dim_around", {0.4f}); m_pConfig->addConfigValue("decoration:screen_shader", {STRVAL_EMPTY}); - m_pConfig->addConfigValue("dwindle:pseudotile", {0L}); - m_pConfig->addConfigValue("dwindle:force_split", {0L}); - m_pConfig->addConfigValue("dwindle:permanent_direction_override", {0L}); - m_pConfig->addConfigValue("dwindle:preserve_split", {0L}); + m_pConfig->addConfigValue("dwindle:pseudotile", Hyprlang::INT{0}); + m_pConfig->addConfigValue("dwindle:force_split", Hyprlang::INT{0}); + m_pConfig->addConfigValue("dwindle:permanent_direction_override", Hyprlang::INT{0}); + m_pConfig->addConfigValue("dwindle:preserve_split", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:special_scale_factor", {1.f}); m_pConfig->addConfigValue("dwindle:split_width_multiplier", {1.0f}); - m_pConfig->addConfigValue("dwindle:no_gaps_when_only", {0L}); - m_pConfig->addConfigValue("dwindle:use_active_for_splits", {1L}); + m_pConfig->addConfigValue("dwindle:no_gaps_when_only", Hyprlang::INT{0}); + m_pConfig->addConfigValue("dwindle:use_active_for_splits", Hyprlang::INT{1}); m_pConfig->addConfigValue("dwindle:default_split_ratio", {1.f}); - m_pConfig->addConfigValue("dwindle:smart_split", {0L}); - m_pConfig->addConfigValue("dwindle:smart_resizing", {1L}); + m_pConfig->addConfigValue("dwindle:smart_split", Hyprlang::INT{0}); + m_pConfig->addConfigValue("dwindle:smart_resizing", Hyprlang::INT{1}); m_pConfig->addConfigValue("master:special_scale_factor", {1.f}); m_pConfig->addConfigValue("master:mfact", {0.55f}); - m_pConfig->addConfigValue("master:new_is_master", {1L}); - m_pConfig->addConfigValue("master:always_center_master", {0L}); - m_pConfig->addConfigValue("master:new_on_top", {0L}); - m_pConfig->addConfigValue("master:no_gaps_when_only", {0L}); + m_pConfig->addConfigValue("master:new_is_master", Hyprlang::INT{1}); + m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:orientation", {"left"}); - m_pConfig->addConfigValue("master:inherit_fullscreen", {1L}); - m_pConfig->addConfigValue("master:allow_small_split", {0L}); - m_pConfig->addConfigValue("master:smart_resizing", {1L}); - m_pConfig->addConfigValue("master:drop_at_cursor", {1L}); + m_pConfig->addConfigValue("master:inherit_fullscreen", Hyprlang::INT{1}); + m_pConfig->addConfigValue("master:allow_small_split", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:smart_resizing", Hyprlang::INT{1}); + m_pConfig->addConfigValue("master:drop_at_cursor", Hyprlang::INT{1}); - m_pConfig->addConfigValue("animations:enabled", {1L}); - m_pConfig->addConfigValue("animations:first_launch_animation", {1L}); + m_pConfig->addConfigValue("animations:enabled", Hyprlang::INT{1}); + m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1}); - m_pConfig->addConfigValue("input:follow_mouse", {1L}); - m_pConfig->addConfigValue("input:mouse_refocus", {1L}); - m_pConfig->addConfigValue("input:special_fallthrough", {0L}); + m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:sensitivity", {0.f}); m_pConfig->addConfigValue("input:accel_profile", {STRVAL_EMPTY}); m_pConfig->addConfigValue("input:kb_file", {STRVAL_EMPTY}); @@ -444,65 +446,66 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("input:kb_options", {STRVAL_EMPTY}); m_pConfig->addConfigValue("input:kb_rules", {STRVAL_EMPTY}); m_pConfig->addConfigValue("input:kb_model", {STRVAL_EMPTY}); - m_pConfig->addConfigValue("input:repeat_rate", {25L}); - m_pConfig->addConfigValue("input:repeat_delay", {600L}); - m_pConfig->addConfigValue("input:natural_scroll", {0L}); - m_pConfig->addConfigValue("input:numlock_by_default", {0L}); - m_pConfig->addConfigValue("input:resolve_binds_by_sym", {0L}); - m_pConfig->addConfigValue("input:force_no_accel", {0L}); - m_pConfig->addConfigValue("input:float_switch_override_focus", {1L}); - m_pConfig->addConfigValue("input:left_handed", {0L}); + m_pConfig->addConfigValue("input:repeat_rate", Hyprlang::INT{25}); + m_pConfig->addConfigValue("input:repeat_delay", Hyprlang::INT{600}); + m_pConfig->addConfigValue("input:natural_scroll", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:numlock_by_default", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:resolve_binds_by_sym", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:force_no_accel", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:float_switch_override_focus", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:left_handed", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:scroll_method", {STRVAL_EMPTY}); - m_pConfig->addConfigValue("input:scroll_button", {0L}); - m_pConfig->addConfigValue("input:scroll_button_lock", {0L}); + m_pConfig->addConfigValue("input:scroll_button", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:scroll_button_lock", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:scroll_factor", {1.f}); m_pConfig->addConfigValue("input:scroll_points", {STRVAL_EMPTY}); - m_pConfig->addConfigValue("input:touchpad:natural_scroll", {0L}); - m_pConfig->addConfigValue("input:touchpad:disable_while_typing", {1L}); - m_pConfig->addConfigValue("input:touchpad:clickfinger_behavior", {0L}); + m_pConfig->addConfigValue("input:touchpad:natural_scroll", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:touchpad:disable_while_typing", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:touchpad:clickfinger_behavior", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:touchpad:tap_button_map", {STRVAL_EMPTY}); - m_pConfig->addConfigValue("input:touchpad:middle_button_emulation", {0L}); - m_pConfig->addConfigValue("input:touchpad:tap-to-click", {1L}); - m_pConfig->addConfigValue("input:touchpad:tap-and-drag", {1L}); - m_pConfig->addConfigValue("input:touchpad:drag_lock", {0L}); + m_pConfig->addConfigValue("input:touchpad:middle_button_emulation", Hyprlang::INT{0}); + m_pConfig->addConfigValue("input:touchpad:tap-to-click", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:touchpad:tap-and-drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:touchpad:drag_lock", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:touchpad:scroll_factor", {1.f}); - m_pConfig->addConfigValue("input:touchdevice:transform", {0L}); + m_pConfig->addConfigValue("input:touchdevice:transform", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:touchdevice:output", {"[[Auto]]"}); - m_pConfig->addConfigValue("input:touchdevice:enabled", {1L}); - m_pConfig->addConfigValue("input:tablet:transform", {0L}); + m_pConfig->addConfigValue("input:touchdevice:enabled", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:tablet:transform", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:tablet:output", {STRVAL_EMPTY}); m_pConfig->addConfigValue("input:tablet:region_position", Hyprlang::VEC2{0, 0}); m_pConfig->addConfigValue("input:tablet:region_size", Hyprlang::VEC2{0, 0}); - m_pConfig->addConfigValue("input:tablet:relative_input", {0L}); + m_pConfig->addConfigValue("input:tablet:relative_input", Hyprlang::INT{0}); - m_pConfig->addConfigValue("binds:pass_mouse_when_bound", {0L}); - m_pConfig->addConfigValue("binds:scroll_event_delay", {300L}); - m_pConfig->addConfigValue("binds:workspace_back_and_forth", {0L}); - m_pConfig->addConfigValue("binds:allow_workspace_cycles", {0L}); - m_pConfig->addConfigValue("binds:workspace_center_on", {1L}); - m_pConfig->addConfigValue("binds:focus_preferred_method", {0L}); - m_pConfig->addConfigValue("binds:ignore_group_lock", {0L}); - m_pConfig->addConfigValue("binds:movefocus_cycles_fullscreen", {1L}); + m_pConfig->addConfigValue("binds:pass_mouse_when_bound", Hyprlang::INT{0}); + m_pConfig->addConfigValue("binds:scroll_event_delay", Hyprlang::INT{300}); + m_pConfig->addConfigValue("binds:workspace_back_and_forth", Hyprlang::INT{0}); + m_pConfig->addConfigValue("binds:allow_workspace_cycles", Hyprlang::INT{0}); + m_pConfig->addConfigValue("binds:workspace_center_on", Hyprlang::INT{1}); + m_pConfig->addConfigValue("binds:focus_preferred_method", Hyprlang::INT{0}); + m_pConfig->addConfigValue("binds:ignore_group_lock", Hyprlang::INT{0}); + m_pConfig->addConfigValue("binds:movefocus_cycles_fullscreen", Hyprlang::INT{1}); - m_pConfig->addConfigValue("gestures:workspace_swipe", {0L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_fingers", {3L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_distance", {300L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_invert", {1L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_min_speed_to_force", {30L}); + m_pConfig->addConfigValue("gestures:workspace_swipe", Hyprlang::INT{0}); + m_pConfig->addConfigValue("gestures:workspace_swipe_fingers", Hyprlang::INT{3}); + m_pConfig->addConfigValue("gestures:workspace_swipe_distance", Hyprlang::INT{300}); + m_pConfig->addConfigValue("gestures:workspace_swipe_invert", Hyprlang::INT{1}); + m_pConfig->addConfigValue("gestures:workspace_swipe_min_speed_to_force", Hyprlang::INT{30}); m_pConfig->addConfigValue("gestures:workspace_swipe_cancel_ratio", {0.5f}); - m_pConfig->addConfigValue("gestures:workspace_swipe_create_new", {1L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_direction_lock", {1L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_direction_lock_threshold", {10L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_forever", {0L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_numbered", {0L}); - m_pConfig->addConfigValue("gestures:workspace_swipe_use_r", {0L}); + m_pConfig->addConfigValue("gestures:workspace_swipe_create_new", Hyprlang::INT{1}); + m_pConfig->addConfigValue("gestures:workspace_swipe_direction_lock", Hyprlang::INT{1}); + m_pConfig->addConfigValue("gestures:workspace_swipe_direction_lock_threshold", Hyprlang::INT{10}); + m_pConfig->addConfigValue("gestures:workspace_swipe_forever", Hyprlang::INT{0}); + m_pConfig->addConfigValue("gestures:workspace_swipe_numbered", Hyprlang::INT{0}); + m_pConfig->addConfigValue("gestures:workspace_swipe_use_r", Hyprlang::INT{0}); - m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", {1L}); - m_pConfig->addConfigValue("xwayland:force_zero_scaling", {0L}); + m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", Hyprlang::INT{1}); + m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0}); - m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", {1L}); - m_pConfig->addConfigValue("opengl:force_introspection", {2L}); + m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); + m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2}); - m_pConfig->addConfigValue("autogenerated", {0L}); + m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:col.active_border", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0xffffffff"}); m_pConfig->addConfigValue("general:col.inactive_border", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0xff444444"}); @@ -529,29 +532,29 @@ CConfigManager::CConfigManager() { m_pConfig->addSpecialConfigValue("device", "kb_options", {STRVAL_EMPTY}); m_pConfig->addSpecialConfigValue("device", "kb_rules", {STRVAL_EMPTY}); m_pConfig->addSpecialConfigValue("device", "kb_model", {STRVAL_EMPTY}); - m_pConfig->addSpecialConfigValue("device", "repeat_rate", {25L}); - m_pConfig->addSpecialConfigValue("device", "repeat_delay", {600L}); - m_pConfig->addSpecialConfigValue("device", "natural_scroll", {0L}); + m_pConfig->addSpecialConfigValue("device", "repeat_rate", Hyprlang::INT{25}); + m_pConfig->addSpecialConfigValue("device", "repeat_delay", Hyprlang::INT{600}); + m_pConfig->addSpecialConfigValue("device", "natural_scroll", Hyprlang::INT{0}); m_pConfig->addSpecialConfigValue("device", "tap_button_map", {STRVAL_EMPTY}); - m_pConfig->addSpecialConfigValue("device", "numlock_by_default", {0L}); - m_pConfig->addSpecialConfigValue("device", "resolve_binds_by_sym", {0L}); - m_pConfig->addSpecialConfigValue("device", "disable_while_typing", {1L}); - m_pConfig->addSpecialConfigValue("device", "clickfinger_behavior", {0L}); - m_pConfig->addSpecialConfigValue("device", "middle_button_emulation", {0L}); - m_pConfig->addSpecialConfigValue("device", "tap-to-click", {1L}); - m_pConfig->addSpecialConfigValue("device", "tap-and-drag", {1L}); - m_pConfig->addSpecialConfigValue("device", "drag_lock", {0L}); - m_pConfig->addSpecialConfigValue("device", "left_handed", {0L}); + m_pConfig->addSpecialConfigValue("device", "numlock_by_default", Hyprlang::INT{0}); + m_pConfig->addSpecialConfigValue("device", "resolve_binds_by_sym", Hyprlang::INT{0}); + m_pConfig->addSpecialConfigValue("device", "disable_while_typing", Hyprlang::INT{1}); + m_pConfig->addSpecialConfigValue("device", "clickfinger_behavior", Hyprlang::INT{0}); + m_pConfig->addSpecialConfigValue("device", "middle_button_emulation", Hyprlang::INT{0}); + m_pConfig->addSpecialConfigValue("device", "tap-to-click", Hyprlang::INT{1}); + m_pConfig->addSpecialConfigValue("device", "tap-and-drag", Hyprlang::INT{1}); + m_pConfig->addSpecialConfigValue("device", "drag_lock", Hyprlang::INT{0}); + m_pConfig->addSpecialConfigValue("device", "left_handed", Hyprlang::INT{0}); m_pConfig->addSpecialConfigValue("device", "scroll_method", {STRVAL_EMPTY}); - m_pConfig->addSpecialConfigValue("device", "scroll_button", {0L}); - m_pConfig->addSpecialConfigValue("device", "scroll_button_lock", {0L}); + m_pConfig->addSpecialConfigValue("device", "scroll_button", Hyprlang::INT{0}); + m_pConfig->addSpecialConfigValue("device", "scroll_button_lock", Hyprlang::INT{0}); m_pConfig->addSpecialConfigValue("device", "scroll_points", {STRVAL_EMPTY}); - m_pConfig->addSpecialConfigValue("device", "transform", {0L}); + m_pConfig->addSpecialConfigValue("device", "transform", Hyprlang::INT{0}); m_pConfig->addSpecialConfigValue("device", "output", {STRVAL_EMPTY}); - m_pConfig->addSpecialConfigValue("device", "enabled", {1L}); // only for mice, touchpads, and touchdevices + m_pConfig->addSpecialConfigValue("device", "enabled", Hyprlang::INT{1}); // only for mice, touchpads, and touchdevices m_pConfig->addSpecialConfigValue("device", "region_position", Hyprlang::VEC2{0, 0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "region_size", Hyprlang::VEC2{0, 0}); // only for tablets - m_pConfig->addSpecialConfigValue("device", "relative_input", {0L}); // only for tablets + m_pConfig->addSpecialConfigValue("device", "relative_input", Hyprlang::INT{0}); // only for tablets // keywords m_pConfig->registerHandler(&::handleRawExec, "exec", {false}); @@ -617,6 +620,7 @@ void CConfigManager::setDefaultAnimationVars() { if (isFirstLaunch) { INITANIMCFG("global"); INITANIMCFG("windows"); + INITANIMCFG("layers"); INITANIMCFG("fade"); INITANIMCFG("border"); INITANIMCFG("borderangle"); @@ -644,6 +648,7 @@ void CConfigManager::setDefaultAnimationVars() { animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr}; CREATEANIMCFG("windows", "global"); + CREATEANIMCFG("layers", "global"); CREATEANIMCFG("fade", "global"); CREATEANIMCFG("border", "global"); CREATEANIMCFG("borderangle", "global"); @@ -658,6 +663,7 @@ void CConfigManager::setDefaultAnimationVars() { CREATEANIMCFG("fadeSwitch", "fade"); CREATEANIMCFG("fadeShadow", "fade"); CREATEANIMCFG("fadeDim", "fade"); + CREATEANIMCFG("fadeLayers", "fade"); CREATEANIMCFG("specialWorkspace", "workspaces"); } @@ -942,8 +948,8 @@ SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) { return *IT; } -std::vector CConfigManager::getMatchingRules(CWindow* pWindow, bool dynamic) { - if (!g_pCompositor->windowValidMapped(pWindow)) +std::vector CConfigManager::getMatchingRules(CWindow* pWindow, bool dynamic, bool shadowExec) { + if (!g_pCompositor->windowExists(pWindow)) return std::vector(); std::vector returns; @@ -1090,7 +1096,7 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow, bool } } - if (anyExecFound) // remove exec rules to unclog searches in the future, why have the garbage here. + if (anyExecFound && !shadowExec) // remove exec rules to unclog searches in the future, why have the garbage here. execRequestedRules.erase(std::remove_if(execRequestedRules.begin(), execRequestedRules.end(), [&](const SExecRequestedRule& other) { return std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == other.iPid; }); })); @@ -1228,9 +1234,9 @@ void CConfigManager::ensureMonitorStatus() { } void CConfigManager::ensureVRR(CMonitor* pMonitor) { - static auto* const PVRR = reinterpret_cast(getConfigValuePtr("misc:vrr")); + static auto PVRR = reinterpret_cast(getConfigValuePtr("misc:vrr")); - static auto ensureVRRForDisplay = [&](CMonitor* m) -> void { + static auto ensureVRRForDisplay = [&](CMonitor* m) -> void { if (!m->output || m->createdByUser) return; @@ -1547,6 +1553,8 @@ std::optional CConfigManager::handleMonitor(const std::string& comm return {}; } + std::string error = ""; + if (ARGS[1].starts_with("pref")) { newrule.resolution = Vector2D(); } else if (ARGS[1].starts_with("highrr")) { @@ -1557,30 +1565,43 @@ std::optional CConfigManager::handleMonitor(const std::string& comm newrule.resolution = Vector2D(newrule.drmMode.hdisplay, newrule.drmMode.vdisplay); newrule.refreshRate = newrule.drmMode.vrefresh / 1000; } else { - newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x'))); - newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@'))); - if (ARGS[1].contains("@")) - newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1)); + if (!ARGS[1].contains("x")) { + error += "invalid resolution "; + newrule.resolution = Vector2D(); + } else { + newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x'))); + newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@'))); + + if (ARGS[1].contains("@")) + newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1)); + } } if (ARGS[2].starts_with("auto")) { newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX); } else { - newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x'))); - newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1)); + if (!ARGS[2].contains("x")) { + error += "invalid offset "; + newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX); + } else { + newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x'))); + newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1)); + } } - std::string error = ""; - if (ARGS[3].starts_with("auto")) { newrule.scale = -1; } else { - newrule.scale = stof(ARGS[3]); + if (!isNumber(ARGS[3], true)) + error += "invalid scale "; + else { + newrule.scale = stof(ARGS[3]); - if (newrule.scale < 0.25f) { - error = "invalid scale"; - newrule.scale = 1; + if (newrule.scale < 0.25f) { + error += "invalid scale "; + newrule.scale = 1; + } } } @@ -1594,9 +1615,29 @@ std::optional CConfigManager::handleMonitor(const std::string& comm newrule.enable10bit = ARGS[argno + 1] == "10"; argno++; } else if (ARGS[argno] == "transform") { + if (!isNumber(ARGS[argno + 1])) { + error = "invalid transform "; + argno++; + continue; + } + + const auto NUM = std::stoi(ARGS[argno + 1]); + + if (NUM < 0 || NUM > 7) { + error = "invalid transform "; + argno++; + continue; + } + newrule.transform = (wl_output_transform)std::stoi(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "vrr") { + if (!isNumber(ARGS[argno + 1])) { + error = "invalid vrr "; + argno++; + continue; + } + newrule.vrr = std::stoi(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "workspace") { @@ -1729,6 +1770,17 @@ std::optional CConfigManager::handleAnimation(const std::string& co return {}; } +SParsedKey parseKey(const std::string& key) { + if (isNumber(key) && std::stoi(key) > 9) + return {.keycode = std::stoi(key)}; + else if (key.starts_with("code:") && isNumber(key.substr(5))) + return {.keycode = std::stoi(key.substr(5))}; + else if (key == "catchall") + return {.catchAll = true}; + else + return {.key = key}; +} + std::optional CConfigManager::handleBind(const std::string& command, const std::string& value) { // example: // bind[fl]=SUPER,G,exec,dmenu_run @@ -1804,14 +1856,15 @@ std::optional CConfigManager::handleBind(const std::string& command } if (KEY != "") { - if (isNumber(KEY) && std::stoi(KEY) > 9) - g_pKeybindManager->addKeybind( - SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); - else if (KEY.starts_with("code:") && isNumber(KEY.substr(5))) - g_pKeybindManager->addKeybind( - SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); - else - g_pKeybindManager->addKeybind(SKeybind{KEY, 0, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); + SParsedKey parsedKey = parseKey(KEY); + + if (parsedKey.catchAll && m_szCurrentSubmap == "") { + Debug::log(ERR, "Catchall not allowed outside of submap!"); + return "Invalid catchall, catchall keybinds are only allowed in submaps."; + } + + g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, parsedKey.keycode, parsedKey.catchAll, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, + nonConsuming, transparent, ignoreMods}); } return {}; @@ -1822,7 +1875,7 @@ std::optional CConfigManager::handleUnbind(const std::string& comma const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]); - const auto KEY = ARGS[1]; + const auto KEY = parseKey(ARGS[1]); g_pKeybindManager->removeKeybind(MOD, KEY); @@ -1840,7 +1893,7 @@ bool windowRuleValid(const std::string& RULE) { } bool layerRuleValid(const std::string& RULE) { - return RULE == "noanim" || RULE == "blur" || RULE.starts_with("ignorealpha") || RULE.starts_with("ignorezero") || RULE.starts_with("xray"); + return RULE == "noanim" || RULE == "blur" || RULE.starts_with("ignorealpha") || RULE.starts_with("ignorezero") || RULE.starts_with("xray") || RULE.starts_with("animation"); } std::optional CConfigManager::handleWindowRule(const std::string& command, const std::string& value) { @@ -2226,6 +2279,8 @@ std::optional CConfigManager::handleSource(const std::string& comma return err; } + std::string errorsFromParsing; + for (size_t i = 0; i < glob_buf->gl_pathc; i++) { auto value = absolutePath(glob_buf->gl_pathv[i], configCurrentPath); @@ -2251,12 +2306,17 @@ std::optional CConfigManager::handleSource(const std::string& comma auto configCurrentPathBackup = configCurrentPath; configCurrentPath = value; - m_pConfig->parseFile(value.c_str()); + const auto THISRESULT = m_pConfig->parseFile(value.c_str()); configCurrentPath = configCurrentPathBackup; + + if (THISRESULT.error && errorsFromParsing.empty()) + errorsFromParsing += THISRESULT.getError(); } - return {}; + if (errorsFromParsing.empty()) + return {}; + return errorsFromParsing; } std::optional CConfigManager::handleEnv(const std::string& command, const std::string& value) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index fbc61059..2effb644 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -111,7 +111,7 @@ class CConfigManager { std::string getBoundMonitorStringForWS(const std::string&); const std::deque& getAllWorkspaceRules(); - std::vector getMatchingRules(CWindow*, bool dynamic = true); + std::vector getMatchingRules(CWindow*, bool dynamic = true, bool shadowExec = false); std::vector getMatchingRules(SLayerSurface*); std::unordered_map m_mAdditionalReservedAreas; diff --git a/src/config/ConfigValue.hpp b/src/config/ConfigValue.hpp new file mode 100644 index 00000000..6017a7cd --- /dev/null +++ b/src/config/ConfigValue.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include "../debug/Log.hpp" +#include "../macros.hpp" + +template +class CConfigValue { + public: + CConfigValue(const std::string& val) { + const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val.c_str()); + + p_ = PVHYPRLANG->getDataStaticPtr(); + +#ifdef HYPRLAND_DEBUG + // verify type + const auto ANY = PVHYPRLANG->getValue(); + const auto TYPE = std::type_index(ANY.type()); + + // exceptions + const bool STRINGEX = (typeid(T) == typeid(std::string) && TYPE == typeid(Hyprlang::STRING)); + const bool CUSTOMEX = (typeid(T) == typeid(Hyprlang::CUSTOMTYPE) && (TYPE == typeid(Hyprlang::CUSTOMTYPE*) || TYPE == typeid(void*) /* dunno why it does this? */)); + + RASSERT(typeid(T) == TYPE || STRINGEX || CUSTOMEX, "Mismatched type in CConfigValue, got {} but has {}", typeid(T).name(), TYPE.name()); +#endif + } + + T* ptr() const { + return *(T* const*)p_; + } + + T operator*() const { + return *ptr(); + } + + private: + void* const* p_ = nullptr; +}; + +template <> +inline std::string* CConfigValue::ptr() const { + RASSERT(false, "Impossible to implement ptr() of CConfigValue"); + return nullptr; +} + +template <> +inline std::string CConfigValue::operator*() const { + return std::string{*(Hyprlang::STRING*)p_}; +} + +template <> +inline Hyprlang::STRING* CConfigValue::ptr() const { + return (Hyprlang::STRING*)p_; +} + +template <> +inline Hyprlang::STRING CConfigValue::operator*() const { + return *(Hyprlang::STRING*)p_; +} + +template <> +inline Hyprlang::CUSTOMTYPE* CConfigValue::ptr() const { + return *(Hyprlang::CUSTOMTYPE* const*)p_; +} + +template <> +inline Hyprlang::CUSTOMTYPE CConfigValue::operator*() const { + RASSERT(false, "Impossible to implement operator* of CConfigValue, use ptr()"); + return *ptr(); +} \ No newline at end of file diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 6d1d9751..33cdd0eb 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -123,7 +123,7 @@ misc { } # Example per-device config -# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more +# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more device { name = epic-mouse-v1 sensitivity = -0.5 diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index cf648191..a4bdc761 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -108,18 +108,23 @@ void CrashReporter::createAndSaveCrash(int sig) { std::string addrs = ""; for (size_t i = 0; i < CALLSTACK.size(); ++i) { +#ifdef __GLIBC__ // convert in memory address to VMA address Dl_info info; struct link_map* linkMap; dladdr1((void*)CALLSTACK[i].adr, &info, (void**)&linkMap, RTLD_DL_LINKMAP); size_t vmaAddr = (size_t)CALLSTACK[i].adr - linkMap->l_addr; +#else + // musl doesn't define dladdr1 + size_t vmaAddr = (size_t)CALLSTACK[i].adr; +#endif addrs += std::format("0x{:x} ", vmaAddr); } #ifdef __clang__ const auto CMD = std::format("llvm-addr2line -e {} -Cf {}", FPATH.c_str(), addrs); #else - const auto CMD = std::format("addr2line -e {} -Cf {}", FPATH.c_str(), addrs); + const auto CMD = std::format("addr2line -e {} -Cf {}", FPATH.c_str(), addrs); #endif const auto ADDR2LINE = execAndGet(CMD.c_str()); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 8f29ae72..f13843a3 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -15,6 +15,9 @@ #include #include +#include "../config/ConfigValue.hpp" +#include "../managers/CursorManager.hpp" + static void trimTrailingComma(std::string& str) { if (!str.empty() && str.back() == ',') str.pop_back(); @@ -29,6 +32,38 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) { return workspace->m_szName; } +static std::string formatToString(uint32_t drmFormat) { + switch (drmFormat) { + case DRM_FORMAT_XRGB2101010: return "XRGB2101010"; + case DRM_FORMAT_XBGR2101010: return "XBGR2101010"; + case DRM_FORMAT_XRGB8888: return "XRGB8888"; + case DRM_FORMAT_XBGR8888: return "XBGR8888"; + default: break; + } + + return "Invalid"; +} + +static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { + std::string result; + + if (!wl_list_empty(&pMonitor->output->modes)) { + wlr_output_mode* mode; + + wl_list_for_each(mode, &pMonitor->output->modes, link) { + + if (format == FORMAT_NORMAL) + result += std::format("{}x{}@{:.2f}Hz ", mode->width, mode->height, mode->refresh / 1000.0); + else + result += std::format("\"{}x{}@{:.2f}Hz\",", mode->width, mode->height, mode->refresh / 1000.0); + } + + result.pop_back(); + } + + return result; +} + std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { CVarList vars(request, 0, ' '); auto allMonitors = false; @@ -74,7 +109,9 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { "focused": {}, "dpmsStatus": {}, "vrr": {}, - "activelyTearing": {} + "activelyTearing": {}, + "currentFormat": "{}", + "availableModes": [{}] }},)#", m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, @@ -82,7 +119,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), - m->tearingState.activelyTearing ? "true" : "false"); + m->tearingState.activelyTearing ? "true" : "false", formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); } trimTrailingComma(result); @@ -97,13 +134,14 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial " "workspace: {} ({})\n\treserved: {} " "{} {} {}\n\tscale: {:.2f}\n\ttransform: " - "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", + "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, - (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); + (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing, formatToString(m->drmFormat), + availableModesForOutput(m.get(), format)); } } @@ -171,8 +209,8 @@ static std::string getWindowData(CWindow* w, eHyprCtlOutputFormat format) { "swallowing": "0x{:x}", "focusHistoryID": {} }},)#", - (uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, - (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID, + (uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, + (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))), @@ -187,8 +225,8 @@ static std::string getWindowData(CWindow* w, eHyprCtlOutputFormat format) { "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " "{}\n\txwayland: {}\n\tpinned: " "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", - (uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, - (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID, + (uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (int)w->m_vRealSize.goal().x, + (int)w->m_vRealSize.goal().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))), @@ -205,6 +243,9 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { result += "["; for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) + continue; + result += getWindowData(w.get(), format); } @@ -213,6 +254,9 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { result += "]"; } else { for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) + continue; + result += getWindowData(w.get(), format); } } @@ -718,8 +762,8 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { if (kb.nonConsuming) ret += "n"; - ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, kb.key, kb.keycode, kb.handler, - kb.arg); + ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, kb.key, + kb.keycode, kb.catchAll, kb.handler, kb.arg); } } else { // json @@ -737,11 +781,13 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "submap": "{}", "key": "{}", "keycode": {}, + "catch_all": {}, "dispatcher": "{}", "arg": "{}" }},)#", kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false", - kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); + kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false", escapeJSONStrings(kb.handler), + escapeJSONStrings(kb.arg)); } trimTrailingComma(ret); ret += "]"; @@ -877,7 +923,7 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { g_pInputManager->setTabletConfigs(); // update tablets } - static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general:layout"); + static auto PLAYOUT = CConfigValue("general:layout"); if (COMMAND.contains("general:layout")) g_pLayoutManager->switchToLayout(*PLAYOUT); // update layout @@ -1000,16 +1046,7 @@ std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) if (size <= 0) return "size not positive"; - wlr_xcursor_manager_destroy(g_pCompositor->m_sWLRXCursorMgr); - - g_pCompositor->m_sWLRXCursorMgr = wlr_xcursor_manager_create(theme.c_str(), size); - - setenv("XCURSOR_SIZE", SIZESTR.c_str(), true); - setenv("XCURSOR_THEME", theme.c_str(), true); - - for (auto& m : g_pCompositor->m_vMonitors) { - wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, m->scale); - } + g_pCursorManager->changeTheme(theme, size); return "ok"; } @@ -1108,11 +1145,8 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { bool lock = false; - if (vars.size() > 4) { - if (vars[4].starts_with("lock")) { - lock = true; - } - } + if (request.ends_with("lock")) + lock = true; try { if (PROP == "animationstyle") { @@ -1141,6 +1175,22 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "nomaxsize") { PWINDOW->m_sAdditionalConfigData.noMaxSize.forceSetIgnoreLocked(configStringToInt(VAL), lock); + } else if (PROP == "maxsize") { + PWINDOW->m_sAdditionalConfigData.maxSize.forceSetIgnoreLocked(configStringToVector2D(VAL + " " + vars[4]), lock); + if (lock) { + PWINDOW->m_vRealSize = Vector2D(std::min((double)PWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying().x, PWINDOW->m_vRealSize.goal().x), + std::min((double)PWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying().y, PWINDOW->m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->setHidden(false); + } + } else if (PROP == "minsize") { + PWINDOW->m_sAdditionalConfigData.minSize.forceSetIgnoreLocked(configStringToVector2D(VAL + " " + vars[4]), lock); + if (lock) { + PWINDOW->m_vRealSize = Vector2D(std::max((double)PWINDOW->m_sAdditionalConfigData.minSize.toUnderlying().x, PWINDOW->m_vRealSize.goal().x), + std::max((double)PWINDOW->m_sAdditionalConfigData.minSize.toUnderlying().y, PWINDOW->m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->setHidden(false); + } } else if (PROP == "dimaround") { PWINDOW->m_sAdditionalConfigData.dimAround.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "alphaoverride") { @@ -1221,8 +1271,8 @@ std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) return std::format("vec2: [{}, {}]\nset: {}", std::any_cast(VAL).x, std::any_cast(VAL).y, VAR->m_bSetByUser); else if (TYPE == typeid(Hyprlang::STRING)) return std::format("str: {}\nset: {}", std::any_cast(VAL), VAR->m_bSetByUser); - else if (TYPE == typeid(Hyprlang::CUSTOMTYPE*)) - return std::format("custom type at: {:x}\nset: {}", (uintptr_t)std::any_cast(VAL), VAR->m_bSetByUser); + else if (TYPE == typeid(void*)) + return std::format("custom type: {}\nset: {}", ((ICustomConfigValueData*)std::any_cast(VAL))->toString(), VAR->m_bSetByUser); } else { if (TYPE == typeid(Hyprlang::INT)) return std::format("{{\"option\": \"{}\", \"int\": {}, \"set\": {} }}", curitem, std::any_cast(VAL), VAR->m_bSetByUser); @@ -1233,8 +1283,9 @@ std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) VAR->m_bSetByUser); else if (TYPE == typeid(Hyprlang::STRING)) return std::format("{{\"option\": \"{}\", \"str\": \"{}\", \"set\": {} }}", curitem, escapeJSONStrings(std::any_cast(VAL)), VAR->m_bSetByUser); - else if (TYPE == typeid(Hyprlang::CUSTOMTYPE*)) - return std::format("{{\"option\": \"{}\", \"custom\": \"{:x}\", \"set\": {} }}", curitem, (uintptr_t)std::any_cast(VAL), VAR->m_bSetByUser); + else if (TYPE == typeid(void*)) + return std::format("{{\"option\": \"{}\", \"custom\": \"{}\", \"set\": {} }}", curitem, ((ICustomConfigValueData*)std::any_cast(VAL))->toString(), + VAR->m_bSetByUser); } return "invalid type (internal error)"; @@ -1415,17 +1466,49 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { time = std::stoi(TIME); } catch (std::exception& e) { return "invalid arg 2"; } - CColor color = configStringToInt(vars[3]); + CColor color = configStringToInt(vars[3]); - std::string message = ""; + size_t msgidx = 4; + float fontsize = 13.f; + if (vars[msgidx].length() > 9 && vars[msgidx].compare(0, 9, "fontsize:") == 0) { + const auto FONTSIZE = vars[msgidx].substr(9); - for (size_t i = 4; i < vars.size(); ++i) { - message += vars[i] + " "; + if (!isNumber(FONTSIZE, true)) + return "invalid fontsize kwarg"; + + try { + fontsize = std::stoi(FONTSIZE); + } catch (std::exception& e) { return "invalid fontsize karg"; } + + ++msgidx; } - message.pop_back(); + if (vars.size() <= msgidx) + return "not enough args"; - g_pHyprNotificationOverlay->addNotification(message, color, time, (eIcons)icon); + const auto MESSAGE = vars.join(" ", msgidx); + + g_pHyprNotificationOverlay->addNotification(MESSAGE, color, time, (eIcons)icon, fontsize); + + return "ok"; +} + +std::string dispatchDismissNotify(eHyprCtlOutputFormat format, std::string request) { + CVarList vars(request, 0, ' '); + + int amount = -1; + + if (vars.size() > 1) { + const auto AMOUNT = vars[1]; + if (!isNumber(AMOUNT)) + return "invalid arg 1"; + + try { + amount = std::stoi(AMOUNT); + } catch (std::exception& e) { return "invalid arg 1"; } + } + + g_pHyprNotificationOverlay->dismissNotifications(amount); return "ok"; } @@ -1453,6 +1536,7 @@ CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"reload", false, reloadRequest}); registerCommand(SHyprCtlCommand{"plugin", false, dispatchPlugin}); registerCommand(SHyprCtlCommand{"notify", false, dispatchNotify}); + registerCommand(SHyprCtlCommand{"dismissnotify", false, dispatchDismissNotify}); registerCommand(SHyprCtlCommand{"setprop", false, dispatchSetProp}); registerCommand(SHyprCtlCommand{"seterror", false, dispatchSeterror}); registerCommand(SHyprCtlCommand{"switchxkblayout", false, switchXKBLayoutRequest}); @@ -1476,8 +1560,9 @@ void CHyprCtl::unregisterCommand(const std::shared_ptr& cmd) { } std::string CHyprCtl::getReply(std::string request) { - auto format = eHyprCtlOutputFormat::FORMAT_NORMAL; - bool reloadAll = false; + auto format = eHyprCtlOutputFormat::FORMAT_NORMAL; + bool reloadAll = false; + m_sCurrentRequestParams = {}; // process flags for non-batch requests if (!request.starts_with("[[BATCH]]") && request.contains("/")) { @@ -1498,8 +1583,10 @@ std::string CHyprCtl::getReply(std::string request) { if (c == 'j') format = eHyprCtlOutputFormat::FORMAT_JSON; - if (c == 'r') + else if (c == 'r') reloadAll = true; + else if (c == 'a') + m_sCurrentRequestParams.all = true; } if (sepIndex < request.size()) @@ -1541,7 +1628,7 @@ std::string CHyprCtl::getReply(std::string request) { g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs g_pInputManager->setTabletConfigs(); // update tablets - static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general:layout"); + static auto PLAYOUT = CConfigValue("general:layout"); g_pLayoutManager->switchToLayout(*PLAYOUT); // update layout diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 339acd1b..cad57447 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -16,6 +16,10 @@ class CHyprCtl { int m_iSocketFD = -1; + struct { + bool all = false; + } m_sCurrentRequestParams; + private: void startHyprCtlSocket(); diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 2968134b..ced27814 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -36,20 +36,33 @@ CHyprNotificationOverlay::CHyprNotificationOverlay() { m_szIconFontName = fonts.substr(COLON + 2, LASTCHAR - (COLON + 2)); } -void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon) { +void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) { const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique()).get(); PNOTIF->text = text; PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->started.reset(); - PNOTIF->timeMs = timeMs; - PNOTIF->icon = icon; + PNOTIF->timeMs = timeMs; + PNOTIF->icon = icon; + PNOTIF->fontSize = fontSize; for (auto& m : g_pCompositor->m_vMonitors) { g_pCompositor->scheduleFrameForMonitor(m.get()); } } +void CHyprNotificationOverlay::dismissNotifications(const int amount) { + if (amount == -1) + m_dNotifications.clear(); + else { + const int AMT = std::min(amount, static_cast(m_dNotifications.size())); + + for (int i = 0; i < AMT; ++i) { + m_dNotifications.pop_front(); + } + } +} + CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { static constexpr auto ANIM_DURATION_MS = 600.0; static constexpr auto ANIM_LAG_MS = 100.0; @@ -61,28 +74,25 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { float offsetY = 10; float maxWidth = 0; - const auto SCALE = pMonitor->scale; - const auto FONTSIZE = std::clamp((int)(13.f * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40); + const auto SCALE = pMonitor->scale; const auto MONSIZE = pMonitor->vecPixelSize; cairo_text_extents_t cairoExtents; int iconW = 0, iconH = 0; - PangoLayout* pangoLayout; - PangoFontDescription* pangoFD; - - pangoLayout = pango_cairo_create_layout(m_pCairo); - pangoFD = pango_font_description_from_string(("Sans " + std::to_string(FONTSIZE * ICON_SCALE)).c_str()); - pango_layout_set_font_description(pangoLayout, pangoFD); - cairo_select_font_face(m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(m_pCairo, FONTSIZE); const auto PBEZIER = g_pAnimationManager->getBezier("default"); for (auto& notif : m_dNotifications) { - const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD; + const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD; + const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40); + + PangoLayout* pangoLayout = pango_cairo_create_layout(m_pCairo); + PangoFontDescription* pangoFD = pango_font_description_from_string(("Sans " + std::to_string(FONTSIZE * ICON_SCALE)).c_str()); + pango_layout_set_font_description(pangoLayout, pangoFD); + cairo_set_font_size(m_pCairo, FONTSIZE); // first rect (bg, col) const float FIRSTRECTANIMP = @@ -162,10 +172,10 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { if (maxWidth < NOTIFSIZE.x) maxWidth = NOTIFSIZE.x; - } - pango_font_description_free(pangoFD); - g_object_unref(pangoLayout); + pango_font_description_free(pangoFD); + g_object_unref(pangoLayout); + } // cleanup notifs std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; }); diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 7a883f15..5599b71b 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -31,8 +31,9 @@ struct SNotification { std::string text = ""; CColor color; CTimer started; - float timeMs = 0; - eIcons icon = ICON_NONE; + float timeMs = 0; + eIcons icon = ICON_NONE; + float fontSize = 13.f; }; class CHyprNotificationOverlay { @@ -40,7 +41,8 @@ class CHyprNotificationOverlay { CHyprNotificationOverlay(); void draw(CMonitor* pMonitor); - void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE); + void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); + void dismissNotifications(const int amount); bool hasAny(); private: diff --git a/src/desktop/Constraint.cpp b/src/desktop/Constraint.cpp new file mode 100644 index 00000000..662f0990 --- /dev/null +++ b/src/desktop/Constraint.cpp @@ -0,0 +1,123 @@ +#include "Constraint.hpp" +#include "WLSurface.hpp" +#include "../Compositor.hpp" + +CConstraint::CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner) : m_pOwner(owner), m_pConstraint(constraint) { + initSignals(); + + m_vCursorPosOnActivate = g_pInputManager->getMouseCoordsInternal(); + + g_pInputManager->m_vConstraints.push_back(this); + + if (g_pCompositor->m_pLastFocus == m_pOwner->wlr()) + activate(); +} + +CConstraint::~CConstraint() { + std::erase(g_pInputManager->m_vConstraints, this); +} + +static void onConstraintDestroy(void* owner, void* data) { + const auto CONSTRAINT = (CConstraint*)owner; + CONSTRAINT->onDestroy(); +} + +static void onConstraintSetRegion(void* owner, void* data) { + const auto CONSTRAINT = (CConstraint*)owner; + CONSTRAINT->onSetRegion(); +} + +void CConstraint::initSignals() { + hyprListener_setConstraintRegion.initCallback(&m_pConstraint->events.set_region, ::onConstraintSetRegion, this, "CConstraint"); + hyprListener_destroyConstraint.initCallback(&m_pConstraint->events.destroy, ::onConstraintDestroy, this, "CConstraint"); +} + +void CConstraint::onDestroy() { + if (active()) + deactivate(); + + // this is us + m_pOwner->m_pConstraint.reset(); +} + +void CConstraint::onSetRegion() { + if (!m_bActive) + return; + + m_rRegion.set(&m_pConstraint->region); + m_vPositionHint = m_rRegion.closestPoint(m_vPositionHint); + g_pInputManager->simulateMouseMovement(); // to warp the cursor if anything's amiss +} + +void CConstraint::onCommit() { + if (!m_bActive) + return; + + const auto COMMITTED = m_pConstraint->current.committed; + + if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { + m_bHintSet = true; + m_vPositionHint = {m_pConstraint->current.cursor_hint.x, m_pConstraint->current.cursor_hint.y}; + g_pInputManager->simulateMouseMovement(); + } + + if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) + onSetRegion(); +} + +CRegion CConstraint::logicConstraintRegion() { + CRegion rg = m_rRegion; + const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal(); + const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{}; + rg.translate(CONSTRAINTPOS); + return rg; +} + +CWLSurface* CConstraint::owner() { + return m_pOwner; +} + +bool CConstraint::isLocked() { + return m_pConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED; +} + +Vector2D CConstraint::logicPositionHint() { + const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal(); + const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{}; + + return m_bHintSet ? CONSTRAINTPOS + m_vPositionHint : m_vCursorPosOnActivate; +} + +void CConstraint::deactivate() { + if (!m_bActive) + return; + + wlr_pointer_constraint_v1_send_deactivated(m_pConstraint); + m_bActive = false; + + if (isLocked()) + g_pCompositor->warpCursorTo(logicPositionHint(), true); + + if (m_pConstraint->lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT) + m_bDead = true; +} + +void CConstraint::activate() { + if (m_bActive || m_bDead) + return; + + // TODO: hack, probably not a super duper great idea + if (g_pCompositor->m_sSeat.seat->pointer_state.focused_surface != m_pOwner->wlr()) { + const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal(); + const auto LOCAL = SURFBOX.has_value() ? logicPositionHint() - SURFBOX->pos() : Vector2D{}; + wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, m_pOwner->wlr(), LOCAL.x, LOCAL.y); + } + + g_pCompositor->warpCursorTo(logicPositionHint(), true); + wlr_pointer_constraint_v1_send_activated(m_pConstraint); + m_bActive = true; +} + +bool CConstraint::active() { + return m_bActive; +} diff --git a/src/desktop/Constraint.hpp b/src/desktop/Constraint.hpp new file mode 100644 index 00000000..34690217 --- /dev/null +++ b/src/desktop/Constraint.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "../includes.hpp" +#include "../helpers/Region.hpp" +#include "../helpers/WLListener.hpp" + +class CWLSurface; + +class CConstraint { + public: + CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner); + ~CConstraint(); + + void onCommit(); + void onDestroy(); + void onSetRegion(); + CRegion logicConstraintRegion(); + bool isLocked(); + Vector2D logicPositionHint(); + + void deactivate(); + void activate(); + bool active(); + + CWLSurface* owner(); + + private: + bool m_bActive = false; + CWLSurface* m_pOwner = nullptr; + wlr_pointer_constraint_v1* m_pConstraint; + + CRegion m_rRegion; + bool m_bHintSet = false; + Vector2D m_vPositionHint = {-1, -1}; + Vector2D m_vCursorPosOnActivate = {-1, -1}; + + // for oneshot constraints that have been activated once + bool m_bDead = false; + + DYNLISTENER(destroyConstraint); + DYNLISTENER(setConstraintRegion); + + void initSignals(); +}; \ No newline at end of file diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp new file mode 100644 index 00000000..98d5881a --- /dev/null +++ b/src/desktop/Popup.cpp @@ -0,0 +1,247 @@ +#include "Popup.hpp" +#include "../Compositor.hpp" + +CPopup::CPopup(CWindow* pOwner) : m_pWindowOwner(pOwner) { + initAllSignals(); +} + +CPopup::CPopup(SLayerSurface* pOwner) : m_pLayerOwner(pOwner) { + initAllSignals(); +} + +CPopup::CPopup(wlr_xdg_popup* popup, CPopup* pOwner) : m_pParent(pOwner), m_pWLR(popup) { + m_pWLR->base->data = this; + m_sWLSurface.assign(popup->base->surface, this); + + m_pLayerOwner = pOwner->m_pLayerOwner; + m_pWindowOwner = pOwner->m_pWindowOwner; + + m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height}; + unconstrain(); + + initAllSignals(); +} + +CPopup::~CPopup() { + m_sWLSurface.unassign(); + if (m_pWLR) + m_pWLR->base->data = nullptr; + + hyprListener_commitPopup.removeCallback(); + hyprListener_repositionPopup.removeCallback(); + hyprListener_mapPopup.removeCallback(); + hyprListener_unmapPopup.removeCallback(); + hyprListener_newPopup.removeCallback(); + hyprListener_destroyPopup.removeCallback(); +} + +static void onNewPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onNewPopup((wlr_xdg_popup*)data); +} + +static void onMapPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onMap(); +} + +static void onDestroyPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onDestroy(); +} + +static void onUnmapPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onUnmap(); +} + +static void onCommitPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onCommit(); +} + +static void onRepositionPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onReposition(); +} + +void CPopup::initAllSignals() { + + if (!m_pWLR) { + if (m_pWindowOwner) + hyprListener_newPopup.initCallback(&m_pWindowOwner->m_uSurface.xdg->events.new_popup, ::onNewPopup, this, "CPopup Head"); + else if (m_pLayerOwner) + hyprListener_newPopup.initCallback(&m_pLayerOwner->layerSurface->events.new_popup, ::onNewPopup, this, "CPopup Head"); + else + ASSERT(false); + + return; + } + + hyprListener_repositionPopup.initCallback(&m_pWLR->events.reposition, ::onRepositionPopup, this, "CPopup"); + hyprListener_destroyPopup.initCallback(&m_pWLR->events.destroy, ::onDestroyPopup, this, "CPopup"); + hyprListener_mapPopup.initCallback(&m_sWLSurface.wlr()->events.map, ::onMapPopup, this, "CPopup"); + hyprListener_unmapPopup.initCallback(&m_sWLSurface.wlr()->events.unmap, ::onUnmapPopup, this, "CPopup"); + hyprListener_commitPopup.initCallback(&m_sWLSurface.wlr()->events.commit, ::onCommitPopup, this, "CPopup"); + hyprListener_newPopup.initCallback(&m_pWLR->base->events.new_popup, ::onNewPopup, this, "CPopup"); +} + +void CPopup::onNewPopup(wlr_xdg_popup* popup) { + const auto POPUP = m_vChildren.emplace_back(std::make_unique(popup, this)).get(); + Debug::log(LOG, "New popup at wlr {:x} and hl {:x}", (uintptr_t)popup, (uintptr_t)POPUP); +} + +void CPopup::onDestroy() { + m_bInert = true; + + if (!m_pParent) + return; // head node + + std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; }); +} + +void CPopup::onMap() { + m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height}; + const auto COORDS = coordsGlobal(); + + CBox box; + wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr()); + box.applyFromWlr().translate(COORDS).expand(4); + g_pHyprRenderer->damageBox(&box); + + m_vLastPos = coordsRelativeToParent(); + + g_pInputManager->simulateMouseMovement(); + + m_pSubsurfaceHead = std::make_unique(this); + + unconstrain(); + sendScale(); +} + +void CPopup::onUnmap() { + m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height}; + const auto COORDS = coordsGlobal(); + + CBox box; + wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr()); + box.applyFromWlr().translate(COORDS).expand(4); + g_pHyprRenderer->damageBox(&box); + + m_pSubsurfaceHead.reset(); + + g_pInputManager->simulateMouseMovement(); +} + +void CPopup::onCommit(bool ignoreSiblings) { + if (m_pWLR->base->initial_commit) { + wlr_xdg_surface_schedule_configure(m_pWLR->base); + return; + } + + const auto COORDS = coordsGlobal(); + const auto COORDSLOCAL = coordsRelativeToParent(); + + if (m_vLastSize != Vector2D{m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height} || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) { + CBox box = {localToGlobal(m_vLastPos), m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height}; + box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + + m_vLastPos = COORDSLOCAL; + } + + if (!ignoreSiblings) + m_pSubsurfaceHead->recheckDamageForSubsurfaces(); + + g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y); + + m_bRequestedReposition = false; +} + +void CPopup::onReposition() { + Debug::log(LOG, "Popup {:x} requests reposition", (uintptr_t)this); + + m_bRequestedReposition = true; + + m_vLastPos = coordsRelativeToParent(); + + unconstrain(); +} + +void CPopup::unconstrain() { + const auto COORDS = t1ParentCoords(); + const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS); + + if (!PMONITOR) + return; + + CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + wlr_xdg_popup_unconstrain_from_box(m_pWLR, box.pWlr()); +} + +Vector2D CPopup::coordsRelativeToParent() { + Vector2D offset; + + CPopup* current = this; + + offset -= {m_pWLR->base->current.geometry.x, m_pWLR->base->current.geometry.y}; + + while (current->m_pParent) { + + offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; + offset += {current->m_pWLR->current.geometry.x, current->m_pWLR->current.geometry.y}; + + current = current->m_pParent; + } + + return offset; +} + +Vector2D CPopup::coordsGlobal() { + return localToGlobal(coordsRelativeToParent()); +} + +Vector2D CPopup::localToGlobal(const Vector2D& rel) { + return t1ParentCoords() + rel; +} + +Vector2D CPopup::t1ParentCoords() { + if (m_pWindowOwner) + return m_pWindowOwner->m_vRealPosition.value(); + if (m_pLayerOwner) + return m_pLayerOwner->realPosition.value(); + + ASSERT(false); + return {}; +} + +void CPopup::recheckTree() { + CPopup* curr = this; + while (curr->m_pParent) { + curr = curr->m_pParent; + } + + curr->recheckChildrenRecursive(); +} + +void CPopup::recheckChildrenRecursive() { + for (auto& c : m_vChildren) { + c->onCommit(true); + c->recheckChildrenRecursive(); + } +} + +Vector2D CPopup::size() { + return m_vLastSize; +} + +void CPopup::sendScale() { + if (m_pWindowOwner) + g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pWindowOwner->m_pWLSurface.m_fLastScale); + else if (m_pLayerOwner) + g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pLayerOwner->surface.m_fLastScale); + else + UNREACHABLE(); +} diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp new file mode 100644 index 00000000..5f7af085 --- /dev/null +++ b/src/desktop/Popup.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include "Subsurface.hpp" + +struct SLayerSurface; + +class CPopup { + public: + // dummy head nodes + CPopup(CWindow* pOwner); + CPopup(SLayerSurface* pOwner); + + // real nodes + CPopup(wlr_xdg_popup* popup, CPopup* pOwner); + + ~CPopup(); + + Vector2D coordsRelativeToParent(); + Vector2D coordsGlobal(); + + Vector2D size(); + + void onNewPopup(wlr_xdg_popup* popup); + void onDestroy(); + void onMap(); + void onUnmap(); + void onCommit(bool ignoreSiblings = false); + void onReposition(); + + void recheckTree(); + + CWLSurface m_sWLSurface; + + private: + // T1 owners, each popup has to have one of these + CWindow* m_pWindowOwner = nullptr; + SLayerSurface* m_pLayerOwner = nullptr; + + // T2 owners + CPopup* m_pParent = nullptr; + + wlr_xdg_popup* m_pWLR = nullptr; + + Vector2D m_vLastSize = {}; + Vector2D m_vLastPos = {}; + + bool m_bRequestedReposition = false; + + bool m_bInert = false; + + // + std::vector> m_vChildren; + std::unique_ptr m_pSubsurfaceHead; + + // signals + DYNLISTENER(newPopup); + DYNLISTENER(destroyPopup); + DYNLISTENER(mapPopup); + DYNLISTENER(unmapPopup); + DYNLISTENER(commitPopup); + DYNLISTENER(repositionPopup); + + void initAllSignals(); + void unconstrain(); + void recheckChildrenRecursive(); + void sendScale(); + + Vector2D localToGlobal(const Vector2D& rel); + Vector2D t1ParentCoords(); +}; \ No newline at end of file diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp new file mode 100644 index 00000000..c3538ee1 --- /dev/null +++ b/src/desktop/Subsurface.cpp @@ -0,0 +1,243 @@ +#include "Subsurface.hpp" +#include "../events/Events.hpp" +#include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" + +static void onNewSubsurface(void* owner, void* data); + +CSubsurface::CSubsurface(CWindow* pOwner) : m_pWindowParent(pOwner) { + initSignals(); + + wlr_subsurface* wlrSubsurface; + wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_below, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } + wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_above, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } +} + +CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) { + initSignals(); + + wlr_subsurface* wlrSubsurface; + wl_list_for_each(wlrSubsurface, &pOwner->m_sWLSurface.wlr()->current.subsurfaces_below, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } + wl_list_for_each(wlrSubsurface, &pOwner->m_sWLSurface.wlr()->current.subsurfaces_above, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } +} + +CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { + m_sWLSurface.assign(pSubsurface->surface, this); + initSignals(); + initExistingSubsurfaces(); +} + +CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { + m_sWLSurface.assign(pSubsurface->surface, this); + initSignals(); + initExistingSubsurfaces(); +} + +CSubsurface::~CSubsurface() { + hyprListener_newSubsurface.removeCallback(); + + if (!m_pSubsurface) + return; + + hyprListener_commitSubsurface.removeCallback(); + hyprListener_destroySubsurface.removeCallback(); +} + +static void onNewSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onNewSubsurface((wlr_subsurface*)data); +} + +static void onDestroySubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onDestroy(); +} + +static void onCommitSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onCommit(); +} + +static void onMapSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onMap(); +} + +static void onUnmapSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onUnmap(); +} + +void CSubsurface::initSignals() { + if (m_pSubsurface) { + hyprListener_commitSubsurface.initCallback(&m_pSubsurface->surface->events.commit, &onCommitSubsurface, this, "CSubsurface"); + hyprListener_destroySubsurface.initCallback(&m_pSubsurface->events.destroy, &onDestroySubsurface, this, "CSubsurface"); + hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); + hyprListener_mapSubsurface.initCallback(&m_pSubsurface->surface->events.map, &onMapSubsurface, this, "CSubsurface"); + hyprListener_unmapSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface"); + } else { + if (m_pWindowParent) + hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head"); + else if (m_pPopupParent) + hyprListener_newSubsurface.initCallback(&m_pPopupParent->m_sWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head"); + else + RASSERT(false, "CSubsurface::initSignals empty subsurface"); + } +} + +void CSubsurface::checkSiblingDamage() { + if (!m_pParent) + return; // ?????????? + + const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; + + for (auto& n : m_pParent->m_vChildren) { + if (n.get() == this) + continue; + + const auto COORDS = n->coordsGlobal(); + g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + } +} + +void CSubsurface::recheckDamageForSubsurfaces() { + for (auto& n : m_vChildren) { + const auto COORDS = n->coordsGlobal(); + g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y); + } +} + +void CSubsurface::onCommit() { + // no damaging if it's not visible + if (m_pWindowParent && !g_pHyprRenderer->shouldRenderWindow(m_pWindowParent)) { + m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + + static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); + if (*PLOGDAMAGE) + Debug::log(LOG, "Refusing to commit damage from a subsurface of {} because it's invisible.", m_pWindowParent); + return; + } + + const auto COORDS = coordsGlobal(); + + g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y); + + if (m_pPopupParent) + m_pPopupParent->recheckTree(); + if (m_pWindowParent) // I hate you firefox why are you doing this + m_pWindowParent->m_pPopupHead->recheckTree(); + + // I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox) + checkSiblingDamage(); + + if (m_vLastSize != Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}) { + CBox box{COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + } +} + +void CSubsurface::onDestroy() { + // destroy children + m_vChildren.clear(); + + m_bInert = true; + + if (!m_pSubsurface) + return; // dummy node, nothing to do, it's the parent dying + + // kill ourselves + std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; }); +} + +void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) { + CSubsurface* PSUBSURFACE = nullptr; + + if (m_pWindowParent) + PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pWindowParent)).get(); + else if (m_pPopupParent) + PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pPopupParent)).get(); + PSUBSURFACE->m_pParent = this; + + ASSERT(PSUBSURFACE); +} + +void CSubsurface::onMap() { + m_vLastSize = {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + + const auto COORDS = coordsGlobal(); + CBox box{COORDS, m_vLastSize}; + box.expand(4); + g_pHyprRenderer->damageBox(&box); + + if (m_pWindowParent) + m_pWindowParent->updateSurfaceScaleTransformDetails(); +} + +void CSubsurface::onUnmap() { + const auto COORDS = coordsGlobal(); + CBox box{COORDS, m_vLastSize}; + box.expand(4); + g_pHyprRenderer->damageBox(&box); + + if (m_sWLSurface.wlr() == g_pCompositor->m_pLastFocus) + g_pInputManager->releaseAllMouseButtons(); + + g_pInputManager->simulateMouseMovement(); + + // TODO: should this remove children? Currently it won't, only on .destroy +} + +Vector2D CSubsurface::coordsRelativeToParent() { + Vector2D offset; + + CSubsurface* current = this; + + while (current->m_pParent) { + + offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; + offset += {current->m_pSubsurface->current.x, current->m_pSubsurface->current.y}; + + current = current->m_pParent; + } + + return offset; +} + +Vector2D CSubsurface::coordsGlobal() { + Vector2D coords = coordsRelativeToParent(); + + if (m_pWindowParent) + coords += m_pWindowParent->m_vRealPosition.value(); + else if (m_pPopupParent) + coords += m_pPopupParent->coordsGlobal(); + + return coords; +} + +void CSubsurface::initExistingSubsurfaces() { + if (m_pWindowParent) + return; + + wlr_subsurface* wlrSubsurface; + wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_below, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } + wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_above, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } +} + +Vector2D CSubsurface::size() { + return {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; +} diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp new file mode 100644 index 00000000..ca02a6d5 --- /dev/null +++ b/src/desktop/Subsurface.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "../defines.hpp" +#include +#include "WLSurface.hpp" + +class CWindow; +class CPopup; + +class CSubsurface { + public: + // root dummy nodes + CSubsurface(CWindow* pOwner); + CSubsurface(CPopup* pOwner); + + // real nodes + CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner); + CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner); + + ~CSubsurface(); + + Vector2D coordsRelativeToParent(); + Vector2D coordsGlobal(); + + Vector2D size(); + + void onCommit(); + void onDestroy(); + void onNewSubsurface(wlr_subsurface* pSubsurface); + void onMap(); + void onUnmap(); + + void recheckDamageForSubsurfaces(); + + private: + DYNLISTENER(destroySubsurface); + DYNLISTENER(commitSubsurface); + DYNLISTENER(newSubsurface); + DYNLISTENER(mapSubsurface); + DYNLISTENER(unmapSubsurface); + + wlr_subsurface* m_pSubsurface = nullptr; + CWLSurface m_sWLSurface; + Vector2D m_vLastSize = {}; + + // if nullptr, means it's a dummy node + CSubsurface* m_pParent = nullptr; + + CWindow* m_pWindowParent = nullptr; + CPopup* m_pPopupParent = nullptr; + + std::vector> m_vChildren; + + bool m_bInert = false; + + void initSignals(); + void initExistingSubsurfaces(); + void checkSiblingDamage(); +}; \ No newline at end of file diff --git a/src/helpers/WLSurface.cpp b/src/desktop/WLSurface.cpp similarity index 53% rename from src/helpers/WLSurface.cpp rename to src/desktop/WLSurface.cpp index 25f11feb..b102c5ce 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -1,14 +1,38 @@ #include "WLSurface.hpp" #include "../Compositor.hpp" -CWLSurface::CWLSurface(wlr_surface* pSurface) { - m_pWLRSurface = pSurface; - init(); -} - void CWLSurface::assign(wlr_surface* pSurface) { m_pWLRSurface = pSurface; init(); + m_bInert = false; +} + +void CWLSurface::assign(wlr_surface* pSurface, CWindow* pOwner) { + m_pWindowOwner = pOwner; + m_pWLRSurface = pSurface; + init(); + m_bInert = false; +} + +void CWLSurface::assign(wlr_surface* pSurface, SLayerSurface* pOwner) { + m_pLayerOwner = pOwner; + m_pWLRSurface = pSurface; + init(); + m_bInert = false; +} + +void CWLSurface::assign(wlr_surface* pSurface, CSubsurface* pOwner) { + m_pSubsurfaceOwner = pOwner; + m_pWLRSurface = pSurface; + init(); + m_bInert = false; +} + +void CWLSurface::assign(wlr_surface* pSurface, CPopup* pOwner) { + m_pPopupOwner = pOwner; + m_pWLRSurface = pSurface; + init(); + m_bInert = false; } void CWLSurface::unassign() { @@ -28,20 +52,20 @@ wlr_surface* CWLSurface::wlr() const { } bool CWLSurface::small() const { - if (!m_pOwner || !exists()) + if (!m_pWindowOwner || !exists()) return false; - return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1; + return m_pWindowOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pWindowOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1; } Vector2D CWLSurface::correctSmallVec() const { - if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall) + if (!m_pWindowOwner || !exists() || !small() || m_bFillIgnoreSmall) return {}; const auto SIZE = getViewporterCorrectedSize(); - return Vector2D{(m_pOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * - (m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize); + return Vector2D{(m_pWindowOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pWindowOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * + (m_pWindowOwner->m_vRealSize.value() / m_pWindowOwner->m_vReportedSize); } Vector2D CWLSurface::getViewporterCorrectedSize() const { @@ -79,9 +103,16 @@ void CWLSurface::destroy() { if (!m_pWLRSurface) return; + m_pConstraint.reset(); + hyprListener_destroy.removeCallback(); + hyprListener_commit.removeCallback(); m_pWLRSurface->data = nullptr; - m_pOwner = nullptr; + m_pWindowOwner = nullptr; + m_pLayerOwner = nullptr; + m_pPopupOwner = nullptr; + m_pSubsurfaceOwner = nullptr; + m_bInert = true; if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface) g_pCompositor->m_pLastFocus = nullptr; @@ -95,6 +126,11 @@ void CWLSurface::destroy() { Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this); } +static void onCommit(void* owner, void* data) { + const auto SURF = (CWLSurface*)owner; + SURF->onCommit(); +} + void CWLSurface::init() { if (!m_pWLRSurface) return; @@ -105,6 +141,56 @@ void CWLSurface::init() { hyprListener_destroy.initCallback( &m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface"); + hyprListener_commit.initCallback(&m_pWLRSurface->events.commit, ::onCommit, this, "CWLSurface"); Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this); -} \ No newline at end of file +} + +CWindow* CWLSurface::getWindow() { + return m_pWindowOwner; +} + +SLayerSurface* CWLSurface::getLayer() { + return m_pLayerOwner; +} + +CPopup* CWLSurface::getPopup() { + return m_pPopupOwner; +} + +CSubsurface* CWLSurface::getSubsurface() { + return m_pSubsurfaceOwner; +} + +bool CWLSurface::desktopComponent() { + return m_pLayerOwner || m_pWindowOwner || m_pSubsurfaceOwner || m_pPopupOwner; +} + +std::optional CWLSurface::getSurfaceBoxGlobal() { + if (!desktopComponent()) + return {}; + + if (m_pWindowOwner) + return m_pWindowOwner->getWindowMainSurfaceBox(); + if (m_pLayerOwner) + return m_pLayerOwner->geometry; + if (m_pPopupOwner) + return CBox{m_pPopupOwner->coordsGlobal(), m_pPopupOwner->size()}; + if (m_pSubsurfaceOwner) + return CBox{m_pSubsurfaceOwner->coordsGlobal(), m_pSubsurfaceOwner->size()}; + + return {}; +} + +void CWLSurface::appendConstraint(wlr_pointer_constraint_v1* constraint) { + m_pConstraint = std::make_unique(constraint, this); +} + +void CWLSurface::onCommit() { + if (m_pConstraint) + m_pConstraint->onCommit(); +} + +CConstraint* CWLSurface::constraint() { + return m_pConstraint.get(); +} diff --git a/src/helpers/WLSurface.hpp b/src/desktop/WLSurface.hpp similarity index 53% rename from src/helpers/WLSurface.hpp rename to src/desktop/WLSurface.hpp index eab4ac48..b9306eea 100644 --- a/src/helpers/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -1,17 +1,25 @@ #pragma once #include "../defines.hpp" -#include "Region.hpp" +#include "../helpers/Region.hpp" +#include "Constraint.hpp" class CWindow; +struct SLayerSurface; +class CSubsurface; +class CPopup; class CWLSurface { public: CWLSurface() = default; - CWLSurface(wlr_surface* pSurface); ~CWLSurface(); + // anonymous surfaces are non-desktop components, e.g. a cursor surface or a DnD void assign(wlr_surface* pSurface); + void assign(wlr_surface* pSurface, CWindow* pOwner); + void assign(wlr_surface* pSurface, SLayerSurface* pOwner); + void assign(wlr_surface* pSurface, CSubsurface* pOwner); + void assign(wlr_surface* pSurface, CPopup* pOwner); void unassign(); CWLSurface(const CWLSurface&) = delete; @@ -25,13 +33,22 @@ class CWLSurface { Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces Vector2D getViewporterCorrectedSize() const; CRegion logicalDamage() const; + void onCommit(); + + // getters for owners. + CWindow* getWindow(); + SLayerSurface* getLayer(); + CPopup* getPopup(); + CSubsurface* getSubsurface(); + + // desktop components misc utils + std::optional getSurfaceBoxGlobal(); + void appendConstraint(wlr_pointer_constraint_v1* constraint); + CConstraint* constraint(); // allow stretching. Useful for plugins. bool m_bFillIgnoreSmall = false; - // if present, means this is a base surface of a window. Cleaned on unassign() - CWindow* m_pOwner = nullptr; - // track surface data and avoid dupes float m_fLastScale = 0; int m_iLastScale = 0; @@ -59,14 +76,30 @@ class CWLSurface { } static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) { + if (!pSurface) + return nullptr; return (CWLSurface*)pSurface->data; } private: - wlr_surface* m_pWLRSurface = nullptr; + bool m_bInert = true; - void destroy(); - void init(); + wlr_surface* m_pWLRSurface = nullptr; + + CWindow* m_pWindowOwner = nullptr; + SLayerSurface* m_pLayerOwner = nullptr; + CPopup* m_pPopupOwner = nullptr; + CSubsurface* m_pSubsurfaceOwner = nullptr; + + // + std::unique_ptr m_pConstraint; + + void destroy(); + void init(); + bool desktopComponent(); DYNLISTENER(destroy); + DYNLISTENER(commit); + + friend class CConstraint; }; \ No newline at end of file diff --git a/src/helpers/Workspace.cpp b/src/desktop/Workspace.cpp similarity index 87% rename from src/helpers/Workspace.cpp rename to src/desktop/Workspace.cpp index ad8ae4ad..23f76309 100644 --- a/src/helpers/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -1,7 +1,8 @@ #include "Workspace.hpp" #include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" -CWorkspace::CWorkspace(int monitorID, std::string name, bool special) { +CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special) { const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); if (!PMONITOR) { @@ -10,12 +11,13 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) { } m_iMonitorID = monitorID; + m_iID = id; m_szName = name; m_bIsSpecialWorkspace = special; m_vRenderOffset.m_pWorkspace = this; - m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), - nullptr, AVARDAMAGE_ENTIRE); + m_vRenderOffset.create(special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr, + AVARDAMAGE_ENTIRE); m_fAlpha.m_pWorkspace = this; m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr, AVARDAMAGE_ENTIRE); @@ -29,6 +31,7 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) { m_szName = RULEFORTHIS.defaultName.value(); g_pEventManager->postEvent({"createworkspace", m_szName}); + g_pEventManager->postEvent({"createworkspacev2", std::format("{},{}", m_iID, m_szName)}); EMIT_HOOK_EVENT("createWorkspace", this); } @@ -38,12 +41,13 @@ CWorkspace::~CWorkspace() { Debug::log(LOG, "Destroying workspace ID {}", m_iID); g_pEventManager->postEvent({"destroyworkspace", m_szName}); + g_pEventManager->postEvent({"destroyworkspacev2", std::format("{},{}", m_iID, m_szName)}); EMIT_HOOK_EVENT("destroyWorkspace", this); } void CWorkspace::startAnim(bool in, bool left, bool instant) { - const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; - static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces"); + const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; + static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); if (ANIMSTYLE.starts_with("slidefade")) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); @@ -95,7 +99,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } else if (ANIMSTYLE == "slidevert") { // fallback is slide const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - const auto YDISTANCE = PMONITOR->vecSize.y + **PWORKSPACEGAP; + const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP; m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. @@ -108,7 +112,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } else { // fallback is slide const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - const auto XDISTANCE = PMONITOR->vecSize.x + **PWORKSPACEGAP; + const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP; m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. diff --git a/src/helpers/Workspace.hpp b/src/desktop/Workspace.hpp similarity index 85% rename from src/helpers/Workspace.hpp rename to src/desktop/Workspace.hpp index a0bbb815..15b7c0e2 100644 --- a/src/helpers/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -1,6 +1,6 @@ #pragma once -#include "AnimatedVariable.hpp" +#include "../helpers/AnimatedVariable.hpp" #include #include "../defines.hpp" @@ -14,7 +14,7 @@ class CWindow; class CWorkspace { public: - CWorkspace(int monitorID, std::string name, bool special = false); + CWorkspace(int id, int monitorID, std::string name, bool special = false); ~CWorkspace(); // Workspaces ID-based have IDs > 0 @@ -35,9 +35,9 @@ class CWorkspace { wl_array m_wlrCoordinateArr; // for animations - CAnimatedVariable m_vRenderOffset; - CAnimatedVariable m_fAlpha; - bool m_bForceRendering = false; + CAnimatedVariable m_vRenderOffset; + CAnimatedVariable m_fAlpha; + bool m_bForceRendering = false; // "scratchpad" bool m_bIsSpecialWorkspace = false; diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index 1ba6cad4..f0d68337 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -74,7 +74,7 @@ void Events::listener_newInput(wl_listener* listener, void* data) { Debug::log(LOG, "Attached a touch device with name {}", DEVICE->name); g_pInputManager->newTouchDevice(DEVICE); break; - case WLR_INPUT_DEVICE_TABLET_TOOL: + case WLR_INPUT_DEVICE_TABLET: Debug::log(LOG, "Attached a tablet tool with name {}", DEVICE->name); g_pInputManager->newTabletTool(DEVICE); break; @@ -97,44 +97,14 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) { Debug::log(LOG, "New mouse constraint at {:x}", (uintptr_t)PCONSTRAINT); - g_pInputManager->m_lConstraints.emplace_back(); - const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back(); + const auto SURFACE = CWLSurface::surfaceFromWlr(PCONSTRAINT->surface); - CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse; - CONSTRAINT->constraint = PCONSTRAINT; - - CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint"); - CONSTRAINT->hyprListener_setConstraintRegion.initCallback(&PCONSTRAINT->events.set_region, &Events::listener_setConstraintRegion, CONSTRAINT, "Constraint"); - - if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) { - g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT); - - if (!CONSTRAINT->hintSet) - CONSTRAINT->positionHint = Vector2D{-1, -1}; - } -} - -void Events::listener_destroyConstraint(void* owner, void* data) { - const auto PCONSTRAINT = (SConstraint*)owner; - - if (PCONSTRAINT->pMouse->currentConstraint == PCONSTRAINT->constraint) { - PCONSTRAINT->pMouse->hyprListener_commitConstraint.removeCallback(); - - const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse); - - if (PWINDOW && PCONSTRAINT->active && PCONSTRAINT->constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) - g_pInputManager->warpMouseToConstraintMiddle(PCONSTRAINT); - - PCONSTRAINT->pMouse->currentConstraint = nullptr; + if (!SURFACE) { + Debug::log(ERR, "Refusing a constraint from an unassigned wl_surface {:x}", (uintptr_t)PCONSTRAINT->surface); + return; } - Debug::log(LOG, "Unconstrained mouse from {:x}", (uintptr_t)PCONSTRAINT->constraint); - - g_pInputManager->m_lConstraints.remove(*PCONSTRAINT); -} - -void Events::listener_setConstraintRegion(void* owner, void* data) { - // no + SURFACE->appendConstraint(PCONSTRAINT); } void Events::listener_newVirtPtr(wl_listener* listener, void* data) { diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 8b737f32..a105846e 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -22,25 +22,6 @@ namespace Events { DYNLISTENFUNC(unmapLayerSurface); DYNLISTENFUNC(commitLayerSurface); - // Subsurfaces - DYNLISTENFUNC(newSubsurfaceNode); - DYNLISTENFUNC(destroySubsurfaceNode); - DYNLISTENFUNC(mapSubsurface); - DYNLISTENFUNC(unmapSubsurface); - DYNLISTENFUNC(destroySubsurface); - DYNLISTENFUNC(commitSubsurface); - - // Popups - DYNLISTENFUNC(newPopup); // LayerSurface - - DYNLISTENFUNC(newPopupXDG); - DYNLISTENFUNC(mapPopupXDG); - DYNLISTENFUNC(unmapPopupXDG); - DYNLISTENFUNC(destroyPopupXDG); - DYNLISTENFUNC(commitPopupXDG); - DYNLISTENFUNC(newPopupFromPopupXDG); - DYNLISTENFUNC(repositionPopupXDG); - // Surface XDG (window) LISTENER(newXDGToplevel); LISTENER(activateXDG); @@ -84,10 +65,7 @@ namespace Events { DYNLISTENFUNC(keyboardMod); DYNLISTENFUNC(keyboardDestroy); - DYNLISTENFUNC(commitConstraint); LISTENER(newConstraint); - DYNLISTENFUNC(setConstraintRegion); - DYNLISTENFUNC(destroyConstraint); // Various LISTENER(requestMouse); diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index 9ef9b025..4e61baa0 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -46,12 +46,12 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) { layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface"); layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface"); layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface"); - layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface"); layerSurface->layerSurface = WLRLAYERSURFACE; layerSurface->layer = WLRLAYERSURFACE->current.layer; WLRLAYERSURFACE->data = layerSurface; layerSurface->monitorID = PMONITOR->ID; + layerSurface->popupHead = std::make_unique(layerSurface); layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace); @@ -66,6 +66,8 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID); + layersurface->popupHead.reset(); + if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)"); @@ -87,7 +89,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { layersurface->hyprListener_destroyLayerSurface.removeCallback(); layersurface->hyprListener_mapLayerSurface.removeCallback(); layersurface->hyprListener_unmapLayerSurface.removeCallback(); - layersurface->hyprListener_newPopup.removeCallback(); // rearrange to fix the reserved areas if (PMONITOR) { @@ -113,9 +114,6 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive; layersurface->surface = layersurface->layerSurface->surface; - // anim - layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); - // fix if it changed its mon const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output); @@ -147,7 +145,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE && // don't focus if constrained - (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint); + (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()); if (GRABSFOCUS) { g_pCompositor->focusSurface(layersurface->layerSurface->surface); @@ -156,6 +154,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y); wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y); wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y); + g_pInputManager->m_bEmptyFocusCursorSet = false; } layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y); @@ -166,8 +165,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; - layersurface->alpha.setValue(0); - layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS) ? 0.f : 1.f); + layersurface->startAnimation(!(layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); layersurface->readyToDelete = false; layersurface->fadingOut = false; @@ -198,23 +196,17 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { layersurface->mapped = false; - layersurface->fadingOut = true; - - layersurface->alpha.setValueAndWarp(0.f); + layersurface->startAnimation(false); return; } - // anim - layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); - // make a snapshot and start fade g_pHyprOpenGL->makeLayerSnapshot(layersurface); - layersurface->alpha = 0.f; + + layersurface->startAnimation(false); layersurface->mapped = false; - layersurface->fadingOut = true; - g_pCompositor->addToFadingOutSafe(layersurface); const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output); @@ -244,7 +236,7 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface); - if (!foundSurface) { + if (!foundSurface && g_pCompositor->m_pLastWindow) { // if there isn't any, focus the last window const auto PLASTWINDOW = g_pCompositor->m_pLastWindow; g_pCompositor->focusWindow(nullptr); @@ -335,8 +327,20 @@ void Events::listener_commitLayerSurface(void* owner, void* data) { } } - if (layersurface->layerSurface->current.keyboard_interactive && - (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained + if (layersurface->realPosition.goal() != layersurface->geometry.pos()) { + if (layersurface->realPosition.isBeingAnimated()) + layersurface->realPosition = layersurface->geometry.pos(); + else + layersurface->realPosition.setValueAndWarp(layersurface->geometry.pos()); + } + if (layersurface->realSize.goal() != layersurface->geometry.size()) { + if (layersurface->realSize.isBeingAnimated()) + layersurface->realSize = layersurface->geometry.size(); + else + layersurface->realSize.setValueAndWarp(layersurface->geometry.size()); + } + + if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) // don't focus if constrained && !layersurface->keyboardExclusive && layersurface->mapped) { g_pCompositor->focusSurface(layersurface->layerSurface->surface); @@ -344,7 +348,8 @@ void Events::listener_commitLayerSurface(void* owner, void* data) { g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y); wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y); wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y); - } else if (!layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) && + g_pInputManager->m_bEmptyFocusCursorSet = false; + } else if (!layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) && layersurface->keyboardExclusive) { g_pInputManager->refocus(); } diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 35721832..8d0a9710 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -4,6 +4,7 @@ #include "../helpers/WLClasses.hpp" #include "../managers/input/InputManager.hpp" #include "../render/Renderer.hpp" +#include "../managers/CursorManager.hpp" // ------------------------------ // // __ __ _____ _____ _____ // @@ -63,15 +64,26 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) { } ATOM.second = reply->atom; + + free(reply); } wlr_xwayland_set_seat(g_pXWaylandManager->m_sWLRXWayland, g_pCompositor->m_sSeat.seat); - const auto XCURSOR = wlr_xcursor_manager_get_xcursor(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", 1); - if (XCURSOR) { - wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width, - XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y); - } + g_pCursorManager->setXWaylandCursor(g_pXWaylandManager->m_sWLRXWayland); + + const auto ROOT = xcb_setup_roots_iterator(xcb_get_setup(XCBCONNECTION)).data->root; + auto cookie = xcb_get_property(XCBCONNECTION, 0, ROOT, HYPRATOMS["_NET_SUPPORTING_WM_CHECK"], XCB_ATOM_ANY, 0, 2048); + auto reply = xcb_get_property_reply(XCBCONNECTION, cookie, nullptr); + + const auto XWMWINDOW = *(xcb_window_t*)xcb_get_property_value(reply); + const char* name = "Hyprland"; + + xcb_change_property(wlr_xwayland_get_xwm_connection(g_pXWaylandManager->m_sWLRXWayland), XCB_PROP_MODE_REPLACE, XWMWINDOW, HYPRATOMS["_NET_WM_NAME"], HYPRATOMS["UTF8_STRING"], + 8, // format + strlen(name), name); + + free(reply); xcb_disconnect(XCBCONNECTION); #endif @@ -169,6 +181,7 @@ void Events::listener_sessionActive(wl_listener* listener, void* data) { for (auto& m : g_pCompositor->m_vMonitors) { g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); } g_pConfigManager->m_bWantsMonitorReload = true; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 01ea24f8..e235096b 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -4,6 +4,7 @@ #include "../render/Renderer.hpp" #include "Events.hpp" #include "../debug/HyprCtl.hpp" +#include "../config/ConfigValue.hpp" // --------------------------------------------------------- // // __ __ ____ _ _ _____ _______ ____ _____ _____ // @@ -147,12 +148,12 @@ void Events::listener_monitorFrame(void* owner, void* data) { PMONITOR->tearingState.frameScheduledWhileBusy = false; } - static auto* const PENABLERAT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time"); - static auto* const PRATSAFE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone"); + static auto PENABLERAT = CConfigValue("misc:render_ahead_of_time"); + static auto PRATSAFE = CConfigValue("misc:render_ahead_safezone"); PMONITOR->lastPresentationTimer.reset(); - if (**PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) { + if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) { if (!PMONITOR->RATScheduled) { // render g_pHyprRenderer->renderMonitor(PMONITOR); @@ -162,14 +163,14 @@ void Events::listener_monitorFrame(void* owner, void* data) { const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR); - if (max + **PRATSAFE > 1000.0 / PMONITOR->refreshRate) + if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate) return; const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis(); PMONITOR->RATScheduled = true; - const auto ESTRENDERTIME = std::ceil(avg + **PRATSAFE); + const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE); const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp deleted file mode 100644 index 41707b6a..00000000 --- a/src/events/Popups.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "Events.hpp" - -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" - -// --------------------------------------------- // -// _____ ____ _____ _ _ _____ _____ // -// | __ \ / __ \| __ \| | | | __ \ / ____| // -// | |__) | | | | |__) | | | | |__) | (___ // -// | ___/| | | | ___/| | | | ___/ \___ \ // -// | | | |__| | | | |__| | | ____) | // -// |_| \____/|_| \____/|_| |_____/ // -// // -// --------------------------------------------- // - -void addPopupGlobalCoords(void* pPopup, int* x, int* y) { - SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup; - - auto curPopup = PPOPUP; - - int px = 0; - int py = 0; - - while (true) { - px += curPopup->popup->current.geometry.x; - py += curPopup->popup->current.geometry.y; - - if (curPopup == PPOPUP && PPOPUP->parentWindow) { - px -= curPopup->popup->base->current.geometry.x; - py -= curPopup->popup->base->current.geometry.y; - } - - if (curPopup->popup && !curPopup->parentPopup && !curPopup->parentWindow) { - const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->popup->base->surface->input_region); - px -= EXTENTSSURFACE->x1; - py -= EXTENTSSURFACE->y1; - } - - if (curPopup->parentPopup) { - curPopup = curPopup->parentPopup; - } else { - break; - } - } - - px += PPOPUP->lx; - py += PPOPUP->ly; - - *x += px; - *y += py; -} - -void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) { - pHyprPopup->popup = popup; - - pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup"); - pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->surface->events.map, &Events::listener_mapPopupXDG, 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_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; - - CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; - - wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr()); - - pHyprPopup->monitor = PMONITOR; - - Debug::log(LOG, "Popup: Unconstrained from lx ly: {:j5}, pHyprPopup lx ly: {:.5f} {:.5f}", PMONITOR->vecPosition, (float)pHyprPopup->lx, (float)pHyprPopup->ly); -} - -void Events::listener_newPopup(void* owner, void* data) { - SLayerSurface* layersurface = (SLayerSurface*)owner; - - ASSERT(layersurface); - - Debug::log(LOG, "New layer popup created from surface {:x}", (uintptr_t)layersurface); - - const auto WLRPOPUP = (wlr_xdg_popup*)data; - - const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique()).get(); - - const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID); - - PNEWPOPUP->popup = WLRPOPUP; - PNEWPOPUP->lx = layersurface->position.x; - PNEWPOPUP->ly = layersurface->position.y; - PNEWPOPUP->monitor = PMONITOR; - PNEWPOPUP->parentLS = layersurface; - createNewPopup(WLRPOPUP, PNEWPOPUP); -} - -void Events::listener_newPopupXDG(void* owner, void* data) { - CWindow* PWINDOW = (CWindow*)owner; - - ASSERT(PWINDOW); - - if (!PWINDOW->m_bIsMapped) - return; - - Debug::log(LOG, "New layer popup created from XDG window {}", PWINDOW); - - const auto WLRPOPUP = (wlr_xdg_popup*)data; - - const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique()).get(); - - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - - PNEWPOPUP->popup = WLRPOPUP; - PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x; - PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y; - PNEWPOPUP->parentWindow = PWINDOW; - PNEWPOPUP->monitor = PMONITOR; - createNewPopup(WLRPOPUP, PNEWPOPUP); -} - -void Events::listener_newPopupFromPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - ASSERT(PPOPUP); - - if (PPOPUP->parentWindow) - Debug::log(LOG, "New popup created from XDG Window popup {:x} -> {}", (uintptr_t)PPOPUP, PPOPUP->parentWindow); - else - Debug::log(LOG, "New popup created from Non-Window popup {:x}", (uintptr_t)PPOPUP); - - const auto WLRPOPUP = (wlr_xdg_popup*)data; - - const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique()).get(); - - PNEWPOPUP->popup = WLRPOPUP; - PNEWPOPUP->parentPopup = PPOPUP; - PNEWPOPUP->lx = PPOPUP->lx; - PNEWPOPUP->ly = PPOPUP->ly; - PNEWPOPUP->parentWindow = PPOPUP->parentWindow; - PNEWPOPUP->monitor = PPOPUP->monitor; - - createNewPopup(WLRPOPUP, PNEWPOPUP); -} - -void Events::listener_mapPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - ASSERT(PPOPUP); - - Debug::log(LOG, "New XDG Popup mapped at {} {}", (int)PPOPUP->lx, (int)PPOPUP->ly); - - if (PPOPUP->parentWindow) - PPOPUP->parentWindow->m_lPopupSurfaces.emplace_back(PPOPUP->popup->base->surface); - else if (PPOPUP->parentLS) - PPOPUP->parentLS->popupSurfaces.emplace_back(PPOPUP->popup->base->surface); - - PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow); - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); - - if (PPOPUP->monitor) { - g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale); - g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform); - } - - Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree); -} - -void Events::listener_repositionPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - Debug::log(LOG, "XDG Popup {:x} asks for a reposition", (uintptr_t)PPOPUP); - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - PPOPUP->lastPos = {lx - extents.x, ly - extents.y}; - PPOPUP->repositionRequested = true; - - const auto PMONITOR = g_pCompositor->m_pLastMonitor; - - CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x, - PMONITOR->vecSize.y}; - wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr()); -} - -void Events::listener_unmapPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - Debug::log(LOG, "XDG Popup unmapped"); - - ASSERT(PPOPUP); - - if (PPOPUP->popup->base->surface == g_pCompositor->m_pLastFocus) - g_pInputManager->releaseAllMouseButtons(); - - SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree); - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); - - if (PPOPUP->parentWindow) - std::erase(PPOPUP->parentWindow->m_lPopupSurfaces, PPOPUP->popup->base->surface); - else if (PPOPUP->parentLS) - std::erase(PPOPUP->parentLS->popupSurfaces, PPOPUP->popup->base->surface); - - PPOPUP->pSurfaceTree = nullptr; - - g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface -} - -void Events::listener_commitPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - if (PPOPUP->popup->base->initial_commit) { - wlr_xdg_surface_schedule_configure(PPOPUP->popup->base); - return; - } - - if (g_pCompositor->windowValidMapped(PPOPUP->parentWindow)) { - PPOPUP->lx = PPOPUP->parentWindow->m_vRealPosition.vec().x; - PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y; - } - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - 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); -} - -void Events::listener_destroyPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - ASSERT(PPOPUP); - - Debug::log(LOG, "Destroyed popup XDG {:x}", (uintptr_t)PPOPUP); - - if (PPOPUP->pSurfaceTree) { - SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree); - PPOPUP->pSurfaceTree = nullptr; - } - - std::erase_if(g_pCompositor->m_vXDGPopups, [&](std::unique_ptr& el) { return el.get() == PPOPUP; }); -} diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 81c5c800..1e547efc 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -4,6 +4,7 @@ #include "../helpers/WLClasses.hpp" #include "../managers/input/InputManager.hpp" #include "../render/Renderer.hpp" +#include "../config/ConfigValue.hpp" // ------------------------------------------------------------ // // __ _______ _ _ _____ ______ _______ // @@ -17,8 +18,8 @@ void addViewCoords(void* pWindow, int* x, int* y) { const auto PWINDOW = (CWindow*)pWindow; - *x += PWINDOW->m_vRealPosition.goalv().x; - *y += PWINDOW->m_vRealPosition.goalv().y; + *x += PWINDOW->m_vRealPosition.goal().x; + *y += PWINDOW->m_vRealPosition.goal().y; if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) { wlr_box geom; @@ -30,25 +31,25 @@ void addViewCoords(void* pWindow, int* x, int* y) { } void setAnimToMove(void* data) { - auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove"); + auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove"); - CAnimatedVariable* animvar = (CAnimatedVariable*)data; + CBaseAnimatedVariable* animvar = (CBaseAnimatedVariable*)data; animvar->setConfig(PANIMCFG); } void Events::listener_mapWindow(void* owner, void* data) { - CWindow* PWINDOW = (CWindow*)owner; + CWindow* PWINDOW = (CWindow*)owner; - static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity"); - static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity"); - static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength"); - static auto* const PSWALLOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:enable_swallow"); - static auto* const PSWALLOWREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_regex"); - static auto* const PSWALLOWEXREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex"); - static auto* const PNEWTAKESOVERFS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen"); + static auto PINACTIVEALPHA = CConfigValue("decoration:inactive_opacity"); + static auto PACTIVEALPHA = CConfigValue("decoration:active_opacity"); + static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); + static auto PSWALLOW = CConfigValue("misc:enable_swallow"); + static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); + static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); + static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); - auto PMONITOR = g_pCompositor->m_pLastMonitor; + auto PMONITOR = g_pCompositor->m_pLastMonitor; auto PWORKSPACE = PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); PWINDOW->m_iMonitorID = PMONITOR->ID; PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; @@ -258,8 +259,6 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->applyDynamicRule(r); } - PWINDOW->updateSpecialRenderData(); - // disallow tiled pinned if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating) PWINDOW->m_bPinned = false; @@ -290,7 +289,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!workspaceSilent) { if (pWorkspace->m_bIsSpecialWorkspace) g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID)->setSpecialWorkspace(pWorkspace); - else + else if (PMONITOR->activeWorkspace != REQUESTEDWORKSPACEID) g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspaceName); PMONITOR = g_pCompositor->m_pLastMonitor; @@ -299,6 +298,8 @@ void Events::listener_mapWindow(void* owner, void* data) { workspaceSilent = false; } + PWINDOW->updateSpecialRenderData(); + if (PWINDOW->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; @@ -323,38 +324,10 @@ void Events::listener_mapWindow(void* owner, void* data) { Debug::log(LOG, "Rule size, applying to {}", PWINDOW); PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.starts_with("minsize")) { - try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - - const auto SIZE = - Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y)); - - PWINDOW->m_vRealSize = SIZE; - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); - - PWINDOW->setHidden(false); - } catch (...) { Debug::log(LOG, "Rule minsize failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.starts_with("maxsize")) { - try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - - const auto SIZE = - Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y)); - - PWINDOW->m_vRealSize = SIZE; - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); - - PWINDOW->setHidden(false); - } catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: {} -> {}", r.szRule, r.szValue); } } else if (r.szRule.starts_with("move")) { try { auto value = r.szRule.substr(r.szRule.find(' ') + 1); @@ -390,7 +363,7 @@ void Events::listener_mapWindow(void* owner, void* data) { posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x; } else { posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x + - (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().x); + (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x); } } @@ -409,7 +382,7 @@ void Events::listener_mapWindow(void* owner, void* data) { posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y; } else { posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y + - (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().y); + (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y); } } @@ -417,10 +390,10 @@ void Events::listener_mapWindow(void* owner, void* data) { int borderSize = PWINDOW->getRealBorderSize(); posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize), - (int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goalv().x - borderSize)); + (int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize)); posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize), - (int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goalv().y - borderSize)); + (int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize)); } Debug::log(LOG, "Rule move, applying to {}", PWINDOW); @@ -435,20 +408,20 @@ void Events::listener_mapWindow(void* owner, void* data) { if (ARGS[1] == "1") RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; - PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goalv() / 2.f + RESERVEDOFFSET; + PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; } } // set the pseudo size to the GOAL of our current size // because the windows are animated on RealSize - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv(); + PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal(); g_pCompositor->changeWindowZOrder(PWINDOW, true); } else { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); // Set the pseudo size here too so that it doesnt end up being 0x0 - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10, 10); + PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10); } const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow; @@ -465,9 +438,9 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive) PWINDOW->m_bNoInitialFocus = true; if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) { - if (**PNEWTAKESOVERFS == 0) + if (*PNEWTAKESOVERFS == 0) PWINDOW->m_bNoInitialFocus = true; - else if (**PNEWTAKESOVERFS == 2) + else if (*PNEWTAKESOVERFS == 2) g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID); else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) requestsMaximize = true; @@ -476,21 +449,19 @@ void Events::listener_mapWindow(void* owner, void* data) { } if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus && - (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent && - (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) { + (PWINDOW->m_iX11Type != 2 || + (PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->window_type_len > 0 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && + !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && !g_pInputManager->isConstrained()) { g_pCompositor->focusWindow(PWINDOW); - PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA); - PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : **PDIMSTRENGTH); + PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); + PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH); } else { - PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PINACTIVEALPHA); + PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA); PWINDOW->m_fDimPercent.setValueAndWarp(0); } - Debug::log(LOG, "Window got assigned a surfaceTreeNode {:x}", (uintptr_t)PWINDOW->m_pSurfaceTree); - if (!PWINDOW->m_bIsX11) { PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late"); - PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, @@ -538,8 +509,6 @@ void Events::listener_mapWindow(void* owner, void* data) { // recheck idle inhibitors g_pInputManager->recheckIdleInhibitorStatus(); - PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(PWINDOW->m_pWLSurface.wlr(), addViewCoords, PWINDOW, PWINDOW); - PWINDOW->updateToplevel(); if (workspaceSilent) { @@ -551,7 +520,7 @@ void Events::listener_mapWindow(void* owner, void* data) { } // verify swallowing - if (**PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) { + if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) { // don't swallow ourselves std::regex rgx(*PSWALLOWREGEX); if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) { @@ -622,7 +591,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bFirstMap = false; - Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goalv(), PWINDOW->m_vRealSize.goalv()); + Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal()); auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName; g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, g_pXWaylandManager->getAppIDClass(PWINDOW), PWINDOW->m_szTitle)}); @@ -650,13 +619,16 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); - if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->constraintActive) + if (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) g_pInputManager->sendMotionEventsToFocused(); // fix some xwayland apps that don't behave nicely PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; g_pCompositor->updateWorkspaceWindows(PWINDOW->m_iWorkspaceID); + + if (PMONITOR && PWINDOW->m_iX11Type == 2) + PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; } void Events::listener_unmapWindow(void* owner, void* data) { @@ -672,8 +644,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); if (PMONITOR) { - PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition; - PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec(); + PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition; + PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value(); PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents(); } @@ -685,7 +657,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (!PWINDOW->m_bIsX11) { Debug::log(LOG, "Unregistered late callbacks XDG"); PWINDOW->hyprListener_setTitleWindow.removeCallback(); - PWINDOW->hyprListener_newPopupXDG.removeCallback(); PWINDOW->hyprListener_requestMaximize.removeCallback(); PWINDOW->hyprListener_requestMinimize.removeCallback(); PWINDOW->hyprListener_requestMove.removeCallback(); @@ -745,6 +716,9 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow && PWINDOWCANDIDATE) g_pCompositor->focusWindow(PWINDOWCANDIDATE); + if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->m_iWorkspaceID) == 0) + g_pInputManager->refocus(); + g_pInputManager->sendMotionEventsToFocused(); // CWindow::onUnmap will remove this window's active status, but we can't really do it above. @@ -757,19 +731,14 @@ void Events::listener_unmapWindow(void* owner, void* data) { Debug::log(LOG, "Unmapped was not focused, ignoring a refocus."); } - Debug::log(LOG, "Destroying the SubSurface tree of unmapped window {}", PWINDOW); - SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree); - - PWINDOW->m_pSurfaceTree = nullptr; - PWINDOW->m_bFadingOut = true; g_pCompositor->addToFadingOutSafe(PWINDOW); g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)); - if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it + if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. + PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it // anims g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true); @@ -806,7 +775,26 @@ void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) { - wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, 0, 0); + Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(); + + if (g_pXWaylandManager->shouldBeFloated(PWINDOW, true)) + predSize = {}; + + Vector2D maxSize = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->pending.max_width, PWINDOW->m_uSurface.xdg->toplevel->pending.max_height}; + + if ((maxSize.x > 0 && maxSize.x < predSize.x) || (maxSize.y > 0 && maxSize.y < predSize.y)) + predSize = {}; + + for (auto& r : g_pConfigManager->getMatchingRules(PWINDOW, true, true)) { + if (r.szRule.starts_with("float")) { + predSize = {}; + break; + } + } + + Debug::log(LOG, "Layout predicts size {} for {}", predSize, PWINDOW); + + wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, predSize.x, predSize.y); return; } @@ -820,9 +808,30 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_pPendingSizeAck.reset(); } - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, + g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); + if (!PWINDOW->m_bIsX11) { + PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces(); + PWINDOW->m_pPopupHead->recheckTree(); + } + + // tearing: if solitary, redraw it. This still might be a single surface window + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + if (PMONITOR && PMONITOR->solitaryClient == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && + PWINDOW->m_pWLSurface.wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { + CRegion damageBox{&PWINDOW->m_pWLSurface.wlr()->buffer_damage}; + + if (!damageBox.empty()) { + if (PMONITOR->tearingState.busy) { + PMONITOR->tearingState.frameScheduledWhileBusy = true; + } else { + PMONITOR->tearingState.nextRenderTorn = true; + g_pHyprRenderer->renderMonitor(PMONITOR); + } + } + } + if (PWINDOW->m_bIsX11 || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) return; @@ -832,7 +841,7 @@ void Events::listener_commitWindow(void* owner, void* data) { if (MAXSIZE < Vector2D{1, 1}) return; - const auto REALSIZE = PWINDOW->m_vRealSize.goalv(); + const auto REALSIZE = PWINDOW->m_vRealSize.goal(); Vector2D newSize = REALSIZE; if (MAXSIZE.x < newSize.x) @@ -846,7 +855,7 @@ void Events::listener_commitWindow(void* owner, void* data) { const Vector2D DELTA = REALSIZE - newSize; - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0; + PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0; PWINDOW->m_vRealSize = newSize; g_pXWaylandManager->setWindowSize(PWINDOW, newSize, true); g_pHyprRenderer->damageWindow(PWINDOW); @@ -876,14 +885,10 @@ void Events::listener_destroyWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); - if (PWINDOW->m_pSurfaceTree) { - Debug::log(LOG, "Destroying Subsurface tree of {} in destroyWindow", PWINDOW); - SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree); - PWINDOW->m_pSurfaceTree = nullptr; - } - PWINDOW->m_bReadyToDelete = true; + PWINDOW->m_uSurface.xdg = nullptr; + if (!PWINDOW->m_bFadingOut) { Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW); g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn @@ -896,7 +901,12 @@ void Events::listener_setTitleWindow(void* owner, void* data) { if (!g_pCompositor->windowValidMapped(PWINDOW)) return; - PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW); + const auto NEWTITLE = g_pXWaylandManager->getTitle(PWINDOW); + + if (NEWTITLE == PWINDOW->m_szTitle) + return; + + PWINDOW->m_szTitle = NEWTITLE; g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", std::format("{:x}", (uintptr_t)PWINDOW)}); EMIT_HOOK_EVENT("windowTitle", PWINDOW); @@ -973,9 +983,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) { } void Events::listener_activateXDG(wl_listener* listener, void* data) { - const auto E = (wlr_xdg_activation_v1_request_activate_event*)data; + const auto E = (wlr_xdg_activation_v1_request_activate_event*)data; - static auto* const PFOCUSONACTIVATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:focus_on_activate"); + static auto PFOCUSONACTIVATE = CConfigValue("misc:focus_on_activate"); Debug::log(LOG, "Activate request for surface at {:x}", (uintptr_t)E->surface); @@ -992,7 +1002,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) { PWINDOW->m_bIsUrgent = true; - if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY)) + if (!*PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY)) return; if (PWINDOW->m_bIsFloating) @@ -1003,9 +1013,9 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) { } void Events::listener_activateX11(void* owner, void* data) { - const auto PWINDOW = (CWindow*)owner; + const auto PWINDOW = (CWindow*)owner; - static auto* const PFOCUSONACTIVATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:focus_on_activate"); + static auto PFOCUSONACTIVATE = CConfigValue("misc:focus_on_activate"); Debug::log(LOG, "X11 Activate request for window {}", PWINDOW); @@ -1029,7 +1039,7 @@ void Events::listener_activateX11(void* owner, void* data) { g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)}); EMIT_HOOK_EVENT("urgent", PWINDOW); - if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY)) + if (!*PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY)) return; if (PWINDOW->m_bIsFloating) @@ -1048,13 +1058,15 @@ void Events::listener_configureX11(void* owner, void* data) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); PWINDOW->m_vPendingReportedSize = {E->width, E->height}; PWINDOW->m_vReportedSize = {E->width, E->height}; + if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) + PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; return; } g_pHyprRenderer->damageWindow(PWINDOW); if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == PWINDOW) { - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv(), true); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); g_pInputManager->refocus(); g_pHyprRenderer->damageWindow(PWINDOW); return; @@ -1070,14 +1082,16 @@ void Events::listener_configureX11(void* owner, void* data) { PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS); PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height)); - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); - if (**PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) - PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + if (*PXWLFORCESCALEZERO) { + if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { + PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale); + PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; + } } - PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec(); - PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec(); + PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.value(); + PWINDOW->m_vSize = PWINDOW->m_vRealSize.value(); wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); @@ -1089,7 +1103,7 @@ void Events::listener_configureX11(void* owner, void* data) { if (!g_pCompositor->isWorkspaceVisible(PWINDOW->m_iWorkspaceID)) return; // further things are only for visible windows - PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; + PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace; g_pCompositor->changeWindowZOrder(PWINDOW, true); @@ -1107,8 +1121,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { if (!PWINDOW->m_bIsMapped) return; - const auto POS = PWINDOW->m_vRealPosition.goalv(); - const auto SIZ = PWINDOW->m_vRealSize.goalv(); + const auto POS = PWINDOW->m_vRealPosition.goal(); + const auto SIZ = PWINDOW->m_vRealSize.goal(); if (PWINDOW->m_uSurface.xwayland->width > 1 && PWINDOW->m_uSurface.xwayland->height > 1) PWINDOW->setHidden(false); @@ -1116,14 +1130,14 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->setHidden(true); if (PWINDOW->m_bIsFullscreen || !PWINDOW->m_bIsFloating) { - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv(), true); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); g_pHyprRenderer->damageWindow(PWINDOW); return; } - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y}); + const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y}); if (abs(std::floor(POS.x) - LOGICALPOS.x) > 2 || abs(std::floor(POS.y) - LOGICALPOS.y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) { @@ -1136,25 +1150,25 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { 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)); - if (**PXWLFORCESCALEZERO) { + if (*PXWLFORCESCALEZERO) { if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { - const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale; - PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); - PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0); + const Vector2D DELTA = PWINDOW->m_vRealSize.goal() - PWINDOW->m_vRealSize.goal() / PMONITOR->scale; + PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale); + PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goal() + DELTA / 2.0); } } - PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv(); - PWINDOW->m_vSize = PWINDOW->m_vRealSize.goalv(); + PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); + PWINDOW->m_vSize = PWINDOW->m_vRealSize.goal(); - PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; + PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace; g_pCompositor->changeWindowZOrder(PWINDOW, true); PWINDOW->updateWindowDecos(); g_pHyprRenderer->damageWindow(PWINDOW); - PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv(); - PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goalv(); + PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goal(); + PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goal(); } } diff --git a/src/helpers/AnimatedVariable.cpp b/src/helpers/AnimatedVariable.cpp index 740e604f..3a891e37 100644 --- a/src/helpers/AnimatedVariable.cpp +++ b/src/helpers/AnimatedVariable.cpp @@ -2,12 +2,11 @@ #include "../managers/AnimationManager.hpp" #include "../config/ConfigManager.hpp" -CAnimatedVariable::CAnimatedVariable() { +CBaseAnimatedVariable::CBaseAnimatedVariable(ANIMATEDVARTYPE type) : m_Type(type) { ; // dummy var } -void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) { - m_eVarType = type; +void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) { m_eDamagePolicy = policy; m_pConfig = pAnimConfig; m_pWindow = pWindow; @@ -15,42 +14,11 @@ void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* p m_bDummy = false; } -void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) { - create(type, pAnimConfig, pWindow, policy); - - try { - switch (type) { - case AVARTYPE_FLOAT: { - const auto V = std::any_cast(val); - m_fValue = V; - m_fGoal = V; - break; - } - case AVARTYPE_VECTOR: { - const auto V = std::any_cast(val); - m_vValue = V; - m_vGoal = V; - break; - } - case AVARTYPE_COLOR: { - const auto V = std::any_cast(val); - m_cValue = V; - m_cGoal = V; - break; - } - default: ASSERT(false); break; - } - } catch (std::exception& e) { - Debug::log(ERR, "CAnimatedVariable create error: {}", e.what()); - RASSERT(false, "CAnimatedVariable create error: {}", e.what()); - } -} - -CAnimatedVariable::~CAnimatedVariable() { +CBaseAnimatedVariable::~CBaseAnimatedVariable() { unregister(); } -void CAnimatedVariable::unregister() { +void CBaseAnimatedVariable::unregister() { if (!g_pAnimationManager) return; std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; }); @@ -58,23 +26,23 @@ void CAnimatedVariable::unregister() { disconnectFromActive(); } -void CAnimatedVariable::registerVar() { +void CBaseAnimatedVariable::registerVar() { if (!m_bIsRegistered) g_pAnimationManager->m_vAnimatedVariables.push_back(this); m_bIsRegistered = true; } -int CAnimatedVariable::getDurationLeftMs() { +int CBaseAnimatedVariable::getDurationLeftMs() { return std::max( (int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast(std::chrono::system_clock::now() - animationBegin).count(), 0); } -float CAnimatedVariable::getPercent() { +float CBaseAnimatedVariable::getPercent() { const auto DURATIONPASSED = std::chrono::duration_cast(std::chrono::system_clock::now() - animationBegin).count(); return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f); } -float CAnimatedVariable::getCurveValue() { +float CBaseAnimatedVariable::getCurveValue() { if (!m_bIsBeingAnimated) return 1.f; @@ -86,7 +54,7 @@ float CAnimatedVariable::getCurveValue() { return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT); } -void CAnimatedVariable::connectToActive() { +void CBaseAnimatedVariable::connectToActive() { g_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up if (!m_bIsConnectedToActive) @@ -95,7 +63,7 @@ void CAnimatedVariable::connectToActive() { m_bIsConnectedToActive = true; } -void CAnimatedVariable::disconnectFromActive() { +void CBaseAnimatedVariable::disconnectFromActive() { std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; }); m_bIsConnectedToActive = false; -} \ No newline at end of file +} diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index d87273b3..005f2832 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "Vector2D.hpp" #include "Color.hpp" #include "../macros.hpp" @@ -15,6 +16,30 @@ enum ANIMATEDVARTYPE { AVARTYPE_COLOR }; +// Utility to bind a type with its corresponding ANIMATEDVARTYPE +template +struct typeToANIMATEDVARTYPE_t { + static constexpr ANIMATEDVARTYPE value = AVARTYPE_INVALID; +}; + +template <> +struct typeToANIMATEDVARTYPE_t { + static constexpr ANIMATEDVARTYPE value = AVARTYPE_FLOAT; +}; + +template <> +struct typeToANIMATEDVARTYPE_t { + static constexpr ANIMATEDVARTYPE value = AVARTYPE_VECTOR; +}; + +template <> +struct typeToANIMATEDVARTYPE_t { + static constexpr ANIMATEDVARTYPE value = AVARTYPE_COLOR; +}; + +template +inline constexpr ANIMATEDVARTYPE typeToANIMATEDVARTYPE = typeToANIMATEDVARTYPE_t::value; + enum AVARDAMAGEPOLICY { AVARDAMAGE_NONE = -1, AVARDAMAGE_ENTIRE = 0, @@ -28,174 +53,34 @@ struct SLayerSurface; struct SAnimationPropertyConfig; class CHyprRenderer; -class CAnimatedVariable { +// Utility to define a concept as a list of possible type +template +concept OneOf = (... or std::same_as); + +// Concept to describe which type can be placed into CAnimatedVariable +// This is mainly to get better errors if we put a type that's not supported +// Otherwise template errors are ugly +template +concept Animable = OneOf; + +class CBaseAnimatedVariable { public: - CAnimatedVariable(); // dummy var + CBaseAnimatedVariable(ANIMATEDVARTYPE type); + void create(SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy); - void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY); - void create(ANIMATEDVARTYPE, std::any val, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY); + CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete; + CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete; + CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete; + CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete; - CAnimatedVariable(const CAnimatedVariable&) = delete; - CAnimatedVariable(CAnimatedVariable&&) = delete; - CAnimatedVariable& operator=(const CAnimatedVariable&) = delete; - CAnimatedVariable& operator=(CAnimatedVariable&&) = delete; + virtual ~CBaseAnimatedVariable(); - ~CAnimatedVariable(); + void unregister(); + void registerVar(); - void unregister(); - void registerVar(); - - // gets the current vector value (real time) - const Vector2D& vec() const { - return m_vValue; - } - - // gets the current float value (real time) - const float& fl() const { - return m_fValue; - } - - // gets the current color value (real time) - const CColor& col() const { - return m_cValue; - } - - // gets the goal vector value - const Vector2D& goalv() const { - return m_vGoal; - } - - // gets the goal float value - const float& goalf() const { - return m_fGoal; - } - - // gets the goal color value - const CColor& goalc() const { - return m_cGoal; - } - - CAnimatedVariable& operator=(const Vector2D& v) { - if (v == m_vGoal) - return *this; - - m_vGoal = v; - animationBegin = std::chrono::system_clock::now(); - m_vBegun = m_vValue; - - onAnimationBegin(); - - return *this; - } - - CAnimatedVariable& operator=(const float& v) { - if (v == m_fGoal) - return *this; - - m_fGoal = v; - animationBegin = std::chrono::system_clock::now(); - m_fBegun = m_fValue; - - onAnimationBegin(); - - return *this; - } - - CAnimatedVariable& operator=(const CColor& v) { - if (v == m_cGoal) - return *this; - - m_cGoal = v; - animationBegin = std::chrono::system_clock::now(); - m_cBegun = m_cValue; - - onAnimationBegin(); - - return *this; - } - - // Sets the actual stored value, without affecting the goal, but resets the timer - void setValue(const Vector2D& v) { - if (v == m_vValue) - return; - - m_vValue = v; - animationBegin = std::chrono::system_clock::now(); - m_vBegun = m_vValue; - - onAnimationBegin(); - } - - // Sets the actual stored value, without affecting the goal, but resets the timer - void setValue(const float& v) { - if (v == m_fValue) - return; - - m_fValue = v; - animationBegin = std::chrono::system_clock::now(); - m_vBegun = m_vValue; - - onAnimationBegin(); - } - - // Sets the actual stored value, without affecting the goal, but resets the timer - void setValue(const CColor& v) { - if (v == m_cValue) - return; - - m_cValue = v; - animationBegin = std::chrono::system_clock::now(); - m_vBegun = m_vValue; - - onAnimationBegin(); - } - - // Sets the actual value and goal - void setValueAndWarp(const Vector2D& v) { - m_vGoal = v; - warp(); - } - - // Sets the actual value and goal - void setValueAndWarp(const float& v) { - m_fGoal = v; - warp(); - } - - // Sets the actual value and goal - void setValueAndWarp(const CColor& v) { - m_cGoal = v; - warp(); - } - - // checks if an animation is in progress - inline bool isBeingAnimated() { - return m_bIsBeingAnimated; - } - - void warp(bool endCallback = true) { - switch (m_eVarType) { - case AVARTYPE_FLOAT: { - m_fValue = m_fGoal; - break; - } - case AVARTYPE_VECTOR: { - m_vValue = m_vGoal; - break; - } - case AVARTYPE_COLOR: { - m_cValue = m_cGoal; - break; - } - default: UNREACHABLE(); - } - - m_bIsBeingAnimated = false; - - if (endCallback) - onAnimationEnd(); - } + virtual void warp(bool endCallback = true) = 0; + // void setConfig(SAnimationPropertyConfig* pConfig) { m_pConfig = pConfig; } @@ -212,6 +97,11 @@ class CAnimatedVariable { /* returns the current curve value */ float getCurveValue(); + // checks if an animation is in progress + inline bool isBeingAnimated() { + return m_bIsBeingAnimated; + } + /* sets a function to be ran when the animation finishes. if an animation is not running, runs instantly. if "remove" is set to true, will remove the callback when ran. */ @@ -245,20 +135,7 @@ class CAnimatedVariable { m_bRemoveEndAfterRan = false; } - private: - Vector2D m_vValue = Vector2D(0, 0); - float m_fValue = 0; - CColor m_cValue; - - Vector2D m_vGoal = Vector2D(0, 0); - float m_fGoal = 0; - CColor m_cGoal; - - Vector2D m_vBegun = Vector2D(0, 0); - float m_fBegun = 0; - CColor m_cBegun; - - // owners + protected: void* m_pWindow = nullptr; void* m_pWorkspace = nullptr; void* m_pLayer = nullptr; @@ -271,8 +148,8 @@ class CAnimatedVariable { std::chrono::system_clock::time_point animationBegin; - ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID; AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE; + ANIMATEDVARTYPE m_Type; bool m_bRemoveEndAfterRan = true; bool m_bRemoveBeginAfterRan = true; @@ -281,7 +158,9 @@ class CAnimatedVariable { std::function m_fUpdateCallback; bool m_bIsConnectedToActive = false; + void connectToActive(); + void disconnectFromActive(); // methods @@ -314,3 +193,86 @@ class CAnimatedVariable { friend struct SLayerSurface; friend class CHyprRenderer; }; + +template +class CAnimatedVariable : public CBaseAnimatedVariable { + public: + CAnimatedVariable() : CBaseAnimatedVariable(typeToANIMATEDVARTYPE) {} // dummy var + + void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) { + create(pAnimConfig, pWindow, policy); + m_Value = value; + m_Goal = value; + } + + using CBaseAnimatedVariable::create; + + CAnimatedVariable(const CAnimatedVariable&) = delete; + CAnimatedVariable(CAnimatedVariable&&) = delete; + CAnimatedVariable& operator=(const CAnimatedVariable&) = delete; + CAnimatedVariable& operator=(CAnimatedVariable&&) = delete; + + ~CAnimatedVariable() = default; + + // gets the current vector value (real time) + const VarType& value() const { + return m_Value; + } + + // gets the goal vector value + const VarType& goal() const { + return m_Goal; + } + + CAnimatedVariable& operator=(const VarType& v) { + if (v == m_Goal) + return *this; + + m_Goal = v; + animationBegin = std::chrono::system_clock::now(); + m_Begun = m_Value; + + onAnimationBegin(); + + return *this; + } + + // Sets the actual stored value, without affecting the goal, but resets the timer + void setValue(const VarType& v) { + if (v == m_Value) + return; + + m_Value = v; + animationBegin = std::chrono::system_clock::now(); + m_Begun = m_Value; + + onAnimationBegin(); + } + + // Sets the actual value and goal + void setValueAndWarp(const VarType& v) { + m_Goal = v; + warp(); + } + + void warp(bool endCallback = true) override { + m_Value = m_Goal; + + m_bIsBeingAnimated = false; + + if (endCallback) + onAnimationEnd(); + } + + private: + VarType m_Value{}; + VarType m_Goal{}; + VarType m_Begun{}; + + // owners + + friend class CAnimationManager; + friend class CWorkspace; + friend struct SLayerSurface; + friend class CHyprRenderer; +}; diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp index 59578f23..e9e0eeeb 100644 --- a/src/helpers/Box.cpp +++ b/src/helpers/Box.cpp @@ -116,6 +116,24 @@ CBox& CBox::noNegativeSize() { return *this; } +CBox& CBox::intersection(const CBox other) { + const float newTop = std::max(y, other.y); + const float newBottom = std::min(y + h, other.y + other.h); + const float newLeft = std::max(x, other.x); + const float newRight = std::min(x + w, other.x + other.w); + y = newTop; + x = newLeft; + w = newRight - newLeft; + h = newBottom - newTop; + + if (w <= 0 || h <= 0) { + w = 0; + h = 0; + } + + return *this; +} + CBox CBox::roundInternal() { float newW = x + w - std::floor(x); float newH = y + h - std::floor(y); diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp index fd31a7b7..e38d6108 100644 --- a/src/helpers/Box.hpp +++ b/src/helpers/Box.hpp @@ -52,6 +52,7 @@ class CBox { CBox& addExtents(const SWindowDecorationExtents& e); CBox& expand(const double& value); CBox& noNegativeSize(); + CBox& intersection(const CBox other); CBox copy() const; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 2905ce2b..2b83832c 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -649,8 +649,8 @@ int64_t getPPIDof(int64_t pid) { return 0; #else - std::string dir = "/proc/" + std::to_string(pid) + "/status"; - FILE* infile; + std::string dir = "/proc/" + std::to_string(pid) + "/status"; + FILE* infile; infile = fopen(dir.c_str(), "r"); if (!infile) @@ -722,6 +722,32 @@ int64_t configStringToInt(const std::string& VALUE) { return std::stoll(VALUE); } +Vector2D configStringToVector2D(const std::string& VALUE) { + std::istringstream iss(VALUE); + std::string token; + + if (!std::getline(iss, token, ' ') && !std::getline(iss, token, ',')) + throw std::invalid_argument("Invalid string format"); + + if (!isNumber(token)) + throw std::invalid_argument("Invalid x value"); + + long long x = std::stoll(token); + + if (!std::getline(iss, token)) + throw std::invalid_argument("Invalid string format"); + + if (!isNumber(token)) + throw std::invalid_argument("Invalid y value"); + + long long y = std::stoll(token); + + if (std::getline(iss, token)) + throw std::invalid_argument("Invalid string format"); + + return Vector2D(x, y); +} + double normalizeAngleRad(double ang) { if (ang > M_PI * 2) { while (ang > M_PI * 2) diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 23fc6e5a..d8a86b95 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -28,6 +28,7 @@ void logSystemInfo(); std::string execAndGet(const char*); int64_t getPPIDof(int64_t pid); int64_t configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); std::optional getPlusMinusKeywordResult(std::string in, float relative); void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); double normalizeAngleRad(double ang); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 2dd2a2d9..9126f936 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -4,6 +4,8 @@ #include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" + int ratHandler(void* data) { g_pHyprRenderer->renderMonitor((CMonitor*)data); @@ -54,11 +56,12 @@ void CMonitor::onConnect(bool noRule) { szDescription = output->description ? output->description : ""; // remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description - szDescription.erase(std::remove(szDescription.begin(), szDescription.end(), ','), szDescription.end()); + std::erase(szDescription, ','); // field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix szShortDescription = removeBeginEndSpacesTabs(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : "")); + std::erase(szShortDescription, ','); if (!wlr_backend_is_drm(output->backend)) createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable @@ -161,8 +164,6 @@ void CMonitor::onConnect(bool noRule) { wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y); - wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale); - Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output); setupDefaultWS(monitorRule); @@ -189,8 +190,6 @@ void CMonitor::onConnect(bool noRule) { if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet g_pCompositor->setActiveMonitor(this); - wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale); - g_pHyprRenderer->arrangeLayersForMonitor(ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); @@ -330,8 +329,8 @@ void CMonitor::onDisconnect(bool destroy) { } void CMonitor::addDamage(const pixman_region32_t* rg) { - static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor"); - if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { + static auto PZOOMFACTOR = CConfigValue("misc:cursor_zoom_factor"); + if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { wlr_damage_ring_add_whole(&damage); g_pCompositor->scheduleFrameForMonitor(this); } else if (wlr_damage_ring_add(&damage, rg)) @@ -343,8 +342,8 @@ void CMonitor::addDamage(const CRegion* rg) { } void CMonitor::addDamage(const CBox* box) { - static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor"); - if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { + static auto PZOOMFACTOR = CConfigValue("misc:cursor_zoom_factor"); + if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { wlr_damage_ring_add_whole(&damage); g_pCompositor->scheduleFrameForMonitor(this); } @@ -361,9 +360,8 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const { if (selector.starts_with("desc:")) { // match by description const auto DESCRIPTIONSELECTOR = selector.substr(5); - const auto DESCRIPTION = removeBeginEndSpacesTabs(szDescription.substr(0, szDescription.find_first_of('('))); - return DESCRIPTIONSELECTOR == szDescription || DESCRIPTIONSELECTOR == DESCRIPTION; + return DESCRIPTIONSELECTOR == szShortDescription || DESCRIPTIONSELECTOR == szDescription; } else { // match by selector return szName == selector; @@ -412,9 +410,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { if (newDefaultWorkspaceName == "") newDefaultWorkspaceName = std::to_string(WORKSPACEID); - PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique(ID, newDefaultWorkspaceName)).get(); - - PNEWWORKSPACE->m_iID = WORKSPACEID; + PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique(WORKSPACEID, ID, newDefaultWorkspaceName)).get(); } activeWorkspace = PNEWWORKSPACE->m_iID; @@ -568,11 +564,11 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool } if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) { - static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse"); - CWindow* pWindow = pWorkspace->getLastFocusedWindow(); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + CWindow* pWindow = pWorkspace->getLastFocusedWindow(); if (!pWindow) { - if (**PFOLLOWMOUSE == 1) + if (*PFOLLOWMOUSE == 1) pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!pWindow) @@ -591,6 +587,7 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); g_pEventManager->postEvent(SHyprIPCEvent{"workspace", pWorkspace->m_szName}); + g_pEventManager->postEvent(SHyprIPCEvent{"workspacev2", std::format("{},{}", pWorkspace->m_iID, pWorkspace->m_szName)}); EMIT_HOOK_EVENT("workspace", pWorkspace); } @@ -601,6 +598,12 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool g_pConfigManager->ensureVRR(this); g_pCompositor->updateSuspendedStates(); + + if (specialWorkspaceID) { + const auto PSPECIALWS = g_pCompositor->getWorkspaceByID(specialWorkspaceID); + if (PSPECIALWS->m_bHasFullscreenWindow) + g_pCompositor->updateFullscreenFadeOnWorkspace(PSPECIALWS); + } } void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) { @@ -626,6 +629,10 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { else g_pInputManager->refocus(); + g_pCompositor->updateFullscreenFadeOnWorkspace(PWORKSPACE); + + g_pConfigManager->ensureVRR(this); + g_pCompositor->updateSuspendedStates(); return; @@ -643,6 +650,10 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { PMONITORWORKSPACEOWNER->specialWorkspaceID = 0; g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITORWORKSPACEOWNER->ID); g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + PMONITORWORKSPACEOWNER->szName}); + + const auto PACTIVEWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITORWORKSPACEOWNER->activeWorkspace); + g_pCompositor->updateFullscreenFadeOnWorkspace(PACTIVEWORKSPACE); + animate = false; } @@ -661,11 +672,11 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) { // if it's floating and the middle isnt on the current mon, move it to the center const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); - Vector2D pos = w->m_vRealPosition.goalv(); + Vector2D pos = w->m_vRealPosition.goal(); if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x, PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) { // not on any monitor, center - pos = middle() / 2.f - w->m_vRealSize.goalv() / 2.f; + pos = middle() / 2.f - w->m_vRealSize.goal() / 2.f; } else pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition; @@ -686,6 +697,10 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { g_pHyprRenderer->damageMonitor(this); + g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); + + g_pConfigManager->ensureVRR(this); + g_pCompositor->updateSuspendedStates(); } diff --git a/src/helpers/Splashes.hpp b/src/helpers/Splashes.hpp index e7a1cb5f..4a4fd022 100644 --- a/src/helpers/Splashes.hpp +++ b/src/helpers/Splashes.hpp @@ -75,6 +75,8 @@ inline const std::vector SPLASHES = { "Join the discord server!", "Thanks ThatOneCalculator!", "The AUR packages always work, except for the times they don't.", - "Funny animation compositor woo" + "Funny animation compositor woo", + // + "2 years!" // clang-format on }; \ No newline at end of file diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp deleted file mode 100644 index b4ea6d85..00000000 --- a/src/helpers/SubsurfaceTree.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#include "SubsurfaceTree.hpp" -#include "../events/Events.hpp" -#include "../Compositor.hpp" - -void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) { - if (!node->pSurface || !node->pSurface->exists()) - return; - - *lx += node->pSurface->wlr()->current.dx; - *ly += node->pSurface->wlr()->current.dy; - - if (node->offsetfn) { - // This is the root node - RASSERT(!node->pSubsurface, "Node had no subsurface!"); - node->offsetfn(node->globalOffsetData, lx, ly); - } else { - RASSERT(node->pSubsurface, "Node had no subsurface!"); - - *lx += node->pSubsurface->pSubsurface->current.x; - *ly += node->pSubsurface->pSubsurface->current.y; - - addSurfaceGlobalOffset(node->pParent, lx, ly); - } -} - -SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) { - const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back(); - - if (pSurface->data) - PNODE->pSurface = (CWLSurface*)pSurface->data; - else { - PNODE->pInternalSurface = pSurface; - PNODE->pSurface = &PNODE->pInternalSurface; - } - - PNODE->pWindowOwner = pWindow; - - PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode"); - PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode"); - PNODE->hyprListener_destroy.initCallback(&pSurface->events.destroy, &Events::listener_destroySubsurfaceNode, PNODE, "SurfaceTreeNode"); - - wlr_subsurface* wlrSubsurface; - wl_list_for_each(wlrSubsurface, &pSurface->current.subsurfaces_below, current.link) { - Events::listener_newSubsurfaceNode(PNODE, wlrSubsurface); - } - wl_list_for_each(wlrSubsurface, &pSurface->current.subsurfaces_above, current.link) { - Events::listener_newSubsurfaceNode(PNODE, wlrSubsurface); - } - - return PNODE; -} - -SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) { - const auto PNODE = createTree(surface, pWindow); - PNODE->pParent = pParent; - PNODE->pSubsurface = pSubsurface; - - Debug::log(LOG, "Creating a subsurface Node! {}", pWindow); - - return PNODE; -} - -SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) { - const auto PNODE = createTree(pSurface, pWindow); - - Debug::log(LOG, "Creating a surfaceTree Root! {}", pWindow); - - PNODE->offsetfn = fn; - PNODE->globalOffsetData = data; - - return PNODE; -} - -void destroySubsurface(SSubsurface* pSubsurface); - -void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) { - bool exists = false; - for (auto& n : surfaceTreeNodes) { - if (&n == pNode) { - exists = true; - break; - } - } - - if (!exists) { - Debug::log(ERR, "Tried to remove a SurfaceTreeNode that doesn't exist?? (Node {:x})", (uintptr_t)pNode); - return; - } - - for (auto& c : pNode->childSubsurfaces) - destroySubsurface(&c); - - pNode->childSubsurfaces.clear(); - - pNode->hyprListener_commit.removeCallback(); - pNode->hyprListener_destroy.removeCallback(); - pNode->hyprListener_newSubsurface.removeCallback(); - - // damage - if (pNode->pSurface && pNode->pSurface->exists()) { - CBox extents = {}; - wlr_surface_get_extends(pNode->pSurface->wlr(), extents.pWlr()); - extents.applyFromWlr(); - - int lx = 0, ly = 0; - addSurfaceGlobalOffset(pNode, &lx, &ly); - - extents.x += lx; - extents.y += ly; - - g_pHyprRenderer->damageBox(&extents); - } - - // remove references to this node - for (auto& tn : surfaceTreeNodes) { - for (auto& cs : tn.childSubsurfaces) { - if (cs.pChild == pNode) - cs.pChild = nullptr; - } - } - - surfaceTreeNodes.remove(*pNode); - - Debug::log(LOG, "SurfaceTree Node removed"); -} - -void destroySubsurface(SSubsurface* pSubsurface) { - if (pSubsurface->pChild) { - SubsurfaceTree::destroySurfaceTree(pSubsurface->pChild); - pSubsurface->pChild = nullptr; - } - - pSubsurface->hyprListener_destroy.removeCallback(); - pSubsurface->hyprListener_map.removeCallback(); - pSubsurface->hyprListener_unmap.removeCallback(); -} - -// -// Subsurface listeners -// - -void Events::listener_newSubsurfaceNode(void* owner, void* data) { - SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner; - - const auto PSUBSURFACE = (wlr_subsurface*)data; - - const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back(); - - Debug::log(LOG, "Added a new subsurface {:x}", (uintptr_t)PSUBSURFACE); - - PNEWSUBSURFACE->pSubsurface = PSUBSURFACE; - PNEWSUBSURFACE->pParent = pNode; - - PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->surface->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface"); - PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->surface->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface"); - PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface"); - - PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner; - - if (PSUBSURFACE->surface->mapped) - listener_mapSubsurface(PNEWSUBSURFACE, nullptr); - - wlr_subsurface* existingWlrSubsurface; - wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) { - listener_newSubsurfaceNode(pNode, existingWlrSubsurface); - } - wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_above, current.link) { - listener_newSubsurfaceNode(pNode, existingWlrSubsurface); - } -} - -void Events::listener_mapSubsurface(void* owner, void* data) { - SSubsurface* subsurface = (SSubsurface*)owner; - - if (subsurface->pChild) - return; - - Debug::log(LOG, "Subsurface {:x} mapped", (uintptr_t)subsurface->pSubsurface); - - subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner); - - if (subsurface->pWindowOwner) - subsurface->pWindowOwner->updateSurfaceScaleTransformDetails(); -} - -void Events::listener_unmapSubsurface(void* owner, void* data) { - SSubsurface* subsurface = (SSubsurface*)owner; - - Debug::log(LOG, "Subsurface {:x} unmapped", (uintptr_t)subsurface); - - if (subsurface->pSubsurface->surface == g_pCompositor->m_pLastFocus) - g_pInputManager->releaseAllMouseButtons(); - - if (subsurface->pChild) { - const auto PNODE = subsurface->pChild; - - const auto IT = - std::find_if(SubsurfaceTree::surfaceTreeNodes.begin(), SubsurfaceTree::surfaceTreeNodes.end(), [&](const SSurfaceTreeNode& other) { return &other == PNODE; }); - - if (IT != SubsurfaceTree::surfaceTreeNodes.end()) { - if (PNODE->pSurface && PNODE->pSurface->exists()) { - int lx = 0, ly = 0; - addSurfaceGlobalOffset(PNODE, &lx, &ly); - - CBox extents = {lx, ly, 0, 0}; - - extents.width = PNODE->pSurface->wlr()->current.width; - extents.height = PNODE->pSurface->wlr()->current.height; - - g_pHyprRenderer->damageBox(&extents); - } - - // SubsurfaceTree::destroySurfaceTree(subsurface->pChild); - // subsurface->pChild = nullptr; - } - } - - g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface -} - -void Events::listener_commitSubsurface(void* owner, void* data) { - SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner; - - // no damaging if it's not visible - if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) { - pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{}; - - static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); - if (**PLOGDAMAGE) - Debug::log(LOG, "Refusing to commit damage from {} because it's invisible.", pNode->pWindowOwner); - return; - } - - int lx = 0, ly = 0; - - addSurfaceGlobalOffset(pNode, &lx, &ly); - - const double SCALE = pNode->pWindowOwner && pNode->pWindowOwner->m_bIsX11 ? 1.0 / pNode->pWindowOwner->m_fX11SurfaceScaledBy : 1.0; - - // I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox) - // What this does is that basically, if the pNode is a child of some other node, on commit, - // it will also damage (check & damage if needed) all its siblings. - if (pNode->pParent) - for (auto& cs : pNode->pParent->childSubsurfaces) { - const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D(); - - if (&cs != pNode->pSubsurface && cs.pSubsurface) { - g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y, SCALE); - } - } - - if (pNode->pSurface && pNode->pSurface->exists()) { - g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE); - - if (pNode->lastSize != Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} && pNode->pWindowOwner) - g_pHyprRenderer->damageWindow(pNode->pWindowOwner); - } - - if (pNode->pWindowOwner) { - if (pNode->pWindowOwner->m_bIsX11) - pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. - - // tearing: if solitary, redraw it. This still might be a single surface window - const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); - if (PMONITOR && PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear && - pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { - CRegion damageBox{&pNode->pSurface->wlr()->buffer_damage}; - - if (!damageBox.empty()) { - if (PMONITOR->tearingState.busy) { - PMONITOR->tearingState.frameScheduledWhileBusy = true; - } else { - PMONITOR->tearingState.nextRenderTorn = true; - g_pHyprRenderer->renderMonitor(PMONITOR); - } - } - } - } - - pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{}; -} - -void Events::listener_destroySubsurface(void* owner, void* data) { - SSubsurface* subsurface = (SSubsurface*)owner; - - if (subsurface->pChild) { - SubsurfaceTree::destroySurfaceTree(subsurface->pChild); - } - - Debug::log(LOG, "Subsurface {:x} destroyed", (uintptr_t)subsurface); - - subsurface->hyprListener_destroy.removeCallback(); - subsurface->hyprListener_map.removeCallback(); - subsurface->hyprListener_unmap.removeCallback(); - - subsurface->pParent->childSubsurfaces.remove(*subsurface); -} - -void Events::listener_destroySubsurfaceNode(void* owner, void* data) { - SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner; - - Debug::log(LOG, "Subsurface Node {:x} destroyed", (uintptr_t)pNode); - - for (auto& c : pNode->childSubsurfaces) - destroySubsurface(&c); - - pNode->hyprListener_commit.removeCallback(); - pNode->hyprListener_newSubsurface.removeCallback(); - pNode->hyprListener_destroy.removeCallback(); - - SubsurfaceTree::surfaceTreeNodes.remove(*pNode); -} diff --git a/src/helpers/SubsurfaceTree.hpp b/src/helpers/SubsurfaceTree.hpp deleted file mode 100644 index 7a8b8fb8..00000000 --- a/src/helpers/SubsurfaceTree.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include "../defines.hpp" -#include -#include "WLSurface.hpp" - -struct SSubsurface; -class CWindow; - -typedef void (*applyGlobalOffsetFn)(void*, int*, int*); - -struct SSurfaceTreeNode { - CWLSurface* pSurface = nullptr; // actual surface - CWLSurface pInternalSurface; // not present for head nodes to not dupe wlr_surface ownership - - DYNLISTENER(newSubsurface); - DYNLISTENER(commit); - DYNLISTENER(destroy); - - SSurfaceTreeNode* pParent = nullptr; - SSubsurface* pSubsurface = nullptr; - - std::list childSubsurfaces; - - applyGlobalOffsetFn offsetfn; - void* globalOffsetData; - CWindow* pWindowOwner = nullptr; - - Vector2D lastSize; - - // - bool operator==(const SSurfaceTreeNode& rhs) const { - return pSurface == rhs.pSurface; - } -}; - -struct SSubsurface { - wlr_subsurface* pSubsurface = nullptr; - - SSurfaceTreeNode* pParent = nullptr; - SSurfaceTreeNode* pChild = nullptr; - - DYNLISTENER(map); - DYNLISTENER(unmap); - DYNLISTENER(destroy); - - CWindow* pWindowOwner = nullptr; - - // - bool operator==(const SSubsurface& rhs) const { - return pSubsurface == rhs.pSubsurface; - } -}; - -namespace SubsurfaceTree { - SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr); - void destroySurfaceTree(SSurfaceTreeNode*); - - inline std::list surfaceTreeNodes; -}; diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp index 960145b9..c71271c8 100644 --- a/src/helpers/WLClasses.cpp +++ b/src/helpers/WLClasses.cpp @@ -3,9 +3,17 @@ #include "../Compositor.hpp" SLayerSurface::SLayerSurface() { - alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE); - alpha.m_pLayer = this; + alpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeLayers"), nullptr, AVARDAMAGE_ENTIRE); + realPosition.create(g_pConfigManager->getAnimationPropertyConfig("layers"), nullptr, AVARDAMAGE_ENTIRE); + realSize.create(g_pConfigManager->getAnimationPropertyConfig("layers"), nullptr, AVARDAMAGE_ENTIRE); + alpha.m_pLayer = this; + realPosition.m_pLayer = this; + realSize.m_pLayer = this; alpha.registerVar(); + realPosition.registerVar(); + realSize.registerVar(); + + alpha.setValueAndWarp(0.f); } SLayerSurface::~SLayerSurface() { @@ -22,6 +30,7 @@ void SLayerSurface::applyRules() { ignoreAlpha = false; ignoreAlphaValue = 0.f; xray = -1; + animationStyle.reset(); for (auto& rule : g_pConfigManager->getMatchingRules(this)) { if (rule.rule == "noanim") @@ -44,82 +53,193 @@ void SLayerSurface::applyRules() { try { xray = configStringToInt(vars[1]); } catch (...) {} + } else if (rule.rule.starts_with("animation")) { + CVarList vars{rule.rule, 2, 's'}; + animationStyle = vars[1]; } } } -CRegion SConstraint::getLogicCoordsRegion() { - CRegion result; +void SLayerSurface::startAnimation(bool in, bool instant) { + const auto ANIMSTYLE = animationStyle.value_or(realPosition.m_pConfig->pValues->internalStyle); - if (!constraint) - return result; + if (ANIMSTYLE == "slide") { + // get closest edge + const auto MIDDLE = geometry.middle(); - const auto PWINDOWOWNER = g_pCompositor->getWindowFromSurface(constraint->surface); + const auto PMONITOR = g_pCompositor->getMonitorFromVector(MIDDLE); - if (!PWINDOWOWNER) - return result; + const std::array edgePoints = { + PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0}, + PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y}, + PMONITOR->vecPosition + Vector2D{0, PMONITOR->vecSize.y}, + PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, + }; - result.add(&constraint->region); // surface-local coords + float closest = std::numeric_limits::max(); + size_t leader = 0; + for (size_t i = 0; i < 4; ++i) { + float dist = MIDDLE.distance(edgePoints[i]); + if (dist < closest) { + leader = i; + closest = dist; + } + } - if (!PWINDOWOWNER->m_bIsX11) { - result.translate(PWINDOWOWNER->m_vRealPosition.goalv()); - return result; + realSize.setValueAndWarp(geometry.size()); + alpha.setValueAndWarp(1.f); + + Vector2D prePos; + + switch (leader) { + case 0: + // TOP + prePos = {geometry.x, PMONITOR->vecPosition.y - geometry.h}; + break; + case 1: + // BOTTOM + prePos = {geometry.x, PMONITOR->vecPosition.y + PMONITOR->vecPosition.y}; + break; + case 2: + // LEFT + prePos = {PMONITOR->vecPosition.x - geometry.w, geometry.y}; + break; + case 3: + // RIGHT + prePos = {PMONITOR->vecPosition.x + PMONITOR->vecSize.x, geometry.y}; + break; + default: UNREACHABLE(); + } + + if (in) { + realPosition.setValueAndWarp(prePos); + realPosition = geometry.pos(); + } else { + realPosition.setValueAndWarp(geometry.pos()); + realPosition = prePos; + } + + } else if (ANIMSTYLE.starts_with("popin")) { + float minPerc = 0.f; + if (ANIMSTYLE.find("%") != std::string::npos) { + try { + auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ')); + minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { + ; // oops + } + } + + minPerc *= 0.01; + + const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5}); + const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f; + + alpha.setValueAndWarp(in ? 0.f : 1.f); + alpha = in ? 1.f : 0.f; + + if (in) { + realSize.setValueAndWarp(GOALSIZE); + realPosition.setValueAndWarp(GOALPOS); + realSize = geometry.size(); + realPosition = geometry.pos(); + } else { + realSize.setValueAndWarp(geometry.size()); + realPosition.setValueAndWarp(geometry.pos()); + realSize = GOALSIZE; + realPosition = GOALPOS; + } + } else { + // fade + realPosition.setValueAndWarp(geometry.pos()); + realSize.setValueAndWarp(geometry.size()); + alpha = in ? 1.f : 0.f; } - const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goalv() : - g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y}); - - const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ? g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) : g_pCompositor->getMonitorFromVector(COORDS); - - if (!PMONITOR) - return CRegion{}; - - result.scale(PMONITOR->xwaylandScale); - - result.translate(COORDS); - - return result; + if (!in) + fadingOut = true; } -Vector2D SConstraint::getLogicConstraintPos() { - if (!constraint) - return {}; +bool SLayerSurface::isFadedOut() { + if (!fadingOut) + return false; - const auto PWINDOWOWNER = g_pCompositor->getWindowFromSurface(constraint->surface); - - if (!PWINDOWOWNER) - return {}; - - if (!PWINDOWOWNER->m_bIsX11) - return PWINDOWOWNER->m_vRealPosition.goalv(); - - const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goalv() : - g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y}); - - return COORDS; + return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated(); } -Vector2D SConstraint::getLogicConstraintSize() { - if (!constraint) - return {}; +void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { + xkb_state_unref(xkbTranslationState); - const auto PWINDOWOWNER = g_pCompositor->getWindowFromSurface(constraint->surface); + if (keymap) { + Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); + xkbTranslationState = xkb_state_new(keymap); + return; + } - if (!PWINDOWOWNER) - return {}; + const auto WLRKB = wlr_keyboard_from_input_device(keyboard); + const auto KEYMAP = WLRKB->keymap; + const auto STATE = WLRKB->xkb_state; + const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); - if (!PWINDOWOWNER->m_bIsX11) - return PWINDOWOWNER->m_vRealSize.goalv(); + const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ? - g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) : - g_pCompositor->getMonitorFromVector(g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y})); + for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { + if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { + Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i); - if (!PMONITOR) - return {}; + CVarList keyboardLayouts(currentRules.layout, 0, ','); + CVarList keyboardModels(currentRules.model, 0, ','); + CVarList keyboardVariants(currentRules.variant, 0, ','); - const auto SIZE = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealSize.goalv() : - Vector2D{PWINDOWOWNER->m_uSurface.xwayland->width, PWINDOWOWNER->m_uSurface.xwayland->height} * PMONITOR->xwaylandScale; + xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""}; - return SIZE; -} \ No newline at end of file + std::string layout, model, variant; + layout = keyboardLayouts[i % keyboardLayouts.size()]; + model = keyboardModels[i % keyboardModels.size()]; + variant = keyboardVariants[i % keyboardVariants.size()]; + + rules.layout = layout.c_str(); + rules.model = model.c_str(); + rules.variant = variant.c_str(); + + auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!KEYMAP) { + Debug::log(ERR, "updateXKBTranslationState: keymap failed 1, fallback without model/variant"); + rules.model = ""; + rules.variant = ""; + KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + if (!KEYMAP) { + Debug::log(ERR, "updateXKBTranslationState: keymap failed 2, fallback to us"); + rules.layout = "us"; + KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + xkbTranslationState = xkb_state_new(KEYMAP); + + xkb_keymap_unref(KEYMAP); + xkb_context_unref(PCONTEXT); + + return; + } + } + + Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this); + + xkb_rule_names rules = { + .rules = currentRules.rules.c_str(), + .model = currentRules.model.c_str(), + .layout = currentRules.layout.c_str(), + .variant = currentRules.variant.c_str(), + .options = currentRules.options.c_str(), + }; + + const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + xkbTranslationState = xkb_state_new(NEWKEYMAP); + + xkb_keymap_unref(NEWKEYMAP); + xkb_context_unref(PCONTEXT); +} diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 6cc9b5d5..5fc2692a 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -4,9 +4,10 @@ #include "../defines.hpp" #include "wlr-layer-shell-unstable-v1-protocol.h" #include "../Window.hpp" -#include "SubsurfaceTree.hpp" +#include "../desktop/Subsurface.hpp" +#include "../desktop/Popup.hpp" #include "AnimatedVariable.hpp" -#include "WLSurface.hpp" +#include "../desktop/WLSurface.hpp" #include "Region.hpp" struct SLayerRule { @@ -18,42 +19,50 @@ struct SLayerSurface { SLayerSurface(); ~SLayerSurface(); - void applyRules(); + void applyRules(); + void startAnimation(bool in, bool instant = false); + bool isFadedOut(); - wlr_layer_surface_v1* layerSurface; - wl_list link; + CAnimatedVariable realPosition; + CAnimatedVariable realSize; - bool keyboardExclusive = false; + wlr_layer_surface_v1* layerSurface; + wl_list link; - CWLSurface surface; - std::list popupSurfaces; + bool keyboardExclusive = false; + + CWLSurface surface; + + // desktop components + std::unique_ptr popupHead; DYNLISTENER(destroyLayerSurface); DYNLISTENER(mapLayerSurface); DYNLISTENER(unmapLayerSurface); DYNLISTENER(commitLayerSurface); - DYNLISTENER(newPopup); - CBox geometry = {0, 0, 0, 0}; - Vector2D position; - zwlr_layer_shell_v1_layer layer; + CBox geometry = {0, 0, 0, 0}; + Vector2D position; + zwlr_layer_shell_v1_layer layer; - bool mapped = false; + bool mapped = false; - int monitorID = -1; + int monitorID = -1; - std::string szNamespace = ""; + std::string szNamespace = ""; - CAnimatedVariable alpha; - bool fadingOut = false; - bool readyToDelete = false; - bool noProcess = false; - bool noAnimations = false; + CAnimatedVariable alpha; + bool fadingOut = false; + bool readyToDelete = false; + bool noProcess = false; + bool noAnimations = false; - bool forceBlur = false; - int xray = -1; - bool ignoreAlpha = false; - float ignoreAlphaValue = 0.f; + bool forceBlur = false; + int xray = -1; + bool ignoreAlpha = false; + float ignoreAlphaValue = 0.f; + + std::optional animationStyle; // For the list lookup bool operator==(const SLayerSurface& rhs) const { @@ -139,6 +148,8 @@ struct SKeyboard { int numlockOn = -1; bool resolveBindsBySym = false; + void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); + // For the list lookup bool operator==(const SKeyboard& rhs) const { return keyboard == rhs.keyboard; @@ -146,20 +157,14 @@ struct SKeyboard { }; struct SMouse { - wlr_input_device* mouse = nullptr; + wlr_input_device* mouse = nullptr; - wlr_pointer_constraint_v1* currentConstraint = nullptr; - bool constraintActive = false; + std::string name = ""; - CRegion confinedTo; + bool virt = false; - std::string name = ""; + bool connected = false; // means connected to the cursor - bool virt = false; - - bool connected = false; // means connected to the cursor - - DYNLISTENER(commitConstraint); DYNLISTENER(destroyMouse); bool operator==(const SMouse& b) const { @@ -167,59 +172,8 @@ struct SMouse { } }; -struct SConstraint { - SMouse* pMouse = nullptr; - wlr_pointer_constraint_v1* constraint = nullptr; - - bool active = false; - - bool hintSet = false; - Vector2D positionHint = {-1, -1}; // the position hint, but will use cursorPosOnActivate if unset - Vector2D cursorPosOnActivate = {-1, -1}; - - DYNLISTENER(setConstraintRegion); - DYNLISTENER(destroyConstraint); - - CRegion getLogicCoordsRegion(); - Vector2D getLogicConstraintPos(); - Vector2D getLogicConstraintSize(); - - // - bool operator==(const SConstraint& b) const { - return constraint == b.constraint; - } -}; - class CMonitor; -struct SXDGPopup { - CWindow* parentWindow = nullptr; - SLayerSurface* parentLS = nullptr; - SXDGPopup* parentPopup = nullptr; - wlr_xdg_popup* popup = nullptr; - CMonitor* monitor = nullptr; - - DYNLISTENER(newPopupFromPopupXDG); - DYNLISTENER(destroyPopupXDG); - DYNLISTENER(mapPopupXDG); - DYNLISTENER(unmapPopupXDG); - DYNLISTENER(commitPopupXDG); - DYNLISTENER(repositionPopupXDG); - - double lx; - double ly; - - Vector2D lastPos = {}; - bool repositionRequested = false; - - SSurfaceTreeNode* pSurfaceTree = nullptr; - - // For the list lookup - bool operator==(const SXDGPopup& rhs) const { - return popup == rhs.popup; - } -}; - struct SSeat { wlr_seat* seat = nullptr; wl_client* exclusiveClient = nullptr; @@ -410,7 +364,7 @@ struct STearingController { DYNLISTENER(set); DYNLISTENER(destroy); - bool operator==(const STearingController& other) { + bool operator==(const STearingController& other) const { return pWlrHint == other.pWlrHint; } }; @@ -420,7 +374,7 @@ struct SShortcutInhibitor { DYNLISTENER(destroy); - bool operator==(const SShortcutInhibitor& other) { + bool operator==(const SShortcutInhibitor& other) const { return pWlrInhibitor == other.pWlrInhibitor; } }; diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp index ce4d2707..afb8a946 100644 --- a/src/helpers/Watchdog.cpp +++ b/src/helpers/Watchdog.cpp @@ -1,6 +1,7 @@ #include "Watchdog.hpp" #include #include "config/ConfigManager.hpp" +#include "../config/ConfigValue.hpp" CWatchdog::~CWatchdog() { m_bExitThread = true; @@ -13,7 +14,7 @@ CWatchdog::CWatchdog() { m_iMainThreadPID = pthread_self(); m_pWatchdog = std::make_unique([this] { - static auto* const PTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout"); + static auto PTIMEOUT = CConfigValue("debug:watchdog_timeout"); while (1337) { std::unique_lock lk(m_mWatchdogMutex); @@ -21,7 +22,7 @@ CWatchdog::CWatchdog() { if (!m_bWillWatch) m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; }); else { - if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(**PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false) + if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false) pthread_kill(m_iMainThreadPID, SIGUSR1); } @@ -37,9 +38,9 @@ CWatchdog::CWatchdog() { } void CWatchdog::startWatching() { - static auto* const PTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout"); + static auto PTIMEOUT = CConfigValue("debug:watchdog_timeout"); - if (**PTIMEOUT == 0) + if (*PTIMEOUT == 0) return; m_tTriggered = std::chrono::high_resolution_clock::now(); diff --git a/src/helpers/XWaylandStubs.hpp b/src/helpers/XWaylandStubs.hpp index 89e0b41f..c21041cd 100644 --- a/src/helpers/XWaylandStubs.hpp +++ b/src/helpers/XWaylandStubs.hpp @@ -167,4 +167,6 @@ inline wlr_xwayland_surface* wlr_xwayland_surface_try_from_wlr_surface(wlr_surfa inline bool wlr_xwayland_or_surface_wants_focus(const wlr_xwayland_surface*) { return false; -} \ No newline at end of file +} + +inline void wlr_xwayland_set_cursor(wlr_xwayland* wlr_xwayland, uint8_t* pixels, uint32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) {} \ No newline at end of file diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 6a91ba87..97a18e8c 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -139,7 +139,7 @@ void CHyprError::draw() { if (m_bQueuedDestroy) { if (!m_fFadeOpacity.isBeingAnimated()) { - if (m_fFadeOpacity.fl() == 0.f) { + if (m_fFadeOpacity.value() == 0.f) { m_bQueuedDestroy = false; m_tTexture.destroyTexture(); m_bIsCreated = false; @@ -164,7 +164,7 @@ void CHyprError::draw() { m_bMonitorChanged = false; - g_pHyprOpenGL->renderTexture(m_tTexture, &monbox, m_fFadeOpacity.fl(), 0); + g_pHyprOpenGL->renderTexture(m_tTexture, &monbox, m_fFadeOpacity.value(), 0); } void CHyprError::destroy() { diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index cee648e2..aaa8bd12 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -16,16 +16,16 @@ class CHyprError { void destroy(); private: - void createQueued(); - std::string m_szQueued = ""; - CColor m_cQueued; - bool m_bQueuedDestroy = false; - bool m_bIsCreated = false; - CTexture m_tTexture; - CAnimatedVariable m_fFadeOpacity; - CBox m_bDamageBox = {0, 0, 0, 0}; + void createQueued(); + std::string m_szQueued = ""; + CColor m_cQueued; + bool m_bQueuedDestroy = false; + bool m_bIsCreated = false; + CTexture m_tTexture; + CAnimatedVariable m_fFadeOpacity; + CBox m_bDamageBox = {0, 0, 0, 0}; - bool m_bMonitorChanged = false; + bool m_bMonitorChanged = false; }; -inline std::unique_ptr g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time. \ No newline at end of file +inline std::unique_ptr g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time. diff --git a/src/includes.hpp b/src/includes.hpp index 961729ad..6a1e5bc3 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -63,7 +63,6 @@ extern "C" { #include #include #include -#include #include #include #include @@ -76,6 +75,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 0f4a5f87..cc4bc0b3 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -1,15 +1,16 @@ #include "DwindleLayout.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { if (children[0]) { - static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split"); - static auto* const PPRESERVESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:preserve_split"); - static auto* const PFLMULT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier"); + static auto PSMARTSPLIT = CConfigValue("dwindle:smart_split"); + static auto PPRESERVESPLIT = CConfigValue("dwindle:preserve_split"); + static auto PFLMULT = CConfigValue("dwindle:split_width_multiplier"); - if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0) - splitTop = box.h * **PFLMULT > box.w; + if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) + splitTop = box.h * *PFLMULT > box.w; if (verticalOverride == true) splitTop = true; @@ -127,29 +128,29 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for const auto PWINDOW = pNode->pWindow; // get specific gaps and rules for this workspace, // if user specified them in config - const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(pNode->workspaceID)); + + if (!g_pCompositor->windowExists(PWINDOW)) { + Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); + onWindowRemovedTiling(PWINDOW); + return; + } if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) return; PWINDOW->updateSpecialRenderData(); - static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only"); - static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in"); - static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out"); - auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData(); - auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData(); + static auto PNOGAPSWHENONLY = CConfigValue("dwindle:no_gaps_when_only"); + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* const PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); + auto* const PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); - auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); - auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); + auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); + auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); - if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) { - Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); - onWindowRemovedTiling(PWINDOW); - return; - } - - CBox nodeBox = pNode->box; + CBox nodeBox = pNode->box; nodeBox.round(); PWINDOW->m_vSize = nodeBox.size(); @@ -157,10 +158,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for 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))) { - 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; @@ -172,7 +173,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft; PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); return; } @@ -215,11 +216,11 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for calcPos = calcPos + RESERVED.topLeft; calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight); - if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) { + if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) && !PWINDOW->m_bIsFullscreen) { // if special, we adjust the coords a bit - static auto* const PSCALEFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor"); + static auto PSCALEFACTOR = CConfigValue("dwindle:special_scale_factor"); - CBox wb = {calcPos + (calcSize - calcSize * **PSCALEFACTOR) / 2.f, calcSize * **PSCALEFACTOR}; + CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; wb.round(); // avoid rounding mess PWINDOW->m_vRealPosition = wb.pos(); @@ -253,12 +254,12 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire return; m_lDwindleNodesData.push_back(SDwindleNodeData()); - const auto PNODE = &m_lDwindleNodesData.back(); + const auto PNODE = &m_lDwindleNodesData.back(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - static auto* const PUSEACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits"); - static auto* const PDEFAULTSPLIT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio"); + static auto PUSEACTIVE = CConfigValue("dwindle:use_active_for_splits"); + static auto PDEFAULTSPLIT = CConfigValue("dwindle:default_split_ratio"); if (direction != DIRECTION_DEFAULT && overrideDirection == DIRECTION_DEFAULT) overrideDirection = direction; @@ -275,13 +276,13 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS); if (PMONITOR->ID == MONFROMCURSOR->ID && - (PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !**PUSEACTIVE) { + (PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) { OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS)); if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR)) OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS); - } else if (**PUSEACTIVE) { + } else if (*PUSEACTIVE) { if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) { OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow); @@ -343,8 +344,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire && pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window m_lDwindleNodesData.remove(*PNODE); - static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current"); - (**USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); OPENINGON->pWindow->setGroupCurrent(pWindow); pWindow->applyGroupRules(); @@ -367,20 +368,20 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire NEWPARENT->workspaceID = OPENINGON->workspaceID; NEWPARENT->pParent = OPENINGON->pParent; NEWPARENT->isNode = true; // it is a node - NEWPARENT->splitRatio = std::clamp(**PDEFAULTSPLIT, 0.1f, 1.9f); + NEWPARENT->splitRatio = std::clamp(*PDEFAULTSPLIT, 0.1f, 1.9f); - const auto PWIDTHMULTIPLIER = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier"); + static auto PWIDTHMULTIPLIER = CConfigValue("dwindle:split_width_multiplier"); // if cursor over first child, make it first, etc - const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * **PWIDTHMULTIPLIER; + const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER; NEWPARENT->splitTop = !SIDEBYSIDE; - static auto* const PFORCESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:force_split"); - static auto* const PERMANENTDIRECTIONOVERRIDE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override"); - static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split"); + static auto PFORCESPLIT = CConfigValue("dwindle:force_split"); + static auto PERMANENTDIRECTIONOVERRIDE = CConfigValue("dwindle:permanent_direction_override"); + static auto PSMARTSPLIT = CConfigValue("dwindle:smart_split"); - bool horizontalOverride = false; - bool verticalOverride = false; + bool horizontalOverride = false; + bool verticalOverride = false; // let user select position -> top, right, bottom, left if (overrideDirection != DIRECTION_DEFAULT) { @@ -401,9 +402,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } // whether or not the override persists after opening one window - if (**PERMANENTDIRECTIONOVERRIDE == 0) + if (*PERMANENTDIRECTIONOVERRIDE == 0) overrideDirection = DIRECTION_DEFAULT; - } else if (**PSMARTSPLIT == 1) { + } else if (*PSMARTSPLIT == 1) { const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2; const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w; const auto DELTA = MOUSECOORDS - PARENT_CENTER; @@ -434,11 +435,11 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire NEWPARENT->children[1] = OPENINGON; } } - } else if (**PFORCESPLIT == 0 || !pWindow->m_bFirstMap) { + } else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) { if ((SIDEBYSIDE && - VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / **PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || + VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || (!SIDEBYSIDE && - VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / **PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { + VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { // we are hovering over the first node, make PNODE first. NEWPARENT->children[1] = OPENINGON; NEWPARENT->children[0] = PNODE; @@ -448,7 +449,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire NEWPARENT->children[1] = PNODE; } } else { - if (**PFORCESPLIT == 1) { + if (*PFORCESPLIT == 1) { NEWPARENT->children[1] = OPENINGON; NEWPARENT->children[0] = PNODE; } else { @@ -467,7 +468,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } // Update the children - if (!verticalOverride && (NEWPARENT->box.w * **PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) { + if (!verticalOverride && (NEWPARENT->box.w * *PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) { // split left/right -> forced OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)}; PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)}; @@ -548,6 +549,27 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { g_pHyprRenderer->damageMonitor(PMONITOR); if (PMONITOR->specialWorkspaceID) { + const auto PSPECIALWS = g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID); + + if (PSPECIALWS->m_bHasFullscreenWindow) { + const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PSPECIALWS->m_iID); + + if (PSPECIALWS->m_efFullscreenMode == FULLSCREEN_FULL) { + PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; + PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; + } else if (PSPECIALWS->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { + SDwindleNodeData fakeNode; + fakeNode.pWindow = PFULLWINDOW; + fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; + fakeNode.workspaceID = PSPECIALWS->m_iID; + PFULLWINDOW->m_vPosition = fakeNode.box.pos(); + PFULLWINDOW->m_vSize = fakeNode.box.size(); + fakeNode.ignoreFullscreenChecks = true; + + applyNodeDataToWindow(&fakeNode); + } + } + const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->specialWorkspaceID); if (TOPNODE && PMONITOR) { @@ -606,13 +628,13 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0)); + PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goal() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goal() + pixResize).y, 20.0)); PWINDOW->updateWindowDecos(); return; } - const auto PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes"); - const auto PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing"); + static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); + static auto PSMARTRESIZING = CConfigValue("dwindle:smart_resizing"); // get some data about our window const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); @@ -625,7 +647,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (!m_PseudoDragFlags.started) { m_PseudoDragFlags.started = true; - const auto pseudoSize = PWINDOW->m_vRealSize.goalv(); + const auto pseudoSize = PWINDOW->m_vRealSize.goal(); const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2))); if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) { @@ -655,7 +677,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn PWINDOW->m_vPseudoSize = {std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, wbox.w), std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, wbox.h)}; PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize; - PNODE->recalcSizePosRecursive(**PANIMATE == 0); + PNODE->recalcSizePosRecursive(*PANIMATE == 0); return; } @@ -669,7 +691,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (DISPLAYBOTTOM && DISPLAYTOP) allowedMovement.y = 0; - if (**PSMARTRESIZING == 1) { + if (*PSMARTRESIZING == 1) { // Identify inner and outer nodes for both directions SDwindleNodeData* PVOUTER = nullptr; SDwindleNodeData* PVINNER = nullptr; @@ -703,14 +725,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (PHINNER) { const auto ORIGINAL = PHINNER->box.w; - PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0); + PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); if (PHINNER->pParent->children[0] == PHINNER) PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9); else PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9); - PHINNER->pParent->recalcSizePosRecursive(**PANIMATE == 0); + PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } else - PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0); + PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } if (PVOUTER) { @@ -718,14 +740,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (PVINNER) { const auto ORIGINAL = PVINNER->box.h; - PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0); + PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); if (PVINNER->pParent->children[0] == PVINNER) PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9); else PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9); - PVINNER->pParent->recalcSizePosRecursive(**PANIMATE == 0); + PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } else - PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0); + PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } } else { // get the correct containers to apply splitratio to @@ -744,11 +766,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (PARENTSIDEBYSIDE) { allowedMovement.x *= 2.f / PPARENT->box.w; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(**PANIMATE == 0); + PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } else { allowedMovement.y *= 2.f / PPARENT->box.h; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(**PANIMATE == 0); + PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } return; @@ -763,11 +785,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (PARENTSIDEBYSIDE) { allowedMovement.x *= 2.f / PPARENT->box.w; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(**PANIMATE == 0); + PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } else { allowedMovement.y *= 2.f / PPARENT->box.h; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(**PANIMATE == 0); + PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } return; @@ -782,8 +804,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9); TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9); - SIDECONTAINER->recalcSizePosRecursive(**PANIMATE == 0); - TOPCONTAINER->recalcSizePosRecursive(**PANIMATE == 0); + SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0); + TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0); } } @@ -791,7 +813,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree if (!g_pCompositor->windowValidMapped(pWindow)) return; - if (on == pWindow->m_bIsFullscreen || g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID)) + if (on == pWindow->m_bIsFullscreen) return; // ignore const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); @@ -805,10 +827,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree // save position and size if floating if (pWindow->m_bIsFloating && on) { - pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv(); - pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv(); - pWindow->m_vPosition = pWindow->m_vRealPosition.goalv(); - pWindow->m_vSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); + pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); + pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); + pWindow->m_vSize = pWindow->m_vRealSize.goal(); } // otherwise, accept it. @@ -853,14 +875,15 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree fakeNode.workspaceID = pWindow->m_iWorkspaceID; pWindow->m_vPosition = fakeNode.box.pos(); pWindow->m_vSize = fakeNode.box.size(); + fakeNode.ignoreFullscreenChecks = true; - applyNodeDataToWindow(&fakeNode, true); + applyNodeDataToWindow(&fakeNode); } } g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); g_pCompositor->changeWindowZOrder(pWindow, true); @@ -940,9 +963,16 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { auto PNODE = getNodeFromWindow(pWindow); auto PNODE2 = getNodeFromWindow(pWindow2); - if (!PNODE2 || !PNODE) { + if (!PNODE2 || !PNODE) return; - } + + const bool FS1 = pWindow->m_bIsFullscreen; + const bool FS2 = pWindow2->m_bIsFullscreen; + + if (FS1) + g_pCompositor->setWindowFullscreen(pWindow, false); + if (FS2) + g_pCompositor->setWindowFullscreen(pWindow2, false); SDwindleNodeData* ACTIVE1 = nullptr; SDwindleNodeData* ACTIVE2 = nullptr; @@ -959,9 +989,8 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { // recalc the workspace getMasterNodeOnWorkspace(PNODE->workspaceID)->recalcSizePosRecursive(); - if (PNODE2->workspaceID != PNODE->workspaceID) { + if (PNODE2->workspaceID != PNODE->workspaceID) getMasterNodeOnWorkspace(PNODE2->workspaceID)->recalcSizePosRecursive(); - } if (ACTIVE1) { ACTIVE1->box = PNODE->box; @@ -977,6 +1006,11 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { g_pHyprRenderer->damageWindow(pWindow); g_pHyprRenderer->damageWindow(pWindow2); + + if (FS1) + g_pCompositor->setWindowFullscreen(pWindow2, true); + if (FS2) + g_pCompositor->setWindowFullscreen(pWindow, true); } void CHyprDwindleLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) { @@ -1093,3 +1127,48 @@ void CHyprDwindleLayout::onEnable() { void CHyprDwindleLayout::onDisable() { m_lDwindleNodesData.clear(); } + +Vector2D CHyprDwindleLayout::predictSizeForNewWindow() { + if (!g_pCompositor->m_pLastMonitor) + return {}; + + // get window candidate + CWindow* candidate = g_pCompositor->m_pLastWindow; + + if (!candidate) + candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + + // create a fake node + SDwindleNodeData node; + + if (!candidate) + return g_pCompositor->m_pLastMonitor->vecSize; + else { + const auto PNODE = getNodeFromWindow(candidate); + + if (!PNODE) + return {}; + + node = *PNODE; + node.pWindow = nullptr; + + CBox box = PNODE->box; + + static auto PFLMULT = CConfigValue("dwindle:split_width_multiplier"); + + bool splitTop = box.h * *PFLMULT > box.w; + + const auto SPLITSIDE = !splitTop; + + if (SPLITSIDE) + node.box = {{}, {box.w / 2.0, box.h}}; + else + node.box = {{}, {box.w, box.h / 2.0}}; + + // TODO: make this better and more accurate + + return node.box.size(); + } + + return {}; +} diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index f5501b28..fc73540a 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -59,6 +59,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual void alterSplitRatio(CWindow*, float, bool); virtual std::string getLayoutName(); virtual void replaceWindowDataWith(CWindow* from, CWindow* to); + virtual Vector2D predictSizeForNewWindow(); virtual void onEnable(); virtual void onDisable(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 49e20435..f992899d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -2,6 +2,7 @@ #include "../defines.hpp" #include "../Compositor.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "../config/ConfigValue.hpp" void IHyprLayout::onWindowCreated(CWindow* pWindow, eDirection direction) { if (pWindow->m_bIsFloating) { @@ -87,7 +88,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { desiredGeometry.y = xy.y; } - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); if (!PMONITOR) { Debug::log(ERR, "{:m} has an invalid monitor in onWindowCreatedFloating!!!", pWindow); @@ -105,7 +106,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { } // reject any windows with size <= 5x5 - if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5) + if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5) pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; if (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) { @@ -113,11 +114,11 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { if (pWindow->m_uSurface.xwayland->x != 0 && pWindow->m_uSurface.xwayland->y != 0) pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords({pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y}); else - pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, - PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f); + pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f, + PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f); } else { - pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, - PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f); + pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f, + PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f); } } else { // we respect the size. @@ -151,8 +152,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { } } - if (**PXWLFORCESCALEZERO && pWindow->m_bIsX11) - pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale; + if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) + pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale; if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) { pWindow->m_vRealPosition.warp(); @@ -160,11 +161,11 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { } if (pWindow->m_iX11Type != 2) { - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); g_pCompositor->changeWindowZOrder(pWindow, true); } else { - pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goal(); pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; } } @@ -172,7 +173,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { void IHyprLayout::onBeginDragWindow() { const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; - m_vBeginDragSizeXY = Vector2D(); + m_iMouseMoveEventCount = 1; + m_vBeginDragSizeXY = Vector2D(); // Window will be floating. Let's check if it's valid. It should be, but I don't like crashing. if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) { @@ -200,22 +202,42 @@ void IHyprLayout::onBeginDragWindow() { if (!DRAGGINGWINDOW->m_bIsFloating) { if (g_pInputManager->dragMode == MBIND_MOVE) { - DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goalv() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); + DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_bIsFloating = true; DRAGGINGWINDOW->m_bDraggingTiled = true; - DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goalv() / 2.f; + DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goal() / 2.f; } } m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); - m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goalv(); - m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv(); + m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goal(); + m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goal(); m_vLastDragXY = m_vBeginDragXY; // get the grab corner - if (m_vBeginDragXY.x < m_vBeginDragPositionXY.x + m_vBeginDragSizeXY.x / 2.0) { + static auto RESIZECORNER = CConfigValue("general:resize_corner"); + if (*RESIZECORNER != 0 && *RESIZECORNER <= 4 && DRAGGINGWINDOW->m_bIsFloating) { + switch (*RESIZECORNER) { + case 1: + m_eGrabbedCorner = CORNER_TOPLEFT; + g_pInputManager->setCursorImageUntilUnset("nw-resize"); + break; + case 2: + m_eGrabbedCorner = CORNER_TOPRIGHT; + g_pInputManager->setCursorImageUntilUnset("ne-resize"); + break; + case 3: + m_eGrabbedCorner = CORNER_BOTTOMRIGHT; + g_pInputManager->setCursorImageUntilUnset("se-resize"); + break; + case 4: + m_eGrabbedCorner = CORNER_BOTTOMLEFT; + g_pInputManager->setCursorImageUntilUnset("sw-resize"); + break; + } + } else if (m_vBeginDragXY.x < m_vBeginDragPositionXY.x + m_vBeginDragSizeXY.x / 2.0) { if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0) { m_eGrabbedCorner = CORNER_TOPLEFT; g_pInputManager->setCursorImageUntilUnset("nw-resize"); @@ -247,6 +269,8 @@ void IHyprLayout::onBeginDragWindow() { void IHyprLayout::onEndDragWindow() { const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; + m_iMouseMoveEventCount = 1; + if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) { if (DRAGGINGWINDOW) { g_pInputManager->unsetCursorImage(); @@ -275,8 +299,8 @@ void IHyprLayout::onEndDragWindow() { return; if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) { - static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current"); - (**USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); pWindow->setGroupCurrent(DRAGGINGWINDOW); DRAGGINGWINDOW->updateWindowDecos(); @@ -302,19 +326,36 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { return; } - static auto TIMER = std::chrono::high_resolution_clock::now(); + static auto TIMER = std::chrono::high_resolution_clock::now(), MSTIMER = TIMER; - const auto SPECIAL = g_pCompositor->isWorkspaceSpecial(DRAGGINGWINDOW->m_iWorkspaceID); + const auto SPECIAL = g_pCompositor->isWorkspaceSpecial(DRAGGINGWINDOW->m_iWorkspaceID); - const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y); - const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y); + const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y); + const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y); - static auto* const PANIMATEMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging"); - static auto* const PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes"); + static auto PANIMATEMOUSE = CConfigValue("misc:animate_mouse_windowdragging"); + static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); - if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) || - (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - TIMER).count() < - 1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate)) + const auto TIMERDELTA = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - TIMER).count(); + const auto MSDELTA = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - MSTIMER).count(); + const auto MSMONITOR = 1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate; + static int totalMs = 0; + bool canSkipUpdate = true; + + MSTIMER = std::chrono::high_resolution_clock::now(); + + if (m_iMouseMoveEventCount == 1) + totalMs = 0; + + if (MSMONITOR > 16.0) { + totalMs += MSDELTA < MSMONITOR ? MSDELTA : std::round(totalMs * 1.0 / m_iMouseMoveEventCount); + m_iMouseMoveEventCount += 1; + + // check if time-window is enough to skip update on 60hz monitor + canSkipUpdate = std::clamp(MSMONITOR - TIMERDELTA, 0.0, MSMONITOR) > totalMs * 1.0 / m_iMouseMoveEventCount; + } + + if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) || (TIMERDELTA < MSMONITOR && canSkipUpdate)) return; TIMER = std::chrono::high_resolution_clock::now(); @@ -325,20 +366,20 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->dragMode == MBIND_MOVE) { - CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goalv()}; + CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goal()}; wb.round(); - if (**PANIMATEMOUSE) + if (*PANIMATEMOUSE) DRAGGINGWINDOW->m_vRealPosition = wb.pos(); else DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal()); } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { - Vector2D MINSIZE = Vector2D(20, 20); - Vector2D MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW); + Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sAdditionalConfigData.minSize.toUnderlying()); + Vector2D MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying()); Vector2D newSize = m_vBeginDragSizeXY; Vector2D newPos = m_vBeginDragPositionXY; @@ -386,7 +427,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { CBox wb = {newPos, newSize}; wb.round(); - if (**PANIMATE) { + if (*PANIMATE) { DRAGGINGWINDOW->m_vRealSize = wb.size(); DRAGGINGWINDOW->m_vRealPosition = wb.pos(); } else { @@ -394,14 +435,14 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); } - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal()); } else { resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); } } // get middle point - Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f; + Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.value() + DRAGGINGWINDOW->m_vRealSize.value() / 2.f; // and check its monitor const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle); @@ -435,18 +476,23 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { EMIT_HOOK_EVENT("changeFloatingMode", pWindow); if (!TILED) { - const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f); + const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); pWindow->m_iMonitorID = PNEWMON->ID; pWindow->moveToWorkspace(PNEWMON->specialWorkspaceID != 0 ? PNEWMON->specialWorkspaceID : PNEWMON->activeWorkspace); pWindow->updateGroupOutputs(); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNEWMON->specialWorkspaceID != 0 ? PNEWMON->specialWorkspaceID : PNEWMON->activeWorkspace); + + if (PWORKSPACE->m_bHasFullscreenWindow) + g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false); + // save real pos cuz the func applies the default 5,5 mid - const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv(); - const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv(); + const auto PSAVEDPOS = pWindow->m_vRealPosition.goal(); + const auto PSAVEDSIZE = pWindow->m_vRealSize.goal(); // if the window is pseudo, update its size if (!pWindow->m_bDraggingTiled) - pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vPseudoSize = pWindow->m_vRealSize.goal(); pWindow->m_vLastFloatingSize = PSAVEDSIZE; @@ -468,10 +514,11 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { g_pCompositor->changeWindowZOrder(pWindow, true); - CBox wb = {pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; + CBox wb = {pWindow->m_vRealPosition.goal() + (pWindow->m_vRealSize.goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; wb.round(); - if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) { + if (DELTALESSTHAN(pWindow->m_vRealSize.value().x, pWindow->m_vLastFloatingSize.x, 10) && + DELTALESSTHAN(pWindow->m_vRealSize.value().y, pWindow->m_vLastFloatingSize.y, 10)) { wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}}; } @@ -505,7 +552,7 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) { return; } - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta; + PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + delta; g_pHyprRenderer->damageWindow(PWINDOW); } @@ -591,6 +638,11 @@ void IHyprLayout::bringWindowToTop(CWindow* pWindow) { void IHyprLayout::requestFocusForWindow(CWindow* pWindow) { bringWindowToTop(pWindow); g_pCompositor->focusWindow(pWindow); + g_pCompositor->warpCursorTo(pWindow->middle()); +} + +Vector2D IHyprLayout::predictSizeForNewWindow() { + return Vector2D{}; } IHyprLayout::~IHyprLayout() {} diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 5c74078e..d3f8dfa6 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -181,7 +181,14 @@ class IHyprLayout { */ virtual void requestFocusForWindow(CWindow*); + /* + Called to predict the size of a newly opened window to send it a configure. + Return 0,0 if unpredictable + */ + virtual Vector2D predictSizeForNewWindow(); + private: + int m_iMouseMoveEventCount; Vector2D m_vBeginDragXY; Vector2D m_vLastDragXY; Vector2D m_vBeginDragPositionXY; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 6a3cd492..9e7f8880 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -3,6 +3,7 @@ #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "config/ConfigDataValues.hpp" #include +#include "../config/ConfigValue.hpp" SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) { for (auto& nd : m_lMasterNodesData) { @@ -42,9 +43,9 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { //create on the fly if it doesn't exist yet const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back(); PWORKSPACEDATA->workspaceID = ws; - const auto orientation = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("master:orientation"); + static auto PORIENTATION = CConfigValue("master:orientation"); const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts; - std::string orientationForWs = *orientation; + std::string orientationForWs = *PORIENTATION; if (layoutoptsForWs.contains("orientation")) orientationForWs = layoutoptsForWs.at("orientation"); @@ -81,26 +82,26 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc if (pWindow->m_bIsFloating) return; - static auto* const PNEWTOP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:new_on_top"); + static auto PNEWTOP = CConfigValue("master:new_on_top"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto PNODE = **PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); + const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); PNODE->workspaceID = pWindow->m_iWorkspaceID; PNODE->pWindow = pWindow; - static auto* const PNEWISMASTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:new_is_master"); + static auto PNEWISMASTER = CConfigValue("master:new_is_master"); - const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); - static auto* const PMFACT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("master:mfact"); - float lastSplitPercent = **PMFACT; + const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); + static auto PMFACT = CConfigValue("master:mfact"); + float lastSplitPercent = *PMFACT; - auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID ? - getNodeFromWindow(g_pCompositor->m_pLastWindow) : - getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID); + auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID ? + getNodeFromWindow(g_pCompositor->m_pLastWindow) : + getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID); - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) { if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) @@ -113,8 +114,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc m_lMasterNodesData.remove(*PNODE); - static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current"); - (**USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); OPENINGON->pWindow->setGroupCurrent(pWindow); pWindow->applyGroupRules(); @@ -129,14 +130,14 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc pWindow->applyGroupRules(); - static auto* const PDROPATCURSOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:drop_at_cursor"); - const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID); - eOrientation orientation = PWORKSPACEDATA->orientation; - const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); + static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); + const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID); + eOrientation orientation = PWORKSPACEDATA->orientation; + const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); - bool forceDropAsMaster = false; + bool forceDropAsMaster = false; // if dragging window to move, drop it at the cursor position instead of bottom/top of stack - if (**PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) { + if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) { if (WINDOWSONWORKSPACE > 2) { for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) { if (it->workspaceID != pWindow->m_iWorkspaceID) @@ -192,7 +193,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc } } - if ((**PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) || + if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) || forceDropAsMaster) { for (auto& nd : m_lMasterNodesData) { if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { @@ -238,16 +239,15 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { if (!PNODE) return; - const auto WORKSPACEID = PNODE->workspaceID; - const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); - static const auto* SMALLSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:allow_small_split"); + const auto WORKSPACEID = PNODE->workspaceID; + const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); + static auto SMALLSPLIT = CConfigValue("master:allow_small_split"); pWindow->updateSpecialRenderData(); - if (pWindow->m_bIsFullscreen) - g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); - if (PNODE->isMaster && (MASTERSLEFT <= 1 || **SMALLSPLIT == 1)) { + if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) { // find a new master from top of the list for (auto& nd : m_lMasterNodesData) { if (!nd.isMaster && nd.workspaceID == WORKSPACEID) { @@ -295,6 +295,28 @@ void CHyprMasterLayout::recalculateMonitor(const int& monid) { g_pHyprRenderer->damageMonitor(PMONITOR); if (PMONITOR->specialWorkspaceID) { + const auto PSPECIALWS = g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID); + + if (PSPECIALWS->m_bHasFullscreenWindow) { + const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PSPECIALWS->m_iID); + + if (PSPECIALWS->m_efFullscreenMode == FULLSCREEN_FULL) { + PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; + PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; + } else if (PSPECIALWS->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { + SMasterNodeData fakeNode; + fakeNode.pWindow = PFULLWINDOW; + fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + fakeNode.workspaceID = PSPECIALWS->m_iID; + PFULLWINDOW->m_vPosition = fakeNode.position; + PFULLWINDOW->m_vSize = fakeNode.size; + fakeNode.ignoreFullscreenChecks = true; + + applyNodeDataToWindow(&fakeNode); + } + } + calculateWorkspace(PMONITOR->specialWorkspaceID); } @@ -337,19 +359,19 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (!PMASTERNODE) return; - eOrientation orientation = PWORKSPACEDATA->orientation; - bool centerMasterWindow = false; - static auto* const ALWAYSCENTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:always_center_master"); - static auto* const PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:smart_resizing"); + eOrientation orientation = PWORKSPACEDATA->orientation; + bool centerMasterWindow = false; + static auto ALWAYSCENTER = CConfigValue("master:always_center_master"); + static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); - 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; + 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 (STACKWINDOWS >= 2 || (**ALWAYSCENTER == 1)) { + if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) { centerMasterWindow = true; } else { orientation = ORIENTATION_LEFT; @@ -362,7 +384,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { float masterAccumulatedSize = 0; float slaveAccumulatedSize = 0; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { // check the total width and height so that later // if larger/smaller than screen size them down/up for (auto& nd : m_lMasterNodesData) { @@ -400,7 +422,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (WIDTH > widthLeft * 0.9f && mastersLeft > 1) WIDTH = widthLeft * 0.9f; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { nd.percSize *= WSSIZE.x / masterAccumulatedSize; WIDTH = masterAverageSize * nd.percSize; } @@ -437,7 +459,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1) HEIGHT = heightLeft * 0.9f; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { nd.percSize *= WSSIZE.y / masterAccumulatedSize; HEIGHT = masterAverageSize * nd.percSize; } @@ -474,7 +496,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (WIDTH > widthLeft * 0.9f && slavesLeft > 1) WIDTH = widthLeft * 0.9f; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { nd.percSize *= WSSIZE.x / slaveAccumulatedSize; WIDTH = slaveAverageSize * nd.percSize; } @@ -504,7 +526,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { nd.percSize *= WSSIZE.y / slaveAccumulatedSize; HEIGHT = slaveAverageSize * nd.percSize; } @@ -535,7 +557,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { const float slaveAverageHeightR = WSSIZE.y / slavesLeftR; float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightR = 0; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { for (auto& nd : m_lMasterNodesData) { if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) continue; @@ -570,7 +592,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; - if (**PSMARTRESIZING) { + if (*PSMARTRESIZING) { if (onRight) { nd.percSize *= WSSIZE.y / slaveAccumulatedHeightR; HEIGHT = slaveAverageHeightR * nd.percSize; @@ -634,15 +656,15 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->updateSpecialRenderData(); - static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only"); - static auto* const PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes"); - static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in"); - static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out"); - auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData(); - auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData(); + static auto PNOGAPSWHENONLY = CConfigValue("master:no_gaps_when_only"); + static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); + auto* PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); - auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); - auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); + auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); + auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); if (!g_pCompositor->windowValidMapped(PWINDOW)) { Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); @@ -652,11 +674,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_vSize = pNode->size; PWINDOW->m_vPosition = pNode->position; - if (**PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) && + if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { - 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; @@ -668,7 +690,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft; PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); return; } @@ -687,10 +709,10 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { calcPos = calcPos + RESERVED.topLeft; calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight); - if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) { - static auto* const PSCALEFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("master:special_scale_factor"); + if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) && !PWINDOW->m_bIsFullscreen) { + static auto PSCALEFACTOR = CConfigValue("master:special_scale_factor"); - CBox wb = {calcPos + (calcSize - calcSize * **PSCALEFACTOR) / 2.f, calcSize * **PSCALEFACTOR}; + CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; wb.round(); // avoid rounding mess PWINDOW->m_vRealPosition = wb.pos(); @@ -732,32 +754,32 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0)); + PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goal() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goal() + pixResize).y, 20.0)); PWINDOW->updateWindowDecos(); return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); - static auto* const ALWAYSCENTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:always_center_master"); - static auto* const PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:smart_resizing"); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); + static auto ALWAYSCENTER = CConfigValue("master:always_center_master"); + static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); - eOrientation orientation = PWORKSPACEDATA->orientation; - bool centered = orientation == ORIENTATION_CENTER && (**ALWAYSCENTER == 1); - double delta = 0; + eOrientation orientation = PWORKSPACEDATA->orientation; + bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1); + double delta = 0; - const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); - const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); - const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); - const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); + const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); + const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); + const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); + const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); - const bool LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT; - const bool TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT; - const bool NONE = corner == CORNER_NONE; + const bool LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT; + const bool TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT; + const bool NONE = corner == CORNER_NONE; - const auto MASTERS = getMastersOnWorkspace(PNODE->workspaceID); - const auto WINDOWS = getNodesOnWorkspace(PNODE->workspaceID); - const auto STACKWINDOWS = WINDOWS - MASTERS; + const auto MASTERS = getMastersOnWorkspace(PNODE->workspaceID); + const auto WINDOWS = getNodesOnWorkspace(PNODE->workspaceID); + const auto STACKWINDOWS = WINDOWS - MASTERS; if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 && !centered) return; @@ -800,7 +822,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto SIZE = isStackVertical ? WSSIZE.y / nodesInSameColumn : WSSIZE.x / nodesInSameColumn; if (RESIZEDELTA != 0 && nodesInSameColumn > 1) { - if (!**PSMARTRESIZING) { + if (!*PSMARTRESIZING) { PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); } else { const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); @@ -870,7 +892,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen if (!g_pCompositor->windowValidMapped(pWindow)) return; - if (on == pWindow->m_bIsFullscreen || g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID)) + if (on == pWindow->m_bIsFullscreen) return; // ignore const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); @@ -884,10 +906,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen // save position and size if floating if (pWindow->m_bIsFloating && on) { - pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv(); - pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv(); - pWindow->m_vPosition = pWindow->m_vRealPosition.goalv(); - pWindow->m_vSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); + pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); + pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); + pWindow->m_vSize = pWindow->m_vRealSize.goal(); } // otherwise, accept it. @@ -941,7 +963,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); g_pCompositor->changeWindowZOrder(pWindow, true); @@ -976,6 +998,8 @@ void CHyprMasterLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) { onWindowRemovedTiling(pWindow); pWindow->moveToWorkspace(PWINDOW2->m_iWorkspaceID); pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID; + const auto pMonitor = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + g_pCompositor->setActiveMonitor(pMonitor); onWindowCreatedTiling(pWindow); } else { // if same monitor, switch windows @@ -992,8 +1016,6 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { if (!PNODE2 || !PNODE) return; - const auto inheritFullscreen = prepareLoseFocus(pWindow); - if (PNODE->workspaceID != PNODE2->workspaceID) { std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID); std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID); @@ -1009,8 +1031,6 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { g_pHyprRenderer->damageWindow(pWindow); g_pHyprRenderer->damageWindow(pWindow2); - - prepareNewFocus(pWindow2, inheritFullscreen); } void CHyprMasterLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) { @@ -1051,35 +1071,27 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) { return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow; } -bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) { - if (!pWindow) - return false; - - //if the current window is fullscreen, make it normal again if we are about to lose focus - if (pWindow->m_bIsFullscreen) { - g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); - static auto* const INHERIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen"); - return **INHERIT == 1; - } - - return false; -} - -void CHyprMasterLayout::prepareNewFocus(CWindow* pWindow, bool inheritFullscreen) { - if (!pWindow) - return; - - if (inheritFullscreen) - g_pCompositor->setWindowFullscreen(pWindow, true, g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_efFullscreenMode); -} - std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) { auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) { if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO)) return; - g_pCompositor->focusWindow(PWINDOWTOCHANGETO); - g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle()); + if (header.pWindow->m_bIsFullscreen) { + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(header.pWindow->m_iWorkspaceID); + const auto FSMODE = PWORKSPACE->m_efFullscreenMode; + static auto INHERITFULLSCREEN = CConfigValue("master:inherit_fullscreen"); + g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); + g_pCompositor->focusWindow(PWINDOWTOCHANGETO); + if (*INHERITFULLSCREEN) + g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE); + } else { + g_pCompositor->focusWindow(PWINDOWTOCHANGETO); + g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle()); + } + + g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO; + g_pInputManager->simulateMouseMovement(); + g_pInputManager->m_pForcedFocus = nullptr; }; CVarList vars(message, 0, ' '); @@ -1113,23 +1125,19 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto NEWCHILD = PMASTER->pWindow; if (PMASTER->pWindow != PWINDOW) { - const auto NEWMASTER = PWINDOW; - const bool newFocusToChild = vars.size() >= 2 && vars[1] == "child"; - const bool inheritFullscreen = prepareLoseFocus(NEWMASTER); + const auto NEWMASTER = PWINDOW; + const bool newFocusToChild = vars.size() >= 2 && vars[1] == "child"; switchWindows(NEWMASTER, NEWCHILD); const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER; switchToWindow(NEWFOCUS); - prepareNewFocus(NEWFOCUS, inheritFullscreen); } else { for (auto& n : m_lMasterNodesData) { if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) { - const auto NEWMASTER = n.pWindow; - const bool inheritFullscreen = prepareLoseFocus(NEWCHILD); + const auto NEWMASTER = n.pWindow; switchWindows(NEWMASTER, NEWCHILD); const bool newFocusToMaster = vars.size() >= 2 && vars[1] == "master"; const auto NEWFOCUS = newFocusToMaster ? NEWMASTER : NEWCHILD; switchToWindow(NEWFOCUS); - prepareNewFocus(NEWFOCUS, inheritFullscreen); break; } } @@ -1147,8 +1155,6 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PWINDOW) return 0; - const bool inheritFullscreen = prepareLoseFocus(PWINDOW); - const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID); if (!PMASTER) @@ -1156,7 +1162,6 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (PMASTER->pWindow != PWINDOW) { switchToWindow(PMASTER->pWindow); - prepareNewFocus(PMASTER->pWindow, inheritFullscreen); } else if (vars.size() >= 2 && vars[1] == "master") { return 0; } else { @@ -1164,7 +1169,6 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri for (auto& n : m_lMasterNodesData) { if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) { switchToWindow(n.pWindow); - prepareNewFocus(n.pWindow, inheritFullscreen); break; } } @@ -1177,22 +1181,16 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PWINDOW) return 0; - const bool inheritFullscreen = prepareLoseFocus(PWINDOW); - const auto PNEXTWINDOW = getNextWindow(PWINDOW, true); switchToWindow(PNEXTWINDOW); - prepareNewFocus(PNEXTWINDOW, inheritFullscreen); } else if (command == "cycleprev") { const auto PWINDOW = header.pWindow; if (!PWINDOW) return 0; - const bool inheritFullscreen = prepareLoseFocus(PWINDOW); - const auto PPREVWINDOW = getNextWindow(PWINDOW, false); switchToWindow(PPREVWINDOW); - prepareNewFocus(PPREVWINDOW, inheritFullscreen); } else if (command == "swapnext") { if (!g_pCompositor->windowValidMapped(header.pWindow)) return 0; @@ -1205,9 +1203,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true); if (PWINDOWTOSWAPWITH) { - prepareLoseFocus(header.pWindow); + g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); switchWindows(header.pWindow, PWINDOWTOSWAPWITH); - g_pCompositor->focusWindow(header.pWindow); + switchToWindow(header.pWindow); } } else if (command == "swapprev") { if (!g_pCompositor->windowValidMapped(header.pWindow)) @@ -1221,9 +1219,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false); if (PWINDOWTOSWAPWITH) { - prepareLoseFocus(header.pWindow); + g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); switchWindows(header.pWindow, PWINDOWTOSWAPWITH); - g_pCompositor->focusWindow(header.pWindow); + switchToWindow(header.pWindow); } } else if (command == "addmaster") { if (!g_pCompositor->windowValidMapped(header.pWindow)) @@ -1232,15 +1230,15 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (header.pWindow->m_bIsFloating) return 0; - const auto PNODE = getNodeFromWindow(header.pWindow); + const auto PNODE = getNodeFromWindow(header.pWindow); - const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID); - const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID); - static const auto* SMALLSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:allow_small_split"); + const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID); + const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID); + static auto SMALLSPLIT = CConfigValue("master:allow_small_split"); - if (MASTERS + 2 > WINDOWS && **SMALLSPLIT == 0) + if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0) return 0; - prepareLoseFocus(header.pWindow); + g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); if (!PNODE || PNODE->isMaster) { // first non-master node @@ -1272,7 +1270,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (WINDOWS < 2 || MASTERS < 2) return 0; - prepareLoseFocus(header.pWindow); + g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); if (!PNODE || !PNODE->isMaster) { // first non-master node @@ -1293,7 +1291,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PWINDOW) return 0; - prepareLoseFocus(PWINDOW); + g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID); @@ -1348,9 +1346,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri nd.isMaster = true; const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd); m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT); - const bool inheritFullscreen = prepareLoseFocus(PWINDOW); switchToWindow(nd.pWindow); - prepareNewFocus(nd.pWindow, inheritFullscreen); OLDMASTER->isMaster = false; m_lMasterNodesData.splice(m_lMasterNodesData.end(), m_lMasterNodesData, OLDMASTERIT); break; @@ -1376,9 +1372,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri nd.isMaster = true; const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd); m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT); - const bool inheritFullscreen = prepareLoseFocus(PWINDOW); switchToWindow(nd.pWindow); - prepareNewFocus(nd.pWindow, inheritFullscreen); OLDMASTER->isMaster = false; m_lMasterNodesData.splice(m_lMasterNodesData.begin(), m_lMasterNodesData, OLDMASTERIT); break; @@ -1405,7 +1399,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi if (!PWINDOW) return; - prepareLoseFocus(PWINDOW); + g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID); @@ -1459,6 +1453,33 @@ void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) { applyNodeDataToWindow(PNODE); } +Vector2D CHyprMasterLayout::predictSizeForNewWindow() { + static auto PNEWISMASTER = CConfigValue("master:new_is_master"); + + if (!g_pCompositor->m_pLastMonitor) + return {}; + + const int NODES = getNodesOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + + if (NODES <= 0) + return g_pCompositor->m_pLastMonitor->vecSize; + + const auto MASTER = getMasterNodeOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + if (!MASTER) // wtf + return {}; + + if (*PNEWISMASTER) { + return MASTER->size; + } else { + const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + + // TODO: make this better + return {g_pCompositor->m_pLastMonitor->vecSize.x - MASTER->size.x, g_pCompositor->m_pLastMonitor->vecSize.y / (SLAVES + 1)}; + } + + return {}; +} + void CHyprMasterLayout::onEnable() { for (auto& w : g_pCompositor->m_vWindows) { if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index e316556a..6f8ea120 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -65,6 +65,7 @@ class CHyprMasterLayout : public IHyprLayout { virtual void alterSplitRatio(CWindow*, float, bool); virtual std::string getLayoutName(); virtual void replaceWindowDataWith(CWindow* from, CWindow* to); + virtual Vector2D predictSizeForNewWindow(); virtual void onEnable(); virtual void onDisable(); @@ -86,8 +87,6 @@ class CHyprMasterLayout : public IHyprLayout { void calculateWorkspace(const int&); CWindow* getNextWindow(CWindow*, bool); int getMastersOnWorkspace(const int&); - bool prepareLoseFocus(CWindow*); - void prepareNewFocus(CWindow*, bool inherit_fullscreen); friend struct SMasterNodeData; friend struct SMasterWorkspaceData; @@ -107,4 +106,4 @@ struct std::formatter : std::formatter { std::format_to(out, ", window: {:x}", node->pWindow); return std::format_to(out, "]"); } -}; \ No newline at end of file +}; diff --git a/src/macros.hpp b/src/macros.hpp index 19b4cbc6..02ca185d 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -6,6 +6,7 @@ #ifndef NDEBUG #ifdef HYPRLAND_DEBUG +#define HYPRLAND_DEBUG #define ISDEBUG true #else #define ISDEBUG false diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 23584827..f9dfa6fa 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -1,6 +1,8 @@ #include "AnimationManager.hpp" #include "../Compositor.hpp" #include "HookSystemManager.hpp" +#include "macros.hpp" +#include "../config/ConfigValue.hpp" int wlTick(void* data) { if (g_pAnimationManager) @@ -51,22 +53,22 @@ void CAnimationManager::tick() { if (m_vActiveAnimatedVariables.empty()) return; - bool animGlobalDisabled = false; + bool animGlobalDisabled = false; - static auto* const PANIMENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("animations:enabled"); + static auto PANIMENABLED = CConfigValue("animations:enabled"); - if (!**PANIMENABLED) + if (!*PANIMENABLED) animGlobalDisabled = true; - static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:drop_shadow"); + static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:drop_shadow"); - const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); + const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); - std::vector animationEndedVars; + std::vector animationEndedVars; for (auto& av : m_vActiveAnimatedVariables) { - if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !**PSHADOWSENABLED) { + if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) { av->warp(false); animationEndedVars.push_back(av); continue; @@ -84,8 +86,13 @@ void CAnimationManager::tick() { CBox WLRBOXPREV = {0, 0, 0, 0}; if (PWINDOW) { - WLRBOXPREV = PWINDOW->getFullWindowBoundingBox(); - PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + CBox bb = PWINDOW->getFullWindowBoundingBox(); + const auto PWINDOWWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); + if (PWINDOWWORKSPACE) + bb.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); + WLRBOXPREV = bb; + + PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); if (!PMONITOR) continue; animationsDisabled = animationsDisabled || PWINDOW->m_sAdditionalConfigData.forceNoAnims; @@ -93,15 +100,29 @@ void CAnimationManager::tick() { PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); if (!PMONITOR) continue; - WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y}; + WLRBOXPREV = {PMONITOR->vecPosition, PMONITOR->vecSize}; // TODO: just make this into a damn callback already vax... for (auto& w : g_pCompositor->m_vWindows) { if (!w->isHidden() && w->m_bIsMapped && w->m_bIsFloating) g_pHyprRenderer->damageWindow(w.get()); } + + // if a workspace window is on any monitor, damage it + for (auto& w : g_pCompositor->m_vWindows) { + for (auto& m : g_pCompositor->m_vMonitors) { + if (w->m_iWorkspaceID == PWORKSPACE->m_iID && g_pCompositor->windowValidMapped(w.get()) && g_pHyprRenderer->shouldRenderWindow(w.get(), m.get(), PWORKSPACE)) { + CBox bb = w->getFullWindowBoundingBox(); + bb.translate(PWORKSPACE->m_vRenderOffset.value()); + if (PWORKSPACE->m_bIsSpecialWorkspace) + bb.scaleFromCenter(1.1); // for some reason special ws windows getting border artifacts if you close it too quickly... + bb.intersection({m->vecPosition, m->vecSize}); + g_pHyprRenderer->damageBox(&bb); + } + } + } } else if (PLAYER) { - WLRBOXPREV = PLAYER->geometry; + WLRBOXPREV = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()}; PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f); if (!PMONITOR) continue; @@ -113,78 +134,48 @@ void CAnimationManager::tick() { // beziers are with a switch unforto // TODO: maybe do something cleaner - switch (av->m_eVarType) { + auto updateVariable = [&](CAnimatedVariable& av) { + // for disabled anims just warp + if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { + av.warp(false); + return; + } + + if (SPENT >= 1.f || av.m_Begun == av.m_Goal) { + av.warp(false); + return; + } + + const auto DELTA = av.m_Goal - av.m_Begun; + const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); + + if (BEZIER != m_mBezierCurves.end()) + av.m_Value = av.m_Begun + DELTA * BEZIER->second.getYForPoint(SPENT); + else + av.m_Value = av.m_Begun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT); + }; + + switch (av->m_Type) { case AVARTYPE_FLOAT: { - // for disabled anims just warp - if (av->m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { - av->warp(false); - break; - } - - if (SPENT >= 1.f || av->m_fBegun == av->m_fGoal) { - av->warp(false); - break; - } - - const auto DELTA = av->m_fGoal - av->m_fBegun; - const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier); - - if (BEZIER != m_mBezierCurves.end()) - av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA; - else - av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA; + auto typedAv = static_cast*>(av); + updateVariable(*typedAv); break; } case AVARTYPE_VECTOR: { - // for disabled anims just warp - if (av->m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { - av->warp(false); - break; - } - - if (SPENT >= 1.f || av->m_vBegun == av->m_vGoal) { - av->warp(false); - break; - } - - const auto DELTA = av->m_vGoal - av->m_vBegun; - const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier); - - if (BEZIER != m_mBezierCurves.end()) - av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT); - else - av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT); + auto typedAv = static_cast*>(av); + updateVariable(*typedAv); break; } case AVARTYPE_COLOR: { - // for disabled anims just warp - if (av->m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { - av->warp(false); - break; - } - - if (SPENT >= 1.f || av->m_cBegun == av->m_cGoal) { - av->warp(false); - break; - } - - const auto DELTA = av->m_cGoal - av->m_cBegun; - const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier); - - if (BEZIER != m_mBezierCurves.end()) - av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT); - else - av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT); + auto typedAv = static_cast*>(av); + updateVariable(*typedAv); break; } - default: { - ; - } + default: UNREACHABLE(); } - // set size and pos if valid, but only if damage policy entire (dont if border for example) if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2) - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); // check if we did not finish animating. If so, trigger onAnimationEnd. if (!av->isBeingAnimated()) @@ -203,7 +194,10 @@ void CAnimationManager::tick() { if (PWINDOW) { PWINDOW->updateWindowDecos(); - g_pHyprRenderer->damageWindow(PWINDOW); + auto bb = PWINDOW->getFullWindowBoundingBox(); + const auto PWINDOWWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); + bb.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); + g_pHyprRenderer->damageBox(&bb); } else if (PWORKSPACE) { for (auto& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden()) @@ -216,7 +210,7 @@ void CAnimationManager::tick() { if (w->m_bIsFloating) { auto bb = w->getFullWindowBoundingBox(); - bb.translate(PWORKSPACE->m_vRenderOffset.vec()); + bb.translate(PWORKSPACE->m_vRenderOffset.value()); g_pHyprRenderer->damageBox(&bb); } } @@ -250,7 +244,10 @@ void CAnimationManager::tick() { BORDERSIZE + ROUNDINGSIZE); // bottom // damage for new box - const CBox WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y}; + CBox WLRBOXNEW = {PWINDOW->m_vRealPosition.value(), PWINDOW->m_vRealSize.value()}; + const auto PWINDOWWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); + if (PWINDOWWORKSPACE) + WLRBOXNEW.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, @@ -323,23 +320,23 @@ bool CAnimationManager::bezierExists(const std::string& bezier) { // void CAnimationManager::animationPopin(CWindow* pWindow, bool close, float minPerc) { - const auto GOALPOS = pWindow->m_vRealPosition.goalv(); - const auto GOALSIZE = pWindow->m_vRealSize.goalv(); + const auto GOALPOS = pWindow->m_vRealPosition.goal(); + const auto GOALSIZE = pWindow->m_vRealSize.goal(); if (!close) { pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); - pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vValue / 2.f); + pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Value / 2.f); } else { pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); - pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vGoal / 2.f; + pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Goal / 2.f; } } void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool close) { pWindow->m_vRealSize.warp(false); // size we preserve in slide - const auto GOALPOS = pWindow->m_vRealPosition.goalv(); - const auto GOALSIZE = pWindow->m_vRealSize.goalv(); + const auto GOALPOS = pWindow->m_vRealPosition.goal(); + const auto GOALSIZE = pWindow->m_vRealSize.goal(); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); @@ -513,6 +510,27 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config, if (style == "loop" || style == "once") return ""; return "unknown style"; + } else if (config.starts_with("layers")) { + if (style == "fade" || style == "" || style == "slide") + return ""; + else if (style.starts_with("popin")) { + // try parsing + float minPerc = 0.f; + if (style.find("%") != std::string::npos) { + try { + auto percstr = style.substr(style.find_last_of(' ')); + minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { return "invalid minperc"; } + + return ""; + } + + minPerc; // fix warning + + return ""; + } + return ""; + return "unknown style"; } else { return "animation has no styles"; } diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 281c61f8..ae82a60b 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -28,8 +28,8 @@ class CAnimationManager { std::unordered_map getAllBeziers(); - std::vector m_vAnimatedVariables; - std::vector m_vActiveAnimatedVariables; + std::vector m_vAnimatedVariables; + std::vector m_vActiveAnimatedVariables; wl_event_source* m_pAnimationTick; @@ -52,4 +52,4 @@ class CAnimationManager { void animationSlide(CWindow*, std::string force = "", bool close = false); }; -inline std::unique_ptr g_pAnimationManager; \ No newline at end of file +inline std::unique_ptr g_pAnimationManager; diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp new file mode 100644 index 00000000..c3916e4b --- /dev/null +++ b/src/managers/CursorManager.cpp @@ -0,0 +1,231 @@ +#include "CursorManager.hpp" +#include "Compositor.hpp" +#include "../config/ConfigValue.hpp" + +extern "C" { +#include +#include +} + +static int cursorAnimTimer(void* data) { + g_pCursorManager->tickAnimatedCursor(); + return 1; +} + +CCursorManager::CCursorManager() { + m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str()); + + // find default size. First, HYPRCURSOR_SIZE, then XCURSOR_SIZE, then 24 + auto SIZE = getenv("HYPRCURSOR_SIZE"); + if (SIZE) { + try { + m_iSize = std::stoi(SIZE); + } catch (...) { ; } + } + + SIZE = getenv("XCURSOR_SIZE"); + if (SIZE && m_iSize == 0) { + try { + m_iSize = std::stoi(SIZE); + } catch (...) { ; } + } + + if (m_iSize == 0) + m_iSize = 24; + + m_pWLRXCursorMgr = wlr_xcursor_manager_create(getenv("XCURSOR_THEME"), m_iSize); + wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); + + m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr); + + updateTheme(); + + g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateTheme(); }); +} + +void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { + std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; }); +} + +static void cursorBufferDestroy(struct wlr_buffer* wlr_buffer) { + CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); + g_pCursorManager->dropBufferRef(buffer->parent); +} + +static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t flags, void** data, uint32_t* format, size_t* stride) { + CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); + + if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) + return false; + + *data = cairo_image_surface_get_data(buffer->surface); + *stride = cairo_image_surface_get_stride(buffer->surface); + *format = DRM_FORMAT_ARGB8888; + return true; +} + +static void cursorBufferEndDataPtr(struct wlr_buffer* wlr_buffer) { + ; +} + +// +static const wlr_buffer_impl bufferImpl = { + .destroy = cursorBufferDestroy, + .begin_data_ptr_access = cursorBufferBeginDataPtr, + .end_data_ptr_access = cursorBufferEndDataPtr, +}; + +CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { + wlrBuffer.surface = surf; + wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); + wlrBuffer.parent = this; +} + +CCursorManager::CCursorBuffer::~CCursorBuffer() { + ; // will be freed in .destroy +} + +wlr_buffer* CCursorManager::getCursorBuffer() { + return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr; +} + +void CCursorManager::setCursorSurface(wlr_surface* surf, const Vector2D& hotspot) { + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspot.x, hotspot.y); + + m_bOurBufferConnected = false; +} + +void CCursorManager::setCursorFromName(const std::string& name) { + + static auto PUSEHYPRCURSOR = CConfigValue("misc:enable_hyprcursor"); + + if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR) { + wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, m_pWLRXCursorMgr, name.c_str()); + return; + } + + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo); + + if (m_sCurrentCursorShapeData.images.size() < 1) { + // fallback to a default if available + constexpr const std::array fallbackShapes = {"default", "left_ptr"}; + + for (auto& s : fallbackShapes) { + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); + + if (m_sCurrentCursorShapeData.images.size() > 0) + break; + } + + if (m_sCurrentCursorShapeData.images.size() < 1) { + Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName"); + return; + } + } + + m_vCursorBuffers.emplace_back(std::make_unique(m_sCurrentCursorShapeData.images[0].surface, + Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, + Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); + + if (g_pCompositor->m_sWLRCursor) { + wlr_cursor_set_buffer(g_pCompositor->m_sWLRCursor, getCursorBuffer(), m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY, + m_fCursorScale); + if (m_vCursorBuffers.size() > 1) + wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + } + + m_bOurBufferConnected = true; + + if (m_sCurrentCursorShapeData.images.size() > 1) { + // animated + wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[0].delay); + m_iCurrentAnimationFrame = 0; + } else { + // disarm + wl_event_source_timer_update(m_pAnimationTimer, 0); + } +} + +void CCursorManager::tickAnimatedCursor() { + if (m_sCurrentCursorShapeData.images.size() < 2 || !m_bOurBufferConnected) + return; + + m_iCurrentAnimationFrame++; + if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) + m_iCurrentAnimationFrame = 0; + + m_vCursorBuffers.emplace_back(std::make_unique( + m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface, + Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size}, + Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY})); + + if (g_pCompositor->m_sWLRCursor) + wlr_cursor_set_buffer(g_pCompositor->m_sWLRCursor, getCursorBuffer(), m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, + m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY, m_fCursorScale); + + wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay); +} + +SCursorImageData CCursorManager::dataFor(const std::string& name) { + + if (!m_pHyprcursor->valid()) + return {}; + + const auto IMAGES = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo); + + if (IMAGES.images.empty()) + return {}; + + return IMAGES.images[0]; +} + +void CCursorManager::setXWaylandCursor(wlr_xwayland* xwayland) { + const auto CURSOR = dataFor("left_ptr"); + if (CURSOR.surface) { + wlr_xwayland_set_cursor(xwayland, cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), CURSOR.size, CURSOR.size, CURSOR.hotspotX, + CURSOR.hotspotY); + } else if (const auto XCURSOR = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left_ptr", 1); XCURSOR) { + wlr_xwayland_set_cursor(xwayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width, XCURSOR->images[0]->height, + XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y); + } else + Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); +} + +void CCursorManager::updateTheme() { + float highestScale = 1.0; + + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->scale > highestScale) + highestScale = m->scale; + } + + if (highestScale * m_iSize == m_sCurrentStyleInfo.size) + return; + + if (m_sCurrentStyleInfo.size && m_pHyprcursor->valid()) + m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); + + m_sCurrentStyleInfo.size = m_iSize * highestScale; + m_fCursorScale = highestScale; + + if (m_pHyprcursor->valid()) + m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo); + + setCursorFromName("left_ptr"); + + for (auto& m : g_pCompositor->m_vMonitors) { + m->forceFullFrames = 5; + g_pCompositor->scheduleFrameForMonitor(m.get()); + } +} + +void CCursorManager::changeTheme(const std::string& name, const int size) { + m_pHyprcursor = std::make_unique(name.empty() ? "" : name.c_str()); + m_szTheme = name; + m_iSize = size; + + setenv("XCURSOR_SIZE", std::to_string(m_iSize).c_str(), true); + setenv("XCURSOR_THEME", name.c_str(), true); + + updateTheme(); +} diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp new file mode 100644 index 00000000..0e8d99bc --- /dev/null +++ b/src/managers/CursorManager.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include +#include +#include +#include "../includes.hpp" +#include "../helpers/Vector2D.hpp" + +struct wlr_buffer; +struct wlr_xcursor_manager; +struct wlr_xwayland; + +class CCursorManager { + public: + CCursorManager(); + + wlr_buffer* getCursorBuffer(); + + void setCursorFromName(const std::string& name); + void setCursorSurface(wlr_surface* surf, const Vector2D& hotspot); + + void changeTheme(const std::string& name, const int size); + void updateTheme(); + SCursorImageData dataFor(const std::string& name); // for xwayland + void setXWaylandCursor(wlr_xwayland* xwayland); + + void tickAnimatedCursor(); + + class CCursorBuffer { + public: + CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot); + ~CCursorBuffer(); + + struct SCursorWlrBuffer { + wlr_buffer base; + cairo_surface_t* surface = nullptr; + bool dropped = false; + CCursorBuffer* parent = nullptr; + } wlrBuffer; + + private: + Vector2D size; + Vector2D hotspot; + + friend class CCursorManager; + }; + + void dropBufferRef(CCursorBuffer* ref); + + bool m_bOurBufferConnected = false; + + private: + std::vector> m_vCursorBuffers; + + std::unique_ptr m_pHyprcursor; + + std::string m_szTheme = ""; + int m_iSize = 24; + float m_fCursorScale = 1.0; + + Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo; + + wl_event_source* m_pAnimationTimer = nullptr; + int m_iCurrentAnimationFrame = 0; + Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; + + // xcursor fallback + wlr_xcursor_manager* m_pWLRXCursorMgr = nullptr; +}; + +inline std::unique_ptr g_pCursorManager; \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 481b8987..2125e9ba 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2,6 +2,7 @@ #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "debug/Log.hpp" #include "helpers/VarList.hpp" +#include "../config/ConfigValue.hpp" #include @@ -95,18 +96,9 @@ void CKeybindManager::addKeybind(SKeybind kb) { m_pActiveKeybind = nullptr; } -void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) { +void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) { - if (isNumber(key) && std::stoi(key) > 9) { - const uint32_t KEYNUM = std::stoi(key); - - if (it->modmask == mod && it->keycode == KEYNUM) { - it = m_lKeybinds.erase(it); - - if (it == m_lKeybinds.end()) - break; - } - } else if (it->modmask == mod && it->key == key) { + if (it->modmask == mod && it->key == key.key && it->keycode == key.keycode && it->catchAll == key.catchAll) { it = m_lKeybinds.erase(it); if (it == m_lKeybinds.end()) @@ -164,26 +156,26 @@ void CKeybindManager::updateXKBTranslationState() { m_pXKBTranslationState = nullptr; } - static auto* const PFILEPATH = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_file"); - static auto* const PRULES = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_rules"); - static auto* const PMODEL = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_model"); - static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_layout"); - static auto* const PVARIANT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_variant"); - static auto* const POPTIONS = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_options"); + static auto PFILEPATH = CConfigValue("input:kb_file"); + static auto PRULES = CConfigValue("input:kb_rules"); + static auto PMODEL = CConfigValue("input:kb_model"); + static auto PLAYOUT = CConfigValue("input:kb_layout"); + static auto PVARIANT = CConfigValue("input:kb_variant"); + static auto POPTIONS = CConfigValue("input:kb_options"); - const std::string FILEPATH = std::string{*PFILEPATH} == STRVAL_EMPTY ? "" : *PFILEPATH; - const std::string RULES = std::string{*PRULES} == STRVAL_EMPTY ? "" : *PRULES; - const std::string MODEL = std::string{*PMODEL} == STRVAL_EMPTY ? "" : *PMODEL; - const std::string LAYOUT = std::string{*PLAYOUT} == STRVAL_EMPTY ? "" : *PLAYOUT; - const std::string VARIANT = std::string{*PVARIANT} == STRVAL_EMPTY ? "" : *PVARIANT; - const std::string OPTIONS = std::string{*POPTIONS} == STRVAL_EMPTY ? "" : *POPTIONS; + const std::string FILEPATH = std::string{*PFILEPATH} == STRVAL_EMPTY ? "" : *PFILEPATH; + const std::string RULES = std::string{*PRULES} == STRVAL_EMPTY ? "" : *PRULES; + const std::string MODEL = std::string{*PMODEL} == STRVAL_EMPTY ? "" : *PMODEL; + const std::string LAYOUT = std::string{*PLAYOUT} == STRVAL_EMPTY ? "" : *PLAYOUT; + const std::string VARIANT = std::string{*PVARIANT} == STRVAL_EMPTY ? "" : *PVARIANT; + const std::string OPTIONS = std::string{*POPTIONS} == STRVAL_EMPTY ? "" : *POPTIONS; - xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; - const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - FILE* const KEYMAPFILE = FILEPATH == "" ? NULL : fopen(absolutePath(FILEPATH, g_pConfigManager->configCurrentPath).c_str(), "r"); + xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; + const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + FILE* const KEYMAPFILE = FILEPATH == "" ? NULL : fopen(absolutePath(FILEPATH, g_pConfigManager->configCurrentPath).c_str(), "r"); - auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) : - xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) : + xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); if (KEYMAPFILE) fclose(KEYMAPFILE); @@ -234,7 +226,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace); const auto PNEWMAINWORKSPACE = g_pCompositor->getWorkspaceByID(monitor->activeWorkspace); - g_pCompositor->setActiveMonitor(monitor); + g_pInputManager->unconstrainMouse(); PNEWMAINWORKSPACE->rememberPrevWorkspace(PWORKSPACE); const auto PNEWWORKSPACE = monitor->specialWorkspaceID != 0 ? g_pCompositor->getWorkspaceByID(monitor->specialWorkspaceID) : PNEWMAINWORKSPACE; @@ -243,10 +235,15 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { if (PNEWWINDOW) { g_pCompositor->focusWindow(PNEWWINDOW); g_pCompositor->warpCursorTo(PNEWWINDOW->middle()); + + g_pInputManager->m_pForcedFocus = PNEWWINDOW; + g_pInputManager->simulateMouseMovement(); + g_pInputManager->m_pForcedFocus = nullptr; } else { g_pCompositor->focusWindow(nullptr); g_pCompositor->warpCursorTo(monitor->middle()); } + g_pCompositor->setActiveMonitor(monitor); return true; } @@ -257,6 +254,9 @@ void CKeybindManager::switchToWindow(CWindow* PWINDOWTOCHANGETO) { if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO) return; + // remove constraints + g_pInputManager->unconstrainMouse(); + if (PLASTWINDOW && PLASTWINDOW->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && PLASTWINDOW->m_bIsFullscreen) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PLASTWINDOW->m_iWorkspaceID); const auto FSMODE = PWORKSPACE->m_efFullscreenMode; @@ -323,6 +323,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard .keycode = KEYCODE, .modmaskAtPressTime = MODS, .sent = true, + .submapAtPress = m_szCurrentSelectedSubmap, }; bool suppressEvent = false; @@ -353,7 +354,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard bool foundInPressedKeys = false; for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) { if (it->keycode == KEYCODE) { - suppressEvent = handleKeybinds(MODS, *it, false); + if (it->submapAtPress == m_szCurrentSelectedSubmap) + handleKeybinds(MODS, *it, false); foundInPressedKeys = true; suppressEvent = !it->sent; it = m_dPressedKeys.erase(it); @@ -374,11 +376,11 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard } bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) { - const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); - static auto* const PDELAY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:scroll_event_delay"); + static auto PDELAY = CConfigValue("binds:scroll_event_delay"); - if (m_tScrollTimer.getMillis() < **PDELAY) { + if (m_tScrollTimer.getMillis() < *PDELAY) { m_tScrollTimer.reset(); return true; // timer hasn't passed yet! } @@ -386,12 +388,12 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) { m_tScrollTimer.reset(); bool found = false; - if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) { + if (e->source == WL_POINTER_AXIS_SOURCE_WHEEL && e->orientation == WL_POINTER_AXIS_VERTICAL_SCROLL) { if (e->delta < 0) found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true); else found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true); - } else if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_HORIZONTAL) { + } else if (e->source == WL_POINTER_AXIS_SOURCE_WHEEL && e->orientation == WL_POINTER_AXIS_HORIZONTAL_SCROLL) { if (e->delta < 0) found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true); else @@ -422,7 +424,7 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { .modmaskAtPressTime = MODS, }; - if (e->state == WLR_BUTTON_PRESSED) { + if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) { m_dPressedKeys.push_back(KEY); suppressEvent = handleKeybinds(MODS, KEY, true); @@ -456,7 +458,7 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { } void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) { - if (e->state == WLR_BUTTON_PRESSED) { + if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) { mouse("1resizewindow"); } else { mouse("0resizewindow"); @@ -523,13 +525,16 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi } else if (k.keycode != 0) { if (key.keycode != k.keycode) continue; + } else if (k.catchAll) { + if (found) + continue; } else { // oMg such performance hit!!11! // this little maneouver is gonna cost us 4µs const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); if (KBKEY == 0) { - // Keysym failed to resolve from the key name of the the currently iterated bind. + // Keysym failed to resolve from the key name of the currently iterated bind. // This happens for names such as `switch:off:Lid Switch` as well as some keys // (such as yen and ro). // @@ -791,9 +796,9 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { close(socket[1]); read(socket[0], &grandchild, sizeof(grandchild)); close(socket[0]); - // clear child and leave child to init + // clear child and leave grandchild to init waitpid(child, NULL, 0); - if (child < 0) { + if (grandchild < 0) { Debug::log(LOG, "Fail to create the second fork"); return 0; } @@ -870,8 +875,8 @@ void CKeybindManager::centerWindow(std::string args) { if (args == "1") RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; - PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goalv() / 2.f + RESERVEDOFFSET; - PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv(); + PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; + PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); } void CKeybindManager::toggleActivePseudo(std::string args) { @@ -892,11 +897,11 @@ void CKeybindManager::changeworkspace(std::string args) { // Workspace_back_and_forth being enabled means that an attempt to switch to // the current workspace will instead switch to the previous. - static auto* const PBACKANDFORTH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth"); - static auto* const PALLOWWORKSPACECYCLES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles"); - static auto* const PWORKSPACECENTERON = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:workspace_center_on"); + static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); + static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); + static auto PWORKSPACECENTERON = CConfigValue("binds:workspace_center_on"); - const auto PMONITOR = g_pCompositor->m_pLastMonitor; + const auto PMONITOR = g_pCompositor->m_pLastMonitor; if (!PMONITOR) return; @@ -929,7 +934,7 @@ void CKeybindManager::changeworkspace(std::string args) { const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; - if (BISWORKSPACECURRENT && (!(**PBACKANDFORTH || EXPLICITPREVIOUS) || PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1)) + if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1)) return; g_pInputManager->unconstrainMouse(); @@ -961,14 +966,14 @@ void CKeybindManager::changeworkspace(std::string args) { Vector2D middle = PMONITORWORKSPACEOWNER->middle(); if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) { g_pCompositor->focusWindow(PLAST); - if (**PWORKSPACECENTERON == 1) + if (*PWORKSPACECENTERON == 1) middle = PLAST->middle(); } g_pCompositor->warpCursorTo(middle); } if (BISWORKSPACECURRENT) { - if (**PALLOWWORKSPACECYCLES) + if (*PALLOWWORKSPACECYCLES) pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE); else if (!EXPLICITPREVIOUS) pWorkspaceToChangeTo->rememberPrevWorkspace(nullptr); @@ -989,9 +994,6 @@ void CKeybindManager::fullscreenActive(std::string args) { if (!PWINDOW) return; - if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) - return; - PWINDOW->m_bDontSendFullscreen = false; if (args == "2") PWINDOW->m_bDontSendFullscreen = true; @@ -1026,10 +1028,10 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { return; } - auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); - CMonitor* pMonitor = nullptr; - const auto POLDWS = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); - static auto* const PALLOWWORKSPACECYCLES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles"); + auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); + CMonitor* pMonitor = nullptr; + const auto POLDWS = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); + static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); g_pHyprRenderer->damageWindow(PWINDOW); @@ -1055,7 +1057,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { g_pCompositor->focusWindow(PWINDOW); g_pCompositor->warpCursorTo(PWINDOW->middle()); - if (**PALLOWWORKSPACECYCLES) + if (*PALLOWWORKSPACECYCLES) pWorkspace->rememberPrevWorkspace(POLDWS); } @@ -1107,8 +1109,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { } void CKeybindManager::moveFocusTo(std::string args) { - static auto* const PFULLCYCLE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:movefocus_cycles_fullscreen"); - char arg = args[0]; + static auto PFULLCYCLE = CConfigValue("binds:movefocus_cycles_fullscreen"); + char arg = args[0]; if (!isDirection(args)) { Debug::log(ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); @@ -1121,10 +1123,7 @@ void CKeybindManager::moveFocusTo(std::string args) { return; } - // remove constraints - g_pInputManager->unconstrainMouse(); - - const auto PWINDOWTOCHANGETO = **PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ? + const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ? (arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) : g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); @@ -1139,8 +1138,8 @@ void CKeybindManager::moveFocusTo(std::string args) { if (tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg))) return; - static auto* const PNOFALLBACK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_focus_fallback"); - if (**PNOFALLBACK) + static auto PNOFALLBACK = CConfigValue("general:no_focus_fallback"); + if (*PNOFALLBACK) return; Debug::log(LOG, "No monitor found in direction {}, falling back to next window on current workspace", arg); @@ -1158,9 +1157,6 @@ void CKeybindManager::focusUrgentOrLast(std::string args) { if (!PWINDOWURGENT && !PWINDOWPREV) return; - // remove constraints - g_pInputManager->unconstrainMouse(); - switchToWindow(PWINDOWURGENT ? PWINDOWURGENT : PWINDOWPREV); } @@ -1171,9 +1167,6 @@ void CKeybindManager::focusCurrentOrLast(std::string args) { if (!PWINDOWPREV) return; - // remove constraints - g_pInputManager->unconstrainMouse(); - switchToWindow(PWINDOWPREV); } @@ -1227,14 +1220,14 @@ void CKeybindManager::moveActiveTo(std::string args) { switch (arg) { case 'l': vPos.x = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break; - case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goalv().x - BORDERSIZE + PMONITOR->vecPosition.x; break; + case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break; case 't': case 'u': vPos.y = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break; case 'b': - case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goalv().y - BORDERSIZE + PMONITOR->vecPosition.y; break; + case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break; } - PLASTWINDOW->m_vRealPosition = Vector2D(vPos.x != 0 ? vPos.x : PLASTWINDOW->m_vRealPosition.goalv().x, vPos.y != 0 ? vPos.y : PLASTWINDOW->m_vRealPosition.goalv().y); + PLASTWINDOW->m_vRealPosition = Vector2D(vPos.x != 0 ? vPos.x : PLASTWINDOW->m_vRealPosition.goal().x, vPos.y != 0 ? vPos.y : PLASTWINDOW->m_vRealPosition.goal().y); return; } @@ -1382,22 +1375,22 @@ void CKeybindManager::moveCursorToCorner(std::string arg) { switch (CORNER) { case 0: // bottom left - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x, - PWINDOW->m_vRealPosition.vec().y + PWINDOW->m_vRealSize.vec().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x, + PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y); break; case 1: // bottom right - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x + PWINDOW->m_vRealSize.vec().x, - PWINDOW->m_vRealPosition.vec().y + PWINDOW->m_vRealSize.vec().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, + PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y); break; case 2: // top right - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x + PWINDOW->m_vRealSize.vec().x, - PWINDOW->m_vRealPosition.vec().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, + PWINDOW->m_vRealPosition.value().y); break; case 3: // top left - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y); break; } } @@ -1462,8 +1455,8 @@ void CKeybindManager::workspaceOpt(std::string args) { continue; if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) { - const auto SAVEDPOS = w->m_vRealPosition.vec(); - const auto SAVEDSIZE = w->m_vRealSize.vec(); + const auto SAVEDPOS = w->m_vRealPosition.value(); + const auto SAVEDSIZE = w->m_vRealSize.value(); w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating; g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w); @@ -1472,8 +1465,8 @@ void CKeybindManager::workspaceOpt(std::string args) { w->m_vRealPosition.setValueAndWarp(SAVEDPOS); w->m_vRealSize.setValueAndWarp(SAVEDSIZE); g_pXWaylandManager->setWindowSize(w, SAVEDSIZE); - w->m_vRealSize = w->m_vRealSize.vec() + Vector2D(4, 4); - w->m_vRealPosition = w->m_vRealPosition.vec() - Vector2D(2, 2); + w->m_vRealSize = w->m_vRealSize.value() + Vector2D(4, 4); + w->m_vRealPosition = w->m_vRealPosition.value() - Vector2D(2, 2); } } } @@ -1556,9 +1549,9 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { std::string workspaceName; - const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); + int workspaceID = getWorkspaceIDFromString(args, workspaceName); - if (WORKSPACEID == WORKSPACE_INVALID) { + if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); return; } @@ -1570,38 +1563,51 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { return; } - auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); + auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID); - if (!PWORKSPACE) { - PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, PCURRMONITOR->ID); + if (!pWorkspace) { + pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID); // we can skip the moving, since it's already on the current monitor - changeworkspace(PWORKSPACE->getConfigName()); + changeworkspace(pWorkspace->getConfigName()); return; } - if (PWORKSPACE->m_iMonitorID != PCURRMONITOR->ID) { - const auto POLDMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); + + if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspace == workspaceID && pWorkspace->m_sPrevWorkspace.iID != -1) { + const int PREVWORKSPACEID = pWorkspace->m_sPrevWorkspace.iID; + const auto PREVWORKSPACENAME = pWorkspace->m_sPrevWorkspace.name; + // Workspace to focus is previous workspace + pWorkspace = g_pCompositor->getWorkspaceByID(PREVWORKSPACEID); + if (!pWorkspace) + pWorkspace = g_pCompositor->createNewWorkspace(PREVWORKSPACEID, PCURRMONITOR->ID, PREVWORKSPACENAME); + + workspaceID = pWorkspace->m_iID; + } + + if (pWorkspace->m_iMonitorID != PCURRMONITOR->ID) { + const auto POLDMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); if (!POLDMONITOR) { // wat Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"); return; } - if (POLDMONITOR->activeWorkspace == WORKSPACEID) { + if (POLDMONITOR->activeWorkspace == workspaceID) { g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR); return; } else { - g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PCURRMONITOR, true); + g_pCompositor->moveWorkspaceToMonitor(pWorkspace, PCURRMONITOR, true); } } - changeworkspace(PWORKSPACE->getConfigName()); + changeworkspace(pWorkspace->getConfigName()); } void CKeybindManager::toggleSpecialWorkspace(std::string args) { - static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse"); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - std::string workspaceName = ""; - int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName); + std::string workspaceName = ""; + int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName); if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { Debug::log(ERR, "Invalid workspace passed to special"); @@ -1609,7 +1615,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { } bool requestedWorkspaceIsAlreadyOpen = false; - const auto PMONITOR = **PFOLLOWMOUSE == 1 ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->m_pLastMonitor; + const auto PMONITOR = *PFOLLOWMOUSE == 1 ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->m_pLastMonitor; int specialOpenOnMonitor = PMONITOR->specialWorkspaceID; for (auto& m : g_pCompositor->m_vMonitors) { @@ -1656,14 +1662,14 @@ void CKeybindManager::resizeActive(std::string args) { if (!g_pCompositor->m_pLastWindow || g_pCompositor->m_pLastWindow->m_bIsFullscreen) return; - const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv()); + const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goal()); if (SIZ.x < 1 || SIZ.y < 1) return; - g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - g_pCompositor->m_pLastWindow->m_vRealSize.goalv()); + g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - g_pCompositor->m_pLastWindow->m_vRealSize.goal()); - if (g_pCompositor->m_pLastWindow->m_vRealSize.goalv().x > 1 && g_pCompositor->m_pLastWindow->m_vRealSize.goalv().y > 1) + if (g_pCompositor->m_pLastWindow->m_vRealSize.goal().x > 1 && g_pCompositor->m_pLastWindow->m_vRealSize.goal().y > 1) g_pCompositor->m_pLastWindow->setHidden(false); } @@ -1671,9 +1677,9 @@ void CKeybindManager::moveActive(std::string args) { if (!g_pCompositor->m_pLastWindow || g_pCompositor->m_pLastWindow->m_bIsFullscreen) return; - const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv()); + const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goal()); - g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - g_pCompositor->m_pLastWindow->m_vRealPosition.goalv()); + g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - g_pCompositor->m_pLastWindow->m_vRealPosition.goal()); } void CKeybindManager::moveWindow(std::string args) { @@ -1691,9 +1697,9 @@ void CKeybindManager::moveWindow(std::string args) { if (PWINDOW->m_bIsFullscreen) return; - const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goalv()); + const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goal()); - g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goalv(), PWINDOW); + g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goal(), PWINDOW); } void CKeybindManager::resizeWindow(std::string args) { @@ -1711,14 +1717,14 @@ void CKeybindManager::resizeWindow(std::string args) { if (PWINDOW->m_bIsFullscreen) return; - const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv()); + const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goal()); if (SIZ.x < 1 || SIZ.y < 1) return; - g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), CORNER_NONE, PWINDOW); + g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goal(), CORNER_NONE, PWINDOW); - if (PWINDOW->m_vRealSize.goalv().x > 1 && PWINDOW->m_vRealSize.goalv().y > 1) + if (PWINDOW->m_vRealSize.goal().x > 1 && PWINDOW->m_vRealSize.goal().y > 1) PWINDOW->setHidden(false); } @@ -1855,20 +1861,20 @@ void CKeybindManager::pass(std::string regexp) { if (g_pKeybindManager->m_uLastCode != 0) wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED); else - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WLR_BUTTON_PRESSED); + wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); } else if (g_pKeybindManager->m_iPassPressed == 0) if (g_pKeybindManager->m_uLastCode != 0) wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED); else - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WLR_BUTTON_RELEASED); + wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); else { // dynamic call of the dispatcher if (g_pKeybindManager->m_uLastCode != 0) { wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED); wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED); } else { - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WLR_BUTTON_PRESSED); - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WLR_BUTTON_RELEASED); + wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); + wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); } } @@ -2144,8 +2150,8 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property! - static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current"); - pWindowInDirection = **USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail(); + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail(); pWindowInDirection->insertWindowToGroup(pWindow); pWindowInDirection->setGroupCurrent(pWindow); @@ -2159,9 +2165,9 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi } void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir) { - static auto* const BFOCUSREMOVEDWINDOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:focus_removed_window"); - const auto PWINDOWPREV = pWindow->getGroupPrevious(); - eDirection direction; + static auto BFOCUSREMOVEDWINDOW = CConfigValue("group:focus_removed_window"); + const auto PWINDOWPREV = pWindow->getGroupPrevious(); + eDirection direction; switch (dir[0]) { case 't': @@ -2186,7 +2192,7 @@ void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; } - if (**BFOCUSREMOVEDWINDOW) { + if (*BFOCUSREMOVEDWINDOW) { g_pCompositor->focusWindow(pWindow); g_pCompositor->warpCursorTo(pWindow->middle()); } else { @@ -2196,11 +2202,11 @@ void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& } void CKeybindManager::moveIntoGroup(std::string args) { - char arg = args[0]; + char arg = args[0]; - static auto* const PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock"); + static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); - if (!**PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) + if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) return; if (!isDirection(args)) { @@ -2219,16 +2225,16 @@ void CKeybindManager::moveIntoGroup(std::string args) { return; // Do not move window into locked group if binds:ignore_group_lock is false - if (!**PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked))) + if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked))) return; moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); } void CKeybindManager::moveOutOfGroup(std::string args) { - static auto* const PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock"); + static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); - if (!**PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) + if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) return; CWindow* PWINDOW = nullptr; @@ -2245,9 +2251,9 @@ void CKeybindManager::moveOutOfGroup(std::string args) { } void CKeybindManager::moveWindowOrGroup(std::string args) { - char arg = args[0]; + char arg = args[0]; - static auto* const PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock"); + static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); if (!isDirection(args)) { Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); @@ -2258,7 +2264,7 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { if (!PWINDOW || PWINDOW->m_bIsFullscreen) return; - if (!**PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) { + if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) { g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args); return; } @@ -2271,13 +2277,13 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { // note: PWINDOWINDIR is not null implies !PWINDOW->m_bIsFloating if (PWINDOWINDIR && PWINDOWINDIR->m_sGroupData.pNextWindow) { // target is group - if (!**PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) { + if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) { g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args); g_pCompositor->warpCursorTo(PWINDOW->middle()); } else moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); } else if (PWINDOWINDIR) { // target is regular window - if ((!**PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) { + if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) { g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args); g_pCompositor->warpCursorTo(PWINDOW->middle()); } else @@ -2293,14 +2299,14 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { } void CKeybindManager::setIgnoreGroupLock(std::string args) { - static auto* const BIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock"); + static auto PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock"); if (args == "toggle") - **BIGNOREGROUPLOCK = !*BIGNOREGROUPLOCK; + **PIGNOREGROUPLOCK = !**PIGNOREGROUPLOCK; else - **BIGNOREGROUPLOCK = args == "on"; + **PIGNOREGROUPLOCK = args == "on"; - g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**BIGNOREGROUPLOCK)}); + g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**PIGNOREGROUPLOCK)}); } void CKeybindManager::denyWindowFromGroup(std::string args) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index edd9ede2..07b77398 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -13,6 +13,7 @@ class CPluginSystem; struct SKeybind { std::string key = ""; uint32_t keycode = 0; + bool catchAll = false; uint32_t modmask = 0; std::string handler = ""; std::string arg = ""; @@ -42,6 +43,13 @@ struct SPressedKeyWithMods { uint32_t keycode = 0; uint32_t modmaskAtPressTime = 0; bool sent = false; + std::string submapAtPress = ""; +}; + +struct SParsedKey { + std::string key = ""; + uint32_t keycode = 0; + bool catchAll = false; }; class CKeybindManager { @@ -57,7 +65,7 @@ class CKeybindManager { void onSwitchOffEvent(const std::string&); void addKeybind(SKeybind); - void removeKeybind(uint32_t, const std::string&); + void removeKeybind(uint32_t, const SParsedKey&); uint32_t stringToModMask(std::string); uint32_t keycodeToModifier(xkb_keycode_t); void clearKeybinds(); diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 89c08566..a0374b85 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -1,5 +1,6 @@ #include "SessionLockManager.hpp" #include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" static void handleSurfaceMap(void* owner, void* data) { const auto PSURFACE = (SSessionLockSurface*)owner; @@ -14,8 +15,6 @@ static void handleSurfaceMap(void* owner, void* data) { if (PMONITOR) g_pHyprRenderer->damageMonitor(PMONITOR); - - g_pSessionLockManager->activateLock(); // activate lock here to prevent the red screen from flashing before that } static void handleSurfaceCommit(void* owner, void* data) { @@ -44,9 +43,9 @@ static void handleSurfaceDestroy(void* owner, void* data) { void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) { - static auto* const PALLOWRELOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:allow_session_lock_restore"); + static auto PALLOWRELOCK = CConfigValue("misc:allow_session_lock_restore"); - if (m_sSessionLock.active && (!**PALLOWRELOCK || m_sSessionLock.pWlrLock)) { + if (m_sSessionLock.active && (!*PALLOWRELOCK || m_sSessionLock.pWlrLock)) { Debug::log(LOG, "Attempted to lock a locked session!"); wlr_session_lock_v1_destroy(pWlrLock); return; @@ -96,6 +95,8 @@ void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) { m_sSessionLock.active = false; + m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.clear(); + g_pCompositor->m_sSeat.exclusiveClient = nullptr; g_pInputManager->refocus(); @@ -125,13 +126,15 @@ void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) { pWlrLock, "wlr_session_lock_v1"); wlr_session_lock_v1_send_locked(pWlrLock); + + g_pSessionLockManager->activateLock(); } bool CSessionLockManager::isSessionLocked() { return m_sSessionLock.active; } -SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(const int& id) { +SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64_t id) { for (auto& sls : m_sSessionLock.vSessionLockSurfaces) { if (sls->iMonitorID == id) { if (sls->mapped) @@ -144,6 +147,20 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(const return nullptr; } +// We don't want the red screen to flash. +// This violates the protocol a bit, but tries to handle the missing sync between a lock surface beeing created and the red screen beeing drawn. +float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { + const auto& NOMAPPEDSURFACETIMER = m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.find(id); + + if (NOMAPPEDSURFACETIMER == m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.end()) { + m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.emplace(id, CTimer()); + m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers[id].reset(); + return 0.f; + } + + return std::clamp(NOMAPPEDSURFACETIMER->second.getSeconds() - /* delay for screencopy */ 0.5f, 0.f, 1.f); +} + bool CSessionLockManager::isSurfaceSessionLock(wlr_surface* pSurface) { for (auto& sls : m_sSessionLock.vSessionLockSurfaces) { if (sls->pWlrLockSurface->surface == pSurface) @@ -155,6 +172,17 @@ bool CSessionLockManager::isSurfaceSessionLock(wlr_surface* pSurface) { void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) { std::erase_if(m_sSessionLock.vSessionLockSurfaces, [&](const auto& other) { return pSLS == other.get(); }); + + if (g_pCompositor->m_pLastFocus) + return; + + for (auto& sls : m_sSessionLock.vSessionLockSurfaces) { + if (!sls->mapped) + continue; + + g_pCompositor->focusSurface(sls->pWlrLockSurface->surface); + break; + } } void CSessionLockManager::activateLock() { diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index 51232867..c2c539db 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -1,10 +1,13 @@ #pragma once #include "../defines.hpp" +#include "../helpers/Timer.hpp" +#include +#include struct SSessionLockSurface { wlr_session_lock_surface_v1* pWlrLockSurface = nullptr; - int iMonitorID = -1; + uint64_t iMonitorID = -1; bool mapped = false; @@ -18,6 +21,7 @@ struct SSessionLock { wlr_session_lock_v1* pWlrLock = nullptr; std::vector> vSessionLockSurfaces; + std::unordered_map mMonitorsWithoutMappedSurfaceTimers; DYNLISTENER(newSurface); DYNLISTENER(unlock); @@ -30,7 +34,9 @@ class CSessionLockManager { ~CSessionLockManager() = default; void onNewSessionLock(wlr_session_lock_v1*); - SSessionLockSurface* getSessionLockSurfaceForMonitor(const int&); + SSessionLockSurface* getSessionLockSurfaceForMonitor(uint64_t); + + float getRedScreenAlphaForMonitor(uint64_t); bool isSessionLocked(); bool isSurfaceSessionLock(wlr_surface*); diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp index ee58a8ce..cd892503 100644 --- a/src/managers/ThreadManager.cpp +++ b/src/managers/ThreadManager.cpp @@ -1,15 +1,16 @@ #include "ThreadManager.hpp" #include "../debug/HyprCtl.hpp" #include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" int slowUpdate = 0; int handleTimer(void* data) { - const auto PTM = (CThreadManager*)data; + const auto PTM = (CThreadManager*)data; - static auto* const PDISABLECFGRELOAD = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:disable_autoreload"); + static auto PDISABLECFGRELOAD = CConfigValue("misc:disable_autoreload"); - if (**PDISABLECFGRELOAD != 1) + if (*PDISABLECFGRELOAD != 1) g_pConfigManager->tick(); wl_event_source_timer_update(PTM->m_esConfigTimer, 1000); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index b46004e6..e37a08f7 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../events/Events.hpp" #include "xdg-output-unstable-v1-protocol.h" +#include "../config/ConfigValue.hpp" #define OUTPUT_MANAGER_VERSION 3 #define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3 @@ -55,7 +56,7 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { if (pWindow->m_bIsX11) { - setWindowSize(pWindow, pWindow->m_vRealSize.vec()); // update xwayland output pos + setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos if (activate) { wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); @@ -98,15 +99,18 @@ void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, CBox* pbox) { } std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) { - if (!pWindow->m_bIsMapped) - return ""; - try { if (pWindow->m_bIsX11) { + if (!pWindow->m_bIsMapped) + return ""; + if (pWindow->m_uSurface.xwayland && pWindow->m_uSurface.xwayland->title) { return std::string(pWindow->m_uSurface.xwayland->title); } } else if (pWindow->m_uSurface.xdg) { + if (pWindow->m_bFadingOut || !pWindow->m_uSurface.xdg) + return ""; + if (pWindow->m_uSurface.xdg->toplevel && pWindow->m_uSurface.xdg->toplevel->title) { return std::string(pWindow->m_uSurface.xdg->toplevel->title); } @@ -119,15 +123,18 @@ std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) { } std::string CHyprXWaylandManager::getAppIDClass(CWindow* pWindow) { - if (!pWindow->m_bIsMapped) - return ""; - try { if (pWindow->m_bIsX11) { + if (!pWindow->m_bIsMapped) + return ""; + if (pWindow->m_uSurface.xwayland && pWindow->m_uSurface.xwayland->_class) { return std::string(pWindow->m_uSurface.xwayland->_class); } } else if (pWindow->m_uSurface.xdg) { + if (pWindow->m_bFadingOut || !pWindow->m_uSurface.xdg) + return ""; + if (pWindow->m_uSurface.xdg->toplevel && pWindow->m_uSurface.xdg->toplevel->app_id) { return std::string(pWindow->m_uSurface.xdg->toplevel->app_id); } @@ -147,19 +154,19 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) { void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) { - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); // calculate pos // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = pWindow->m_vRealPosition.vec(); + Vector2D windowPos = pWindow->m_vRealPosition.value(); if (pWindow->m_bIsX11 && PMONITOR) { windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor - if (**PXWLFORCESCALEZERO) + if (*PXWLFORCESCALEZERO) windowPos = windowPos * PMONITOR->scale; // scale if applicable windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland } @@ -172,7 +179,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f pWindow->m_fX11SurfaceScaledBy = 1.f; - if (**PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) { + if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) { size = size * PMONITOR->scale; pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; } @@ -198,7 +205,7 @@ wlr_surface* CHyprXWaylandManager::surfaceAt(CWindow* pWindow, const Vector2D& c return wlr_xdg_surface_surface_at(pWindow->m_uSurface.xdg, client.x, client.y, &surface.x, &surface.y); } -bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) { +bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow, bool pending) { if (pWindow->m_bIsX11) { for (size_t i = 0; i < pWindow->m_uSurface.xwayland->window_type_len; i++) if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || @@ -216,9 +223,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) { pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"]) pWindow->m_bX11ShouldntFocus = true; - if (pWindow->m_uSurface.xwayland->window_type[i] != HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"]) - pWindow->m_bNoInitialFocus = true; - + pWindow->m_bNoInitialFocus = true; return true; } @@ -243,7 +248,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) { if (SIZEHINTS && (pWindow->m_uSurface.xwayland->parent || ((SIZEHINTS->min_width == SIZEHINTS->max_width) && (SIZEHINTS->min_height == SIZEHINTS->max_height)))) return true; } else { - const auto PSTATE = &pWindow->m_uSurface.xdg->toplevel->current; + const auto PSTATE = pending ? &pWindow->m_uSurface.xdg->toplevel->pending : &pWindow->m_uSurface.xdg->toplevel->current; if ((PSTATE->min_width != 0 && PSTATE->min_height != 0 && (PSTATE->min_width == PSTATE->max_width || PSTATE->min_height == PSTATE->max_height)) || pWindow->m_uSurface.xdg->toplevel->parent) @@ -260,7 +265,7 @@ void CHyprXWaylandManager::moveXWaylandWindow(CWindow* pWindow, const Vector2D& if (!pWindow->m_bIsX11) return; - wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y); + wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, pWindow->m_vRealSize.value().x, pWindow->m_vRealSize.value().y); } void CHyprXWaylandManager::checkBorders(CWindow* pWindow) { @@ -315,14 +320,29 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) { return MAXSIZE; } +Vector2D CHyprXWaylandManager::getMinSizeForWindow(CWindow* pWindow) { + if (!g_pCompositor->windowValidMapped(pWindow)) + return Vector2D(0, 0); + + if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel)) + return Vector2D(0, 0); + + auto MINSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->min_width, pWindow->m_uSurface.xwayland->size_hints->min_height) : + Vector2D(pWindow->m_uSurface.xdg->toplevel->current.min_width, pWindow->m_uSurface.xdg->toplevel->current.min_height); + + MINSIZE = MINSIZE.clamp({1, 1}); + + return MINSIZE; +} + Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - CMonitor* pMonitor = nullptr; - double bestDistance = __FLT_MAX__; + CMonitor* pMonitor = nullptr; + double bestDistance = __FLT_MAX__; for (auto& m : g_pCompositor->m_vMonitors) { - const auto SIZ = **PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; + const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; double distance = vecToRectDistanceSquared(coord, {m->vecXWaylandPosition.x, m->vecXWaylandPosition.y}, {m->vecXWaylandPosition.x + SIZ.x - 1, m->vecXWaylandPosition.y + SIZ.y - 1}); @@ -339,7 +359,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { // get local coords Vector2D result = coord - pMonitor->vecXWaylandPosition; // if scaled, unscale - if (**PXWLFORCESCALEZERO) + if (*PXWLFORCESCALEZERO) result = result / pMonitor->scale; // add pos result = result + pMonitor->vecPosition; diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index e41313e0..c374f579 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -23,10 +23,11 @@ class CHyprXWaylandManager { void setWindowStyleTiled(CWindow*, uint32_t); void setWindowFullscreen(CWindow*, bool); wlr_surface* surfaceAt(CWindow*, const Vector2D&, Vector2D&); - bool shouldBeFloated(CWindow*); + bool shouldBeFloated(CWindow*, bool pending = false); void moveXWaylandWindow(CWindow*, const Vector2D&); void checkBorders(CWindow*); Vector2D getMaxSizeForWindow(CWindow*); + Vector2D getMinSizeForWindow(CWindow*); Vector2D xwaylandToWaylandCoords(const Vector2D&); }; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2c8c2d7c..9072f27a 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -2,9 +2,10 @@ #include "../../Compositor.hpp" #include "wlr/types/wlr_switch.h" #include +#include "../../config/ConfigValue.hpp" CInputManager::~CInputManager() { - m_lConstraints.clear(); + m_vConstraints.clear(); m_lKeyboards.clear(); m_lMice.clear(); m_lTablets.clear(); @@ -16,20 +17,20 @@ CInputManager::~CInputManager() { } void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) { - static auto* const PSENS = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("general:sensitivity"); - static auto* const PNOACCEL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:force_no_accel"); - static auto* const PSENSTORAW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:apply_sens_to_raw"); + static auto PSENS = CConfigValue("general:sensitivity"); + static auto PNOACCEL = CConfigValue("input:force_no_accel"); + static auto PSENSTORAW = CConfigValue("general:apply_sens_to_raw"); - const auto DELTA = **PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y); + const auto DELTA = *PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y); - if (**PSENSTORAW == 1) - wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * **PSENS, - DELTA.y * **PSENS, e->unaccel_dx * **PSENS, e->unaccel_dy * **PSENS); + if (*PSENSTORAW == 1) + wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * *PSENS, + DELTA.y * *PSENS, e->unaccel_dx * *PSENS, e->unaccel_dy * *PSENS); else wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y, e->unaccel_dx, e->unaccel_dy); - wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * **PSENS, DELTA.y * **PSENS); + wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * *PSENS, DELTA.y * *PSENS); mouseMoveUnified(e->time_msec); @@ -56,7 +57,7 @@ void CInputManager::simulateMouseMovement() { } void CInputManager::sendMotionEventsToFocused() { - if (!g_pCompositor->m_pLastFocus) + if (!g_pCompositor->m_pLastFocus || isConstrained()) return; // todo: this sucks ass @@ -66,24 +67,26 @@ void CInputManager::sendMotionEventsToFocused() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition.goalv() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{})); + const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition.goal() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{})); + + m_bEmptyFocusCursorSet = false; wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, g_pCompositor->m_pLastFocus, LOCAL.x, LOCAL.y); wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, now.tv_sec * 1000 + now.tv_nsec / 10000000, LOCAL.x, LOCAL.y); } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { - static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse"); - static auto* const PMOUSEREFOCUS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:mouse_refocus"); - static auto* const PMOUSEDPMS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms"); - static auto* const PFOLLOWONDND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd"); - static auto* const PFLOATBEHAVIOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus"); - static auto* const PMOUSEFOCUSMON = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor"); - static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border"); - static auto* const PRESIZECURSORICON = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border"); - static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor"); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + static auto PFOLLOWONDND = CConfigValue("misc:always_follow_on_dnd"); + static auto PFLOATBEHAVIOR = CConfigValue("input:float_switch_override_focus"); + static auto PMOUSEFOCUSMON = CConfigValue("misc:mouse_move_focuses_monitor"); + static auto PRESIZEONBORDER = CConfigValue("general:resize_on_border"); + static auto PRESIZECURSORICON = CConfigValue("general:hover_icon_on_border"); + static auto PZOOMFACTOR = CConfigValue("misc:cursor_zoom_factor"); - const auto FOLLOWMOUSE = **PFOLLOWONDND && m_sDrag.drag ? 1 : **PFOLLOWMOUSE; + const auto FOLLOWMOUSE = *PFOLLOWONDND && m_sDrag.drag ? 1 : *PFOLLOWMOUSE; m_pFoundSurfaceToFocus = nullptr; m_pFoundLSToFocus = nullptr; @@ -97,7 +100,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) return; - if (!g_pCompositor->m_bDPMSStateON && **PMOUSEDPMS) { + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) { // enable dpms g_pKeybindManager->dpms("on"); } @@ -121,7 +124,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (PMONITOR == nullptr) return; - if (**PZOOMFACTOR != 1.f) + if (*PZOOMFACTOR != 1.f) g_pHyprRenderer->damageMonitor(PMONITOR); if (!PMONITOR->solitaryClient && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0) @@ -134,61 +137,33 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (forcedFocus) { pFoundWindow = forcedFocus; - surfacePos = pFoundWindow->m_vRealPosition.vec(); + surfacePos = pFoundWindow->m_vRealPosition.value(); foundSurface = pFoundWindow->m_pWLSurface.wlr(); } // constraints - // All constraints TODO: multiple mice? - if (g_pCompositor->m_sSeat.mouse && g_pCompositor->m_sSeat.mouse->currentConstraint && !g_pCompositor->m_sSeat.exclusiveClient && !g_pSessionLockManager->isSessionLocked()) { - // XWayland windows sometimes issue constraints weirdly. - // TODO: We probably should search their parent. wlr_xwayland_surface->parent - const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse); - const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint); + if (g_pCompositor->m_sSeat.mouse && isConstrained()) { + const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus); + const auto CONSTRAINT = SURF->constraint(); - if (!CONSTRAINTWINDOW || !PCONSTRAINT) { - unconstrainMouse(); - } else { - // Native Wayland apps know how 2 constrain themselves. - // XWayland, we just have to accept them. Might cause issues, but thats XWayland for ya. - const auto CONSTRAINTPOS = PCONSTRAINT->getLogicConstraintPos(); - const auto CONSTRAINTSIZE = PCONSTRAINT->getLogicConstraintSize(); - - if (g_pCompositor->m_sSeat.mouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) { - // we just snap the cursor to where it should be. - - if (PCONSTRAINT->hintSet) - wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, CONSTRAINTPOS.x + PCONSTRAINT->positionHint.x, - CONSTRAINTPOS.y + PCONSTRAINT->positionHint.y); - - return; // don't process anything else, the cursor is locked. The surface should not receive any further events. - // these are usually FPS games. They will use the relative motion. + if (SURF && CONSTRAINT) { + if (CONSTRAINT->isLocked()) { + const auto HINT = CONSTRAINT->logicPositionHint(); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, HINT.x, HINT.y); } else { - // we restrict the cursor to the confined region - const auto REGION = PCONSTRAINT->getLogicCoordsRegion(); + const auto RG = CONSTRAINT->logicConstraintRegion(); + const auto CLOSEST = RG.closestPoint(mouseCoords); + const auto BOX = SURF->getSurfaceBoxGlobal(); + const auto CLOSESTLOCAL = (CLOSEST - (BOX.has_value() ? BOX->pos() : Vector2D{})) * (SURF->getWindow() ? SURF->getWindow()->m_fX11SurfaceScaledBy : 1.0); - if (!REGION.containsPoint(mouseCoords)) { - if (g_pCompositor->m_sSeat.mouse->constraintActive) { - const auto CLOSEST = REGION.closestPoint(mouseCoords); - wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, NULL, CLOSEST.x, CLOSEST.y); - mouseCoords = getMouseCoordsInternal(); - } - } else { - if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) { - g_pCompositor->m_sSeat.mouse->constraintActive = true; - } - } + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, CLOSEST.x, CLOSEST.y); + wlr_seat_pointer_send_motion(g_pCompositor->m_sSeat.seat, time, CLOSESTLOCAL.x, CLOSESTLOCAL.y); } - if (CONSTRAINTWINDOW->m_bIsX11) { - foundSurface = CONSTRAINTWINDOW->m_pWLSurface.wlr(); - surfacePos = CONSTRAINTWINDOW->m_vRealPosition.vec(); - } else { - g_pCompositor->vectorWindowToSurface(mouseCoords, CONSTRAINTWINDOW, surfaceCoords); - } + return; - pFoundWindow = CONSTRAINTWINDOW; - } + } else + Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF, (uintptr_t)CONSTRAINT); } // update stuff @@ -220,7 +195,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal()); - if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor && (**PMOUSEFOCUSMON || refocus)) + if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor && (*PMOUSEFOCUSMON || refocus)) g_pCompositor->setActiveMonitor(PMONITOR); if (g_pSessionLockManager->isSessionLocked()) { @@ -273,7 +248,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { surfacePos = Vector2D(-1337, -1337); } else { foundSurface = pFoundWindow->m_pWLSurface.wlr(); - surfacePos = pFoundWindow->m_vRealPosition.vec(); + surfacePos = pFoundWindow->m_vRealPosition.value(); } } @@ -302,7 +277,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); } else { foundSurface = pFoundWindow->m_pWLSurface.wlr(); - surfacePos = pFoundWindow->m_vRealPosition.vec(); + surfacePos = pFoundWindow->m_vRealPosition.value(); } } } @@ -320,7 +295,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (!foundSurface) { if (!m_bEmptyFocusCursorSet) { - if (**PRESIZEONBORDER && **PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) { + if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) { m_eBorderIconDirection = BORDERICON_NONE; unsetCursorImage(); } @@ -390,7 +365,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (pFoundWindow) { // change cursor icon if hovering over border - if (**PRESIZEONBORDER && **PRESIZECURSORICON) { + if (*PRESIZEONBORDER && *PRESIZECURSORICON) { if (!pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) { setCursorIconOnBorder(pFoundWindow); } else if (m_eBorderIconDirection != BORDERICON_NONE) { @@ -400,7 +375,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (FOLLOWMOUSE != 1 && !refocus) { if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow && - ((pFoundWindow->m_bIsFloating && **PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && **PFLOATBEHAVIOR != 0))) { + ((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) { // enter if change floating style if (FOLLOWMOUSE != 3 && allowKeyboardRefocus) g_pCompositor->focusWindow(pFoundWindow, foundSurface); @@ -438,7 +413,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bLastFocusOnLS = false; } else { - if (**PRESIZEONBORDER && **PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) { + if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) { m_eBorderIconDirection = BORDERICON_NONE; unsetCursorImage(); } @@ -466,7 +441,7 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { m_tmrLastCursorMovement.reset(); - if (e->state == WLR_BUTTON_PRESSED) { + if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) { m_lCurrentlyHeldButtons.push_back(e->button); } else { if (std::find_if(m_lCurrentlyHeldButtons.begin(), m_lCurrentlyHeldButtons.end(), [&](const auto& other) { return other == e->button; }) == m_lCurrentlyHeldButtons.end()) @@ -480,7 +455,7 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { default: break; } - if (m_bFocusHeldByButtons && m_lCurrentlyHeldButtons.empty() && e->state == WLR_BUTTON_RELEASED) { + if (m_bFocusHeldByButtons && m_lCurrentlyHeldButtons.empty() && e->state == WL_POINTER_BUTTON_STATE_RELEASED) { if (m_bRefocusHeldByButtons) refocus(); else @@ -605,15 +580,15 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { // notify the keybind manager - static auto* const PPASSMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound"); - const auto PASS = g_pKeybindManager->onMouseEvent(e); - static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse"); - static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border"); - static auto* const PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size"); - static auto* const PBORDERGRABEXTEND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area"); - const auto BORDER_GRAB_AREA = **PRESIZEONBORDER ? **PBORDERSIZE + **PBORDERGRABEXTEND : 0; + static auto PPASSMOUSE = CConfigValue("binds:pass_mouse_when_bound"); + const auto PASS = g_pKeybindManager->onMouseEvent(e); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PRESIZEONBORDER = CConfigValue("general:resize_on_border"); + static auto PBORDERSIZE = CConfigValue("general:border_size"); + static auto PBORDERGRABEXTEND = CConfigValue("general:extend_border_grab_area"); + const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; - if (!PASS && !**PPASSMOUSE) + if (!PASS && !*PPASSMOUSE) return; const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); @@ -624,9 +599,9 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { // clicking on border triggers resize // TODO detect click on LS properly - if (**PRESIZEONBORDER && !m_bLastFocusOnLS && e->state == WLR_BUTTON_PRESSED) { + if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e->state == WL_POINTER_BUTTON_STATE_PRESSED) { if (w && !w->m_bIsFullscreen) { - const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) { @@ -638,10 +613,10 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { switch (e->state) { case WLR_BUTTON_PRESSED: - if (**PFOLLOWMOUSE == 3) // don't refocus on full loose + if (*PFOLLOWMOUSE == 3) // don't refocus on full loose break; - if ((!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) /* No constraints */ + if ((!g_pCompositor->m_sSeat.mouse || !isConstrained()) /* No constraints */ && (w && g_pCompositor->m_pLastWindow != w) /* window should change */) { // a bit hacky // if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus @@ -693,11 +668,12 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) { } void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { - static auto* const PSCROLLFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor"); + static auto PINPUTSCROLLFACTOR = CConfigValue("input:scroll_factor"); + static auto PTOUCHPADSCROLLFACTOR = CConfigValue("input:touchpad:scroll_factor"); - auto factor = (**PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : **PSCROLLFACTOR); + auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e->source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR); - const auto EMAP = std::unordered_map{{"event", e}}; + const auto EMAP = std::unordered_map{{"event", e}}; EMIT_HOOK_EVENT_CANCELLABLE("mouseAxis", EMAP); bool passEvent = g_pKeybindManager->onAxisEvent(e); @@ -716,7 +692,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { } wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source, - WLR_AXIS_RELATIVE_DIRECTION_IDENTICAL); + WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); } Vector2D CInputManager::getMouseCoordsInternal() { @@ -908,11 +884,10 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - xkb_state_unref(pKeyboard->xkbTranslationState); - pKeyboard->xkbTranslationState = xkb_state_new(KEYMAP); - wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP); + pKeyboard->updateXKBTranslationState(); + wlr_keyboard_modifiers wlrMods = {0}; if (NUMLOCKON == 1) { @@ -1189,8 +1164,8 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar const auto EMAP = std::unordered_map{{"keyboard", pKeyboard}, {"event", e}}; EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP); - static auto* const PDPMS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:key_press_enables_dpms"); - if (**PDPMS && !g_pCompositor->m_bDPMSStateON) { + static auto PDPMS = CConfigValue("misc:key_press_enables_dpms"); + if (*PDPMS && !g_pCompositor->m_bDPMSStateON) { // enable dpms g_pKeybindManager->dpms("on"); } @@ -1246,6 +1221,8 @@ void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) { const auto LAYOUT = getActiveLayoutForKeyboard(pKeyboard); + pKeyboard->updateXKBTranslationState(); + g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUT}); EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, (void*)&LAYOUT})); } @@ -1277,133 +1254,27 @@ void CInputManager::updateDragIcon() { } } -void CInputManager::recheckConstraint(SMouse* pMouse) { - if (!pMouse->currentConstraint) - return; - - const auto PREGION = &pMouse->currentConstraint->region; - - if (pMouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED) - pMouse->confinedTo.set(PREGION); - else - pMouse->confinedTo.clear(); -} - -void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* constraint) { - - if (pMouse->currentConstraint == constraint) - return; - - const auto MOUSECOORDS = getMouseCoordsInternal(); - const auto PCONSTRAINT = constraintFromWlr(constraint); - - pMouse->hyprListener_commitConstraint.removeCallback(); - - if (pMouse->currentConstraint) - wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint); - - if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(constraint->surface); PWINDOW) { - const auto RELATIVETO = PWINDOW->m_bIsX11 ? - (PWINDOW->m_bIsMapped ? PWINDOW->m_vRealPosition.goalv() : - g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) : - PWINDOW->m_vRealPosition.goalv(); - - PCONSTRAINT->cursorPosOnActivate = (MOUSECOORDS - RELATIVETO) * PWINDOW->m_fX11SurfaceScaledBy; - } - - if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { - PCONSTRAINT->hintSet = true; - PCONSTRAINT->positionHint = {constraint->current.cursor_hint.x, constraint->current.cursor_hint.y}; - } - - if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) - warpMouseToConstraintMiddle(PCONSTRAINT); - - pMouse->currentConstraint = constraint; - pMouse->constraintActive = true; - - if (pixman_region32_not_empty(&constraint->current.region)) - pixman_region32_intersect(&constraint->region, &constraint->surface->input_region, &constraint->current.region); - else - pixman_region32_copy(&constraint->region, &constraint->surface->input_region); - - // warp to the constraint - recheckConstraint(pMouse); - - PCONSTRAINT->active = true; - - wlr_pointer_constraint_v1_send_activated(pMouse->currentConstraint); - - pMouse->hyprListener_commitConstraint.initCallback(&pMouse->currentConstraint->surface->events.commit, &Events::listener_commitConstraint, pMouse, "Mouse constraint commit"); - - Debug::log(LOG, "Constrained mouse to {:x}", (uintptr_t)pMouse->currentConstraint); -} - -void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) { - - if (!pConstraint) - return; - - const auto PWINDOW = g_pCompositor->getWindowFromSurface(pConstraint->constraint->surface); - - if (PWINDOW) { - const auto RELATIVETO = pConstraint->getLogicConstraintPos(); - const auto HINTSCALE = PWINDOW->m_fX11SurfaceScaledBy; - - auto HINT = pConstraint->hintSet ? pConstraint->positionHint : pConstraint->cursorPosOnActivate; - - if (HINT == Vector2D{-1, -1}) - HINT = pConstraint->getLogicConstraintSize() / 2.f; - - if (HINT != Vector2D{-1, -1}) { - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + HINT.x / HINTSCALE, RELATIVETO.y + HINT.y / HINTSCALE); - wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); - } - } -} - void CInputManager::unconstrainMouse() { - if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) + if (!g_pCompositor->m_sSeat.mouse) return; - const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse); + for (auto& c : m_vConstraints) { + if (!c->active()) + continue; - if (CONSTRAINTWINDOW) - g_pXWaylandManager->activateSurface(CONSTRAINTWINDOW->m_pWLSurface.wlr(), false); - - wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint); - - const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint); - if (PCONSTRAINT) - PCONSTRAINT->active = false; - - g_pCompositor->m_sSeat.mouse->constraintActive = false; - - // TODO: its better to somehow detect the workspace... - g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr; - - g_pCompositor->m_sSeat.mouse->hyprListener_commitConstraint.removeCallback(); + c->deactivate(); + } } -void Events::listener_commitConstraint(void* owner, void* data) { - const auto PMOUSE = (SMouse*)owner; +bool CInputManager::isConstrained() { + for (auto& c : m_vConstraints) { + if (!c->active() || c->owner()->wlr() != g_pCompositor->m_pLastFocus) + continue; - if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { - const auto PCONSTRAINT = g_pInputManager->constraintFromWlr(PMOUSE->currentConstraint); - if (PCONSTRAINT) { // should never be null but who knows - PCONSTRAINT->positionHint = Vector2D(PMOUSE->currentConstraint->current.cursor_hint.x, PMOUSE->currentConstraint->current.cursor_hint.y); - PCONSTRAINT->hintSet = true; - } + return true; } - if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) { - if (pixman_region32_not_empty(&PMOUSE->currentConstraint->current.region)) - pixman_region32_intersect(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region, &PMOUSE->currentConstraint->current.region); - else - pixman_region32_copy(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region); - - g_pInputManager->recheckConstraint(PMOUSE); - } + return false; } void CInputManager::updateCapabilities() { @@ -1669,15 +1540,6 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) { return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); } -SConstraint* CInputManager::constraintFromWlr(wlr_pointer_constraint_v1* constraint) { - for (auto& c : m_lConstraints) { - if (c.constraint == constraint) - return &c; - } - - return nullptr; -} - void CInputManager::releaseAllMouseButtons() { const auto buttonsCopy = m_lCurrentlyHeldButtons; @@ -1685,7 +1547,7 @@ void CInputManager::releaseAllMouseButtons() { return; for (auto& mb : buttonsCopy) { - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, 0, mb, WLR_BUTTON_RELEASED); + wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, 0, mb, WL_POINTER_BUTTON_STATE_RELEASED); } m_lCurrentlyHeldButtons.clear(); @@ -1698,17 +1560,17 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { return; } - static auto* const PEXTENDBORDERGRAB = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area"); - const int BORDERSIZE = w->getRealBorderSize(); - const int ROUNDING = w->rounding(); + static auto PEXTENDBORDERGRAB = CConfigValue("general:extend_border_grab_area"); + const int BORDERSIZE = w->getRealBorderSize(); + const int ROUNDING = w->rounding(); // give a small leeway (10 px) for corner icon const auto CORNER = ROUNDING + BORDERSIZE + 10; const auto mouseCoords = getMouseCoordsInternal(); CBox box = w->getWindowMainSurfaceBox(); eBorderIconDirection direction = BORDERICON_NONE; - CBox boxFullGrabInput = {box.x - **PEXTENDBORDERGRAB - BORDERSIZE, box.y - **PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (**PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (**PEXTENDBORDERGRAB + BORDERSIZE)}; + CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (w->hasPopupAt(mouseCoords)) direction = BORDERICON_NONE; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index e32e27f8..fd3aefe5 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -7,6 +7,8 @@ #include "../../helpers/Timer.hpp" #include "InputMethodRelay.hpp" +class CConstraint; + enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL @@ -80,11 +82,8 @@ class CInputManager { void destroyMouse(wlr_input_device*); void destroySwitch(SSwitchDevice*); - void constrainMouse(SMouse*, wlr_pointer_constraint_v1*); - void warpMouseToConstraintMiddle(SConstraint*); - void recheckConstraint(SMouse*); void unconstrainMouse(); - SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*); + bool isConstrained(); std::string getActiveLayoutForKeyboard(SKeyboard*); Vector2D getMouseCoordsInternal(); @@ -120,13 +119,12 @@ class CInputManager { bool m_bWasDraggingWindow = false; // for refocus to be forced - CWindow* m_pForcedFocus = nullptr; + CWindow* m_pForcedFocus = nullptr; - SDrag m_sDrag; + SDrag m_sDrag; - std::list m_lConstraints; - std::list m_lKeyboards; - std::list m_lMice; + std::list m_lKeyboards; + std::list m_lMice; // tablets std::list m_lTablets; @@ -145,25 +143,28 @@ class CInputManager { // Exclusive layer surfaces std::deque m_dExclusiveLSes; - void newTabletTool(wlr_input_device*); - void newTabletPad(wlr_input_device*); - void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false); - void newIdleInhibitor(wlr_idle_inhibitor_v1*); - void recheckIdleInhibitorStatus(); + // constraints + std::vector m_vConstraints; - void onSwipeBegin(wlr_pointer_swipe_begin_event*); - void onSwipeEnd(wlr_pointer_swipe_end_event*); - void onSwipeUpdate(wlr_pointer_swipe_update_event*); + void newTabletTool(wlr_input_device*); + void newTabletPad(wlr_input_device*); + void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false); + void newIdleInhibitor(wlr_idle_inhibitor_v1*); + void recheckIdleInhibitorStatus(); - SSwipeGesture m_sActiveSwipe; + void onSwipeBegin(wlr_pointer_swipe_begin_event*); + void onSwipeEnd(wlr_pointer_swipe_end_event*); + void onSwipeUpdate(wlr_pointer_swipe_update_event*); - SKeyboard* m_pActiveKeyboard = nullptr; + SSwipeGesture m_sActiveSwipe; - CTimer m_tmrLastCursorMovement; + SKeyboard* m_pActiveKeyboard = nullptr; - CInputMethodRelay m_sIMERelay; + CTimer m_tmrLastCursorMovement; - void updateKeyboardsLeds(wlr_input_device* pKeyboard); + CInputMethodRelay m_sIMERelay; + + void updateKeyboardsLeds(wlr_input_device* pKeyboard); // for shared mods uint32_t accumulateModsFromAllKBs(); @@ -190,13 +191,15 @@ class CInputManager { CWindow* m_pLastMouseFocus = nullptr; wlr_surface* m_pLastMouseSurface = nullptr; + // + bool m_bEmptyFocusCursorSet = false; + private: bool m_bCursorImageOverridden = false; eBorderIconDirection m_eBorderIconDirection = BORDERICON_NONE; // for click behavior override eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT; - bool m_bEmptyFocusCursorSet = false; Vector2D m_vLastCursorPosFloored = Vector2D(); void processMouseDownNormal(wlr_pointer_button_event* e); diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index aef9bb69..fb668cc2 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -192,8 +192,8 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { const auto PWINDOW = g_pCompositor->getWindowFromSurface(PFOCUSEDSURFACE); if (PWINDOW) { - parentPos = PWINDOW->m_vRealPosition.goalv(); - parentSize = PWINDOW->m_vRealSize.goalv(); + parentPos = PWINDOW->m_vRealPosition.goal(); + parentSize = PWINDOW->m_vRealSize.goal(); pMonitor = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); } } @@ -298,7 +298,7 @@ void CInputMethodRelay::damagePopup(SIMEPopup* pPopup) { const auto PWINDOW = g_pCompositor->getWindowFromSurface(PFOCUSEDSURFACE); if (PWINDOW) { - parentPos = PWINDOW->m_vRealPosition.goalv(); + parentPos = PWINDOW->m_vRealPosition.goal(); } } diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 83332285..9f9e95f6 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include "../../defines.hpp" #include "../../helpers/WLClasses.hpp" @@ -50,4 +51,4 @@ class CInputMethodRelay { friend class CHyprRenderer; friend class CInputManager; friend class CTextInputV1ProtocolManager; -}; \ No newline at end of file +}; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 1cc1b031..937266af 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -1,12 +1,13 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" +#include "../../config/ConfigValue.hpp" void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) { - static auto* const PSWIPE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe"); - static auto* const PSWIPEFINGERS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers"); - static auto* const PSWIPENEW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new"); + static auto PSWIPE = CConfigValue("gestures:workspace_swipe"); + static auto PSWIPEFINGERS = CConfigValue("gestures:workspace_swipe_fingers"); + static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); - if (e->fingers != **PSWIPEFINGERS || **PSWIPE == 0 || g_pSessionLockManager->isSessionLocked()) + if (e->fingers != *PSWIPEFINGERS || *PSWIPE == 0 || g_pSessionLockManager->isSessionLocked()) return; int onMonitor = 0; @@ -16,7 +17,7 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) { } } - if (onMonitor < 2 && !**PSWIPENEW) + if (onMonitor < 2 && !*PSWIPENEW) return; // disallow swiping when there's 1 workspace on a monitor beginWorkspaceSwipe(); @@ -44,20 +45,20 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { if (!m_sActiveSwipe.pWorkspaceBegin) return; // no valid swipe - static auto* const PSWIPEPERC = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio"); - static auto* const PSWIPEDIST = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance"); - static auto* const PSWIPEFORC = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force"); - static auto* const PSWIPENEW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new"); - static auto* const PSWIPENUMBER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered"); - static auto* const PSWIPEUSER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r"); - static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces"); - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + static auto PSWIPEPERC = CConfigValue("gestures:workspace_swipe_cancel_ratio"); + static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); + static auto PSWIPEFORC = CConfigValue("gestures:workspace_swipe_min_speed_to_force"); + static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); + static auto PSWIPENUMBER = CConfigValue("gestures:workspace_swipe_numbered"); + static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); + static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); // commit std::string wsname = ""; - auto workspaceIDLeft = getWorkspaceIDFromString(**PSWIPENUMBER ? "-1" : (**PSWIPEUSER ? "r-1" : "m-1"), wsname); - auto workspaceIDRight = getWorkspaceIDFromString(**PSWIPENUMBER ? "+1" : (**PSWIPEUSER ? "r+1" : "m+1"), wsname); + auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : (*PSWIPEUSER ? "r-1" : "m-1"), wsname); + auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : (*PSWIPEUSER ? "r+1" : "m+1"), wsname); // If we've been swiping off the right end with PSWIPENEW enabled, there is // no workspace there yet, and we need to choose an ID for a new one now. @@ -68,7 +69,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { // be counterintuitive to swipe rightwards onto a new workspace and end up // left of where we started. Instead, it's one more than the greatest // workspace ID that currently exists. - if (workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID && **PSWIPENEW) { + if (workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID && *PSWIPENEW) { int maxWorkspace = 0; for (const auto& ws : g_pCompositor->m_vWorkspaces) { maxWorkspace = std::max(maxWorkspace, ws->m_iID); @@ -79,13 +80,13 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER - const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec(); - const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + **PWORKSPACEGAP; - const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + **PWORKSPACEGAP; + const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.value(); + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; CWorkspace* pSwitchedTo = nullptr; - if ((abs(m_sActiveSwipe.delta) < **PSWIPEDIST * **PSWIPEPERC && (**PSWIPEFORC == 0 || (**PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < **PSWIPEFORC))) || + if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) { // revert if (abs(m_sActiveSwipe.delta) < 2) { @@ -118,7 +119,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin; } else if (m_sActiveSwipe.delta < 0) { // switch to left - const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_vRenderOffset.vec() : Vector2D(); + const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_vRenderOffset.value() : Vector2D(); if (PWORKSPACEL) m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDLeft); @@ -144,7 +145,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { pSwitchedTo = PWORKSPACEL; } else { // switch to right - const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset.vec() : Vector2D(); + const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset.value() : Vector2D(); if (PWORKSPACER) m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDRight); @@ -194,40 +195,40 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { if (!m_sActiveSwipe.pWorkspaceBegin) return; - static auto* const PSWIPEDIST = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance"); - static auto* const PSWIPEINVR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert"); - static auto* const PSWIPENEW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new"); - static auto* const PSWIPEDIRLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_direction_lock"); - static auto* const PSWIPEDIRLOCKTHRESHOLD = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_direction_lock_threshold"); - static auto* const PSWIPEFOREVER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_forever"); - static auto* const PSWIPENUMBER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered"); - static auto* const PSWIPEUSER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r"); - static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces"); + static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); + static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); + static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); + static auto PSWIPEDIRLOCK = CConfigValue("gestures:workspace_swipe_direction_lock"); + static auto PSWIPEDIRLOCKTHRESHOLD = CConfigValue("gestures:workspace_swipe_direction_lock_threshold"); + static auto PSWIPEFOREVER = CConfigValue("gestures:workspace_swipe_forever"); + static auto PSWIPENUMBER = CConfigValue("gestures:workspace_swipe_numbered"); + static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); + static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); - const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + **PWORKSPACEGAP; - const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + **PWORKSPACEGAP; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); - 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); m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(e->dx)) / (m_sActiveSwipe.speedPoints + 1); m_sActiveSwipe.speedPoints++; std::string wsname = ""; - auto workspaceIDLeft = getWorkspaceIDFromString(**PSWIPENUMBER ? "-1" : (**PSWIPEUSER ? "r-1" : "m-1"), wsname); - auto workspaceIDRight = getWorkspaceIDFromString(**PSWIPENUMBER ? "+1" : (**PSWIPEUSER ? "r+1" : "m+1"), wsname); + auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : (*PSWIPEUSER ? "r-1" : "m-1"), wsname); + auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : (*PSWIPEUSER ? "r+1" : "m+1"), wsname); - if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !**PSWIPENEW) { + if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) { m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe return; } m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = true; - m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-**PSWIPEDIST, (double)**PSWIPEDIST); + m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST); - if ((m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDLeft && **PSWIPENEW && (m_sActiveSwipe.delta < 0)) || + if ((m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDLeft && *PSWIPENEW && (m_sActiveSwipe.delta < 0)) || (m_sActiveSwipe.delta > 0 && g_pCompositor->getWindowsOnWorkspace(m_sActiveSwipe.pWorkspaceBegin->m_iID) == 0 && workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID) || (m_sActiveSwipe.delta < 0 && m_sActiveSwipe.pWorkspaceBegin->m_iID <= workspaceIDLeft)) { @@ -236,10 +237,10 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { return; } - if (**PSWIPEDIRLOCK) { + if (*PSWIPEDIRLOCK) { if (m_sActiveSwipe.initialDirection != 0 && m_sActiveSwipe.initialDirection != (m_sActiveSwipe.delta < 0 ? -1 : 1)) m_sActiveSwipe.delta = 0; - else if (m_sActiveSwipe.initialDirection == 0 && abs(m_sActiveSwipe.delta) > **PSWIPEDIRLOCKTHRESHOLD) + else if (m_sActiveSwipe.initialDirection == 0 && abs(m_sActiveSwipe.delta) > *PSWIPEDIRLOCKTHRESHOLD) m_sActiveSwipe.initialDirection = m_sActiveSwipe.delta < 0 ? -1 : 1; } @@ -247,13 +248,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft); if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID || !PWORKSPACE) { - if (**PSWIPENEW || **PSWIPENUMBER) { + if (*PSWIPENEW || *PSWIPENUMBER) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / **PSWIPEDIST) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / **PSWIPEDIST) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -275,11 +276,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / **PSWIPEDIST) * YDISTANCE - YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / **PSWIPEDIST) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE - YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / **PSWIPEDIST) * XDISTANCE - XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / **PSWIPEDIST) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE - XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); @@ -287,13 +288,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight); if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID || !PWORKSPACE) { - if (**PSWIPENEW || **PSWIPENUMBER) { + if (*PSWIPENEW || *PSWIPENUMBER) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / **PSWIPEDIST) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / **PSWIPEDIST) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -315,11 +316,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / **PSWIPEDIST) * YDISTANCE + YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / **PSWIPEDIST) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE + YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / **PSWIPEDIST) * XDISTANCE + XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / **PSWIPEDIST) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE + XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); @@ -329,8 +330,8 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); - if (**PSWIPEFOREVER) { - if (abs(m_sActiveSwipe.delta) >= **PSWIPEDIST) { + if (*PSWIPEFOREVER) { + if (abs(m_sActiveSwipe.delta) >= *PSWIPEDIST) { onSwipeEnd(nullptr); beginWorkspaceSwipe(); } diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 959ce432..f692620c 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -267,7 +267,7 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti } if (motion) { - auto local = CURSORPOS - PWINDOW->m_vRealPosition.goalv(); + auto local = CURSORPOS - PWINDOW->m_vRealPosition.goal(); if (PWINDOW->m_bIsX11) local = local * PWINDOW->m_fX11SurfaceScaledBy; diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 600df302..3247a229 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -19,7 +19,7 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) { if (m_ecbClickBehavior == CLICKMODE_KILL) { wlr_pointer_button_event e; - e.state = WLR_BUTTON_PRESSED; + e.state = WL_POINTER_BUTTON_STATE_PRESSED; g_pInputManager->processMouseDownKill(&e); return; } @@ -34,8 +34,8 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) { if (m_sTouchData.touchFocusWindow) { if (m_sTouchData.touchFocusWindow->m_bIsX11) { - local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; - m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goalv(); + local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goal()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; + m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goal(); } else { g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow, local); m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local; diff --git a/src/meson.build b/src/meson.build index 2d72280c..59771fcf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,6 +11,7 @@ executable('Hyprland', src, dependency('wayland-client'), wlroots.get_variable('wlroots'), dependency('cairo'), + dependency('hyprcursor'), dependency('hyprlang', version: '>= 0.3.2'), dependency('libdrm'), dependency('egl'), diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index b6326960..494aa640 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -296,7 +296,7 @@ APICALL std::vector HyprlandAPI::findFunctionsByName(HANDLE hand const auto FPATH = std::filesystem::canonical(exe); #elif defined(__OpenBSD__) // Neither KERN_PROC_PATHNAME nor /proc are supported - const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland"); + const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland"); #else const auto FPATH = std::filesystem::canonical("/proc/self/exe"); #endif diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 6d0aa8bc..a0c05b22 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -484,9 +484,9 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* } CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y}); - g_pHyprOpenGL->setMonitorTransformEnabled(false); - g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + g_pHyprOpenGL->setMonitorTransformEnabled(false); #ifndef GLES2 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); @@ -535,15 +535,17 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { if (!sourceTex) return false; - CRegion fakeDamage = {0, 0, frame->box.width, frame->box.height}; + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer)) return false; - CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y}); - g_pHyprOpenGL->setMonitorTransformEnabled(false); - g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} + .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlr_output_transform_invert(frame->pMonitor->output->transform), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprRenderer->endRender(); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index e7ea787d..88e56954 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -212,7 +212,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou PFRAME->dmabufFormat = DRM_FORMAT_INVALID; } - PFRAME->box = {0, 0, (int)(PFRAME->pWindow->m_vRealSize.vec().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.vec().y * PMONITOR->scale)}; + PFRAME->box = {0, 0, (int)(PFRAME->pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.value().y * PMONITOR->scale)}; int ow, oh; wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); PFRAME->box.transform(PMONITOR->transform, ow, oh).round(); @@ -322,7 +322,7 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp if (PMONITOR != g_pCompositor->getMonitorFromID(f->pWindow->m_iMonitorID)) continue; - CBox geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y}; + CBox geometry = {f->pWindow->m_vRealPosition.value().x, f->pWindow->m_vRealPosition.value().y, f->pWindow->m_vRealSize.value().x, f->pWindow->m_vRealSize.value().y}; if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr())) continue; @@ -404,7 +404,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->m_bBlockSurfaceFeedback = false; if (frame->overlayCursor) - g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); + g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.value()); const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format); if (!PFORMAT) { @@ -450,7 +450,7 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti g_pHyprRenderer->m_bBlockSurfaceFeedback = false; if (frame->overlayCursor) - g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); + g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.value()); g_pHyprRenderer->endRender(); return true; diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 9f6e071d..c097b551 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -1,5 +1,6 @@ #include "XDGOutput.hpp" #include "../Compositor.hpp" +#include "../config/ConfigValue.hpp" #include "xdg-output-unstable-v1-protocol.h" @@ -112,7 +113,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r } void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); if (!pOutput->resource->good() || !pOutput->monitor) return; @@ -120,7 +121,7 @@ void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { 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->vecTransformedSize.x, pOutput->monitor->vecTransformedSize.y); else zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecSize.x, pOutput->monitor->vecSize.y); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index bab07528..b38ab814 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -4,6 +4,7 @@ #include "../helpers/MiscFunctions.hpp" #include "Shaders.hpp" #include +#include "../config/ConfigValue.hpp" inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); @@ -120,10 +121,10 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { // passes requiring introspection are the ones that need to render blur. - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); - static auto* const PXRAY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:xray"); - static auto* const POPTIM = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations"); - static auto* const PBLURSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:special"); + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + static auto PXRAY = CConfigValue("decoration:blur:xray"); + static auto POPTIM = CConfigValue("decoration:blur:new_optimizations"); + static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); if (m_RenderData.mouseZoomFactor != 1.0 || g_pHyprRenderer->m_bCrashingInProgress) return true; @@ -131,7 +132,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty()) return true; - if (**PBLUR == 0) + if (*PBLUR == 0) return false; if (m_RenderData.pCurrentMonData->blurFBShouldRender) @@ -141,13 +142,13 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { - const auto XRAYMODE = ls->xray == -1 ? **PXRAY : ls->xray; + const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; if (ls->forceBlur && !XRAYMODE) return true; } for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - const auto XRAYMODE = ls->xray == -1 ? **PXRAY : ls->xray; + const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; if (ls->forceBlur && !XRAYMODE) return true; } @@ -168,18 +169,18 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (!ws->m_bIsSpecialWorkspace || ws->m_iMonitorID != pMonitor->ID) continue; - if (ws->m_fAlpha.fl() == 0) + if (ws->m_fAlpha.value() == 0) continue; return true; } } - if (**PXRAY) + if (*PXRAY) return false; for (auto& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && **POPTIM && !g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))) + if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && *POPTIM && !g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))) continue; if (!g_pHyprRenderer->shouldRenderWindow(w.get())) @@ -200,7 +201,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional finalDamage) { m_RenderData.pMonitor = pMonitor; - static auto* const PFORCEINTROSPECTION = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("opengl:force_introspection"); + static auto PFORCEINTROSPECTION = CConfigValue("opengl:force_introspection"); #ifndef GLES2 @@ -257,14 +258,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu m_bFakeFrame = fb; if (m_bReloadScreenShader) { - m_bReloadScreenShader = false; - static auto* const PSHADER = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("decoration:screen_shader"); + m_bReloadScreenShader = false; + static auto PSHADER = CConfigValue("decoration:screen_shader"); applyScreenShader(*PSHADER); } const auto PRBO = g_pHyprRenderer->getCurrentRBO(); const bool FBPROPERSIZE = !fb || fb->m_vSize == pMonitor->vecPixelSize; - const bool USERFORCEDINTROSPECTION = **PFORCEINTROSPECTION == 1 ? true : (**PFORCEINTROSPECTION == 2 ? g_pHyprRenderer->isNvidia() : false); // 0 - no, 1 - yes, 2 - nvidia only + const bool USERFORCEDINTROSPECTION = *PFORCEINTROSPECTION == 1 ? true : (*PFORCEINTROSPECTION == 2 ? g_pHyprRenderer->isNvidia() : false); // 0 - no, 1 - yes, 2 - nvidia only if (USERFORCEDINTROSPECTION || m_RenderData.forceIntrospection || !FBPROPERSIZE || m_sFinalScreenShader.program > 0 || (PRBO && pMonitor->vecPixelSize != PRBO->getFB()->m_vSize) || passRequiresIntrospection(pMonitor)) { @@ -290,7 +291,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu } void CHyprOpenGLImpl::end() { - static auto* const PZOOMRIGID = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_rigid"); + static auto PZOOMRIGID = CConfigValue("misc:cursor_zoom_rigid"); TRACY_GPU_ZONE("RenderEnd"); @@ -310,7 +311,7 @@ void CHyprOpenGLImpl::end() { (g_pInputManager->getMouseCoordsInternal() - m_RenderData.pMonitor->vecPosition) * m_RenderData.pMonitor->scale : m_RenderData.pMonitor->vecTransformedSize / 2.f; - monbox.translate(-ZOOMCENTER).scale(m_RenderData.mouseZoomFactor).translate(**PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize / 2.0 : ZOOMCENTER); + monbox.translate(-ZOOMCENTER).scale(m_RenderData.mouseZoomFactor).translate(*PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize / 2.0 : ZOOMCENTER); if (monbox.x > 0) monbox.x = 0; @@ -353,7 +354,11 @@ void CHyprOpenGLImpl::end() { // check for gl errors const GLenum ERR = glGetError(); +#ifdef GLES2 + if (ERR == GL_CONTEXT_LOST_KHR) /* We don't have infra to recover from this */ +#else if (ERR == GL_CONTEXT_LOST) /* We don't have infra to recover from this */ +#endif RASSERT(false, "glGetError at Opengl::end() returned GL_CONTEXT_LOST. Cannot continue until proper GPU reset handling is implemented."); } @@ -526,7 +531,7 @@ void CHyprOpenGLImpl::initShaders() { void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { - static auto* const PDT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:damage_tracking"); + static auto PDT = CConfigValue("debug:damage_tracking"); m_sFinalScreenShader.destroy(); @@ -553,7 +558,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { m_sFinalScreenShader.tex = glGetUniformLocation(m_sFinalScreenShader.program, "tex"); m_sFinalScreenShader.time = glGetUniformLocation(m_sFinalScreenShader.program, "time"); m_sFinalScreenShader.wl_output = glGetUniformLocation(m_sFinalScreenShader.program, "wl_output"); - if (m_sFinalScreenShader.time != -1 && **PDT != 0 && !g_pHyprRenderer->m_bCrashingInProgress) { + if (m_sFinalScreenShader.time != -1 && *PDT != 0 && !g_pHyprRenderer->m_bCrashingInProgress) { // The screen shader uses the "time" uniform // Since the screen shader could change every frame, damage tracking *needs* to be disabled g_pConfigManager->addParseError("Screen shader: Screen shader uses uniform 'time', which requires debug:damage_tracking to be switched off.\n" @@ -777,8 +782,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* CBox newBox = *pBox; m_RenderData.renderModif.applyToBox(newBox); - static auto* const PDIMINACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_inactive"); - static auto* const PDT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:damage_tracking"); + static auto PDIMINACTIVE = CConfigValue("decoration:dim_inactive"); + static auto PDT = CConfigValue("debug:damage_tracking"); // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); @@ -838,7 +843,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* #endif glUniform1i(shader->tex, 0); - if ((usingFinalShader && **PDT == 0) || CRASHING) { + if ((usingFinalShader && *PDT == 0) || CRASHING) { glUniform1f(shader->time, m_tGlobalTimer.getSeconds()); } else if (usingFinalShader && shader->time != -1) { // Don't let time be unitialised @@ -879,9 +884,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y); glUniform1f(shader->radius, round); - if (allowDim && m_pCurrentWindow && **PDIMINACTIVE) { + if (allowDim && m_pCurrentWindow && *PDIMINACTIVE) { glUniform1i(shader->applyTint, 1); - const auto DIM = m_pCurrentWindow->m_fDimPercent.fl(); + const auto DIM = m_pCurrentWindow->m_fDimPercent.value(); glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); } else { glUniform1i(shader->applyTint, 0); @@ -1063,16 +1068,16 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); // get the config settings - static auto* const PBLURSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:size"); - static auto* const PBLURPASSES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:passes"); - static auto* const PBLURVIBRANCY = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:vibrancy"); - static auto* const PBLURVIBRANCYDARKNESS = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:vibrancy_darkness"); + static auto PBLURSIZE = CConfigValue("decoration:blur:size"); + static auto PBLURPASSES = CConfigValue("decoration:blur:passes"); + static auto PBLURVIBRANCY = CConfigValue("decoration:blur:vibrancy"); + static auto PBLURVIBRANCYDARKNESS = CConfigValue("decoration:blur:vibrancy_darkness"); // prep damage CRegion damage{*originalDamage}; wlr_region_transform(damage.pixman(), damage.pixman(), wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); - wlr_region_expand(damage.pixman(), damage.pixman(), **PBLURPASSES > 10 ? pow(2, 15) : std::clamp(**PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, **PBLURPASSES)); + wlr_region_expand(damage.pixman(), damage.pixman(), *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); // helper const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB; @@ -1083,8 +1088,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // Begin with base color adjustments - global brightness and contrast // TODO: make this a part of the first pass maybe to save on a drawcall? { - static auto* const PBLURCONTRAST = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:contrast"); - static auto* const PBLURBRIGHTNESS = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:brightness"); + static auto PBLURCONTRAST = CConfigValue("decoration:blur:contrast"); + static auto PBLURBRIGHTNESS = CConfigValue("decoration:blur:brightness"); PMIRRORSWAPFB->bind(); @@ -1102,8 +1107,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o wlr_matrix_transpose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix); #endif - glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, **PBLURCONTRAST); - glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, **PBLURBRIGHTNESS); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS); glUniform1i(m_RenderData.pCurrentMonData->m_shBLURPREPARE.tex, 0); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -1147,13 +1152,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o wlr_matrix_transpose(glMatrix, glMatrix); glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); #endif - glUniform1f(pShader->radius, **PBLURSIZE * a); // this makes the blursize change with a + glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) { glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f)); - glUniform1i(m_RenderData.pCurrentMonData->m_shBLUR1.passes, **PBLURPASSES); - glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy, **PBLURVIBRANCY); - glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy_darkness, **PBLURVIBRANCYDARKNESS); + glUniform1i(m_RenderData.pCurrentMonData->m_shBLUR1.passes, *PBLURPASSES); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy, *PBLURVIBRANCY); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy_darkness, *PBLURVIBRANCYDARKNESS); } else glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f)); @@ -1190,20 +1195,20 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o CRegion tempDamage{damage}; // and draw - for (int i = 1; i <= **PBLURPASSES; ++i) { + for (int i = 1; i <= *PBLURPASSES; ++i) { wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down } - for (int i = **PBLURPASSES - 1; i >= 0; --i) { + for (int i = *PBLURPASSES - 1; i >= 0; --i) { wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); // when upsampling we make the region twice as big drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } // finalize the image { - static auto* const PBLURNOISE = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:noise"); - static auto* const PBLURBRIGHTNESS = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:brightness"); + static auto PBLURNOISE = CConfigValue("decoration:blur:noise"); + static auto PBLURBRIGHTNESS = CConfigValue("decoration:blur:brightness"); if (currentRenderToFB == PMIRRORFB) PMIRRORSWAPFB->bind(); @@ -1224,8 +1229,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o wlr_matrix_transpose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); #endif - glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, **PBLURNOISE); - glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, **PBLURBRIGHTNESS); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS); glUniform1i(m_RenderData.pCurrentMonData->m_shBLURFINISH.tex, 0); @@ -1264,11 +1269,11 @@ void CHyprOpenGLImpl::markBlurDirtyForMonitor(CMonitor* pMonitor) { } void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { - static auto* const PBLURNEWOPTIMIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations"); - static auto* const PBLURXRAY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:xray"); - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); + static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); + static auto PBLURXRAY = CConfigValue("decoration:blur:xray"); + static auto PBLUR = CConfigValue("decoration:blur:enabled"); - if (!**PBLURNEWOPTIMIZE || !m_mMonitorRenderResources[pMonitor].blurFBDirty || !**PBLUR) + if (!*PBLURNEWOPTIMIZE || !m_mMonitorRenderResources[pMonitor].blurFBDirty || !*PBLUR) return; // ignore if solitary present, nothing to blur @@ -1292,7 +1297,7 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { const auto PSURFACE = pWindow->m_pWLSurface.wlr(); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - const float A = pWindow->m_fAlpha.fl() * pWindow->m_fActiveInactiveAlpha.fl() * PWORKSPACE->m_fAlpha.fl(); + const float A = pWindow->m_fAlpha.value() * pWindow->m_fActiveInactiveAlpha.value() * PWORKSPACE->m_fAlpha.value(); if (A >= 1.f) { if (PSURFACE->opaque) @@ -1313,7 +1318,7 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { bool hasWindows = false; for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->isHidden() && w->m_bIsMapped && (!w->m_bIsFloating || **PBLURXRAY)) { + if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->isHidden() && w->m_bIsMapped && (!w->m_bIsFloating || *PBLURXRAY)) { // check if window is valid if (!windowShouldBeBlurred(w.get())) @@ -1330,7 +1335,7 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (!ls->layerSurface || ls->xray != 1) continue; - if (ls->layerSurface->surface->opaque && ls->alpha.fl() >= 1.f) + if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f) continue; hasWindows = true; @@ -1386,15 +1391,15 @@ void CHyprOpenGLImpl::preWindowPass() { } bool CHyprOpenGLImpl::preBlurQueued() { - static auto* const PBLURNEWOPTIMIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations"); - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); + static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); + static auto PBLUR = CConfigValue("decoration:blur:enabled"); - return !(!m_RenderData.pCurrentMonData->blurFBDirty || !**PBLURNEWOPTIMIZE || !**PBLUR || !m_RenderData.pCurrentMonData->blurFBShouldRender); + return !(!m_RenderData.pCurrentMonData->blurFBDirty || !*PBLURNEWOPTIMIZE || !*PBLUR || !m_RenderData.pCurrentMonData->blurFBShouldRender); } bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow) { - static auto* const PBLURNEWOPTIMIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations"); - static auto* const PBLURXRAY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:xray"); + static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); + static auto PBLURXRAY = CConfigValue("decoration:blur:xray"); if (!m_RenderData.pCurrentMonData->blurFB.m_cTex.m_iTexID) return false; @@ -1405,7 +1410,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWind if (pLayer && pLayer->xray == 0) return false; - if ((**PBLURNEWOPTIMIZE && pWindow && !pWindow->m_bIsFloating && !g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID)) || **PBLURXRAY) + if ((*PBLURNEWOPTIMIZE && pWindow && !pWindow->m_bIsFloating && !g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID)) || *PBLURXRAY) return true; if ((pLayer && pLayer->xray == 1) || (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 1)) @@ -1417,8 +1422,8 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWind void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); - static auto* const PBLURENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); - static auto* const PNOBLUROVERSIZED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized"); + static auto PBLURENABLED = CConfigValue("decoration:blur:enabled"); + static auto PNOBLUROVERSIZED = CConfigValue("decoration:no_blur_on_oversized"); TRACY_GPU_ZONE("RenderTextureWithBlur"); @@ -1429,7 +1434,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo if (texDamage.empty()) return; - if (**PBLURENABLED == 0 || (**PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || + if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && (m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur || m_pCurrentWindow->m_sAdditionalConfigData.forceRGBX))) { renderTexture(tex, pBox, a, round, false, true); return; @@ -1490,11 +1495,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo // stencil done. Render everything. CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; // render our great blurred FB - static auto* const PBLURIGNOREOPACITY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:ignore_opacity"); - m_bEndFrame = true; // fix transformed - const auto SAVEDRENDERMODIF = m_RenderData.renderModif; - m_RenderData.renderModif = {}; // fix shit - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, **PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false); + static auto PBLURIGNOREOPACITY = CConfigValue("decoration:blur:ignore_opacity"); + m_bEndFrame = true; // fix transformed + const auto SAVEDRENDERMODIF = m_RenderData.renderModif; + m_RenderData.renderModif = {}; // fix shit + renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false); m_bEndFrame = false; m_RenderData.renderModif = SAVEDRENDERMODIF; @@ -1644,7 +1649,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra // will try to copy the bg to apply blur. // this isn't entirely correct, but like, oh well. // small todo: maybe make this correct? :P - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); + static auto* const PBLUR = (Hyprlang::INT* const*)(g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")); const auto BLURVAL = **PBLUR; **PBLUR = 0; @@ -1697,7 +1702,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { // will try to copy the bg to apply blur. // this isn't entirely correct, but like, oh well. // small todo: maybe make this correct? :P - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); + static auto* const PBLUR = (Hyprlang::INT* const*)(g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")); const auto BLURVAL = **PBLUR; **PBLUR = 0; @@ -1754,11 +1759,11 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { RASSERT(m_RenderData.pMonitor, "Tried to render snapshot rect without begin()!"); - const auto PWINDOW = *pWindow; + const auto PWINDOW = *pWindow; - static auto* const PDIMAROUND = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_around"); + static auto PDIMAROUND = CConfigValue("decoration:dim_around"); - auto it = m_mWindowFramebuffers.begin(); + auto it = m_mWindowFramebuffers.begin(); for (; it != m_mWindowFramebuffers.end(); it++) { if (it->first == PWINDOW) { break; @@ -1773,25 +1778,25 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { CBox windowBox; // some mafs to figure out the correct box // the originalClosedPos is relative to the monitor's pos - Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), - (PMONITOR->scale * PWINDOW->m_vRealSize.vec().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale))); + Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.value().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), + (PMONITOR->scale * PWINDOW->m_vRealSize.value().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale))); windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; - windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); - windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); + windowBox.x = ((PWINDOW->m_vRealPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); + windowBox.y = ((PWINDOW->m_vRealPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; - if (**PDIMAROUND && (*pWindow)->m_sAdditionalConfigData.dimAround) { + if (*PDIMAROUND && (*pWindow)->m_sAdditionalConfigData.dimAround) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, **PDIMAROUND * PWINDOW->m_fAlpha.fl())); + g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * PWINDOW->m_fAlpha.value())); g_pHyprRenderer->damageMonitor(PMONITOR); } m_bEndFrame = true; - renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.fl(), &fakeDamage, 0); + renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.value(), &fakeDamage, 0); m_bEndFrame = false; } @@ -1812,13 +1817,22 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID); - CBox monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; + CBox layerBox; + // some mafs to figure out the correct box + // the originalClosedPos is relative to the monitor's pos + Vector2D scaleXY = Vector2D((PMONITOR->scale * PLAYER->realSize.value().x / (PLAYER->geometry.w * PMONITOR->scale)), + (PMONITOR->scale * PLAYER->realSize.value().y / (PLAYER->geometry.h * PMONITOR->scale))); - CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; + layerBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; + layerBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; + layerBox.x = ((PLAYER->realPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((PLAYER->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x); + layerBox.y = ((PLAYER->realPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((PLAYER->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y); + + CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; m_bEndFrame = true; - renderTextureInternalWithDamage(it->second.m_cTex, &monbox, PLAYER->alpha.fl(), &fakeDamage, 0); + renderTextureInternalWithDamage(it->second.m_cTex, &layerBox, PLAYER->alpha.value(), &fakeDamage, 0); m_bEndFrame = false; } @@ -1838,13 +1852,13 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const box = &newBox; - static auto* const PSHADOWPOWER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power"); + static auto PSHADOWPOWER = CConfigValue("decoration:shadow_render_power"); - const auto SHADOWPOWER = std::clamp((int)**PSHADOWPOWER, 1, 4); + const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); - const auto col = color; + const auto col = color; - float matrix[9]; + float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here @@ -1932,16 +1946,16 @@ void CHyprOpenGLImpl::renderMirrored() { } void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY, const Vector2D& size) { - static auto* const PSPLASHCOLOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:col.splash"); + static auto PSPLASHCOLOR = CConfigValue("misc:col.splash"); - static auto* const PSPLASHFONT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:splash_font_family"); + static auto PSPLASHFONT = CConfigValue("misc:splash_font_family"); - cairo_select_font_face(CAIRO, *PSPLASHFONT, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_select_font_face(CAIRO, (*PSPLASHFONT).c_str(), CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); const auto FONTSIZE = (int)(size.y / 76); cairo_set_font_size(CAIRO, FONTSIZE); - const auto COLOR = CColor(**PSPLASHCOLOR); + const auto COLOR = CColor(*PSPLASHCOLOR); cairo_set_source_rgba(CAIRO, COLOR.r, COLOR.g, COLOR.b, COLOR.a); @@ -1958,15 +1972,15 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); - static auto* const PRENDERTEX = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo"); - static auto* const PNOSPLASH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering"); - static auto* const PFORCEWALLPAPER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper"); + static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); + static auto PNOSPLASH = CConfigValue("misc:disable_splash_rendering"); + static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); - const auto FORCEWALLPAPER = std::clamp(**PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); static std::string texPath = ""; - if (**PRENDERTEX) + if (*PRENDERTEX) return; // release the last tex if exists @@ -1988,7 +2002,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { texPath += std::to_string(distribution(engine)); } else - texPath += std::to_string(std::clamp(**PFORCEWALLPAPER, (int64_t)0, (int64_t)2)); + texPath += std::to_string(std::clamp(*PFORCEWALLPAPER, (int64_t)0, (int64_t)2)); texPath += ".png"; @@ -2039,7 +2053,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { cairo_set_source_surface(CAIRO, CAIROISURFACE, 0, 0); cairo_paint(CAIRO); - if (!**PNOSPLASH) + if (!*PNOSPLASH) renderSplash(CAIRO, CAIROSURFACE, origin.y * WPRATIO / MONRATIO * scale, IMAGESIZE); cairo_surface_flush(CAIROSURFACE); @@ -2048,9 +2062,15 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { tex.m_vSize = IMAGESIZE * scale; // copy the data to an OpenGL texture we have - const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA; - const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA; - const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; + const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? +#ifdef GLES2 + GL_RGB32F_EXT : +#else + GL_RGB32F : +#endif + GL_RGBA; + const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA; + const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); glBindTexture(GL_TEXTURE_2D, tex.m_iTexID); @@ -2154,7 +2174,7 @@ void CHyprOpenGLImpl::bindBackOnMain() { } void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { - m_bEndFrame = !enabled; + m_bEndFrame = enabled; } inline const SGLPixelFormat GLES2_FORMATS[] = { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 1e43333b..f6dff805 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -112,7 +112,7 @@ struct SCurrentRenderData { Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); - CBox clipBox = {}; + CBox clipBox = {}; // scaled coordinates uint32_t discardMode = DISCARD_OPAQUE; float discardOpacity = 0.f; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1c3aaab0..cb60cd41 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -3,6 +3,8 @@ #include "linux-dmabuf-unstable-v1-protocol.h" #include "../helpers/Region.hpp" #include +#include "../config/ConfigValue.hpp" +#include "../managers/CursorManager.hpp" extern "C" { #include @@ -29,16 +31,20 @@ CHyprRenderer::CHyprRenderer() { } else { Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks"); - const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD); + const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD); - std::string name = std::string{DRMV->name, DRMV->name_len}; - std::transform(name.begin(), name.end(), name.begin(), tolower); + if (DRMV) { + std::string name = std::string{DRMV->name, DRMV->name_len}; + std::transform(name.begin(), name.end(), name.begin(), tolower); - if (name.contains("nvidia")) - m_bNvidia = true; + if (name.contains("nvidia")) + m_bNvidia = true; - Debug::log(LOG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, - std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + Debug::log(LOG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, + std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + } else { + Debug::log(LOG, "No primary DRM driver information found"); + } drmFreeVersion(DRMV); } @@ -48,12 +54,12 @@ CHyprRenderer::CHyprRenderer() { } static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { - static auto* const PBLURPOPUPS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:popups"); - static auto* const PBLURPOPUPSIGNOREALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:popups_ignorealpha"); + static auto PBLURPOPUPS = CConfigValue("decoration:blur:popups"); + static auto PBLURPOPUPSIGNOREALPHA = CConfigValue("decoration:blur:popups_ignorealpha"); - const auto TEXTURE = wlr_surface_get_texture(surface); - const auto RDATA = (SRenderData*)data; - const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; + const auto TEXTURE = wlr_surface_get_texture(surface); + const auto RDATA = (SRenderData*)data; + const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; if (!TEXTURE) return; @@ -69,29 +75,40 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) // however, if surface buffer w / h < box, we need to adjust them auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface); + const auto PWINDOW = PSURFACE ? PSURFACE->getWindow() : nullptr; - if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) { + if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees PWINDOW */) { const auto CORRECT = PSURFACE->correctSmallVec(); const auto SIZE = PSURFACE->getViewporterCorrectedSize(); if (!INTERACTIVERESIZEINPROGRESS) { - windowBox.x += CORRECT.x; - windowBox.y += CORRECT.y; + windowBox.translate(CORRECT); - windowBox.width = SIZE.x * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x); - windowBox.height = SIZE.y * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y); + windowBox.width = SIZE.x * (PWINDOW->m_vRealSize.value().x / PWINDOW->m_vReportedSize.x); + windowBox.height = SIZE.y * (PWINDOW->m_vRealSize.value().y / PWINDOW->m_vReportedSize.y); } else { windowBox.width = SIZE.x; windowBox.height = SIZE.y; } } + if (PSURFACE && PWINDOW && PWINDOW->m_vRealSize.goal() > PWINDOW->m_vReportedSize && PWINDOW->m_vReportedSize > Vector2D{1, 1}) { + Vector2D size = + Vector2D{windowBox.w * (PWINDOW->m_vReportedSize.x / PWINDOW->m_vRealSize.value().x), windowBox.h * (PWINDOW->m_vReportedSize.y / PWINDOW->m_vRealSize.value().y)}; + Vector2D correct = Vector2D{windowBox.w, windowBox.h} - size; + + windowBox.translate(correct / 2.0); + + windowBox.w = size.x; + windowBox.h = size.y; + } + } else { // here we clamp to 2, these might be some tiny specks windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)}; if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) { // adjust subsurfaces to the window - windowBox.width = (windowBox.width / RDATA->pWindow->m_vReportedSize.x) * RDATA->pWindow->m_vRealSize.vec().x; - windowBox.height = (windowBox.height / RDATA->pWindow->m_vReportedSize.y) * RDATA->pWindow->m_vRealSize.vec().y; + windowBox.width = (windowBox.width / RDATA->pWindow->m_vReportedSize.x) * RDATA->pWindow->m_vRealSize.value().x; + windowBox.height = (windowBox.height / RDATA->pWindow->m_vReportedSize.y) * RDATA->pWindow->m_vRealSize.value().y; } } @@ -148,11 +165,11 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); } } else { - if (RDATA->blur && RDATA->popup && **PBLURPOPUPS) { + if (RDATA->blur && RDATA->popup && *PBLURPOPUPS) { - if (**PBLURPOPUPSIGNOREALPHA != 1.f) { + if (*PBLURPOPUPSIGNOREALPHA != 1.f) { g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; - g_pHyprOpenGL->m_RenderData.discardOpacity = **PBLURPOPUPSIGNOREALPHA; + g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURPOPUPSIGNOREALPHA; } g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, true); @@ -192,7 +209,7 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWo return true; } else { if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->m_bIsFullscreen && !pWindow->m_bIsFloating && !pWindow->m_bCreatedOverFullscreen && - pWindow->m_fAlpha.fl() == 0) + pWindow->m_fAlpha.value() == 0) return false; } } @@ -207,6 +224,15 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWo if (pMonitor->specialWorkspaceID == pWindow->m_iWorkspaceID) return true; + if (pWindow->m_vRealPosition.isBeingAnimated()) { + // render window if window and monitor intersect + // (when moving out of or through a monitor) + CBox windowBox = {pWindow->m_vRealPosition.value(), pWindow->m_vRealSize.value()}; + const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize}; + if (!windowBox.intersection(monitorBox).empty()) + return true; + } + return false; } @@ -247,7 +273,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (w->m_fAlpha.fl() == 0.f) + if (w->m_fAlpha.value() == 0.f) continue; if (w->m_bIsFullscreen || w->m_bIsFloating) @@ -264,7 +290,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (w->m_fAlpha.fl() == 0.f) + if (w->m_fAlpha.value() == 0.f) continue; if (w->m_bIsFullscreen || !w->m_bIsFloating) @@ -294,6 +320,9 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp if (!w->m_bIsFullscreen) continue; + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) + continue; + renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL); if (w->m_iWorkspaceID != pWorkspace->m_iID) @@ -330,7 +359,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork // Non-floating main for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) + if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; if (w->m_bIsFloating) @@ -343,7 +372,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork continue; // render active window after all others of this pass - if (w.get() == g_pCompositor->m_pLastWindow && w->m_iWorkspaceID == pWorkspace->m_iID) { + if (w.get() == g_pCompositor->m_pLastWindow) { lastWindow = w.get(); continue; } @@ -357,7 +386,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork // Non-floating popup for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) + if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; if (w->m_bIsFloating) @@ -375,7 +404,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork // floating on top for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) + if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; if (!w->m_bIsFloating || w->m_bPinned) @@ -384,7 +413,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) + if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) continue; if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) @@ -405,15 +434,18 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* return; } + if (!pWindow->m_bIsMapped) + return; + TRACY_GPU_ZONE("RenderWindow"); - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); - static auto* const PDIMAROUND = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_around"); - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); + const auto REALPOS = pWindow->m_vRealPosition.value() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.value()); + static auto PDIMAROUND = CConfigValue("decoration:dim_around"); + static auto PBLUR = CConfigValue("decoration:blur:enabled"); - SRenderData renderdata = {pMonitor, time}; - CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.vec().x, 5.0), std::max(pWindow->m_vRealSize.vec().y, 5.0)}; + SRenderData renderdata = {pMonitor, time}; + CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.value().x, 5.0), std::max(pWindow->m_vRealSize.value().y, 5.0)}; renderdata.x = textureBox.x; renderdata.y = textureBox.y; @@ -430,8 +462,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* renderdata.surface = pWindow->m_pWLSurface.wlr(); renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding); - renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl()); - renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl(); + renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.value()); + renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later @@ -452,7 +484,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (*PDIMAROUND && pWindow->m_sAdditionalConfigData.dimAround && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, **PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); + g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); } // clip box for animated offsets @@ -460,9 +492,9 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned && !pWindow->m_bIsFullscreen) { Vector2D offset; - if (PWORKSPACE->m_vRenderOffset.vec().x != 0) { + if (PWORKSPACE->m_vRenderOffset.value().x != 0) { const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); - const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().x / PWSMON->vecSize.x; + const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().x / PWSMON->vecSize.x; const auto WINBB = pWindow->getFullWindowBoundingBox(); if (WINBB.x < PWSMON->vecPosition.x) { @@ -470,9 +502,9 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } else if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x) { offset.x = (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS; } - } else if (PWORKSPACE->m_vRenderOffset.vec().y) { + } else if (PWORKSPACE->m_vRenderOffset.value().y != 0) { const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); - const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().y / PWSMON->vecSize.y; + const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().y / PWSMON->vecSize.y; const auto WINBB = pWindow->getFullWindowBoundingBox(); if (WINBB.y < PWSMON->vecPosition.y) { @@ -488,7 +520,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* // if window is floating and we have a slide animation, clip it to its full bb if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) { - CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.vec()).scale(pMonitor->scale); + CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.value()).scale(pMonitor->scale); g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents(); } @@ -521,11 +553,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } } - static auto* const PXWLUSENN = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:use_nearest_neighbor"); - if ((pWindow->m_bIsX11 && **PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) + static auto PXWLUSENN = CConfigValue("xwayland:use_nearest_neighbor"); + if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; - if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && **PBLUR) { + if (!pWindow->m_sAdditionalConfigData.forceNoBlur && pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; wb.scale(pMonitor->scale).round(); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, @@ -606,15 +638,20 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times TRACY_GPU_ZONE("RenderLayer"); - SRenderData renderdata = {pMonitor, time, pLayer->geometry.x, pLayer->geometry.y}; - renderdata.fadeAlpha = pLayer->alpha.fl(); + const auto REALPOS = pLayer->realPosition.value(); + const auto REALSIZ = pLayer->realSize.value(); + + SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; + renderdata.fadeAlpha = pLayer->alpha.value(); renderdata.blur = pLayer->forceBlur; renderdata.surface = pLayer->layerSurface->surface; renderdata.decorate = false; - renderdata.w = pLayer->geometry.width; - renderdata.h = pLayer->geometry.height; + renderdata.w = REALSIZ.x; + renderdata.h = REALSIZ.y; renderdata.blockBlurOptimization = pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM || pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + g_pHyprOpenGL->m_RenderData.clipBox = CBox{0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y}.scale(pMonitor->scale); + g_pHyprOpenGL->m_pCurrentLayer = pLayer; if (pLayer->ignoreAlpha) { @@ -629,7 +666,8 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times renderdata.popup = true; wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata); - g_pHyprOpenGL->m_pCurrentLayer = nullptr; + g_pHyprOpenGL->m_pCurrentLayer = nullptr; + g_pHyprOpenGL->m_RenderData.clipBox = {}; } void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) { @@ -657,13 +695,13 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon } void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { - static auto* const PDIMSPECIAL = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_special"); - static auto* const PBLURSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:special"); - static auto* const PBLUR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); - static auto* const PRENDERTEX = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo"); - static auto* const PBACKGROUNDCOLOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:background_color"); + static auto PDIMSPECIAL = CConfigValue("decoration:dim_special"); + static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); + static auto PBACKGROUNDCOLOR = CConfigValue("misc:background_color"); - SRenderModifData RENDERMODIFDATA; + SRenderModifData RENDERMODIFDATA; if (translate != Vector2D{0, 0}) RENDERMODIFDATA.modifs.push_back({SRenderModifData::eRenderModifType::RMOD_TYPE_TRANSLATE, translate}); if (scale != 1.f) @@ -692,15 +730,15 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* // TODO: check better with solitary after MR for tearing. const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || - !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.vec() != Vector2D{}) { + !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.value() != Vector2D{}) { if (!g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender) setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.damage, pWorkspace); g_pHyprOpenGL->blend(false); if (!canSkipBackBufferClear(pMonitor)) { - if (**PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(**PBACKGROUNDCOLOR)); + if (*PRENDERTEX /* inverted cfg flag */) + g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); else g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" } @@ -732,16 +770,16 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* // and then special for (auto& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.fl() > 0.f && ws->m_bIsSpecialWorkspace) { + if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { const auto SPECIALANIMPROGRS = ws->m_vRenderOffset.isBeingAnimated() ? ws->m_vRenderOffset.getCurveValue() : ws->m_fAlpha.getCurveValue(); const bool ANIMOUT = !pMonitor->specialWorkspaceID; - if (**PDIMSPECIAL != 0.f) { + if (*PDIMSPECIAL != 0.f) { CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, **PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); + g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); } - if (**PBLURSPECIAL && **PBLUR) { + if (*PBLURSPECIAL && *PBLUR) { CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)); } @@ -752,8 +790,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* // special for (auto& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.fl() > 0.f && ws->m_bIsSpecialWorkspace) - renderWorkspaceWindows(pMonitor, ws.get(), time); + if (ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { + if (ws->m_bHasFullscreenWindow) + renderWorkspaceWindowsFullscreen(pMonitor, ws.get(), time); + else + renderWorkspaceWindows(pMonitor, ws.get(), time); + } } // pinned always above @@ -793,16 +835,23 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* g_pHyprOpenGL->m_RenderData.renderModif = {}; } -void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now) { +void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry) { TRACY_GPU_ZONE("RenderLockscreen"); if (g_pSessionLockManager->isSessionLocked()) { - const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID); + Vector2D translate = {geometry.x, geometry.y}; + float scale = (float)geometry.width / pMonitor->vecPixelSize.x; + const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID); if (!PSLS) { // locked with no surface, fill with red - CBox boxe = {0, 0, INT16_MAX, INT16_MAX}; - g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0)); + const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); + + CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; + g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + + if (ALPHA < 1.f) /* animate */ + damageMonitor(pMonitor); } else { renderSessionLockSurface(PSLS, pMonitor, now); } @@ -857,7 +906,7 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac geom.applyFromWlr(); // ignore X and Y, adjust uv - if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) { + if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) { const auto XPERC = (double)geom.x / (double)pSurface->current.width; const auto YPERC = (double)geom.y / (double)pSurface->current.height; const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.width; @@ -868,7 +917,7 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac uvTL = uvTL + TOADDTL; // TODO: make this passed to the func. Might break in the future. - auto maxSize = pWindow->m_vRealSize.vec(); + auto maxSize = pWindow->m_vRealSize.value(); if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall) maxSize = pWindow->m_pWLSurface.getViewporterCorrectedSize(); @@ -943,23 +992,23 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now(); - static auto* const PDEBUGOVERLAY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:overlay"); - static auto* const PDAMAGETRACKINGMODE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:damage_tracking"); - static auto* const PDAMAGEBLINK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:damage_blink"); - static auto* const PNODIRECTSCANOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout"); - static auto* const PVFR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:vfr"); - static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor"); - static auto* const PANIMENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("animations:enabled"); - static auto* const PFIRSTLAUNCHANIM = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("animations:first_launch_animation"); - static auto* const PTEARINGENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:allow_tearing"); + static auto PDEBUGOVERLAY = CConfigValue("debug:overlay"); + static auto PDAMAGETRACKINGMODE = CConfigValue("debug:damage_tracking"); + static auto PDAMAGEBLINK = CConfigValue("debug:damage_blink"); + static auto PNODIRECTSCANOUT = CConfigValue("misc:no_direct_scanout"); + static auto PVFR = CConfigValue("misc:vfr"); + static auto PZOOMFACTOR = CConfigValue("misc:cursor_zoom_factor"); + static auto PANIMENABLED = CConfigValue("animations:enabled"); + static auto PFIRSTLAUNCHANIM = CConfigValue("animations:first_launch_animation"); + static auto PTEARINGENABLED = CConfigValue("general:allow_tearing"); static int damageBlinkCleanup = 0; // because double-buffered - if (!**PDAMAGEBLINK) + if (!*PDAMAGEBLINK) damageBlinkCleanup = 0; static bool firstLaunch = true; - static bool firstLaunchAnimActive = **PFIRSTLAUNCHANIM; + static bool firstLaunchAnimActive = *PFIRSTLAUNCHANIM; float zoomInFactorFirstLaunch = 1.f; @@ -969,7 +1018,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } if (m_tRenderTimer.getSeconds() < 1.5f && firstLaunchAnimActive) { // TODO: make the animation system more damage-flexible so that this can be migrated to there - if (!**PANIMENABLED) { + if (!*PANIMENABLED) { zoomInFactorFirstLaunch = 1.f; firstLaunchAnimActive = false; } else { @@ -982,7 +1031,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { renderStart = std::chrono::high_resolution_clock::now(); - if (**PDEBUGOVERLAY == 1) + if (*PDEBUGOVERLAY == 1) g_pDebugOverlay->frameData(pMonitor); if (pMonitor->framesToSkip > 0) { @@ -1002,7 +1051,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // checks // if (pMonitor->ID == m_pMostHzMonitor->ID || - **PVFR == 1) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that + *PVFR == 1) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that g_pCompositor->sanityCheckWorkspaces(); g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd @@ -1043,7 +1092,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (pMonitor->tearingState.nextRenderTorn) { pMonitor->tearingState.nextRenderTorn = false; - if (!**PTEARINGENABLED) { + if (!*PTEARINGENABLED) { Debug::log(WARN, "Tearing commit requested but the master switch general:allow_tearing is off, ignoring"); return; } @@ -1062,7 +1111,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { shouldTear = true; } - if (!**PNODIRECTSCANOUT && !shouldTear) { + if (!*PNODIRECTSCANOUT && !shouldTear) { if (attemptDirectScanout(pMonitor)) { return; } else if (m_pLastScanout) { @@ -1084,10 +1133,10 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // check the damage bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); - if (!hasChanged && **PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) + if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; - if (**PDAMAGETRACKINGMODE == -1) { + if (*PDAMAGETRACKINGMODE == -1) { Debug::log(CRIT, "Damage tracking mode -1 ????"); return; } @@ -1109,7 +1158,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_ZONE("Render"); if (pMonitor == g_pCompositor->getMonitorFromCursor()) - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(**PZOOMFACTOR, 1.f, INFINITY); + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY); else g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; @@ -1117,6 +1166,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch; g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false; g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; + pMonitor->forceFullFrames = 10; } CRegion damage, finalDamage; @@ -1132,22 +1182,22 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } // if we have no tracking or full tracking, invalidate the entire monitor - if (**PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || **PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || pMonitor->forceFullFrames > 0 || damageBlinkCleanup > 0 || + if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || pMonitor->forceFullFrames > 0 || damageBlinkCleanup > 0 || pMonitor->isMirror() /* why??? */) { damage = {0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10}; finalDamage = damage; } else { - static auto* const PBLURENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"); + static auto PBLURENABLED = CConfigValue("decoration:blur:enabled"); // if we use blur we need to expand the damage for proper blurring // if framebuffer was not offloaded we're not doing introspection aka not blurring so this is redundant and dumb - if (**PBLURENABLED == 1 && g_pHyprOpenGL->m_bOffloadedFramebuffer) { + if (*PBLURENABLED == 1 && g_pHyprOpenGL->m_bOffloadedFramebuffer) { // TODO: can this be optimized? - static auto* const PBLURSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:size"); - static auto* const PBLURPASSES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:blur:passes"); - const auto BLURRADIUS = - **PBLURPASSES > 10 ? pow(2, 15) : std::clamp(**PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, **PBLURPASSES); // is this 2^pass? I don't know but it works... I think. + static auto PBLURSIZE = CConfigValue("decoration:blur:size"); + static auto PBLURPASSES = CConfigValue("decoration:blur:passes"); + const auto BLURRADIUS = + *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think. // now, prep the damage, get the extended damage region wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring @@ -1183,7 +1233,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox); - renderLockscreen(pMonitor, &now); + renderLockscreen(pMonitor, &now, renderBox); if (pMonitor == g_pCompositor->m_pLastMonitor) { g_pHyprNotificationOverlay->draw(pMonitor); @@ -1191,17 +1241,17 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } // for drawing the debug overlay - if (pMonitor == g_pCompositor->m_vMonitors.front().get() && **PDEBUGOVERLAY == 1) { + if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { renderStartOverlay = std::chrono::high_resolution_clock::now(); g_pDebugOverlay->draw(); endRenderOverlay = std::chrono::high_resolution_clock::now(); } - if (**PDAMAGEBLINK && damageBlinkCleanup == 0) { + if (*PDAMAGEBLINK && damageBlinkCleanup == 0) { CBox monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); damageBlinkCleanup = 1; - } else if (**PDAMAGEBLINK) { + } else if (*PDAMAGEBLINK) { damageBlinkCleanup++; if (damageBlinkCleanup > 3) damageBlinkCleanup = 0; @@ -1216,7 +1266,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (renderCursor) { TRACY_GPU_ZONE("RenderCursor"); - bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && **PZOOMFACTOR != 1.f; + bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f; if (lockSoftware) { wlr_output_lock_software_cursors(pMonitor->output, true); @@ -1238,10 +1288,10 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform); wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); - if (**PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || **PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) + if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); - if (**PDAMAGEBLINK) + if (*PDAMAGEBLINK) frameDamage.add(damage); g_pHyprRenderer->damageMirrorsWith(pMonitor, frameDamage); @@ -1258,7 +1308,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, false); - damageMonitor(pMonitor); + wlr_damage_ring_add_whole(&pMonitor->damage); return; } @@ -1269,7 +1319,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, false); - if (**PDAMAGEBLINK || **PVFR == 0 || pMonitor->pendingFrame) + if (*PDAMAGEBLINK || *PVFR == 0 || pMonitor->pendingFrame) g_pCompositor->scheduleFrameForMonitor(pMonitor); pMonitor->pendingFrame = false; @@ -1277,7 +1327,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; g_pDebugOverlay->renderData(pMonitor, µs); - if (**PDEBUGOVERLAY == 1) { + if (*PDEBUGOVERLAY == 1) { if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); @@ -1584,7 +1634,7 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou return; auto* const PSURFACE = CWLSurface::surfaceFromWlr(pSurface); - if (PSURFACE && PSURFACE->m_pOwner && PSURFACE->small()) { + if (PSURFACE && PSURFACE->small()) { const auto CORRECTION = PSURFACE->correctSmallVec(); x += CORRECTION.x; y += CORRECTION.y; @@ -1620,9 +1670,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou m->addDamage(&damageBoxForEach); } - static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); + static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); - if (**PLOGDAMAGE) + if (*PLOGDAMAGE) Debug::log(LOG, "Damage: Surface (extents): xy: {}, {} wh: {}, {}", damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y1, damageBox.pixman()->extents.x2 - damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y2 - damageBox.pixman()->extents.y1); } @@ -1641,9 +1691,9 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) { for (auto& wd : pWindow->m_dWindowDecorations) wd->damageEntire(); - static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); + static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); - if (**PLOGDAMAGE) + if (*PLOGDAMAGE) Debug::log(LOG, "Damage: Window ({}): xy: {}, {} wh: {}, {}", pWindow->m_szTitle, damageBox.x, damageBox.y, damageBox.width, damageBox.height); } @@ -1654,9 +1704,9 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) { CBox damageBox = {0, 0, INT16_MAX, INT16_MAX}; pMonitor->addDamage(&damageBox); - static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); + static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); - if (**PLOGDAMAGE) + if (*PLOGDAMAGE) Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName); } @@ -1673,9 +1723,9 @@ void CHyprRenderer::damageBox(CBox* pBox) { m->addDamage(&damageBox); } - static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); + static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); - if (**PLOGDAMAGE) + if (*PLOGDAMAGE) Debug::log(LOG, "Damage: Box: xy: {}, {} wh: {}, {}", pBox->x, pBox->y, pBox->width, pBox->height); } @@ -1731,7 +1781,7 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) { - static auto* const PDISABLESCALECHECKS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:disable_scale_checks"); + static auto PDISABLESCALECHECKS = CConfigValue("debug:disable_scale_checks"); Debug::log(LOG, "Applying monitor rule for {}", pMonitor->szName); @@ -2008,7 +2058,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = pMonitor->vecSize; Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale; - if (!**PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) { + if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) { // invalid scale, will produce fractional pixels. // find the nearest valid. @@ -2178,17 +2228,17 @@ void CHyprRenderer::setCursorFromName(const std::string& name, bool force) { if (m_bCursorHidden && !force) return; - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); + g_pCursorManager->setCursorFromName(name); } void CHyprRenderer::ensureCursorRenderingMode() { - static auto* const PCURSORTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:cursor_inactive_timeout"); - static auto* const PHIDEONTOUCH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:hide_cursor_on_touch"); + static auto PCURSORTIMEOUT = CConfigValue("general:cursor_inactive_timeout"); + static auto PHIDEONTOUCH = CConfigValue("misc:hide_cursor_on_touch"); - const auto PASSEDCURSORSECONDS = g_pInputManager->m_tmrLastCursorMovement.getSeconds(); + const auto PASSEDCURSORSECONDS = g_pInputManager->m_tmrLastCursorMovement.getSeconds(); - if (**PCURSORTIMEOUT > 0 || **PHIDEONTOUCH) { - const bool HIDE = (**PCURSORTIMEOUT > 0 && **PCURSORTIMEOUT < PASSEDCURSORSECONDS) || (g_pInputManager->m_bLastInputTouch && **PHIDEONTOUCH); + if (*PCURSORTIMEOUT > 0 || *PHIDEONTOUCH) { + const bool HIDE = (*PCURSORTIMEOUT > 0 && *PCURSORTIMEOUT < PASSEDCURSORSECONDS) || (g_pInputManager->m_bLastInputTouch && *PHIDEONTOUCH); if (HIDE && !m_bCursorHidden) { Debug::log(LOG, "Hiding the cursor (timeout)"); @@ -2279,7 +2329,7 @@ void CHyprRenderer::initiateManualCrash() { g_pHyprOpenGL->m_tGlobalTimer.reset(); - static auto* const PDT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:damage_tracking"); + static auto PDT = (Hyprlang::INT* const*)(g_pConfigManager->getConfigValuePtr("debug:damage_tracking")); **PDT = 0; } @@ -2300,8 +2350,8 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, CWorkspace* pWo continue; const auto ROUNDING = w->rounding() * PMONITOR->scale; - const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec()); - const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; + const Vector2D POS = w->m_vRealPosition.value() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.value()); + const Vector2D SIZE = w->m_vRealSize.value() - Vector2D{ROUNDING * 2, ROUNDING * 2}; CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; @@ -2326,8 +2376,8 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorks continue; const auto ROUNDING = w->rounding() * PMONITOR->scale; - const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec()); - const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; + const Vector2D POS = w->m_vRealPosition.value() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.value()); + const Vector2D SIZE = w->m_vRealSize.value() - Vector2D{ROUNDING * 2, ROUNDING * 2}; CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; @@ -2344,7 +2394,7 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { if (!ls->layerSurface) continue; - if (ls->alpha.fl() < 1.f) + if (ls->alpha.value() < 1.f) continue; if (ls->geometry.x != pMonitor->vecPosition.x || ls->geometry.y != pMonitor->vecPosition.y || ls->geometry.width != pMonitor->vecSize.x || @@ -2374,7 +2424,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace); if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID || - PWORKSPACE->m_fAlpha.fl() != 1.f || PWORKSPACE->m_vRenderOffset.vec() != Vector2D{}) + PWORKSPACE->m_fAlpha.value() != 1.f || PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) return; const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -2385,7 +2435,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { if (!PCANDIDATE->opaque()) return; - if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || + if (PCANDIDATE->m_vRealSize.value() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.value() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || PCANDIDATE->m_vRealSize.isBeingAnimated()) return; @@ -2393,13 +2443,15 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { return; for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - if (topls->alpha.fl() != 0.f) + if (topls->alpha.value() != 0.f) return; } for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID == PCANDIDATE->m_iWorkspaceID && w->m_bIsFloating && w->m_bCreatedOverFullscreen && !w->isHidden() && (w->m_bIsMapped || w->m_bFadingOut) && - w.get() != PCANDIDATE) + if (w.get() == PCANDIDATE || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isHidden()) + continue; + + if (w->m_iWorkspaceID == PCANDIDATE->m_iWorkspaceID && w->m_bIsFloating && w->m_bCreatedOverFullscreen && w->visibleOnMonitor(pMonitor)) return; } @@ -2507,8 +2559,8 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode } void CHyprRenderer::endRender() { - const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; - static auto* const PNVIDIAANTIFLICKER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("opengl:nvidia_anti_flicker"); + const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; + static auto PNVIDIAANTIFLICKER = CConfigValue("opengl:nvidia_anti_flicker"); if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); @@ -2521,7 +2573,7 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_FULL_FAKE) return; - if (isNvidia() && **PNVIDIAANTIFLICKER) + if (isNvidia() && *PNVIDIAANTIFLICKER) glFinish(); else glFlush(); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 5eafb639..e480b26d 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -3,7 +3,6 @@ #include "../defines.hpp" #include #include "../helpers/Monitor.hpp" -#include "../helpers/Workspace.hpp" #include "../Window.hpp" #include "OpenGL.hpp" #include "Renderbuffer.hpp" @@ -11,6 +10,7 @@ #include "../helpers/Region.hpp" struct SMonitorRule; +class CWorkspace; // TODO: add fuller damage tracking for updating only parts of a window enum DAMAGETRACKINGMODES { @@ -59,7 +59,7 @@ class CHyprRenderer { void setCursorHidden(bool hide); void calculateUVForSurface(CWindow*, wlr_surface*, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min - void renderLockscreen(CMonitor* pMonitor, timespec* now); + void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry); void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace); void setOccludedForMainWorkspace(CRegion& region, CWorkspace* pWorkspace); // TODO: merge occlusion methods bool canSkipBackBufferClear(CMonitor* pMonitor); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 1ed6c144..ea40ee65 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -1,5 +1,6 @@ #include "CHyprBorderDecoration.hpp" #include "../../Compositor.hpp" +#include "../../config/ConfigValue.hpp" CHyprBorderDecoration::CHyprBorderDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; @@ -40,7 +41,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() { if (!PWORKSPACE) return box; - const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); return box.translate(WORKSPACEOFFSET); } @@ -58,10 +59,10 @@ void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& of auto grad = m_pWindow->m_cRealBorderColor; const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); - float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.fl() : 1.f); + float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.value() : 1.f); if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) { - grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.fl() * M_PI * 2; + grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.value() * M_PI * 2; grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); } @@ -71,7 +72,7 @@ void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& of g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1); if (ANIMATED) { - float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.fl()); + float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.value()); g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2); } } @@ -94,9 +95,9 @@ eDecorationLayer CHyprBorderDecoration::getDecorationLayer() { } uint64_t CHyprBorderDecoration::getDecorationFlags() { - static auto* const PPARTOFWINDOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_part_of_window"); + static auto PPARTOFWINDOW = CConfigValue("general:border_part_of_window"); - return **PPARTOFWINDOW && !doesntWantBorders() ? DECORATION_PART_OF_MAIN_WINDOW : 0; + return *PPARTOFWINDOW && !doesntWantBorders() ? DECORATION_PART_OF_MAIN_WINDOW : 0; } std::string CHyprBorderDecoration::getDisplayName() { diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 4448ce9d..588b23a4 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -1,6 +1,7 @@ #include "CHyprDropShadowDecoration.hpp" #include "../../Compositor.hpp" +#include "../../config/ConfigValue.hpp" CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; @@ -35,9 +36,9 @@ std::string CHyprDropShadowDecoration::getDisplayName() { } void CHyprDropShadowDecoration::damageEntire() { - static auto* const PSHADOWS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:drop_shadow"); + static auto PSHADOWS = CConfigValue("decoration:drop_shadow"); - if (**PSHADOWS != 1) + if (*PSHADOWS != 1) return; // disabled CBox dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, @@ -46,8 +47,8 @@ void CHyprDropShadowDecoration::damageEntire() { } void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) { - m_vLastWindowPos = m_pWindow->m_vRealPosition.vec(); - m_vLastWindowSize = m_pWindow->m_vRealSize.vec(); + m_vLastWindowPos = m_pWindow->m_vRealPosition.value(); + m_vLastWindowSize = m_pWindow->m_vRealSize.value(); m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); @@ -58,7 +59,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (!g_pCompositor->windowValidMapped(m_pWindow)) return; - if (m_pWindow->m_cRealShadowColor.col() == CColor(0, 0, 0, 0)) + if (m_pWindow->m_cRealShadowColor.value() == CColor(0, 0, 0, 0)) return; // don't draw invisible shadows if (!m_pWindow->m_sSpecialRenderData.decorate) @@ -70,32 +71,32 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (m_pWindow->m_sAdditionalConfigData.forceNoShadow) return; - static auto* const PSHADOWS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:drop_shadow"); - static auto* const PSHADOWSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow_range"); - static auto* const PSHADOWIGNOREWINDOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window"); - static auto* const PSHADOWSCALE = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow_scale"); - static auto* const PSHADOWOFFSET = (Hyprlang::VEC2* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow_offset"); + static auto PSHADOWS = CConfigValue("decoration:drop_shadow"); + static auto PSHADOWSIZE = CConfigValue("decoration:shadow_range"); + static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow_ignore_window"); + static auto PSHADOWSCALE = CConfigValue("decoration:shadow_scale"); + static auto PSHADOWOFFSET = CConfigValue("decoration:shadow_offset"); - if (**PSHADOWS != 1) + if (*PSHADOWS != 1) return; // disabled const auto ROUNDINGBASE = m_pWindow->rounding(); const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + m_pWindow->getRealBorderSize() : 0; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID); - const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); // draw the shadow CBox fullBox = m_bLastWindowBoxWithDecos; fullBox.translate(-pMonitor->vecPosition + WORKSPACEOFFSET); - fullBox.x -= **PSHADOWSIZE; - fullBox.y -= **PSHADOWSIZE; - fullBox.w += 2 * **PSHADOWSIZE; - fullBox.h += 2 * **PSHADOWSIZE; + fullBox.x -= *PSHADOWSIZE; + fullBox.y -= *PSHADOWSIZE; + fullBox.w += 2 * *PSHADOWSIZE; + fullBox.h += 2 * *PSHADOWSIZE; - const float SHADOWSCALE = std::clamp(**PSHADOWSCALE, 0.f, 1.f); + const float SHADOWSCALE = std::clamp(*PSHADOWSCALE, 0.f, 1.f); // scale the box in relation to the center of the box - fullBox.scaleFromCenter(SHADOWSCALE).translate(**PSHADOWOFFSET); + fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET); m_vLastWindowPos += WORKSPACEOFFSET; m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2}, @@ -116,7 +117,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D fullBox.scale(pMonitor->scale).round(); - if (**PSHADOWIGNOREWINDOW) { + if (*PSHADOWIGNOREWINDOW) { CBox windowBox = m_bLastWindowBox; CBox withDecos = m_bLastWindowBoxWithDecos; @@ -147,7 +148,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, **PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.col().a), a); + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.value().a), a); // render black window box ("clip") g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), ROUNDING * pMonitor->scale); @@ -155,18 +156,18 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D alphaSwapFB.bind(); // alpha swap just has the shadow color. It will be the "texture" to render. - g_pHyprOpenGL->renderRect(&fullBox, m_pWindow->m_cRealShadowColor.col().stripA(), 0); + g_pHyprOpenGL->renderRect(&fullBox, m_pWindow->m_cRealShadowColor.value().stripA(), 0); LASTFB->bind(); CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->setMonitorTransformEnabled(false); - g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); + g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->m_RenderData.damage = saveDamage; } else { - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, **PSHADOWSIZE * pMonitor->scale, m_pWindow->m_cRealShadowColor.col(), a); + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, m_pWindow->m_cRealShadowColor.value(), a); } if (m_seExtents != m_seReportedExtents) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 20c0240f..defff9ba 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -1,5 +1,6 @@ #include "CHyprGroupBarDecoration.hpp" #include "../../Compositor.hpp" +#include "../../config/ConfigValue.hpp" #include #include @@ -15,31 +16,31 @@ constexpr int BAR_TEXT_PAD = 2; constexpr int BAR_HORIZONTAL_PADDING = 2; CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { - static auto* const PGRADIENTS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:enabled"); - static auto* const PENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:gradients"); - m_pWindow = pWindow; + static auto PGRADIENTS = CConfigValue("group:groupbar:enabled"); + static auto PENABLED = CConfigValue("group:groupbar:gradients"); + m_pWindow = pWindow; - if (m_tGradientActive.m_iTexID == 0 && **PENABLED && **PGRADIENTS) + if (m_tGradientActive.m_iTexID == 0 && *PENABLED && *PGRADIENTS) refreshGroupBarGradients(); } CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {} SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { - static auto* const PHEIGHT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:height"); - static auto* const PENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:enabled"); - static auto* const PRENDERTITLES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles"); - static auto* const PGRADIENTS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:gradients"); - static auto* const PPRIORITY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:priority"); + static auto PHEIGHT = CConfigValue("group:groupbar:height"); + static auto PENABLED = CConfigValue("group:groupbar:enabled"); + static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); + static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); + static auto PPRIORITY = CConfigValue("group:groupbar:priority"); SDecorationPositioningInfo info; info.policy = DECORATION_POSITION_STICKY; info.edges = DECORATION_EDGE_TOP; - info.priority = **PPRIORITY; + info.priority = *PPRIORITY; info.reserved = true; - if (**PENABLED && m_pWindow->m_sSpecialRenderData.decorate) - info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (**PGRADIENTS || **PRENDERTITLES ? **PHEIGHT : 0) + 2}, {0, 0}}; + if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) + info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}}; else info.desiredExtents = {{0, 0}, {0, 0}}; @@ -87,22 +88,22 @@ void CHyprGroupBarDecoration::damageEntire() { void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) { // get how many bars we will draw - int barsToDraw = m_dwGroupMembers.size(); + int barsToDraw = m_dwGroupMembers.size(); - static auto* const PENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:enabled"); - static auto* const PRENDERTITLES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles"); - static auto* const PTITLEFONTSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:font_size"); - static auto* const PHEIGHT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:height"); - static auto* const PGRADIENTS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:gradients"); + static auto PENABLED = CConfigValue("group:groupbar:enabled"); + static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); + static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); + static auto PHEIGHT = CConfigValue("group:groupbar:height"); + static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); - if (!**PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) + if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) return; const auto ASSIGNEDBOX = assignedBoxGlobal(); m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; - const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (**PGRADIENTS || **PRENDERTITLES ? **PHEIGHT : 0) + 2; + const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2; if (DESIREDHEIGHT != ASSIGNEDBOX.h) g_pDecorationPositioner->repositionDeco(this); @@ -117,20 +118,20 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& rect.scale(pMonitor->scale); - static auto* const PGROUPCOLACTIVE = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.active"); - static auto* const PGROUPCOLINACTIVE = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive"); - static auto* const PGROUPCOLACTIVELOCKED = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active"); - static auto* const PGROUPCOLINACTIVELOCKED = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive"); - auto* const GROUPCOLACTIVE = (CGradientValueData*)(*PGROUPCOLACTIVE)->getData(); - auto* const GROUPCOLINACTIVE = (CGradientValueData*)(*PGROUPCOLINACTIVE)->getData(); - auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(*PGROUPCOLACTIVELOCKED)->getData(); - auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(*PGROUPCOLINACTIVELOCKED)->getData(); + static auto PGROUPCOLACTIVE = CConfigValue("group:groupbar:col.active"); + static auto PGROUPCOLINACTIVE = CConfigValue("group:groupbar:col.inactive"); + static auto PGROUPCOLACTIVELOCKED = CConfigValue("group:groupbar:col.locked_active"); + static auto PGROUPCOLINACTIVELOCKED = CConfigValue("group:groupbar:col.locked_inactive"); + auto* const GROUPCOLACTIVE = (CGradientValueData*)(PGROUPCOLACTIVE.ptr())->getData(); + auto* const GROUPCOLINACTIVE = (CGradientValueData*)(PGROUPCOLINACTIVE.ptr())->getData(); + auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData(); + auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData(); - const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; - const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; - const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; + const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; + const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; + const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; - CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; + CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; color.a *= a; g_pHyprOpenGL->renderRect(&rect, color); @@ -145,17 +146,17 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0); } - if (**PRENDERTITLES) { + if (*PRENDERTITLES) { CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); if (!pTitleTex) pTitleTex = m_sTitleTexs.titleTexs .emplace_back(std::make_unique(m_dwGroupMembers[i], - Vector2D{m_fBarWidth * pMonitor->scale, (**PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) + Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) .get(); - rect.y += (ASSIGNEDBOX.h / 2.0 - (**PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; - rect.height = (**PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; + rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; + rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); } @@ -163,7 +164,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth; } - if (**PRENDERTITLES) + if (*PRENDERTITLES) invalidateTextures(); } @@ -181,17 +182,16 @@ void CHyprGroupBarDecoration::invalidateTextures() { } CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) { - szContent = pWindow->m_szTitle; - pWindowOwner = pWindow; - const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); - const auto CAIRO = cairo_create(CAIROSURFACE); - const auto MONITORSCALE = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)->scale; + szContent = pWindow->m_szTitle; + pWindowOwner = pWindow; + const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); + const auto CAIRO = cairo_create(CAIROSURFACE); - static auto* const PTITLEFONTFAMILY = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("group:groupbar:font_family"); - static auto* const PTITLEFONTSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:font_size"); - static auto* const PTEXTCOLOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:text_color"); + static auto PTITLEFONTFAMILY = CConfigValue("group:groupbar:font_family"); + static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); + static auto PTEXTCOLOR = CConfigValue("group:groupbar:text_color"); - const CColor COLOR = CColor(**PTEXTCOLOR); + const CColor COLOR = CColor(*PTEXTCOLOR); // clear the pixmap cairo_save(CAIRO); @@ -203,8 +203,8 @@ CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) { PangoLayout* layout = pango_cairo_create_layout(CAIRO); pango_layout_set_text(layout, szContent.c_str(), -1); - PangoFontDescription* fontDesc = pango_font_description_from_string(*PTITLEFONTFAMILY); - pango_font_description_set_size(fontDesc, **PTITLEFONTSIZE * PANGO_SCALE); + PangoFontDescription* fontDesc = pango_font_description_from_string((*PTITLEFONTFAMILY).c_str()); + pango_font_description_set_size(fontDesc, *PTITLEFONTSIZE * PANGO_SCALE); pango_layout_set_font_description(layout, fontDesc); pango_font_description_free(fontDesc); @@ -301,17 +301,17 @@ void renderGradientTo(CTexture& tex, CGradientValueData* grad) { } void refreshGroupBarGradients() { - static auto* const PGRADIENTS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:enabled"); - static auto* const PENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:gradients"); + static auto PGRADIENTS = CConfigValue("group:groupbar:enabled"); + static auto PENABLED = CConfigValue("group:groupbar:gradients"); - static auto* const PGROUPCOLACTIVE = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.active"); - static auto* const PGROUPCOLINACTIVE = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive"); - static auto* const PGROUPCOLACTIVELOCKED = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active"); - static auto* const PGROUPCOLINACTIVELOCKED = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive"); - auto* const GROUPCOLACTIVE = (CGradientValueData*)(*PGROUPCOLACTIVE)->getData(); - auto* const GROUPCOLINACTIVE = (CGradientValueData*)(*PGROUPCOLINACTIVE)->getData(); - auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(*PGROUPCOLACTIVELOCKED)->getData(); - auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(*PGROUPCOLINACTIVELOCKED)->getData(); + static auto PGROUPCOLACTIVE = CConfigValue("group:groupbar:col.active"); + static auto PGROUPCOLINACTIVE = CConfigValue("group:groupbar:col.inactive"); + static auto PGROUPCOLACTIVELOCKED = CConfigValue("group:groupbar:col.locked_active"); + static auto PGROUPCOLINACTIVELOCKED = CConfigValue("group:groupbar:col.locked_inactive"); + auto* const GROUPCOLACTIVE = (CGradientValueData*)(PGROUPCOLACTIVE.ptr())->getData(); + auto* const GROUPCOLINACTIVE = (CGradientValueData*)(PGROUPCOLINACTIVE.ptr())->getData(); + auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData(); + auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData(); g_pHyprRenderer->makeEGLCurrent(); @@ -322,7 +322,7 @@ void refreshGroupBarGradients() { m_tGradientLockedInactive.destroyTexture(); } - if (!**PENABLED || !**PGRADIENTS) + if (!*PENABLED || !*PGRADIENTS) return; renderGradientTo(m_tGradientActive, GROUPCOLACTIVE); @@ -430,15 +430,15 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point if (e->button == 274) { static Vector2D pressedCursorPos; - if (e->state == WLR_BUTTON_PRESSED) + if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) pressedCursorPos = pos; - else if (e->state == WLR_BUTTON_RELEASED && pressedCursorPos == pos) + else if (e->state == WL_POINTER_BUTTON_STATE_RELEASED && pressedCursorPos == pos) g_pXWaylandManager->sendCloseWindow(m_pWindow->getGroupWindowByIndex(WINDOWINDEX)); return true; } - if (e->state != WLR_BUTTON_PRESSED) + if (e->state != WL_POINTER_BUTTON_STATE_PRESSED) return true; // click on padding @@ -460,9 +460,9 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point } bool CHyprGroupBarDecoration::onScrollOnDeco(const Vector2D& pos, wlr_pointer_axis_event* e) { - static auto* const PGROUPBARSCROLLING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:groupbar:scrolling"); + static auto PGROUPBARSCROLLING = CConfigValue("group:groupbar:scrolling"); - if (!**PGROUPBARSCROLLING || !m_pWindow->m_sGroupData.pNextWindow) + if (!*PGROUPBARSCROLLING || !m_pWindow->m_sGroupData.pNextWindow) return false; if (e->delta > 0) @@ -504,6 +504,6 @@ CBox CHyprGroupBarDecoration::assignedBoxGlobal() { if (!PWORKSPACE) return box; - const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); return box.translate(WORKSPACEOFFSET); } diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index e19c361b..145a697b 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -124,7 +124,7 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { datas.push_back(getDataFor(wd.get(), pWindow)); } - if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize.vec() /* position not changed */ + if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize.value() /* position not changed */ && std::all_of(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(), [pWindow](const auto& data) { return pWindow != data->pWindow || !data->needsReposition; }) /* all window datas are either not for this window or don't need a reposition */ @@ -132,7 +132,7 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { ) return; - WINDOWDATA->lastWindowSize = pWindow->m_vRealSize.vec(); + WINDOWDATA->lastWindowSize = pWindow->m_vRealSize.value(); WINDOWDATA->needsRecalc = false; const bool EPHEMERAL = pWindow->m_vRealSize.isBeingAnimated(); diff --git a/subprojects/wlroots b/subprojects/wlroots index ac846178..538219d3 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit ac8461785665285bfc5cb00a0c3bf3bbce665a90 +Subproject commit 538219d3892b793d2973fd5ddea43b71fac30dd4