From 07a21fdfa9e4d3827457dc3f08a4910703fedd35 Mon Sep 17 00:00:00 2001 From: diniamo <55629891+diniamo@users.noreply.github.com> Date: Sun, 8 Sep 2024 20:20:45 +0200 Subject: [PATCH 0001/1803] github(nix-build): switch to better nix installer, attempt at fixing hash mismatch (#7701) * github(nix-build): switch to DeterminateSystems/nix-installer-action * github(nix-build): switch to a direct git reference instead of cloning * github(nix-ci): attempt to fix CI for pull requests --- .github/workflows/nix-build.yml | 11 +++-------- .github/workflows/nix-ci.yml | 3 +-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index ed0c2ae1..50823629 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -16,17 +16,12 @@ jobs: runs-on: ubuntu-latest steps: - - name: Clone repository - uses: actions/checkout@v4 - with: - ref: ${{ github.ref }} - submodules: recursive - - - uses: cachix/install-nix-action@v27 + - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main + - uses: cachix/cachix-action@v15 with: name: hyprland authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" + - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}&submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" diff --git a/.github/workflows/nix-ci.yml b/.github/workflows/nix-ci.yml index 2f35337d..75c19790 100644 --- a/.github/workflows/nix-ci.yml +++ b/.github/workflows/nix-ci.yml @@ -9,7 +9,6 @@ jobs: secrets: inherit build: - if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure') - needs: update-inputs + if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) uses: ./.github/workflows/nix-build.yml secrets: inherit From 05b48d48d9074041fd7987c36f04bdc1dafa575c Mon Sep 17 00:00:00 2001 From: Davide Conti Date: Sun, 8 Sep 2024 20:36:33 +0200 Subject: [PATCH 0002/1803] config: Limit max volume to 100% --- example/hyprland.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 76e5bcdb..1179a274 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -229,7 +229,7 @@ bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow # Laptop multimedia keys for volume and LCD brightness -bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ +bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle From 6179b17903647d7659749f9f7c79bb9aff97a806 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 8 Sep 2024 22:12:01 +0200 Subject: [PATCH 0003/1803] github: improve issue template (#7699) * github: improve issue template Require to check that you have searched through open and closed issues before committing. * fix yaml syntax * clarify text * validation * revert validation * markdown * done --- .github/ISSUE_TEMPLATE/bug.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index e3e97bef..7d402904 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -2,12 +2,13 @@ name: Bug Report description: Something is not working right labels: ["bug"] body: - - type: markdown + - type: checkboxes attributes: - value: | - ## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists. - - --- + label: Already reported ? * + description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists. + options: + - label: I have searched the existing open and closed issues. + required: true - type: dropdown id: type From 7c4c402bd7f24241c096d809cc80408a469f15cb Mon Sep 17 00:00:00 2001 From: Richard Ayotte Date: Sun, 8 Sep 2024 17:04:07 -0400 Subject: [PATCH 0004/1803] config: include XF86Audio* key bindings to default cfg (#7695) --- example/hyprland.conf | 13 +++++++++---- src/config/defaultConfig.hpp | 14 ++++++++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 1179a274..4adc2d40 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -59,7 +59,7 @@ env = HYPRCURSOR_SIZE,24 # Refer to https://wiki.hyprland.org/Configuring/Variables/ # https://wiki.hyprland.org/Configuring/Variables/#general -general { +general { gaps_in = 5 gaps_out = 20 @@ -70,7 +70,7 @@ general { col.inactive_border = rgba(595959aa) # Set to true enable resizing windows by clicking and dragging on borders and gaps - resize_on_border = false + resize_on_border = false # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on allow_tearing = false @@ -96,7 +96,7 @@ decoration { enabled = true size = 3 passes = 1 - + vibrancy = 0.1696 } } @@ -129,7 +129,7 @@ master { } # https://wiki.hyprland.org/Configuring/Variables/#misc -misc { +misc { force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( } @@ -236,6 +236,11 @@ bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous ############################## ### WINDOWS AND WORKSPACES ### diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index b8d215d1..5843caa3 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -72,7 +72,7 @@ env = HYPRCURSOR_SIZE,24 # Refer to https://wiki.hyprland.org/Configuring/Variables/ # https://wiki.hyprland.org/Configuring/Variables/#general -general { +general { gaps_in = 5 gaps_out = 20 @@ -83,7 +83,7 @@ general { col.inactive_border = rgba(595959aa) # Set to true enable resizing windows by clicking and dragging on borders and gaps - resize_on_border = false + resize_on_border = false # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on allow_tearing = false @@ -109,7 +109,7 @@ decoration { enabled = true size = 3 passes = 1 - + vibrancy = 0.1696 } } @@ -142,7 +142,7 @@ master { } # https://wiki.hyprland.org/Configuring/Variables/#misc -misc { +misc { force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( } @@ -249,6 +249,12 @@ bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous + ############################## ### WINDOWS AND WORKSPACES ### ############################## From e1448732b3a463fc3aafc162d456a3db593253c8 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Mon, 9 Sep 2024 17:58:44 +0900 Subject: [PATCH 0005/1803] tiv1: fix deleting first character (#7716) --- src/managers/input/TextInput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 4c2e326a..d488f173 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -264,7 +264,7 @@ void CTextInput::updateIMEState(SP ime) { INPUT->preeditStyling(0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); INPUT->preeditString(pV1Input->serial, ime->current.preeditString.string.c_str(), ""); } else { - INPUT->preeditCursor(ime->current.preeditString.begin); + INPUT->preeditCursor(0); INPUT->preeditStyling(0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); INPUT->preeditString(pV1Input->serial, "", ""); } From 43e1415e715bb6c6c4ea722ba839210938ac2b07 Mon Sep 17 00:00:00 2001 From: davc0n Date: Mon, 9 Sep 2024 11:01:26 +0200 Subject: [PATCH 0006/1803] assets: Remove execute permission from lockdead.png (#7715) --- assets/install/lockdead.png | Bin 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 assets/install/lockdead.png diff --git a/assets/install/lockdead.png b/assets/install/lockdead.png old mode 100755 new mode 100644 From 04421063af2941c6e27e6dca2bdc2c387778a3a5 Mon Sep 17 00:00:00 2001 From: darkwater Date: Mon, 9 Sep 2024 11:10:08 +0200 Subject: [PATCH 0007/1803] config: add order rule for layers (#7697) --- src/config/ConfigManager.cpp | 2 +- src/desktop/LayerSurface.cpp | 5 +++++ src/desktop/LayerSurface.hpp | 1 + src/render/Renderer.cpp | 4 ++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 852994a7..57cd2350 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2239,7 +2239,7 @@ bool windowRuleValid(const std::string& RULE) { bool layerRuleValid(const std::string& RULE) { static const auto rules = std::unordered_set{"noanim", "blur", "blurpopups", "dimaround"}; - static const auto rulesPrefix = std::vector{"ignorealpha", "ignorezero", "xray", "animation"}; + static const auto rulesPrefix = std::vector{"ignorealpha", "ignorezero", "xray", "animation", "order"}; return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); }); } diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 155a2605..0e7e71b6 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -394,6 +394,11 @@ void CLayerSurface::applyRules() { } else if (rule.rule.starts_with("animation")) { CVarList vars{rule.rule, 2, 's'}; animationStyle = vars[1]; + } else if (rule.rule.starts_with("order")) { + CVarList vars{rule.rule, 2, 's'}; + try { + order = std::stoi(vars[1]); + } catch (...) { Debug::log(ERR, "Invalid value passed to order"); } } } } diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index 84935b34..e0f17039 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -55,6 +55,7 @@ class CLayerSurface { bool ignoreAlpha = false; float ignoreAlphaValue = 0.f; bool dimAround = false; + int64_t order = 0; std::optional animationStyle; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 27fde129..08bf76cb 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1742,6 +1742,10 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + for (auto& la : PMONITOR->m_aLayerSurfaceLayers) { + std::stable_sort(la.begin(), la.end(), [](const PHLLSREF& a, const PHLLSREF& b) { return a->order > b->order; }); + } + for (auto const& la : PMONITOR->m_aLayerSurfaceLayers) arrangeLayerArray(PMONITOR, la, true, &usableArea); From 9609b04ff9e63d16f9b2b9ecfdc732c2c7ebbf2f Mon Sep 17 00:00:00 2001 From: justmessingaround <69480361+DemonKingSwarn@users.noreply.github.com> Date: Mon, 9 Sep 2024 20:49:17 +0530 Subject: [PATCH 0008/1803] man: Fixed the man page to show the new information (#7713) * Update Hyprland.1.rst * Update Hyprland.1 --- docs/Hyprland.1 | 4 ++-- docs/Hyprland.1.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/Hyprland.1 b/docs/Hyprland.1 index 92061da2..465671e1 100644 --- a/docs/Hyprland.1 +++ b/docs/Hyprland.1 @@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor \f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]]. .SH DESCRIPTION .PP -\f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on -wlroots that doesn\[aq]t sacrifice on its looks. +\f[B]Hyprland\f[R] is an independent, highly customizable, +dynamic tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. .PP You can launch Hyprland by either going into a TTY and executing \f[B]Hyprland\f[R], or with a login manager. diff --git a/docs/Hyprland.1.rst b/docs/Hyprland.1.rst index c73b4343..e10d9c6a 100644 --- a/docs/Hyprland.1.rst +++ b/docs/Hyprland.1.rst @@ -14,8 +14,8 @@ SYNOPSIS DESCRIPTION =========== -**Hyprland** is a dynamic tiling Wayland compositor based on -wlroots that doesn't sacrifice on its looks. +**Hyprland** is an independent, highly customizable, +dynamic tiling Wayland compositor that doesn't sacrifice on its looks. You can launch Hyprland by either going into a TTY and executing **Hyprland**, or with a login manager. From 85da1a17d831e2b5db9c1c1e4ce6427d63563562 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 9 Sep 2024 15:19:44 +0000 Subject: [PATCH 0009/1803] [gha] build man pages --- docs/Hyprland.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Hyprland.1 b/docs/Hyprland.1 index 465671e1..2d6e1444 100644 --- a/docs/Hyprland.1 +++ b/docs/Hyprland.1 @@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor \f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]]. .SH DESCRIPTION .PP -\f[B]Hyprland\f[R] is an independent, highly customizable, -dynamic tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. +\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic +tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. .PP You can launch Hyprland by either going into a TTY and executing \f[B]Hyprland\f[R], or with a login manager. From 8237d7e1a4994f70636b2e91584775308f24a584 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 9 Sep 2024 20:29:00 +0000 Subject: [PATCH 0010/1803] input: move dmps activation to input listeners (#7721) --- src/managers/KeybindManager.hpp | 1 + src/managers/PointerManager.cpp | 30 +++++++++++++++++++++++++++++ src/managers/input/InputManager.cpp | 21 +++++++++----------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index bf3b049f..096cd4f9 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -221,6 +221,7 @@ class CKeybindManager { friend class CInputManager; friend class CConfigManager; friend class CWorkspace; + friend class CPointerManager; }; inline std::unique_ptr g_pKeybindManager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index ce9ea4a4..e48c77d5 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -821,6 +821,9 @@ void CPointerManager::attachPointer(SP pointer) { if (!pointer) return; + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + + // auto listener = pointerListeners.emplace_back(makeShared()); listener->pointer = pointer; @@ -836,6 +839,9 @@ void CPointerManager::attachPointer(SP pointer) { g_pInputManager->onMouseMoved(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->motionAbsolute = pointer->pointerEvents.motionAbsolute.registerListener([this] (std::any e) { @@ -844,6 +850,9 @@ void CPointerManager::attachPointer(SP pointer) { g_pInputManager->onMouseWarp(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->button = pointer->pointerEvents.button.registerListener([this] (std::any e) { @@ -872,6 +881,9 @@ void CPointerManager::attachPointer(SP pointer) { g_pInputManager->onSwipeBegin(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->swipeEnd = pointer->pointerEvents.swipeEnd.registerListener([this] (std::any e) { @@ -896,6 +908,9 @@ void CPointerManager::attachPointer(SP pointer) { PROTO::pointerGestures->pinchBegin(E.timeMs, E.fingers); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->pinchEnd = pointer->pointerEvents.pinchEnd.registerListener([this] (std::any e) { @@ -938,6 +953,9 @@ void CPointerManager::attachTouch(SP touch) { if (!touch) return; + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + + // auto listener = touchListeners.emplace_back(makeShared()); listener->touch = touch; @@ -953,6 +971,9 @@ void CPointerManager::attachTouch(SP touch) { g_pInputManager->onTouchDown(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->up = touch->touchEvents.up.registerListener([this] (std::any e) { @@ -987,6 +1008,9 @@ void CPointerManager::attachTablet(SP tablet) { if (!tablet) return; + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + + // auto listener = tabletListeners.emplace_back(makeShared()); listener->tablet = tablet; @@ -1002,6 +1026,9 @@ void CPointerManager::attachTablet(SP tablet) { g_pInputManager->onTabletAxis(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->proximity = tablet->tabletEvents.proximity.registerListener([this] (std::any e) { @@ -1018,6 +1045,9 @@ void CPointerManager::attachTablet(SP tablet) { g_pInputManager->onTabletTip(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->button = tablet->tabletEvents.button.registerListener([this] (std::any e) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f1035c82..03c72919 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -28,6 +28,7 @@ #include "../../managers/PointerManager.hpp" #include "../../managers/SeatManager.hpp" +#include "../../managers/KeybindManager.hpp" #include @@ -135,7 +136,6 @@ void CInputManager::sendMotionEventsToFocused() { void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { 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"); @@ -157,11 +157,6 @@ 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) { - // enable dpms - g_pKeybindManager->dpms("on"); - } - Vector2D mouseCoords = getMouseCoordsInternal(); const auto MOUSECOORDSFLOORED = mouseCoords.floor(); @@ -854,6 +849,8 @@ void CInputManager::newVirtualKeyboard(SP keyboard) } void CInputManager::setupKeyboard(SP keeb) { + static auto PDPMS = CConfigValue("misc:key_press_enables_dpms"); + m_vHIDs.push_back(keeb); try { @@ -882,6 +879,9 @@ void CInputManager::setupKeyboard(SP keeb) { if (PKEEB->enabled) PROTO::idle->onActivity(); + + if (PKEEB->enabled && *PDPMS && !g_pCompositor->m_bDPMSStateON) + g_pKeybindManager->dpms("on"); }, keeb.get()); @@ -893,6 +893,9 @@ void CInputManager::setupKeyboard(SP keeb) { if (PKEEB->enabled) PROTO::idle->onActivity(); + + if (PKEEB->enabled && *PDPMS && !g_pCompositor->m_bDPMSStateON) + g_pKeybindManager->dpms("on"); }, keeb.get()); @@ -1284,12 +1287,6 @@ void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { const auto EMAP = std::unordered_map{{"keyboard", pKeyboard}, {"event", event}}; EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP); - static auto PDPMS = CConfigValue("misc:key_press_enables_dpms"); - if (*PDPMS && !g_pCompositor->m_bDPMSStateON) { - // enable dpms - g_pKeybindManager->dpms("on"); - } - bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard); auto e = std::any_cast(event); From c67b257e51133a2aaeec050fc4d283e2eaea6375 Mon Sep 17 00:00:00 2001 From: davc0n Date: Tue, 10 Sep 2024 12:06:37 +0200 Subject: [PATCH 0011/1803] build: Set cmake_minimum_required to version 3.30 (#7709) * build: Set cmake_minimum_required to version 3.30 * Nix: add patch for CMake min ver --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- nix/cmake-version.patch | 10 ++++++++++ nix/default.nix | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 nix/cmake-version.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index d8424d91..6fdf98db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.27) +cmake_minimum_required(VERSION 3.30) # Get version file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) diff --git a/nix/cmake-version.patch b/nix/cmake-version.patch new file mode 100644 index 00000000..ccc9c738 --- /dev/null +++ b/nix/cmake-version.patch @@ -0,0 +1,10 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6fdf98db..d8424d91 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.30) ++cmake_minimum_required(VERSION 3.27) + + # Get version + file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) diff --git a/nix/default.nix b/nix/default.nix index 1c6a0113..985a4cbb 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -64,6 +64,8 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov patches = [ # forces GCC to use -std=c++26 ./stdcxx.patch + # Nix does not have CMake 3.30 yet, so override the minimum version + ./cmake-version.patch ]; postPatch = '' From 13f90bb87a697866f1bbbacd1473d04f33ec2aa7 Mon Sep 17 00:00:00 2001 From: Alexandre Acebedo Date: Sun, 8 Sep 2024 20:54:12 +0200 Subject: [PATCH 0012/1803] update xdph commit in flake.lock --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 99a544e2..239ec219 100644 --- a/flake.lock +++ b/flake.lock @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1725203932, - "narHash": "sha256-VLULC/OnI+6R9KEP2OIGk+uLJJsfRlaLouZ5gyFd2+Y=", + "lastModified": 1725228143, + "narHash": "sha256-kbSiPA5oXiz1+1eVoRslMi5wylHD6SDT8dS9eZAxXAM=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "2425e8f541525fa7409d9f26a8ffaf92a3767251", + "rev": "11e15b437e7efc39e452f36e15a183225d6bfa39", "type": "github" }, "original": { From 155d44016d0cb11332c454db73d59030cdbd7b13 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Tue, 10 Sep 2024 22:49:10 +0900 Subject: [PATCH 0013/1803] textinput: handle IME resetting (#7731) --- src/managers/input/InputMethodRelay.cpp | 10 ++++++---- src/managers/input/InputMethodRelay.hpp | 4 ++-- src/managers/input/TextInput.cpp | 24 +++++++++++++++++------- src/managers/input/TextInput.hpp | 2 ++ src/protocols/TextInputV1.cpp | 1 + src/protocols/TextInputV1.hpp | 1 + src/protocols/TextInputV3.cpp | 19 ++++++++++++++----- src/protocols/TextInputV3.hpp | 7 ++++++- 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 1608e123..5ef7f331 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -106,20 +106,22 @@ void CInputMethodRelay::updateAllPopups() { } } -void CInputMethodRelay::activateIME(CTextInput* pInput) { +void CInputMethodRelay::activateIME(CTextInput* pInput, bool shouldCommit) { if (m_pIME.expired()) return; m_pIME->activate(); - commitIMEState(pInput); + if (shouldCommit) + commitIMEState(pInput); } -void CInputMethodRelay::deactivateIME(CTextInput* pInput) { +void CInputMethodRelay::deactivateIME(CTextInput* pInput, bool shouldCommit) { if (m_pIME.expired()) return; m_pIME->deactivate(); - commitIMEState(pInput); + if (shouldCommit) + commitIMEState(pInput); } void CInputMethodRelay::commitIMEState(CTextInput* pInput) { diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 5ecc11a2..3d706563 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -21,8 +21,8 @@ class CInputMethodRelay { void onNewTextInput(WP tiv3); void onNewTextInput(WP pTIV1); - void activateIME(CTextInput* pInput); - void deactivateIME(CTextInput* pInput); + void activateIME(CTextInput* pInput, bool shouldCommit = true); + void deactivateIME(CTextInput* pInput, bool shouldCommit = true); void commitIMEState(CTextInput* pInput); void removeTextInput(CTextInput* pInput); diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index d488f173..2769fad0 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -22,6 +22,7 @@ void CTextInput::initCallbacks() { listeners.enable = INPUT->events.enable.registerListener([this](std::any p) { onEnabled(); }); listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); @@ -41,6 +42,7 @@ void CTextInput::initCallbacks() { }); listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); @@ -93,13 +95,21 @@ void CTextInput::onDisabled() { g_pInputManager->m_sIMERelay.deactivateIME(this); } +void CTextInput::onReset() { + if (g_pInputManager->m_sIMERelay.m_pIME.expired()) + return; + + g_pInputManager->m_sIMERelay.deactivateIME(this, false); + g_pInputManager->m_sIMERelay.activateIME(this); +} + void CTextInput::onCommit() { if (g_pInputManager->m_sIMERelay.m_pIME.expired()) { // Debug::log(WARN, "Committing TextInput on no IME!"); return; } - if (!(isV3() ? pV3Input->current.enabled : pV1Input->active)) { + if (!(isV3() ? pV3Input->current.enabled.value : pV1Input->active)) { Debug::log(WARN, "Disabled TextInput commit?"); return; } @@ -128,8 +138,8 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) - pV3Input->current.enabled = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) + pV3Input->current.enabled.value = false; if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -144,8 +154,8 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) - pV3Input->current.enabled = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) + pV3Input->current.enabled.value = false; if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -194,8 +204,8 @@ void CTextInput::leave() { if (isV3()) { pV3Input->leave(focusedSurface()); - if (pV3Input->current.enabled) { - pV3Input->current.enabled = false; + if (pV3Input->current.enabled.value) { + pV3Input->current.enabled.value = false; onDisabled(); } } else diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 0f69866e..f920adc7 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -29,6 +29,7 @@ class CTextInput { void onEnabled(SP surfV1 = nullptr); void onDisabled(); void onCommit(); + void onReset(); bool hasCursorRectangle(); CBox cursorBox(); @@ -47,6 +48,7 @@ class CTextInput { struct { CHyprSignalListener enable; CHyprSignalListener disable; + CHyprSignalListener reset; CHyprSignalListener commit; CHyprSignalListener destroy; CHyprSignalListener surfaceUnmap; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index f25f5aca..dad74b53 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -31,6 +31,7 @@ CTextInputV1::CTextInputV1(SP resource_) : resource(resource_) resource->setReset([this](CZwpTextInputV1* pMgr) { pendingSurrounding.isPending = false; pendingContentType.isPending = false; + events.reset.emit(); }); resource->setSetSurroundingText( diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index c85a1f31..9bee452c 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -37,6 +37,7 @@ class CTextInputV1 { CSignal onCommit; CSignal enable; CSignal disable; + CSignal reset; CSignal destroy; } events; diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 42dc659e..30374104 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -19,17 +19,22 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) resource->setOnDestroy([this](CZwpTextInputV3* r) { PROTO::textInputV3->destroyTextInput(this); }); resource->setCommit([this](CZwpTextInputV3* r) { - bool wasEnabled = current.enabled; + bool wasEnabled = current.enabled.value; current = pending; serial++; - if (wasEnabled && !current.enabled) + if (wasEnabled && !current.enabled.value) events.disable.emit(); - else if (!wasEnabled && current.enabled) + else if (!wasEnabled && current.enabled.value) events.enable.emit(); + else if (current.enabled.value && current.enabled.isEnablePending && current.enabled.isDisablePending) + events.reset.emit(); else events.onCommit.emit(); + + pending.enabled.isEnablePending = false; + pending.enabled.isDisablePending = false; }); resource->setSetSurroundingText([this](CZwpTextInputV3* r, const char* text, int32_t cursor, int32_t anchor) { @@ -54,10 +59,14 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) resource->setEnable([this](CZwpTextInputV3* r) { pending.reset(); - pending.enabled = true; + pending.enabled.value = true; + pending.enabled.isEnablePending = true; }); - resource->setDisable([this](CZwpTextInputV3* r) { pending.enabled = false; }); + resource->setDisable([this](CZwpTextInputV3* r) { + pending.enabled.value = false; + pending.enabled.isDisablePending = true; + }); } CTextInputV3::~CTextInputV3() { diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index 9f6284dc..ba8b75e6 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -31,6 +31,7 @@ class CTextInputV3 { CSignal onCommit; CSignal enable; CSignal disable; + CSignal reset; CSignal destroy; } events; @@ -53,7 +54,11 @@ class CTextInputV3 { CBox cursorBox; } box; - bool enabled = false; + struct { + bool isEnablePending = false; + bool isDisablePending = false; + bool value = false; + } enabled; zwpTextInputV3ChangeCause cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD; From 518399a95bada8bad8a4c29514da9962ce442307 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 11 Sep 2024 09:30:21 +0100 Subject: [PATCH 0014/1803] pointermgr: avoid derefing null outputs --- src/managers/PointerManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index e48c77d5..6b2a40f5 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -675,7 +675,7 @@ void CPointerManager::damageIfSoftware() { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); for (auto const& mw : monitorStates) { - if (mw->monitor.expired()) + if (mw->monitor.expired() || !mw->monitor->output) continue; if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { @@ -789,7 +789,7 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { void CPointerManager::onMonitorLayoutChange() { currentMonitorLayout.monitorBoxes.clear(); for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->isMirror() || !m->m_bEnabled) + if (m->isMirror() || !m->m_bEnabled || !m->output) continue; currentMonitorLayout.monitorBoxes.emplace_back(CBox{m->vecPosition, m->vecSize}); From 7a8c013edcbc59804a98fffa0436efcb268e1cda Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 11 Sep 2024 18:50:59 +0300 Subject: [PATCH 0015/1803] Meson: fix protocols, clean up --- protocols/meson.build | 147 ++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 77 deletions(-) diff --git a/protocols/meson.build b/protocols/meson.build index de650230..d686bacd 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -1,77 +1,75 @@ -wayland_protos = dependency('wayland-protocols', +wayland_protos = dependency( + 'wayland-protocols', version: '>=1.32', fallback: 'wayland-protocols', default_options: ['tests=false'], ) -hyprland_protos = dependency('hyprland-protocols', +hyprland_protos = dependency( + 'hyprland-protocols', version: '>=0.2', - fallback: 'hyprland-protocols', + fallback: 'hyprland-protocols', ) -wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') -hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir') +wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir') +hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir') -hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true) +hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true) hyprwayland_scanner = find_program( hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'), native: true, ) -new_protocols = [ - ['wlr-gamma-control-unstable-v1.xml'], - ['wlr-foreign-toplevel-management-unstable-v1.xml'], - ['wlr-output-power-management-unstable-v1.xml'], - ['input-method-unstable-v2.xml'], - ['virtual-keyboard-unstable-v1.xml'], - ['wlr-virtual-pointer-unstable-v1.xml'], - ['wlr-output-management-unstable-v1.xml'], - ['kde-server-decoration.xml'], - ['wlr-layer-shell-unstable-v1.xml'], - ['wayland-drm.xml'], - ['wlr-data-control-unstable-v1.xml'], - ['wlr-screencopy-unstable-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'], - [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], - [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], - [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], - [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], - [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'], - [wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'], - [wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'], - [wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'], - [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], - [wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'], - [wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'], - [wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'], - [wl_protocol_dir, 'stable/tablet/tablet-v2.xml'], - [wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'], - [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], - [wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'], - [wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'], - [wl_protocol_dir, 'stable/viewporter/viewporter.xml'], - [wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'], - [wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'], - [wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'], - [wl_protocol_dir, 'staging/xdg-dialog/xdg-dialog-v1.xml'], +protocols = [ + 'wlr-gamma-control-unstable-v1.xml', + 'wlr-foreign-toplevel-management-unstable-v1.xml', + 'wlr-output-power-management-unstable-v1.xml', + 'input-method-unstable-v2.xml', + 'virtual-keyboard-unstable-v1.xml', + 'wlr-virtual-pointer-unstable-v1.xml', + 'wlr-output-management-unstable-v1.xml', + 'kde-server-decoration.xml', + 'wlr-layer-shell-unstable-v1.xml', + 'wayland-drm.xml', + 'wlr-data-control-unstable-v1.xml', + 'wlr-screencopy-unstable-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', + wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', + wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', + wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', + wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', + wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml', + wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml', + wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml', + wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml', + wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml', + wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml', + wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml', + wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml', + wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml', + wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', + wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml', + wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml', + wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml', + wayland_protocol_dir / 'stable/tablet/tablet-v2.xml', + wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml', + wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', + wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml', + wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml', + wayland_protocol_dir / 'stable/viewporter/viewporter.xml', + wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml', + wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', + wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', + wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', ] -wl_protos_src = [] -wl_protos_headers = [] - -new_wl_protos = [] -foreach p : new_protocols - xml = join_paths(p) - new_wl_protos += custom_target( - xml.underscorify(), - input: xml, +wl_protocols = [] +foreach protocol : protocols + wl_protocols += custom_target( + protocol.underscorify(), + input: protocol, install: true, install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], @@ -79,31 +77,26 @@ foreach p : new_protocols ) endforeach -wayland_server_dep = dependency('wayland-server', version: '>=1.20.0') -wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir') +# wayland.xml generation +wayland_scanner = dependency('wayland-scanner') +wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir') -wl_server_protos = [ - wayland_server_dir / 'wayland.xml' -] -wl_server_protos_gen = [] -foreach p : wl_server_protos - wl_server_protos_gen += custom_target( - p.underscorify(), - input: p, - install: true, - install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], - output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], - command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'], - ) -endforeach +wayland_xml = wayland_scanner_datadir / 'wayland.xml' +wayland_protocol = custom_target( + wayland_xml.underscorify(), + input: wayland_xml, + install: true, + install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], + output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], + command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'], +) lib_server_protos = static_library( 'server_protos', - wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen, - dependencies: wayland_server_dep.partial_dependency(compile_args: true), + wl_protocols + wayland_protocol, ) server_protos = declare_dependency( link_with: lib_server_protos, - sources: wl_protos_headers + new_wl_protos, + sources: wl_protocols + wayland_protocol, ) From e01da1fd7a50ab0baeaba074f2a14c826b05bf1c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 11 Sep 2024 19:00:47 +0300 Subject: [PATCH 0016/1803] Meson: format --- assets/install/meson.build | 6 +++++- assets/meson.build | 7 ++++++- docs/meson.build | 4 ++-- example/meson.build | 12 ++++++++++-- hyprctl/meson.build | 26 +++++++++++++++++++++----- hyprpm/src/meson.build | 28 ++++++++++++++++++++++------ meson.build | 26 +++++++++++++++++--------- src/meson.build | 6 ++++-- 8 files changed, 87 insertions(+), 28 deletions(-) diff --git a/assets/install/meson.build b/assets/install/meson.build index 1d4fb917..45076469 100644 --- a/assets/install/meson.build +++ b/assets/install/meson.build @@ -2,5 +2,9 @@ globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: files = globber.stdout().strip().split('\n') foreach file : files - install_data(file, install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') + install_data( + file, + install_dir: join_paths(get_option('datadir'), 'hypr'), + install_tag: 'runtime', + ) endforeach diff --git a/assets/meson.build b/assets/meson.build index 0648037a..2a28121d 100644 --- a/assets/meson.build +++ b/assets/meson.build @@ -1,2 +1,7 @@ -install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime') +install_data( + 'hyprland-portals.conf', + install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), + install_tag: 'runtime', +) + subdir('install') diff --git a/docs/meson.build b/docs/meson.build index a5d7e737..6ff51d1a 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -1,2 +1,2 @@ -install_man ('Hyprland.1') -install_man ('hyprctl.1') +install_man('Hyprland.1') +install_man('hyprctl.1') diff --git a/example/meson.build b/example/meson.build index 2fb3a35e..a338644e 100644 --- a/example/meson.build +++ b/example/meson.build @@ -1,2 +1,10 @@ -install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') -install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime') +install_data( + 'hyprland.conf', + install_dir: join_paths(get_option('datadir'), 'hypr'), + install_tag: 'runtime', +) +install_data( + 'hyprland.desktop', + install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), + install_tag: 'runtime', +) diff --git a/hyprctl/meson.build b/hyprctl/meson.build index 5488845f..455f5739 100644 --- a/hyprctl/meson.build +++ b/hyprctl/meson.build @@ -1,10 +1,26 @@ -executable('hyprctl', 'main.cpp', +executable( + 'hyprctl', + 'main.cpp', dependencies: [ dependency('hyprutils', version: '>= 0.1.1'), ], - install: true + install: true, ) -install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl') -install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime') -install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl') +install_data( + 'hyprctl.bash', + install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), + install_tag: 'runtime', + rename: 'hyprctl', +) +install_data( + 'hyprctl.fish', + install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), + install_tag: 'runtime', +) +install_data( + 'hyprctl.zsh', + install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), + install_tag: 'runtime', + rename: '_hyprctl', +) diff --git a/hyprpm/src/meson.build b/hyprpm/src/meson.build index e2c512a5..2ef6c323 100644 --- a/hyprpm/src/meson.build +++ b/hyprpm/src/meson.build @@ -1,15 +1,31 @@ globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') -executable('hyprpm', src, +executable( + 'hyprpm', + src, dependencies: [ dependency('hyprutils', version: '>= 0.1.1'), dependency('threads'), - dependency('tomlplusplus') + dependency('tomlplusplus'), ], - install : true + install: true, ) -install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm') -install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime') -install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm') +install_data( + '../hyprpm.bash', + install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), + install_tag: 'runtime', + rename: 'hyprpm', +) +install_data( + '../hyprpm.fish', + install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), + install_tag: 'runtime', +) +install_data( + '../hyprpm.zsh', + install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), + install_tag: 'runtime', + rename: '_hyprpm', +) diff --git a/meson.build b/meson.build index 6a9b7ac5..123c31ae 100644 --- a/meson.build +++ b/meson.build @@ -1,13 +1,17 @@ -project('Hyprland', 'cpp', 'c', - version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(), - default_options : [ +project( + 'Hyprland', + 'cpp', + 'c', + version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(), + default_options: [ 'warning_level=2', 'default_library=static', 'optimization=3', 'buildtype=release', 'debug=false', 'cpp_std=c++26', - ]) + ], +) datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' add_project_arguments( @@ -16,10 +20,10 @@ add_project_arguments( '-Wno-unused-value', '-Wno-missing-field-initializers', '-Wno-narrowing', - '-Wno-pointer-arith', - datarootdir, + '-Wno-pointer-arith', datarootdir, ], - language: 'cpp') + language: 'cpp', +) cpp_compiler = meson.get_compiler('cpp') if cpp_compiler.check_header('execinfo.h') @@ -34,7 +38,7 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland')) xcb_res_dep = dependency('xcb-res', required: get_option('xwayland')) xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) -gio_dep = dependency('gio-2.0', required:true) +gio_dep = dependency('gio-2.0', required: true) cmake = import('cmake') udis = cmake.subproject('udis86') @@ -47,6 +51,7 @@ endif backtrace_dep = cpp_compiler.find_library('execinfo', required: false) epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs +# Handle options if get_option('systemd').enabled() add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') endif @@ -59,8 +64,10 @@ if get_option('buildtype') == 'debug' add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') endif -version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true) +# Generate hyprland version and populate version.h +run_command('sh', '-c', 'scripts/generateVersion.sh', check: true) +# Install headers globber = run_command('find', 'src', '-name', '*.h*', check: true) headers = globber.stdout().strip().split('\n') foreach file : headers @@ -75,6 +82,7 @@ subdir('assets') subdir('example') subdir('docs') +# Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') import('pkgconfig').generate( diff --git a/src/meson.build b/src/meson.build index 475ecc24..3821bd60 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,9 @@ globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') -executable('Hyprland', src, +executable( + 'Hyprland', + src, link_args: '-rdynamic', cpp_pch: 'pch/pch.hpp', dependencies: [ @@ -38,5 +40,5 @@ executable('Hyprland', src, dependency('pangocairo'), dependency('uuid'), ], - install : true + install: true, ) From 8b9e385943d1a9fd0f8c6070fa1eae507ae26145 Mon Sep 17 00:00:00 2001 From: fufexan Date: Wed, 11 Sep 2024 16:10:51 +0000 Subject: [PATCH 0017/1803] [gha] Nix: update inputs --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 239ec219..55dc6939 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1725199881, - "narHash": "sha256-jsmipf/u1GFZE5tBUkr56CHMN6VpUWCAjfLIhvQijU0=", + "lastModified": 1725753098, + "narHash": "sha256-/NO/h/qD/eJXAQr/fHA4mdDgYsNT9thHQ+oT6KPi2ac=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "f8a687dd29ff019657498f1bd14da2fbbf0e604b", + "rev": "e4a13203112a036fc7f437d391c7810f3dd5ab52", "type": "github" }, "original": { @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1725188252, - "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", + "lastModified": 1725997860, + "narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", + "rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725103162, - "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", + "lastModified": 1725983898, + "narHash": "sha256-4b3A9zPpxAxLnkF9MawJNHDtOOl6ruL0r6Og1TEDGCE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", + "rev": "1355a0cbfeac61d785b7183c0caaec1f97361b43", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1725228143, - "narHash": "sha256-kbSiPA5oXiz1+1eVoRslMi5wylHD6SDT8dS9eZAxXAM=", + "lastModified": 1726046979, + "narHash": "sha256-6SEsjurq9cdTkITA6d49ncAJe4O/8CgRG5/F//s6Xh8=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "11e15b437e7efc39e452f36e15a183225d6bfa39", + "rev": "e695669fd8e1d1be9eaae40f35e00f8bd8b64c18", "type": "github" }, "original": { From 73b9756b8d7ee06fc1c9f072f2a41f2dd1aeb2c9 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Thu, 12 Sep 2024 04:15:01 -0500 Subject: [PATCH 0018/1803] xwayland: remove extra x11 deactivation (#7755) --- src/managers/XWaylandManager.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 144343f8..fad7e451 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -46,11 +46,8 @@ void CHyprXWaylandManager::activateSurface(SP pSurface, bool PWINDOW->m_pXWaylandSurface->restackToTop(); } PWINDOW->m_pXWaylandSurface->activate(activate); - } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) { + } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) PWINDOW->m_pXDGSurface->toplevel->setActive(activate); - if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11) - activateSurface(g_pCompositor->m_pLastFocus.lock(), false); - } } void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { From 118be4dea048df88fd21b84580fe62950c868c8f Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Fri, 13 Sep 2024 01:41:24 +0900 Subject: [PATCH 0019/1803] textinput: fix tiv3 leave (#7761) --- src/managers/input/TextInput.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 2769fad0..e601ad9a 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -138,8 +138,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) - pV3Input->current.enabled.value = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) { + pV3Input->pending.enabled.value = false; + pV3Input->pending.enabled.isDisablePending = false; + pV3Input->pending.enabled.isEnablePending = false; + pV3Input->current.enabled.value = false; + } if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -154,8 +158,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) - pV3Input->current.enabled.value = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) { + pV3Input->pending.enabled.value = false; + pV3Input->pending.enabled.isDisablePending = false; + pV3Input->pending.enabled.isEnablePending = false; + pV3Input->current.enabled.value = false; + } if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -202,13 +210,9 @@ void CTextInput::leave() { enterLocks = 0; } - if (isV3()) { + if (isV3()) pV3Input->leave(focusedSurface()); - if (pV3Input->current.enabled.value) { - pV3Input->current.enabled.value = false; - onDisabled(); - } - } else + else pV1Input->leave(); setFocusedSurface(nullptr); From d505b3366533b71d57156469c926e8b2b75afb89 Mon Sep 17 00:00:00 2001 From: diniamo Date: Fri, 13 Sep 2024 16:21:33 +0200 Subject: [PATCH 0020/1803] nix: use meson --- nix/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nix/default.nix b/nix/default.nix index 985a4cbb..d3c7dd5f 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -4,6 +4,7 @@ pkg-config, pkgconf, makeWrapper, + meson, cmake, ninja, aquamarine, @@ -89,6 +90,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov hyprwayland-scanner jq makeWrapper + meson cmake ninja pkg-config From c35ed8363f321bb9925bc5e6f5ff03a903593802 Mon Sep 17 00:00:00 2001 From: diniamo Date: Fri, 13 Sep 2024 17:29:41 +0200 Subject: [PATCH 0021/1803] nix: adapt cmake options --- nix/cmake-version.patch | 10 ---------- nix/default.nix | 21 +++++++-------------- nix/stdcxx.patch | 12 ------------ 3 files changed, 7 insertions(+), 36 deletions(-) delete mode 100644 nix/cmake-version.patch delete mode 100644 nix/stdcxx.patch diff --git a/nix/cmake-version.patch b/nix/cmake-version.patch deleted file mode 100644 index ccc9c738..00000000 --- a/nix/cmake-version.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 6fdf98db..d8424d91 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -1,4 +1,4 @@ --cmake_minimum_required(VERSION 3.30) -+cmake_minimum_required(VERSION 3.27) - - # Get version - file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) diff --git a/nix/default.nix b/nix/default.nix index d3c7dd5f..8d912fe6 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -62,13 +62,6 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov src = lib.cleanSource ../.; }; - patches = [ - # forces GCC to use -std=c++26 - ./stdcxx.patch - # Nix does not have CMake 3.30 yet, so override the minimum version - ./cmake-version.patch - ]; - postPatch = '' # Fix hardcoded paths to /usr installation sed -i "s#/usr#$out#" src/render/OpenGL.cpp @@ -144,18 +137,18 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.optionals withSystemd [systemd]) ]; - cmakeBuildType = + mesonBuildType = if debug - then "Debug" - else "RelWithDebInfo"; + then "debug" + else "release"; # we want as much debug info as possible dontStrip = debug; - cmakeFlags = [ - (lib.cmakeBool "NO_XWAYLAND" (!enableXWayland)) - (lib.cmakeBool "LEGACY_RENDERER" legacyRenderer) - (lib.cmakeBool "NO_SYSTEMD" (!withSystemd)) + mesonFlags = [ + (lib.mesonEnable "xwayland" enableXWayland) + (lib.mesonEnable "legacy_renderer" legacyRenderer) + (lib.mesonEnable "systemd" withSystemd) ]; postInstall = '' diff --git a/nix/stdcxx.patch b/nix/stdcxx.patch deleted file mode 100644 index 032e494d..00000000 --- a/nix/stdcxx.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index cfbd431f..73e8e0c2 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -64,6 +64,7 @@ endif() - include_directories(. "src/" "subprojects/udis86/" "protocols/") - set(CMAKE_CXX_STANDARD 26) - add_compile_options( -+ -std=c++26 - -Wall - -Wextra - -Wno-unused-parameter From d35e70a8c6599bb058cf86eb87c783ce1cf72471 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 13 Sep 2024 17:56:39 +0100 Subject: [PATCH 0022/1803] cmake: drop ninja dep --- Makefile | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index bc7b750b..59efc0ef 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,24 @@ PREFIX = /usr/local legacyrenderer: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` legacyrendererdebug: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` release: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` debug: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja - cmake --build ./build --config Debug --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build + cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` nopch: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` clear: rm -rf build From 5ee4b19691f413072f6877940ed709774333f84b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 14 Sep 2024 23:35:45 +0100 Subject: [PATCH 0023/1803] data-device: send clock time in motion events remove hack --- src/protocols/core/DataDevice.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 8c1a48d8..43a63949 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -513,7 +513,10 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource if (!box.has_value()) return; - dnd.focusedDevice->sendMotion(0 /* this is a hack */, V - box->pos()); + timespec timeNow; + clock_gettime(CLOCK_MONOTONIC, &timeNow); + + dnd.focusedDevice->sendMotion(timeNow.tv_sec * 1000 + timeNow.tv_nsec / 1000000, V - box->pos()); LOGM(LOG, "Drag motion {}", V - box->pos()); } }); From 4dbdb556fe441506ec5cf129c65b14e514dbcc5a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 14 Sep 2024 23:36:06 +0100 Subject: [PATCH 0024/1803] data-device: don't send default action of move gtk doesn't like it? --- src/protocols/core/DataDevice.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 43a63949..eac80a83 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -82,10 +82,8 @@ void CWLDataOfferResource::sendData() { if (!source) return; - if (resource->version() >= 3) { + if (resource->version() >= 3) resource->sendSourceActions(7); - resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); - } for (auto const& m : source->mimes()) { LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m); From e74efd87e5aa38f9cf84cb3848ee1ab26e5e4bcb Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 14 Sep 2024 17:37:18 -0500 Subject: [PATCH 0025/1803] internal: fix initial cursor warping (#7793) --- src/Compositor.cpp | 34 ++++++++++++++++++++++++++++ src/managers/PointerManager.cpp | 40 +-------------------------------- src/managers/PointerManager.hpp | 1 - 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index da659654..8e1b11b0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2943,6 +2943,38 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } +static void checkDefaultCursorWarp(SP monitor) { + static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); + static bool cursorDefaultDone = false; + static bool firstLaunch = true; + + const auto POS = monitor->middle(); + + // by default, cursor should be set to first monitor detected + // this is needed as a default if the monitor given in config above doesn't exist + if (firstLaunch) { + firstLaunch = false; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + return; + } + + if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) { + if (*PCURSORMONITOR == monitor->szName) { + cursorDefaultDone = true; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + return; + } + } + + // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. + if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } +} + void CCompositor::onNewMonitor(SP output) { // add it to real auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared(output)); @@ -2977,6 +3009,8 @@ void CCompositor::onNewMonitor(SP output) { g_pConfigManager->m_bWantsMonitorReload = true; g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); + checkDefaultCursorWarp(PNEWMONITOR); + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_iMonitorID == PNEWMONITOR->ID) { w->m_iLastSurfaceMonitorID = MONITOR_INVALID; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 6b2a40f5..5a192e13 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -18,13 +18,7 @@ CPointerManager::CPointerManager() { onMonitorLayoutChange(); PMONITOR->events.modeChanged.registerStaticListener( - [this, PMONITOR](void* owner, std::any data) { - g_pEventLoopManager->doLater([this, PMONITOR]() { - onMonitorLayoutChange(); - checkDefaultCursorWarp(PMONITOR, PMONITOR->output->name); - }); - }, - nullptr); + [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.disconnect.registerStaticListener( [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( @@ -44,38 +38,6 @@ CPointerManager::CPointerManager() { }); } -void CPointerManager::checkDefaultCursorWarp(SP monitor, std::string monitorName) { - static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); - static bool cursorDefaultDone = false; - static bool firstLaunch = true; - - const auto POS = monitor->middle(); - - // by default, cursor should be set to first monitor detected - // this is needed as a default if the monitor given in config above doesn't exist - if (firstLaunch) { - firstLaunch = false; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - return; - } - - if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) { - if (*PCURSORMONITOR == monitorName) { - cursorDefaultDone = true; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - return; - } - } - - // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. - if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } -} - void CPointerManager::lockSoftwareAll() { for (auto const& state : monitorStates) state->softwareLocks++; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 082855b5..4a4c4f61 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -26,7 +26,6 @@ class CPointerManager { public: CPointerManager(); - void checkDefaultCursorWarp(SP monitor, std::string monitorName); void attachPointer(SP pointer); void attachTouch(SP touch); void attachTablet(SP tablet); From eb97d949aa31b900d9735bcb8ead47acddc1f339 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Mon, 16 Sep 2024 01:31:38 +0900 Subject: [PATCH 0026/1803] textinput: don't reset if ti isn't enabled (#7798) --- src/managers/input/TextInput.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index e601ad9a..f7a6a350 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -99,6 +99,13 @@ void CTextInput::onReset() { if (g_pInputManager->m_sIMERelay.m_pIME.expired()) return; + if (!focusedSurface()) + return; + + const auto PFOCUSEDTI = g_pInputManager->m_sIMERelay.getFocusedTextInput(); + if (!PFOCUSEDTI || PFOCUSEDTI != this) + return; + g_pInputManager->m_sIMERelay.deactivateIME(this, false); g_pInputManager->m_sIMERelay.activateIME(this); } From e87758529e9d2dc70f318346c66a9d895d4503ce Mon Sep 17 00:00:00 2001 From: AlvinaNancy <152092635+AlvinaNancy@users.noreply.github.com> Date: Sun, 15 Sep 2024 17:25:06 +0000 Subject: [PATCH 0027/1803] internal: Fix change group current fullscreen state query (#7802) --- src/desktop/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index cc5b48af..feced807 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -991,7 +991,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { const auto PCURRENT = getGroupCurrent(); const bool FULLSCREEN = PCURRENT->isFullscreen(); const auto WORKSPACE = PCURRENT->m_pWorkspace; - const auto MODE = PCURRENT->m_sFullscreenState.client; + const auto MODE = PCURRENT->m_sFullscreenState.internal; const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); From 9e356562446f44c471ae38a80506a9df039305d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leiser=20Fern=C3=A1ndez=20Gallo?= Date: Sun, 15 Sep 2024 22:03:42 +0200 Subject: [PATCH 0028/1803] internal: Delay monitor events/hooks (#7797) * Delay monitor messages * Format --- src/helpers/Monitor.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 5b01d651..708a5cc8 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -192,10 +192,6 @@ void CMonitor::onConnect(bool noRule) { if (!activeMonitorRule.mirrorOf.empty()) setMirror(activeMonitorRule.mirrorOf); - g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); - g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); - EMIT_HOOK_EVENT("monitorAdded", this); - if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet g_pCompositor->setActiveMonitor(this); @@ -224,6 +220,10 @@ void CMonitor::onConnect(bool noRule) { PROTO::gamma->applyGammaToState(this); events.connect.emit(); + + g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); + g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); + EMIT_HOOK_EVENT("monitorAdded", this); } void CMonitor::onDisconnect(bool destroy) { @@ -281,9 +281,6 @@ void CMonitor::onDisconnect(bool destroy) { Debug::log(LOG, "Removed monitor {}!", szName); - g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); - EMIT_HOOK_EVENT("monitorRemoved", this); - if (!BACKUPMON) { Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend."); g_pCompositor->enterUnsafeState(); @@ -342,6 +339,9 @@ void CMonitor::onDisconnect(bool destroy) { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } std::erase_if(g_pCompositor->m_vMonitors, [&](SP& el) { return el.get() == this; }); + + g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); + EMIT_HOOK_EVENT("monitorRemoved", this); } void CMonitor::addDamage(const pixman_region32_t* rg) { From e72ae6b25fe019404df31e783ae980f80d3eaa3c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 17 Sep 2024 11:24:54 +0100 Subject: [PATCH 0029/1803] hyprctl: allow parsing empty value fixes #7821 --- src/debug/HyprCtl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 683665be..3d4d8092 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -987,9 +987,9 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { const auto COMMAND = in.substr(0, secondSpacePos); const auto VALUE = in.substr(secondSpacePos + 1); - // If either COMMAND or VALUE is empty, handle accordingly - if (COMMAND.empty() || VALUE.empty()) - return "Invalid input: command or value is empty"; + // If COMMAND is empty, handle accordingly + if (COMMAND.empty()) + return "Invalid input: command is empty"; std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE); From 581f6659f8541476da82ebd819a564780b3a969e Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 17 Sep 2024 12:55:48 +0100 Subject: [PATCH 0030/1803] data-device: conform to reported source actions fixes #7815 --- src/protocols/core/DataDevice.cpp | 21 ++++++++++++++++++--- src/protocols/core/DataDevice.hpp | 3 ++- src/protocols/types/DataDevice.cpp | 4 ++++ src/protocols/types/DataDevice.hpp | 1 + 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index eac80a83..5644f243 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -82,8 +82,19 @@ void CWLDataOfferResource::sendData() { if (!source) return; - if (resource->version() >= 3) - resource->sendSourceActions(7); + const auto SOURCEACTIONS = source->actions(); + + if (resource->version() >= 3 && SOURCEACTIONS > 0) { + resource->sendSourceActions(SOURCEACTIONS); + if (SOURCEACTIONS & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) + resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); + else if (SOURCEACTIONS & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) + resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + else { + LOGM(ERR, "Client bug? dnd source has no action move or copy. Sending move, f this."); + resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); + } + } for (auto const& m : source->mimes()) { LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m); @@ -111,7 +122,7 @@ CWLDataSourceResource::CWLDataSourceResource(SP resource_, SPsetOffer([this](CWlDataSource* r, const char* mime) { mimeTypes.push_back(mime); }); resource->setSetActions([this](CWlDataSource* r, uint32_t a) { LOGM(LOG, "DataSource {:x} actions {}", (uintptr_t)this, a); - actions = (wl_data_device_manager_dnd_action)a; + supportedActions = a; }); } @@ -193,6 +204,10 @@ void CWLDataSourceResource::sendDndAction(wl_data_device_manager_dnd_action a) { resource->sendAction(a); } +uint32_t CWLDataSourceResource::actions() { + return supportedActions; +} + CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 8aaf46be..50e9ac61 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -65,6 +65,7 @@ class CWLDataSourceResource : public IDataSource { virtual bool dndDone(); virtual void error(uint32_t code, const std::string& msg); virtual void sendDndFinished(); + virtual uint32_t actions(); // wl_data_device_manager.dnd_action void sendDndDropPerformed(); void sendDndAction(wl_data_device_manager_dnd_action a); @@ -78,7 +79,7 @@ class CWLDataSourceResource : public IDataSource { WP self; std::vector mimeTypes; - uint32_t actions = 0; + uint32_t supportedActions = 0; private: SP resource; diff --git a/src/protocols/types/DataDevice.cpp b/src/protocols/types/DataDevice.cpp index e95f1c76..36a7a157 100644 --- a/src/protocols/types/DataDevice.cpp +++ b/src/protocols/types/DataDevice.cpp @@ -23,3 +23,7 @@ eDataSourceType IDataSource::type() { void IDataSource::sendDndFinished() { ; } + +uint32_t IDataSource::actions() { + return 7; // all +} diff --git a/src/protocols/types/DataDevice.hpp b/src/protocols/types/DataDevice.hpp index f6757e1c..a62cc35e 100644 --- a/src/protocols/types/DataDevice.hpp +++ b/src/protocols/types/DataDevice.hpp @@ -26,6 +26,7 @@ class IDataSource { virtual void markUsed(); virtual void error(uint32_t code, const std::string& msg) = 0; virtual eDataSourceType type(); + virtual uint32_t actions(); // wl_data_device_manager.dnd_action struct { CSignal destroy; From 3c9716acfd00c6ea1b7bcd1dc63f97b51cc09998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:37:20 +0100 Subject: [PATCH 0031/1803] gammactrl: fix potential crash on monitor removed (#7828) --- src/protocols/GammaControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index d7992981..077d6e2f 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -19,7 +19,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out pMonitor = OUTPUTRES->monitor; - if (!pMonitor) { + if (!pMonitor || !pMonitor->output) { LOGM(ERR, "No CMonitor"); resource->sendFailed(); return; From 0564b46a5e9afbf2fb51a7198452342e43ba4637 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 18 Sep 2024 12:05:17 +0200 Subject: [PATCH 0032/1803] dispatchers: allow moveintogroup when floating (#7818) This allows to use the moveintogroup dispatcher when windows are floating. I don't know why was this disabled in the first place though. Cheers! --- src/managers/KeybindManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2f593d74..dd35bc19 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2730,7 +2730,7 @@ SDispatchResult CKeybindManager::moveIntoGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || PWINDOW->m_bIsFloating || PWINDOW->m_sGroupData.deny) + if (!PWINDOW || PWINDOW->m_sGroupData.deny) return {}; auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); From 883d01084c52fdc5da0e6bfff7fd0f5cf0f62352 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 18 Sep 2024 11:22:07 +0100 Subject: [PATCH 0033/1803] userchecks: add an xdg_current_desktop check ref https://github.com/hyprwm/xdg-desktop-portal-hyprland/issues/251 if the XDG_CURRENT_DESKTOP is externally managed (e.g. DE, DM, etc) Hyprland will not overwrite it. In those cases, if that's undesired, portals and other apps depending on it might break. --- src/Compositor.cpp | 12 +++++++++++- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8e1b11b0..232ba4a6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2696,7 +2696,17 @@ WORKSPACEID CCompositor::getNewSpecialID() { } void CCompositor::performUserChecks() { - ; // intentional + static auto PNOCHECKXDG = CConfigValue("misc:disable_xdg_env_checks"); + + if (!*PNOCHECKXDG) { + const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP"); + if (!CURRENT_DESKTOP_ENV || std::string{CURRENT_DESKTOP_ENV} != "Hyprland") { + g_pHyprNotificationOverlay->addNotification( + std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.", + CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"), + CColor{}, 15000, ICON_WARNING); + } + } } void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) { diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 44b5ee4a..84ac1a41 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1049,6 +1049,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{15, 1, 120}, }, + SConfigOptionDescription{ + .value = "misc:disable_xdg_env_checks", + .description = "disable the warning if XDG environment is externally managed", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * binds: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 57cd2350..27e8fdb0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -371,6 +371,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15}); + m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); From d936eb437b5d33cda21e1502a96dc7d83446aca5 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 18 Sep 2024 17:26:51 +0300 Subject: [PATCH 0034/1803] flake.lock: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 55dc6939..35974921 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1725753098, - "narHash": "sha256-/NO/h/qD/eJXAQr/fHA4mdDgYsNT9thHQ+oT6KPi2ac=", + "lastModified": 1726665257, + "narHash": "sha256-rEzEZtd3iyVo5RJ1OGujOlnywNf3gsrOnjAn1NLciD4=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "e4a13203112a036fc7f437d391c7810f3dd5ab52", + "rev": "752d0fbd141fabb5a1e7f865199b80e6e76f8d8e", "type": "github" }, "original": { From 6b6554adb8c2fba5d89554af6fc467dcd15cedc0 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 14 Sep 2024 00:06:43 +0300 Subject: [PATCH 0035/1803] flake.nix: inherit stdenv from package Means we no longer have to change the base stdenv in two places. --- flake.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index 9e1e3ab4..ef914627 100644 --- a/flake.nix +++ b/flake.nix @@ -95,13 +95,9 @@ devShells = eachSystem (system: { default = pkgsFor.${system}.mkShell.override { - stdenv = pkgsFor.${system}.gcc14Stdenv; + inherit (self.packages.${system}.default) stdenv; } { name = "hyprland-shell"; - nativeBuildInputs = with pkgsFor.${system}; [ - expat - libxml2 - ]; hardeningDisable = ["fortify"]; inputsFrom = [pkgsFor.${system}.hyprland]; packages = [pkgsFor.${system}.clang-tools]; From cbc0ff6ec0670e904758069c3844b05086bb15d3 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 18 Sep 2024 18:54:00 +0300 Subject: [PATCH 0036/1803] Nix: disable PCH --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 8d912fe6..b167a4df 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -149,6 +149,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.mesonEnable "xwayland" enableXWayland) (lib.mesonEnable "legacy_renderer" legacyRenderer) (lib.mesonEnable "systemd" withSystemd) + (lib.mesonEnable "b_pch" false) ]; postInstall = '' From b248d59713d99a8338d25f4765fd2f564069f98b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 18 Sep 2024 19:43:56 +0300 Subject: [PATCH 0037/1803] Nix: fix meson PCH flag --- nix/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index b167a4df..11e18e6c 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -149,7 +149,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.mesonEnable "xwayland" enableXWayland) (lib.mesonEnable "legacy_renderer" legacyRenderer) (lib.mesonEnable "systemd" withSystemd) - (lib.mesonEnable "b_pch" false) + "-Db_pch=false" ]; postInstall = '' From 94140e886ea8c4ac34478d290c212f0f5454ab2e Mon Sep 17 00:00:00 2001 From: Jasson Date: Wed, 18 Sep 2024 13:12:26 -0400 Subject: [PATCH 0038/1803] xwayland: Some readability improvements (#7807) * Readability improvements xwayland server * Made requested changes * removed braces * fix * Ok this time is fixed * Formatting --- src/xwayland/Server.cpp | 194 ++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 89 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index f3bf5768..97caf9e3 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -1,105 +1,115 @@ +#include #ifndef NO_XWAYLAND -#include "Server.hpp" -#include "../defines.hpp" -#include "../Compositor.hpp" -#include "../managers/CursorManager.hpp" -#include "XWayland.hpp" - +#include +#include #include #include +#include +#include #include #include #include -#include #include -#include -#include -#include #include #include +#include #include -#include +#include +#include +#include -// TODO: cleanup -static bool set_cloexec(int fd, bool cloexec) { +#include "Server.hpp" +#include "XWayland.hpp" +#include "debug/Log.hpp" +#include "../defines.hpp" +#include "../Compositor.hpp" +#include "../managers/CursorManager.hpp" + +// Constants +constexpr int SOCKET_DIR_PERMISSIONS = 0755; +constexpr int SOCKET_BACKLOG = 1; +constexpr int MAX_SOCKET_RETRIES = 32; +constexpr int LOCK_FILE_MODE = 044; + +static bool setCloseOnExec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); if (flags == -1) { Debug::log(ERR, "fcntl failed"); return false; } - if (cloexec) { + + if (cloexec) flags = flags | FD_CLOEXEC; - } else { + else flags = flags & ~FD_CLOEXEC; - } + if (fcntl(fd, F_SETFD, flags) == -1) { Debug::log(ERR, "fcntl failed"); return false; } + return true; } -static int openSocket(struct sockaddr_un* addr, size_t path_size) { - int fd, rc; - socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; +void cleanUpSocket(int fd, const char* path) { + close(fd); + if (path[0]) + unlink(path); +} - fd = socket(AF_UNIX, SOCK_STREAM, 0); +static int createSocket(struct sockaddr_un* addr, size_t path_size) { + socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; + int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - Debug::log(ERR, "failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "Failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); return -1; } - if (!set_cloexec(fd, true)) { + + if (!setCloseOnExec(fd, true)) { close(fd); return -1; } - if (addr->sun_path[0]) { + if (addr->sun_path[0]) unlink(addr->sun_path); - } + if (bind(fd, (struct sockaddr*)addr, size) < 0) { - rc = errno; - Debug::log(ERR, "failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - goto cleanup; + Debug::log(ERR, "Failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + cleanUpSocket(fd, addr->sun_path); + return -1; } - if (listen(fd, 1) < 0) { - rc = errno; - Debug::log(ERR, "failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - goto cleanup; + + if (listen(fd, SOCKET_BACKLOG) < 0) { + Debug::log(ERR, "Failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + cleanUpSocket(fd, addr->sun_path); + return -1; } return fd; - -cleanup: - close(fd); - if (addr->sun_path[0]) { - unlink(addr->sun_path); - } - errno = rc; - return -1; } static bool checkPermissionsForSocketDir(void) { struct stat buf; if (lstat("/tmp/.X11-unix", &buf)) { - Debug::log(ERR, "Failed statting X11 socket dir"); + Debug::log(ERR, "Failed to stat X11 socket dir"); return false; } if (!(buf.st_mode & S_IFDIR)) { - Debug::log(ERR, "X11 socket dir is not a dir"); + Debug::log(ERR, "X11 socket dir is not a directory"); return false; } if (!((buf.st_uid == 0) || (buf.st_uid == getuid()))) { - Debug::log(ERR, "X11 socket dir is not ours"); + Debug::log(ERR, "X11 socket dir is not owned by root or current user"); return false; } if (!(buf.st_mode & S_ISVTX)) { if ((buf.st_mode & (S_IWGRP | S_IWOTH))) { - Debug::log(ERR, "X11 socket dir is sticky by others"); + Debug::log(ERR, "X11 socket dir is writable by others"); return false; } } @@ -107,38 +117,51 @@ static bool checkPermissionsForSocketDir(void) { return true; } -static bool openSockets(std::array& sockets, int display) { - auto ret = mkdir("/tmp/.X11-unix", 755); - - if (ret != 0) { - if (errno == EEXIST) { - if (!checkPermissionsForSocketDir()) - return false; - } else { - Debug::log(ERR, "XWayland: couldn't create socket dir"); +static bool ensureSocketDirExists() { + if (mkdir("/tmp/.X11-unix", SOCKET_DIR_PERMISSIONS) != 0) { + if (errno == EEXIST) + return checkPermissionsForSocketDir(); + else { + Debug::log(ERR, "XWayland: Couldn't create socket dir"); return false; } } - std::string path; + return true; +} + +static std::string getSocketPath(int display, bool isLinux) { + if (isLinux) + return std::format("/tmp/.X11-unix{}", display); + + return std::format("/tmp/.X11-unix{}_", display); +} + +static bool openSockets(std::array& sockets, int display) { + if (!ensureSocketDirExists()) + return false; + sockaddr_un addr = {.sun_family = AF_UNIX}; + std::string path; #ifdef __linux__ // cursed... addr.sun_path[0] = 0; - path = std::format("/tmp/.X11-unix/X{}", display); + path = getSocketPath(display, true); strncpy(addr.sun_path + 1, path.c_str(), path.length() + 1); #else - path = std::format("/tmp/.X11-unix/X{}_", display); + path = getSocketPath(display, false); strncpy(addr.sun_path, path.c_str(), path.length() + 1); #endif - sockets[0] = openSocket(&addr, path.length()); + + sockets[0] = createSocket(&addr, path.length()); if (sockets[0] < 0) return false; - path = std::format("/tmp/.X11-unix/X{}", display); + path = getSocketPath(display, true); strncpy(addr.sun_path, path.c_str(), path.length() + 1); - sockets[1] = openSocket(&addr, path.length()); + + sockets[1] = createSocket(&addr, path.length()); if (sockets[1] < 0) { close(sockets[0]); sockets[0] = -1; @@ -160,39 +183,37 @@ static int xwaylandReady(int fd, uint32_t mask, void* data) { static bool safeRemove(const std::string& path) { try { return std::filesystem::remove(path); - } catch (std::exception& e) { Debug::log(ERR, "[XWayland] failed to remove {}", path); } - + } catch (const std::exception& e) { Debug::log(ERR, "[XWayland] Failed to remove {}", path); } return false; } bool CXWaylandServer::tryOpenSockets() { - for (size_t i = 0; i <= 32; ++i) { - auto LOCK = std::format("/tmp/.X{}-lock", i); + for (size_t i = 0; i <= MAX_SOCKET_RETRIES; ++i) { + std::string lockPath = std::format("/tmp/.X{}-lock", i); - if (int fd = open(LOCK.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444); fd >= 0) { + int fd = open(lockPath.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, LOCK_FILE_MODE); + if (fd >= 0) { // we managed to open the lock if (!openSockets(xFDs, i)) { - safeRemove(LOCK); + safeRemove(lockPath); close(fd); continue; } - const auto PIDSTR = std::format("{}", getpid()); - - if (write(fd, PIDSTR.c_str(), PIDSTR.length()) != (long)PIDSTR.length()) { - safeRemove(LOCK); + const std::string pidStr = std::to_string(getpid()); + if (write(fd, pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) { + safeRemove(lockPath); close(fd); continue; } close(fd); - display = i; displayName = std::format(":{}", display); break; } - int fd = open(LOCK.c_str(), O_RDONLY | O_CLOEXEC); + fd = open(lockPath.c_str(), O_RDONLY | O_CLOEXEC); if (fd < 0) continue; @@ -201,21 +222,20 @@ bool CXWaylandServer::tryOpenSockets() { read(fd, pidstr, sizeof(pidstr) - 1); close(fd); - uint64_t pid = 0; + int32_t pid = 0; try { pid = std::stoi(std::string{pidstr, 11}); } catch (...) { continue; } if (kill(pid, 0) != 0 && errno == ESRCH) { - if (!safeRemove(LOCK)) + if (!safeRemove(lockPath)) continue; - i--; } } if (display < 0) { - Debug::log(ERR, "Failed to find a suitable socket for xwayland"); + Debug::log(ERR, "Failed to find a suitable socket for XWayland"); return false; } @@ -232,19 +252,17 @@ CXWaylandServer::~CXWaylandServer() { if (display < 0) return; - if (xFDs[0]) - close(xFDs[0]); - if (xFDs[1]) - close(xFDs[1]); + close(xFDs[0]); + close(xFDs[1]); - auto LOCK = std::format("/tmp/.X{}-lock", display); - safeRemove(LOCK); + std::string lockPath = std::format("/tmp/.X{}-lock", display); + safeRemove(lockPath); std::string path; #ifdef __linux__ - path = std::format("/tmp/.X11-unix/X{}", display); + path = getSocketPath(display, true); #else - path = std::format("/tmp/.X11-unix/X{}_", display); + path = getSocketPath(display, false); #endif safeRemove(path); } @@ -256,7 +274,6 @@ void CXWaylandServer::die() { if (xFDReadEvents[0]) { wl_event_source_remove(xFDReadEvents[0]); wl_event_source_remove(xFDReadEvents[1]); - xFDReadEvents = {nullptr, nullptr}; } @@ -298,7 +315,7 @@ bool CXWaylandServer::create() { } void CXWaylandServer::runXWayland(int notifyFD) { - if (!set_cloexec(xFDs[0], false) || !set_cloexec(xFDs[1], false) || !set_cloexec(waylandFDs[1], false) || !set_cloexec(xwmFDs[1], false)) { + if (!setCloseOnExec(xFDs[0], false) || !setCloseOnExec(xFDs[1], false) || !setCloseOnExec(waylandFDs[1], false) || !setCloseOnExec(xwmFDs[1], false)) { Debug::log(ERR, "Failed to unset cloexec on fds"); _exit(EXIT_FAILURE); } @@ -325,7 +342,7 @@ bool CXWaylandServer::start() { return false; } - if (!set_cloexec(waylandFDs[0], true) || !set_cloexec(waylandFDs[1], true)) { + if (!setCloseOnExec(waylandFDs[0], true) || !setCloseOnExec(waylandFDs[1], true)) { Debug::log(ERR, "set_cloexec failed (1)"); die(); return false; @@ -337,7 +354,7 @@ bool CXWaylandServer::start() { return false; } - if (!set_cloexec(xwmFDs[0], true) || !set_cloexec(xwmFDs[1], true)) { + if (!setCloseOnExec(xwmFDs[0], true) || !setCloseOnExec(xwmFDs[1], true)) { Debug::log(ERR, "set_cloexec failed (2)"); die(); return false; @@ -359,7 +376,7 @@ bool CXWaylandServer::start() { return false; } - if (!set_cloexec(notify[0], true)) { + if (!setCloseOnExec(notify[0], true)) { Debug::log(ERR, "set_cloexec failed (3)"); close(notify[0]); close(notify[1]); @@ -382,9 +399,8 @@ bool CXWaylandServer::start() { if (pid < 0) { Debug::log(ERR, "second fork failed"); _exit(1); - } else if (pid == 0) { + } else if (pid == 0) runXWayland(notify[1]); - } _exit(0); } From e6cf643f5ab1c1545fb858ab1fd9d7538ef9e0f3 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:47:53 +0100 Subject: [PATCH 0039/1803] pointermgr: Hide hardware cursor on leave (#7806) --- src/managers/PointerManager.cpp | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 5a192e13..3dcee431 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -208,9 +208,8 @@ void CPointerManager::recheckEnteredOutputs() { // if we are using hw cursors, prevent // the cursor from being stuck at the last point. - // if we are leaving it, move it to narnia. if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) - s->monitor->output->moveCursor({-1337, -420}); + setHWCursorBuffer(s, nullptr); if (!currentCursorImage.surface) continue; @@ -269,6 +268,8 @@ void CPointerManager::resetCursorImage(bool apply) { void CPointerManager::updateCursorBackend() { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); + const auto CURSORBOX = getCursorBoxGlobal(); + for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); @@ -277,6 +278,15 @@ void CPointerManager::updateCursorBackend() { continue; } + auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty(); + + if (!CROSSES) { + if (state->cursorFrontBuffer) + setHWCursorBuffer(state, nullptr); + + continue; + } + if (state->softwareLocks > 0 || *PNOHW || !attemptHardwareCursor(state)) { Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); @@ -297,17 +307,34 @@ void CPointerManager::onCursorMoved() { if (!hasCursor()) return; + const auto CURSORBOX = getCursorBoxGlobal(); + bool recalc = false; + for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); + auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty(); + + if (!CROSSES && state->cursorFrontBuffer) { + Debug::log(TRACE, "onCursorMoved for output {}: cursor left the viewport, removing it from the backend", m->szName); + setHWCursorBuffer(state, nullptr); + continue; + } else if (CROSSES && !state->cursorFrontBuffer) { + Debug::log(TRACE, "onCursorMoved for output {}: cursor entered the output, but no front buffer, forcing recalc", m->szName); + recalc = true; + } + if (state->hardwareFailed || !state->entered) continue; const auto CURSORPOS = getCursorPosForMonitor(m); m->output->moveCursor(CURSORPOS); } + + if (recalc) + updateCursorBackend(); } bool CPointerManager::attemptHardwareCursor(SP state) { From 1bc05b1f9fd55f2a7371082e6914622e4584ed54 Mon Sep 17 00:00:00 2001 From: Arisa Snowbell Date: Thu, 19 Sep 2024 12:08:02 +0200 Subject: [PATCH 0040/1803] xwayland: use proper path for the XWayland sockets (#7852) fixes #7849 --- src/xwayland/Server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 97caf9e3..5ad9ff23 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -132,9 +132,9 @@ static bool ensureSocketDirExists() { static std::string getSocketPath(int display, bool isLinux) { if (isLinux) - return std::format("/tmp/.X11-unix{}", display); + return std::format("/tmp/.X11-unix/X{}", display); - return std::format("/tmp/.X11-unix{}_", display); + return std::format("/tmp/.X11-unix/X{}_", display); } static bool openSockets(std::array& sockets, int display) { From 71963972bff15acccd9abd0dfd3e70504609b7cc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 19 Sep 2024 11:25:58 +0100 Subject: [PATCH 0041/1803] args: add --version to binary args --- src/main.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 820a248c..525ad4ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,9 @@ #include "config/ConfigManager.hpp" #include "init/initHelpers.hpp" +#include +using namespace Hyprutils::String; + #include #include #include @@ -20,6 +23,7 @@ void help() { std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; + std::cout << " --version -v - Print this binary's version\n"; } int main(int argc, char** argv) { @@ -109,6 +113,24 @@ int main(int argc, char** argv) { } else if (it->compare("-h") == 0 || it->compare("--help") == 0) { help(); + return 0; + } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { + auto commitMsg = trim(GIT_COMMIT_MESSAGE); + std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); + std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; + +#ifdef LEGACY_RENDERER + result += "legacyrenderer\n"; +#endif +#ifndef ISDEBUG + result += "debug\n"; +#endif +#ifdef NO_XWAYLAND + result += "no xwayland\n"; +#endif + + std::cout << result; return 0; } else { std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; From 92df6b0dce1b81b130c2b0e46d206c8c3dbb2971 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 19 Sep 2024 11:39:54 +0100 Subject: [PATCH 0042/1803] version: log build aquamarine version log the built against aq version, might be useful when it's mismatched to identify the problem --- CMakeLists.txt | 7 +++++-- src/debug/HyprCtl.cpp | 7 +++++-- src/main.cpp | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fdf98db..b6ac8efc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,11 +91,14 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) +pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine) + +add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") + pkg_check_modules( deps REQUIRED IMPORTED_TARGET - aquamarine xkbcommon uuid wayland-server @@ -220,7 +223,7 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::deps) +target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps) # used by `make installheaders`, to ensure the headers are generated add_custom_target(generate-protocol-headers) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 3d4d8092..9faefe26 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -858,7 +858,8 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + + "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; @@ -881,8 +882,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "commit_date": "{}", "tag": "{}", "commits": "{}", + "buildAquamarine": "{}", "flags": [)#", - GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS); + GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, + AQUAMARINE_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; diff --git a/src/main.cpp b/src/main.cpp index 525ad4ff..ba6fe505 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,7 +118,8 @@ int main(int argc, char** argv) { auto commitMsg = trim(GIT_COMMIT_MESSAGE); std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + + "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; From dfa1bd0cd48253a446fbe455a46f0f4d23368c02 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 19 Sep 2024 13:48:31 +0000 Subject: [PATCH 0043/1803] Meson: pass AQUAMARINE_VERSION argument --- meson.build | 3 +++ src/meson.build | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 123c31ae..9449c241 100644 --- a/meson.build +++ b/meson.build @@ -30,6 +30,9 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif +aquamarine = dependency('aquamarine') +add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') + xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland')) diff --git a/src/meson.build b/src/meson.build index 3821bd60..928cd5a7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -8,7 +8,7 @@ executable( cpp_pch: 'pch/pch.hpp', dependencies: [ server_protos, - dependency('aquamarine'), + aquamarine, dependency('gbm'), dependency('xcursor'), dependency('wayland-server'), From 9856378384539e35cd943604e6a4d696a9d25447 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 19 Sep 2024 18:53:34 +0300 Subject: [PATCH 0044/1803] Nix: use mold linker --- nix/default.nix | 237 +++++++++++++++++++++++++----------------------- 1 file changed, 122 insertions(+), 115 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 11e18e6c..3d621db6 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,6 +1,7 @@ { lib, stdenv, + stdenvAdapters, pkg-config, pkgconf, makeWrapper, @@ -46,130 +47,136 @@ enableNvidiaPatches ? false, nvidiaPatches ? false, hidpiXWayland ? false, -}: -assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; -assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; -assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; - stdenv.mkDerivation { - pname = "hyprland${lib.optionalString debug "-debug"}"; - inherit version; +}: let + adapters = lib.flatten [ + stdenvAdapters.useMoldLinker + ]; - src = lib.cleanSourceWith { - filter = name: type: let - baseName = baseNameOf (toString name); - in - ! (lib.hasSuffix ".nix" baseName); - src = lib.cleanSource ../.; - }; + customStdenv = builtins.foldl' (acc: adapter: adapter acc) stdenv adapters; +in + assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; + assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; + assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; + customStdenv.mkDerivation { + pname = "hyprland${lib.optionalString debug "-debug"}"; + inherit version; - postPatch = '' - # Fix hardcoded paths to /usr installation - sed -i "s#/usr#$out#" src/render/OpenGL.cpp + src = lib.cleanSourceWith { + filter = name: type: let + baseName = baseNameOf (toString name); + in + ! (lib.hasSuffix ".nix" baseName); + src = lib.cleanSource ../.; + }; - # Remove extra @PREFIX@ to fix pkg-config paths - sed -i "s#@PREFIX@/##g" hyprland.pc.in - ''; + postPatch = '' + # Fix hardcoded paths to /usr installation + sed -i "s#/usr#$out#" src/render/OpenGL.cpp - COMMITS = revCount; - DATE = date; - DIRTY = lib.optionalString (commit == "") "dirty"; - HASH = commit; + # Remove extra @PREFIX@ to fix pkg-config paths + sed -i "s#@PREFIX@/##g" hyprland.pc.in + ''; - depsBuildBuild = [ - pkg-config - ]; + COMMITS = revCount; + DATE = date; + DIRTY = lib.optionalString (commit == "") "dirty"; + HASH = commit; - nativeBuildInputs = [ - hyprwayland-scanner - jq - makeWrapper - meson - cmake - ninja - pkg-config - python3 # for udis86 - wayland-scanner - ]; + depsBuildBuild = [ + pkg-config + ]; - outputs = [ - "out" - "man" - "dev" - ]; + nativeBuildInputs = [ + hyprwayland-scanner + jq + makeWrapper + meson + cmake + ninja + pkg-config + python3 # for udis86 + wayland-scanner + ]; - buildInputs = lib.concatLists [ - [ - aquamarine - cairo - # expat - # fribidi - git - hyprcursor - hyprlang - hyprutils - # libdatrie - libdrm - libGL - libinput - # libselinux - # libsepol - # libthai - libuuid - libxkbcommon - mesa - pango - pciutils - # pcre2 - tomlplusplus - wayland - wayland-protocols - xorg.libXcursor - ] - (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) - (lib.optionals enableXWayland [ - xorg.libxcb - xorg.libXdmcp - xorg.xcbutilerrors - xorg.xcbutilrenderutil - xorg.xcbutilwm - xwayland - ]) - (lib.optionals withSystemd [systemd]) - ]; + outputs = [ + "out" + "man" + "dev" + ]; - mesonBuildType = - if debug - then "debug" - else "release"; - - # we want as much debug info as possible - dontStrip = debug; - - mesonFlags = [ - (lib.mesonEnable "xwayland" enableXWayland) - (lib.mesonEnable "legacy_renderer" legacyRenderer) - (lib.mesonEnable "systemd" withSystemd) - "-Db_pch=false" - ]; - - postInstall = '' - ${lib.optionalString wrapRuntimeDeps '' - wrapProgram $out/bin/Hyprland \ - --suffix PATH : ${lib.makeBinPath [ - binutils + buildInputs = lib.concatLists [ + [ + aquamarine + cairo + # expat + # fribidi + git + hyprcursor + hyprlang + hyprutils + # libdatrie + libdrm + libGL + libinput + # libselinux + # libsepol + # libthai + libuuid + libxkbcommon + mesa + pango pciutils - pkgconf - ]} - ''} - ''; + # pcre2 + tomlplusplus + wayland + wayland-protocols + xorg.libXcursor + ] + (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) + (lib.optionals enableXWayland [ + xorg.libxcb + xorg.libXdmcp + xorg.xcbutilerrors + xorg.xcbutilrenderutil + xorg.xcbutilwm + xwayland + ]) + (lib.optionals withSystemd [systemd]) + ]; - passthru.providedSessions = ["hyprland"]; + mesonBuildType = + if debug + then "debug" + else "release"; - meta = { - homepage = "https://github.com/hyprwm/Hyprland"; - description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; - license = lib.licenses.bsd3; - platforms = lib.platforms.linux; - mainProgram = "Hyprland"; - }; - } + # we want as much debug info as possible + dontStrip = debug; + + mesonFlags = [ + (lib.mesonEnable "xwayland" enableXWayland) + (lib.mesonEnable "legacy_renderer" legacyRenderer) + (lib.mesonEnable "systemd" withSystemd) + "-Db_pch=false" + ]; + + postInstall = '' + ${lib.optionalString wrapRuntimeDeps '' + wrapProgram $out/bin/Hyprland \ + --suffix PATH : ${lib.makeBinPath [ + binutils + pciutils + pkgconf + ]} + ''} + ''; + + passthru.providedSessions = ["hyprland"]; + + meta = { + homepage = "https://github.com/hyprwm/Hyprland"; + description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; + license = lib.licenses.bsd3; + platforms = lib.platforms.linux; + mainProgram = "Hyprland"; + }; + } From 9e98fb0167f8bc6c5eb4510a65b42aaa3b743421 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 20 Sep 2024 10:47:34 +0100 Subject: [PATCH 0045/1803] dmabuffer: attempt importing failed dmabufs as implicit don't ask me why, vulkan doesn't like this. funny note, broken on wlroots :P fixes #7037 --- src/protocols/types/DMABuffer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 63a26c76..a8c7248e 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -16,8 +16,15 @@ CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs auto eglImage = g_pHyprOpenGL->createEGLImage(attrs); - if (!eglImage) - return; + if (!eglImage) { + Debug::log(ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit"); + attrs.modifier = DRM_FORMAT_MOD_INVALID; + eglImage = g_pHyprOpenGL->createEGLImage(attrs); + if (!eglImage) { + Debug::log(ERR, "CDMABuffer: failed to import EGLImage"); + return; + } + } texture = makeShared(attrs, eglImage); // texture takes ownership of the eglImage opaque = FormatUtils::isFormatOpaque(attrs.format); From 4414cd07e257a57362e73d1f6efe1df692ae3762 Mon Sep 17 00:00:00 2001 From: Jasson Date: Fri, 20 Sep 2024 07:32:04 -0400 Subject: [PATCH 0046/1803] xwm: Minor cleanup, add wrappers for basic types (#7856) --- src/xwayland/XDataSource.cpp | 2 +- src/xwayland/XSurface.cpp | 13 ++++---- src/xwayland/XWM.cpp | 37 +++++++++------------ src/xwayland/XWM.hpp | 62 ++++++++++++++++++++++++++++++------ 4 files changed, 74 insertions(+), 40 deletions(-) diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index f4059ee1..c6495435 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -1,8 +1,8 @@ #ifndef NO_XWAYLAND -#include "XDataSource.hpp" #include "XWayland.hpp" #include "../defines.hpp" +#include "XDataSource.hpp" #include diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 02fe2b3b..e734c153 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -5,8 +5,8 @@ #ifndef NO_XWAYLAND -#include "../Compositor.hpp" #include +#include "../Compositor.hpp" CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) { xcb_res_query_client_ids_cookie_t client_id_cookie = {0}; @@ -196,12 +196,11 @@ void CXWaylandSurface::restackToTop() { xcb_configure_window(g_pXWayland->pWM->connection, xID, XCB_CONFIG_WINDOW_STACK_MODE, values); - for (auto it = g_pXWayland->pWM->mappedSurfacesStacking.begin(); it != g_pXWayland->pWM->mappedSurfacesStacking.end(); ++it) { - if (*it == self) { - std::rotate(it, it + 1, g_pXWayland->pWM->mappedSurfacesStacking.end()); - break; - } - } + auto& stack = g_pXWayland->pWM->mappedSurfacesStacking; + auto it = std::find(stack.begin(), stack.end(), self); + + if (it != stack.end()) + std::rotate(it, it + 1, stack.end()); g_pXWayland->pWM->updateClientList(); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index e8e2258a..dcb22eae 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1,20 +1,21 @@ #include "helpers/math/Math.hpp" +#include #ifndef NO_XWAYLAND +#include +#include +#include +#include +#include +#include + #include "XWayland.hpp" #include "../defines.hpp" -#include #include "../Compositor.hpp" +#include "../protocols/core/Seat.hpp" +#include "../managers/SeatManager.hpp" #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" -#include "../managers/SeatManager.hpp" -#include "../protocols/core/Seat.hpp" -#include -#include -#include -#include - -#include #define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f #define INCR_CHUNK_SIZE (64 * 1024) @@ -830,15 +831,15 @@ void CXWM::getRenderFormat() { free(reply); } -CXWM::CXWM() { - connection = xcb_connect_to_fd(g_pXWayland->pServer->xwmFDs[0], nullptr); +CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0]) { - if (int ret = xcb_connection_has_error(connection); ret) { - Debug::log(ERR, "[xwm] Couldn't start, error {}", ret); + if (connection.hasError()) { + Debug::log(ERR, "[xwm] Couldn't start, error {}", connection.hasError()); return; } - if (xcb_errors_context_new(connection, &errors)) { + CXCBErrorContext xcbErrCtx(connection); + if (!xcbErrCtx.isValid()) { Debug::log(ERR, "[xwm] Couldn't allocate errors context"); return; } @@ -867,10 +868,7 @@ CXWM::CXWM() { }; xcb_change_property(connection, XCB_PROP_MODE_REPLACE, screen->root, HYPRATOMS["_NET_SUPPORTED"], XCB_ATOM_ATOM, 32, sizeof(supported) / sizeof(*supported), supported); - xcb_flush(connection); - setActiveWindow(XCB_WINDOW_NONE); - initSelection(); listeners.newWLSurface = PROTO::compositor->events.newSurface.registerListener([this](std::any d) { onNewSurface(std::any_cast>(d)); }); @@ -882,11 +880,6 @@ CXWM::CXWM() { } CXWM::~CXWM() { - if (errors) - xcb_errors_context_free(errors); - - if (connection) - xcb_disconnect(connection); if (eventSource) wl_event_source_remove(eventSource); diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 59695720..ba00dd8d 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -1,17 +1,16 @@ #pragma once -#include "../helpers/signal/Signal.hpp" -#include "../helpers/memory/Memory.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" - #include "XDataSource.hpp" +#include "../helpers/WLListener.hpp" +#include "../helpers/memory/Memory.hpp" +#include "../helpers/signal/Signal.hpp" #include -#include -#include -#include #include +#include +#include +#include struct wl_event_source; class CXWaylandSurfaceResource; @@ -58,6 +57,49 @@ struct SXSelection { std::unique_ptr transfer; }; +class CXCBConnection { + public: + CXCBConnection(int fd) { + connection = xcb_connect_to_fd(fd, nullptr); + } + + ~CXCBConnection() { + if (connection) + xcb_disconnect(connection); + } + + bool hasError() const { + return xcb_connection_has_error(connection); + } + + operator xcb_connection_t*() const { + return connection; + } + + private: + xcb_connection_t* connection = nullptr; +}; + +class CXCBErrorContext { + public: + explicit CXCBErrorContext(xcb_connection_t* connection) { + if (xcb_errors_context_new(connection, &errors) != 0) + errors = nullptr; + } + + ~CXCBErrorContext() { + if (errors) + xcb_errors_context_free(errors); + } + + bool isValid() const { + return errors != nullptr; + } + + private: + xcb_errors_context_t* errors = nullptr; +}; + class CXWM { public: CXWM(); @@ -123,9 +165,9 @@ class CXWM { void readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply); // - xcb_connection_t* connection = nullptr; - xcb_errors_context_t* errors = nullptr; - xcb_screen_t* screen = nullptr; + CXCBConnection connection; + xcb_errors_context_t* errors = nullptr; + xcb_screen_t* screen = nullptr; xcb_window_t wmWindow; From 278583b8a1ab66272a4c437ed1acd7936a6a5c36 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 20 Sep 2024 20:16:13 +0300 Subject: [PATCH 0047/1803] flake.lock: update --- flake.lock | 24 +++++++++++++++--------- flake.nix | 2 ++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 35974921..608c5bbb 100644 --- a/flake.lock +++ b/flake.lock @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1721324119, - "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "lastModified": 1726840673, + "narHash": "sha256-HIPEXyRRVZoqD6U+lFS1B0tsIU7p83FaB9m7KT/x6mQ=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "rev": "b68dab23fc922eae99306988133ee80a40b39ca5", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725983898, - "narHash": "sha256-4b3A9zPpxAxLnkF9MawJNHDtOOl6ruL0r6Og1TEDGCE=", + "lastModified": 1726755586, + "narHash": "sha256-PmUr/2GQGvFTIJ6/Tvsins7Q43KTMvMFhvG6oaYK+Wk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1355a0cbfeac61d785b7183c0caaec1f97361b43", + "rev": "c04d5652cfa9742b1d519688f65d1bbccea9eb7e", "type": "github" }, "original": { @@ -201,6 +201,12 @@ "hyprlang": [ "hyprlang" ], + "hyprutils": [ + "hyprutils" + ], + "hyprwayland-scanner": [ + "hyprwayland-scanner" + ], "nixpkgs": [ "nixpkgs" ], @@ -209,11 +215,11 @@ ] }, "locked": { - "lastModified": 1726046979, - "narHash": "sha256-6SEsjurq9cdTkITA6d49ncAJe4O/8CgRG5/F//s6Xh8=", + "lastModified": 1726851729, + "narHash": "sha256-1z0esr5lBeUMlrPZ9gZmqZT8oTQekxJi53HAW4cH0Ms=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "e695669fd8e1d1be9eaae40f35e00f8bd8b64c18", + "rev": "73b8c4f1150040644cf678aa8bbf2cec48a433cf", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ef914627..ef48b2d1 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,8 @@ inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; inputs.hyprlang.follows = "hyprlang"; + inputs.hyprutils.follows = "hyprutils"; + inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; }; }; From db0b764a5ac22e752d8557cc1e1e5a42ac58c7e4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 20 Sep 2024 22:56:10 +0100 Subject: [PATCH 0048/1803] shm: send a static list of shm formats fixes #7733 --- src/protocols/core/Shm.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index b09326bd..a8c98bb0 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -193,11 +193,8 @@ void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, ui DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010, }; - for (auto const& fmt : g_pHyprOpenGL->getDRMFormats()) { - if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end()) - continue; - - shmFormats.push_back(fmt.drmFormat); + for (auto const& fmt : supportedShmFourccFormats) { + shmFormats.push_back(fmt); } } From 9232bc2c00a57b99ac876b43fdfedfa25c2de774 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Sep 2024 00:33:48 +0100 Subject: [PATCH 0049/1803] internal: move to hyprutils' scopeguard bumps hyprutils dep to 0.2.2 --- CMakeLists.txt | 2 +- flake.lock | 6 +++--- src/helpers/Monitor.cpp | 3 ++- src/helpers/ScopeGuard.cpp | 10 ---------- src/helpers/ScopeGuard.hpp | 13 ------------- src/render/Renderer.cpp | 4 +++- 6 files changed, 9 insertions(+), 29 deletions(-) delete mode 100644 src/helpers/ScopeGuard.cpp delete mode 100644 src/helpers/ScopeGuard.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b6ac8efc..e1718b2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ pkg_check_modules( gio-2.0 hyprlang>=0.3.2 hyprcursor>=0.1.7 - hyprutils>=0.2.1) + hyprutils>=0.2.2) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/flake.lock b/flake.lock index 608c5bbb..024bcf50 100644 --- a/flake.lock +++ b/flake.lock @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1724966483, - "narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=", + "lastModified": 1726874949, + "narHash": "sha256-PNnIpwGqpTvMU3N2r0wMQwK1E+t4Bb5fbJwblQvr+80=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2", + "rev": "d97af4f6bd068c03a518b597675e598f57ea2291", "type": "github" }, "original": { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 708a5cc8..223a3f94 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -2,7 +2,6 @@ #include "MiscFunctions.hpp" #include "math/Math.hpp" #include "sync/SyncReleaser.hpp" -#include "ScopeGuard.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/GammaControl.hpp" @@ -17,7 +16,9 @@ #include "sync/SyncTimeline.hpp" #include #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::Utils; int ratHandler(void* data) { g_pHyprRenderer->renderMonitor((CMonitor*)data); diff --git a/src/helpers/ScopeGuard.cpp b/src/helpers/ScopeGuard.cpp deleted file mode 100644 index 319255cd..00000000 --- a/src/helpers/ScopeGuard.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "ScopeGuard.hpp" - -CScopeGuard::CScopeGuard(const std::function& fn_) : fn(fn_) { - ; -} - -CScopeGuard::~CScopeGuard() { - if (fn) - fn(); -} diff --git a/src/helpers/ScopeGuard.hpp b/src/helpers/ScopeGuard.hpp deleted file mode 100644 index 8a1468eb..00000000 --- a/src/helpers/ScopeGuard.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -// calls a function when it goes out of scope -class CScopeGuard { - public: - CScopeGuard(const std::function& fn_); - ~CScopeGuard(); - - private: - std::function fn; -}; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 08bf76cb..417a3ff8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,7 +1,6 @@ #include "Renderer.hpp" #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" -#include "../helpers/ScopeGuard.hpp" #include "../helpers/sync/SyncReleaser.hpp" #include #include @@ -23,6 +22,9 @@ #include "../helpers/sync/SyncTimeline.hpp" #include "debug/Log.hpp" +#include +using namespace Hyprutils::Utils; + extern "C" { #include } From 8579066c7a1ceb745499ea4e11d5d420b1387ec0 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 21 Sep 2024 14:27:13 +0300 Subject: [PATCH 0050/1803] Nix: clean up derivation --- nix/default.nix | 58 +++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 3d621db6..40675d9a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -48,25 +48,32 @@ nvidiaPatches ? false, hidpiXWayland ? false, }: let - adapters = lib.flatten [ + inherit (builtins) baseNameOf foldl'; + inherit (lib.asserts) assertMsg; + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.lists) flatten concatLists optional optionals; + inherit (lib.sources) cleanSourceWith cleanSource; + inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable; + + adapters = flatten [ stdenvAdapters.useMoldLinker ]; - customStdenv = builtins.foldl' (acc: adapter: adapter acc) stdenv adapters; + customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters; in - assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; - assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; - assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; + assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; + assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; + assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; customStdenv.mkDerivation { - pname = "hyprland${lib.optionalString debug "-debug"}"; + pname = "hyprland${optionalString debug "-debug"}"; inherit version; - src = lib.cleanSourceWith { + src = cleanSourceWith { filter = name: type: let baseName = baseNameOf (toString name); in - ! (lib.hasSuffix ".nix" baseName); - src = lib.cleanSource ../.; + ! (hasSuffix ".nix" baseName); + src = cleanSource ../.; }; postPatch = '' @@ -79,7 +86,7 @@ in COMMITS = revCount; DATE = date; - DIRTY = lib.optionalString (commit == "") "dirty"; + DIRTY = optionalString (commit == "") "dirty"; HASH = commit; depsBuildBuild = [ @@ -104,36 +111,29 @@ in "dev" ]; - buildInputs = lib.concatLists [ + buildInputs = concatLists [ [ aquamarine cairo - # expat - # fribidi git hyprcursor hyprlang hyprutils - # libdatrie libdrm libGL libinput - # libselinux - # libsepol - # libthai libuuid libxkbcommon mesa pango pciutils - # pcre2 tomlplusplus wayland wayland-protocols xorg.libXcursor ] - (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) - (lib.optionals enableXWayland [ + (optionals customStdenv.hostPlatform.isMusl [libexecinfo]) + (optionals enableXWayland [ xorg.libxcb xorg.libXdmcp xorg.xcbutilerrors @@ -141,7 +141,7 @@ in xorg.xcbutilwm xwayland ]) - (lib.optionals withSystemd [systemd]) + (optional withSystemd systemd) ]; mesonBuildType = @@ -152,17 +152,19 @@ in # we want as much debug info as possible dontStrip = debug; - mesonFlags = [ - (lib.mesonEnable "xwayland" enableXWayland) - (lib.mesonEnable "legacy_renderer" legacyRenderer) - (lib.mesonEnable "systemd" withSystemd) - "-Db_pch=false" + mesonFlags = flatten [ + (mapAttrsToList mesonEnable { + "xwayland" = enableXWayland; + "legacy_renderer" = legacyRenderer; + "systemd" = withSystemd; + }) + (mesonBool "b_pch" false) ]; postInstall = '' - ${lib.optionalString wrapRuntimeDeps '' + ${optionalString wrapRuntimeDeps '' wrapProgram $out/bin/Hyprland \ - --suffix PATH : ${lib.makeBinPath [ + --suffix PATH : ${makeBinPath [ binutils pciutils pkgconf From e5ff19ac0f2c8d53a0c847d06a17676e636d6447 Mon Sep 17 00:00:00 2001 From: diniamo Date: Sat, 21 Sep 2024 16:52:11 +0200 Subject: [PATCH 0051/1803] flake: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 024bcf50..76351cc9 100644 --- a/flake.lock +++ b/flake.lock @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1726851729, - "narHash": "sha256-1z0esr5lBeUMlrPZ9gZmqZT8oTQekxJi53HAW4cH0Ms=", + "lastModified": 1726933538, + "narHash": "sha256-xTqnMoJsEojuvqJLuM+U7EZ7q71efaj3pbvjutq4TXc=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "73b8c4f1150040644cf678aa8bbf2cec48a433cf", + "rev": "4880c50146d0c2a3152d2b02f79253810c330c11", "type": "github" }, "original": { From 508bde1f61b1264c9621b937657088f09f318ce0 Mon Sep 17 00:00:00 2001 From: Artur Manuel Date: Mon, 23 Sep 2024 16:40:19 +0100 Subject: [PATCH 0052/1803] core: add HYPRLAND_CONFIG environment variable (#7851) --- src/config/ConfigManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 27e8fdb0..21a3a21e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -683,6 +683,10 @@ std::string CConfigManager::getMainConfigPath() { if (!g_pCompositor->explicitConfigPath.empty()) return g_pCompositor->explicitConfigPath; + if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV) + return CFG_ENV; + Debug::log(TRACE, "Seems as if HYPRLAND_CONFIG isn't set, let's see what we can do with HOME."); + static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); if (paths.first.has_value()) { return paths.first.value(); From f79497087bdea3ea2706606362ba99cfe7a956a0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 23 Sep 2024 17:59:35 +0100 Subject: [PATCH 0053/1803] internal: nuke wlsignal and related old semi-wrappers for wl_signal, they are no longer used --- src/defines.hpp | 1 - src/desktop/Subsurface.cpp | 8 +--- src/desktop/Subsurface.hpp | 4 -- src/devices/IKeyboard.hpp | 1 - src/devices/IPointer.hpp | 1 - src/devices/ITouch.hpp | 1 - src/devices/Tablet.hpp | 1 - src/helpers/WLListener.cpp | 62 ------------------------- src/helpers/WLListener.hpp | 39 ---------------- src/managers/SeatManager.hpp | 1 - src/managers/input/InputMethodPopup.hpp | 1 - src/managers/input/TextInput.hpp | 1 - src/protocols/FocusGrab.hpp | 3 -- src/protocols/PresentationTime.hpp | 2 - src/render/Renderbuffer.hpp | 1 - src/xwayland/XSurface.hpp | 1 - src/xwayland/XWM.hpp | 1 - 17 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 src/helpers/WLListener.cpp delete mode 100644 src/helpers/WLListener.hpp diff --git a/src/defines.hpp b/src/defines.hpp index 0b2c0e0c..41ee4502 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -1,6 +1,5 @@ #include "includes.hpp" #include "debug/Log.hpp" -#include "helpers/WLListener.hpp" #include "helpers/Color.hpp" #include "macros.hpp" #include "desktop/DesktopTypes.hpp" diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 64dd7cf5..893411bd 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -30,13 +30,7 @@ CSubsurface::CSubsurface(SP pSubsurface, CPopup* pOwner) } CSubsurface::~CSubsurface() { - hyprListener_newSubsurface.removeCallback(); - - if (!m_pSubsurface) - return; - - hyprListener_commitSubsurface.removeCallback(); - hyprListener_destroySubsurface.removeCallback(); + ; } void CSubsurface::initSignals() { diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index 101f4f19..7829c489 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -35,10 +35,6 @@ class CSubsurface { void recheckDamageForSubsurfaces(); private: - DYNLISTENER(destroySubsurface); - DYNLISTENER(commitSubsurface); - DYNLISTENER(newSubsurface); - struct { CHyprSignalListener destroySubsurface; CHyprSignalListener commitSubsurface; diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index ad8eaf7e..759b2f58 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index 760ec8dc..f38ef55a 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index cb8a6e90..bf969b2f 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 0efbe796..01901721 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp deleted file mode 100644 index 2ea5c0b6..00000000 --- a/src/helpers/WLListener.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "WLListener.hpp" -#include "MiscFunctions.hpp" -#include -#include "../debug/Log.hpp" -#include "Watchdog.hpp" - -void handleWrapped(wl_listener* listener, void* data) { - CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener); - - if (g_pWatchdog) - g_pWatchdog->startWatching(); - - try { - pWrap->m_pSelf->emit(data); - } catch (std::exception& e) { Debug::log(ERR, "Listener {} threw or timed out and was killed by Watchdog!!! This is bad. what(): {}", (uintptr_t)listener, e.what()); } - - if (g_pWatchdog) - g_pWatchdog->endWatching(); -} - -CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function const& callback, void* pOwner) { - initCallback(pSignal, callback, pOwner); -} - -CHyprWLListener::CHyprWLListener() { - m_swWrapper.m_pSelf = this; - m_swWrapper.m_sListener.notify = &handleWrapped; - wl_list_init(&m_swWrapper.m_sListener.link); -} - -CHyprWLListener::~CHyprWLListener() { - removeCallback(); -} - -void CHyprWLListener::removeCallback() { - if (isConnected()) { - Debug::log(LOG, "Callback {:x} -> {:x}, {} removed.", (uintptr_t)&m_pCallback, (uintptr_t)&m_pOwner, m_szAuthor); - wl_list_remove(&m_swWrapper.m_sListener.link); - wl_list_init(&m_swWrapper.m_sListener.link); - } -} - -bool CHyprWLListener::isConnected() { - return !wl_list_empty(&m_swWrapper.m_sListener.link); -} - -void CHyprWLListener::initCallback(wl_signal* pSignal, std::function const& callback, void* pOwner, std::string author) { - if (isConnected()) { - Debug::log(ERR, "Tried to connect a listener twice?!"); - return; - } - - m_pOwner = pOwner; - m_pCallback = callback; - m_szAuthor = author; - - addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor); -} - -void CHyprWLListener::emit(void* data) { - m_pCallback(m_pOwner, data); -} diff --git a/src/helpers/WLListener.hpp b/src/helpers/WLListener.hpp deleted file mode 100644 index 621458e6..00000000 --- a/src/helpers/WLListener.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include - -class CHyprWLListener { - public: - CHyprWLListener(wl_signal*, std::function const&, void* owner); - CHyprWLListener(); - ~CHyprWLListener(); - - CHyprWLListener(const CHyprWLListener&) = delete; - CHyprWLListener(CHyprWLListener&&) = delete; - CHyprWLListener& operator=(const CHyprWLListener&) = delete; - CHyprWLListener& operator=(CHyprWLListener&&) = delete; - - void initCallback(wl_signal*, std::function const&, void* owner, std::string author = ""); - - void removeCallback(); - - bool isConnected(); - - struct SWrapper { - wl_listener m_sListener; - CHyprWLListener* m_pSelf; - }; - - void emit(void*); - - private: - SWrapper m_swWrapper; - - void* m_pOwner = nullptr; - - std::function m_pCallback = nullptr; - - std::string m_szAuthor = ""; -}; \ No newline at end of file diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index 43ebe8b5..5cc7eee0 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -2,7 +2,6 @@ #include #include -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index f8e4b962..53c11cff 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../../helpers/WLListener.hpp" #include "../../desktop/WLSurface.hpp" #include "../../macros.hpp" #include "../../helpers/math/Math.hpp" diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index f920adc7..3cf07006 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../../helpers/WLListener.hpp" #include "../../macros.hpp" #include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" diff --git a/src/protocols/FocusGrab.hpp b/src/protocols/FocusGrab.hpp index a2d545c5..6fe8780f 100644 --- a/src/protocols/FocusGrab.hpp +++ b/src/protocols/FocusGrab.hpp @@ -53,9 +53,6 @@ class CFocusGrab { bool m_bGrabActive = false; - DYNLISTENER(pointerGrabStarted); - DYNLISTENER(keyboardGrabStarted); - DYNLISTENER(touchGrabStarted); friend class CFocusGrabSurfaceState; }; diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 06c71c9a..421bb838 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -27,8 +27,6 @@ class CQueuedPresentationData { WP pMonitor; WP surface; - DYNLISTENER(destroySurface); - friend class CPresentationFeedback; friend class CPresentationProtocol; }; diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index e6bfa909..ff06bd5a 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -2,7 +2,6 @@ #include "../helpers/signal/Signal.hpp" #include "../helpers/memory/Memory.hpp" -#include "../helpers/WLListener.hpp" #include "Framebuffer.hpp" #include diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 61eee984..7584354e 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../helpers/WLListener.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index ba00dd8d..37c61416 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -2,7 +2,6 @@ #include "../macros.hpp" #include "XDataSource.hpp" -#include "../helpers/WLListener.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/signal/Signal.hpp" From 6c78b03bb7810e074d21d5c41f088bd317c28906 Mon Sep 17 00:00:00 2001 From: diniamo Date: Mon, 23 Sep 2024 18:52:30 +0200 Subject: [PATCH 0054/1803] flake: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 76351cc9..68bb0ed2 100644 --- a/flake.lock +++ b/flake.lock @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1726933538, - "narHash": "sha256-xTqnMoJsEojuvqJLuM+U7EZ7q71efaj3pbvjutq4TXc=", + "lastModified": 1727109343, + "narHash": "sha256-1PFckA8Im7wMSl26okwOKqBZeCFLD3LvZZFaxswDhbY=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "4880c50146d0c2a3152d2b02f79253810c330c11", + "rev": "4adb6c4c41ee5014bfe608123bfeddb26e5f5cea", "type": "github" }, "original": { From d279d7c4c6fe27c1944d8e9b51c4730612c8a9ae Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Sep 2024 00:49:29 +0100 Subject: [PATCH 0055/1803] eventloop: dispatch pending in session on start fixes #7855 #7391 --- src/managers/eventLoop/EventLoopManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index e9b0fa3e..081268c3 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -50,6 +50,10 @@ void CEventLoopManager::enterLoop() { m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); } + // if we have a session, dispatch it to get the pending input devices + if (g_pCompositor->m_pAqBackend->hasSession()) + g_pCompositor->m_pAqBackend->session->dispatchPendingEventsAsync(); + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); From 0a211f29f5952322925b9f982cbf9b0326d45f0f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Sep 2024 01:19:05 +0100 Subject: [PATCH 0056/1803] hyprctl: add defaultName to workspacerules fixes #7886 --- src/debug/HyprCtl.cpp | 67 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 9faefe26..4de9143d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -320,45 +320,48 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputFormat format) { const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; }; if (format == eHyprCtlOutputFormat::FORMAT_JSON) { - const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor)); - const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : ""; - const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : ""; - const std::string gapsIn = (bool)(r.gapsIn) ? - std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) : + const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor)); + const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : ""; + const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : ""; + const std::string gapsIn = (bool)(r.gapsIn) ? + std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) : + ""; + const std::string gapsOut = (bool)(r.gapsOut) ? + std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) : ""; - const std::string gapsOut = (bool)(r.gapsOut) ? - std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) : - ""; - const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; - const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : ""; - const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : ""; - const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : ""; - const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : ""; + const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; + const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : ""; + const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : ""; + const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : ""; + const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : ""; + const std::string defaultName = r.defaultName.has_value() ? std::format(",\n \"defaultName\": \"{}\"", escapeJSONStrings(r.defaultName.value())) : ""; - std::string result = std::format(R"#({{ - "workspaceString": "{}"{}{}{}{}{}{}{}{} + std::string result = + std::format(R"#({{ + "workspaceString": "{}"{}{}{}{}{}{}{}{}{}{}{} }})#", - escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); + escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow, defaultName); return result; } else { - const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "" : escapeJSONStrings(r.monitor)); - const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : ""); - const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : ""); - const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right), - std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) : - std::format("\tgapsIn: \n"); - const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right), - std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) : - std::format("\tgapsOut: \n"); - const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); - const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : ""); - const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : ""); - const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : ""); - const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : ""); + const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "" : escapeJSONStrings(r.monitor)); + const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : ""); + const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : ""); + const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right), + std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) : + std::format("\tgapsIn: \n"); + const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right), + std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) : + std::format("\tgapsOut: \n"); + const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); + const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : ""); + const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : ""); + const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : ""); + const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : ""); + const std::string defaultName = std::format("\tdefaultName: {}\n", r.defaultName.value_or("")); - std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, - borderSize, border, rounding, decorate, shadow); + std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, + borderSize, border, rounding, decorate, shadow, defaultName); return result; } From 00c862686354d139a53222d41a1c80d698a50c43 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 24 Sep 2024 11:25:05 +0100 Subject: [PATCH 0057/1803] hyprctl: add submap request fixes #7898 --- src/debug/HyprCtl.cpp | 9 +++++++++ src/managers/KeybindManager.cpp | 4 ++++ src/managers/KeybindManager.hpp | 1 + 3 files changed, 14 insertions(+) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 4de9143d..87e071d7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1627,6 +1627,14 @@ std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) { return json; } +std::string submapRequest(eHyprCtlOutputFormat format, std::string request) { + std::string submap = g_pKeybindManager->getCurrentSubmap(); + if (submap.empty()) + submap = "default"; + + return format == FORMAT_JSON ? std::format("{{\"{}\"}}\n", escapeJSONStrings(submap)) : (submap + "\n"); +} + CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest}); registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest}); @@ -1648,6 +1656,7 @@ CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest}); registerCommand(SHyprCtlCommand{"locked", true, getIsLocked}); registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions}); + registerCommand(SHyprCtlCommand{"submap", true, submapRequest}); registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest}); registerCommand(SHyprCtlCommand{"reload", false, reloadRequest}); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index dd35bc19..02e2f5e7 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -594,6 +594,10 @@ eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) { return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys); } +std::string CKeybindManager::getCurrentSubmap() { + return m_szCurrentSelectedSubmap; +} + SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) { static auto PDISABLEINHIBIT = CConfigValue("binds:disable_keybind_grabbing"); bool found = false; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 096cd4f9..c81ca86f 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -96,6 +96,7 @@ class CKeybindManager { uint32_t keycodeToModifier(xkb_keycode_t); void clearKeybinds(); void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0); + std::string getCurrentSubmap(); std::unordered_map> m_mDispatchers; From 8f5188269b7d58a90c569fd150435b4330dff7df Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 25 Sep 2024 09:59:18 +0100 Subject: [PATCH 0058/1803] hyprctl: add solitary field to hyprctl monitors --- src/debug/HyprCtl.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 87e071d7..178e9ba8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -103,6 +103,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer "focused": {}, "dpmsStatus": {}, "vrr": {}, + "solitary": "{:x}", "activelyTearing": {}, "disabled": {}, "currentFormat": "{}", @@ -114,19 +115,20 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(), escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), - (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), - (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(), + (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), + availableModesForOutput(m.get(), format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\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->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing, - !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(), + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); } return result; From 2320b2241c0713b8d81e8f467cb99bd4179ad23b Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 25 Sep 2024 10:01:13 +0100 Subject: [PATCH 0059/1803] Internal: move to Mat3x3 from hyprutils (#7902) * Meson: require hyprutils >= 0.2.3 * flake.lock: update hyprutils --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- flake.lock | 6 +- src/helpers/MiscFunctions.cpp | 21 ----- src/helpers/MiscFunctions.hpp | 1 - src/helpers/Monitor.cpp | 9 +-- src/helpers/Monitor.hpp | 2 +- src/helpers/math/Math.cpp | 120 ---------------------------- src/helpers/math/Math.hpp | 10 +-- src/meson.build | 2 +- src/render/OpenGL.cpp | 142 ++++++++++++++-------------------- src/render/OpenGL.hpp | 46 +++++------ 11 files changed, 93 insertions(+), 268 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1718b2d..8055271e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ pkg_check_modules( gio-2.0 hyprlang>=0.3.2 hyprcursor>=0.1.7 - hyprutils>=0.2.2) + hyprutils>=0.2.3) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/flake.lock b/flake.lock index 68bb0ed2..a1f0d88d 100644 --- a/flake.lock +++ b/flake.lock @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1726874949, - "narHash": "sha256-PNnIpwGqpTvMU3N2r0wMQwK1E+t4Bb5fbJwblQvr+80=", + "lastModified": 1727219120, + "narHash": "sha256-wmT+JpnDk6EjgASU2VGfS0nnu6oKA4Cw25o5fzpDD/Q=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "d97af4f6bd068c03a518b597675e598f57ea2291", + "rev": "db956287d3aa194dda91d05c8eb286de2a569edf", "type": "github" }, "original": { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index b9970399..20c79a2b 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -628,27 +628,6 @@ void logSystemInfo() { Debug::log(NONE, "{}", execAndGet("cat /etc/os-release")); } -void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) { - memset(mat, 0, sizeof(*mat) * 9); - - const float* t = transforms[tr]; - float x = 2.0f / w; - float y = 2.0f / h; - - // Rotation + reflection - mat[0] = x * t[0]; - mat[1] = x * t[1]; - mat[3] = y * t[3]; - mat[4] = y * t[4]; - - // Translation - mat[2] = -copysign(1.0f, mat[0] + mat[1]); - mat[5] = -copysign(1.0f, mat[3] + mat[4]); - - // Identity - mat[8] = 1.0f; -} - int64_t getPPIDof(int64_t pid) { #if defined(KERN_PROC_PID) int mib[] = { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 8b2ea0d1..f696fc5d 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -34,7 +34,6 @@ 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); std::vector getBacktrace(); void throwError(const std::string& err); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 223a3f94..a2d4c504 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -772,12 +772,9 @@ Vector2D CMonitor::middle() { } void CMonitor::updateMatrix() { - matrixIdentity(projMatrix.data()); - if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { - matrixTranslate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); - matrixTransform(projMatrix.data(), wlTransformToHyprutils(transform)); - matrixTranslate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); - } + projMatrix = Mat3x3::identity(); + if (transform != WL_OUTPUT_TRANSFORM_NORMAL) + projMatrix.translate(vecPixelSize / 2.0).transform(wlTransformToHyprutils(transform)).translate(-vecTransformedSize / 2.0); } WORKSPACEID CMonitor::activeWorkspaceID() { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 203cac90..97d9f8ab 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -96,7 +96,7 @@ class CMonitor { bool scheduledRecalc = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; float xwaylandScale = 1.f; - std::array projMatrix = {0}; + Mat3x3 projMatrix; std::optional forceSize; SP currentMode; SP cursorSwapchain; diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index fccfd636..d111690e 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -1,6 +1,4 @@ #include "Math.hpp" -#include -#include Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { switch (t) { @@ -17,124 +15,6 @@ Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; } -void matrixIdentity(float mat[9]) { - static const float identity[9] = { - 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - }; - memcpy(mat, identity, sizeof(identity)); -} - -void matrixMultiply(float mat[9], const float a[9], const float b[9]) { - float product[9]; - - product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; - product[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7]; - product[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8]; - - product[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6]; - product[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7]; - product[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8]; - - product[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6]; - product[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7]; - product[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8]; - - memcpy(mat, product, sizeof(product)); -} - -void matrixTranspose(float mat[9], const float a[9]) { - float transposition[9] = { - a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], - }; - memcpy(mat, transposition, sizeof(transposition)); -} - -void matrixTranslate(float mat[9], float x, float y) { - float translate[9] = { - 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, translate); -} - -void matrixScale(float mat[9], float x, float y) { - float scale[9] = { - x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, scale); -} - -void matrixRotate(float mat[9], float rad) { - float rotate[9] = { - cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, rotate); -} - -const std::unordered_map>& getTransforms() { - static std::unordered_map> transforms = { - {HYPRUTILS_TRANSFORM_NORMAL, {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_90, {0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_180, {-1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_270, {0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED, {-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED_90, {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED_180, {1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED_270, {0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - }; - return transforms; -} - -void matrixTransform(float mat[9], eTransform transform) { - matrixMultiply(mat, mat, getTransforms().at(transform).data()); -} - -void matrixProjection(float mat[9], int width, int height, eTransform transform) { - memset(mat, 0, sizeof(*mat) * 9); - - const float* t = getTransforms().at(transform).data(); - float x = 2.0f / width; - float y = 2.0f / height; - - // Rotation + reflection - mat[0] = x * t[0]; - mat[1] = x * t[1]; - mat[3] = y * -t[3]; - mat[4] = y * -t[4]; - - // Translation - mat[2] = -copysign(1.0f, mat[0] + mat[1]); - mat[5] = -copysign(1.0f, mat[3] + mat[4]); - - // Identity - mat[8] = 1.0f; -} - -void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]) { - double x = box.x; - double y = box.y; - double width = box.width; - double height = box.height; - - matrixIdentity(mat); - matrixTranslate(mat, x, y); - - if (rotation != 0) { - matrixTranslate(mat, width / 2, height / 2); - matrixRotate(mat, rotation); - matrixTranslate(mat, -width / 2, -height / 2); - } - - matrixScale(mat, width, height); - - if (transform != HYPRUTILS_TRANSFORM_NORMAL) { - matrixTranslate(mat, 0.5, 0.5); - matrixTransform(mat, transform); - matrixTranslate(mat, -0.5, -0.5); - } - - matrixMultiply(mat, projection, mat); -} - wl_output_transform invertTransform(wl_output_transform tr) { if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) tr = (wl_output_transform)(tr ^ (int)WL_OUTPUT_TRANSFORM_180); diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp index f57cef93..9b73a20f 100644 --- a/src/helpers/math/Math.hpp +++ b/src/helpers/math/Math.hpp @@ -4,17 +4,9 @@ // includes box and vector as well #include +#include using namespace Hyprutils::Math; eTransform wlTransformToHyprutils(wl_output_transform t); -void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); -void matrixProjection(float mat[9], int width, int height, eTransform transform); -void matrixTransform(float mat[9], eTransform transform); -void matrixRotate(float mat[9], float rad); -void matrixScale(float mat[9], float x, float y); -void matrixTranslate(float mat[9], float x, float y); -void matrixTranspose(float mat[9], const float a[9]); -void matrixMultiply(float mat[9], const float a[9], const float b[9]); -void matrixIdentity(float mat[9]); wl_output_transform invertTransform(wl_output_transform tr); diff --git a/src/meson.build b/src/meson.build index 928cd5a7..da46c38c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -16,7 +16,7 @@ executable( dependency('cairo'), dependency('hyprcursor', version: '>=0.1.7'), dependency('hyprlang', version: '>= 0.3.2'), - dependency('hyprutils', version: '>= 0.2.1'), + dependency('hyprutils', version: '>= 0.2.3'), dependency('libdrm'), dependency('egl'), dependency('xkbcommon'), diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 74d3d3cd..ff3d52e4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -755,14 +755,12 @@ void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP< glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); + m_RenderData.projection = Mat3x3::outputProjection(pMonitor->vecPixelSize, HYPRUTILS_TRANSFORM_NORMAL); - matrixIdentity(m_RenderData.monitorProjection.data()); + m_RenderData.monitorProjection = Mat3x3::identity(); if (pMonitor->transform != WL_OUTPUT_TRANSFORM_NORMAL) { const Vector2D tfmd = pMonitor->transform % 2 == 1 ? Vector2D{FBO->m_vSize.y, FBO->m_vSize.x} : FBO->m_vSize; - matrixTranslate(m_RenderData.monitorProjection.data(), FBO->m_vSize.x / 2.0, FBO->m_vSize.y / 2.0); - matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(pMonitor->transform)); - matrixTranslate(m_RenderData.monitorProjection.data(), -tfmd.x / 2.0, -tfmd.y / 2.0); + m_RenderData.monitorProjection.translate(FBO->m_vSize / 2.0).transform(wlTransformToHyprutils(pMonitor->transform)).translate(-tfmd / 2.0); } m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor]; @@ -809,7 +807,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); + m_RenderData.projection = Mat3x3::outputProjection(pMonitor->vecPixelSize, HYPRUTILS_TRANSFORM_NORMAL); m_RenderData.monitorProjection = pMonitor->projMatrix; @@ -1289,20 +1287,17 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; - float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif // premultiply the color as well as we don't work with straight alpha @@ -1386,11 +1381,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB if (m_bEndFrame || TRANSFORMS_MATCH) TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); - float matrix[9]; - projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Debug::log(LOG, "internal:\nmat: {},\nglmat: {}", matrix.toString(), glMatrix.toString()); if (waitTimeline != nullptr) { if (!waitForTimelinePoint(waitTimeline, waitPoint)) { @@ -1442,10 +1436,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glUseProgram(shader->program); #ifndef GLES2 - glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1i(shader->tex, 0); @@ -1556,13 +1550,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { // get transform const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); - float matrix[9]; - projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); - - CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA; + CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA; glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_iTarget, tex->m_iTexID); @@ -1570,10 +1561,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { glUseProgram(shader->program); #ifndef GLES2 - glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1i(shader->tex, 0); @@ -1610,21 +1601,18 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf // get transform const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); - float matrix[9]; - projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); - - CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; + CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; glUseProgram(shader->program); #ifndef GLES2 - glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1i(shader->tex, 0); glUniform1i(shader->alphaMatte, 1); @@ -1667,13 +1655,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glDisable(GL_STENCIL_TEST); // get transforms for the full monitor - const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); - float matrix[9]; + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - projectBox(matrix, MONITORBOX, TRANSFORM, 0, m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(MONITORBOX, TRANSFORM); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); // get the config settings static auto PBLURSIZE = CConfigValue("decoration:blur:size"); @@ -1710,10 +1695,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS); @@ -1755,10 +1740,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // prep two shaders #ifndef GLES2 - glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) { @@ -1832,10 +1817,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE); glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS); @@ -2165,12 +2150,9 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; - float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); const auto BLEND = m_bBlend; blend(true); @@ -2178,10 +2160,10 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail @@ -2471,22 +2453,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; - float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); glEnable(GL_BLEND); glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); @@ -2565,11 +2544,11 @@ void CHyprOpenGLImpl::renderMirrored() { return; // replace monitor projection to undo the mirrored monitor's projection - matrixIdentity(m_RenderData.monitorProjection.data()); - matrixTranslate(m_RenderData.monitorProjection.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); - matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(monitor->transform)); - matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(invertTransform(mirrored->transform))); - matrixTranslate(m_RenderData.monitorProjection.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); + m_RenderData.monitorProjection = Mat3x3::identity() + .translate(monitor->vecPixelSize / 2.0) + .transform(wlTransformToHyprutils(monitor->transform)) + .transform(wlTransformToHyprutils(invertTransform(mirrored->transform))) + .translate(-monitor->vecTransformedSize / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); @@ -2920,16 +2899,15 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { } void CHyprOpenGLImpl::saveMatrix() { - memcpy(m_RenderData.savedProjection, m_RenderData.projection, 9 * sizeof(float)); + m_RenderData.savedProjection = m_RenderData.projection; } void CHyprOpenGLImpl::setMatrixScaleTranslate(const Vector2D& translate, const float& scale) { - matrixScale(m_RenderData.projection, scale, scale); - matrixTranslate(m_RenderData.projection, translate.x, translate.y); + m_RenderData.projection.scale(scale).translate(translate); } void CHyprOpenGLImpl::restoreMatrix() { - memcpy(m_RenderData.projection, m_RenderData.savedProjection, 9 * sizeof(float)); + m_RenderData.projection = m_RenderData.savedProjection; } void CHyprOpenGLImpl::bindOffMain() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 06078a00..0d1c267b 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -94,35 +94,35 @@ struct SMonitorRenderData { }; struct SCurrentRenderData { - CMonitor* pMonitor = nullptr; - PHLWORKSPACE pWorkspace = nullptr; - float projection[9]; - float savedProjection[9]; - std::array monitorProjection; + CMonitor* pMonitor = nullptr; + PHLWORKSPACE pWorkspace = nullptr; + Mat3x3 projection; + Mat3x3 savedProjection; + Mat3x3 monitorProjection; - SMonitorRenderData* pCurrentMonData = nullptr; - CFramebuffer* currentFB = nullptr; // current rendering to - CFramebuffer* mainFB = nullptr; // main to render to - CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc) + SMonitorRenderData* pCurrentMonData = nullptr; + CFramebuffer* currentFB = nullptr; // current rendering to + CFramebuffer* mainFB = nullptr; // main to render to + CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc) - CRegion damage; - CRegion finalDamage; // damage used for funal off -> main + CRegion damage; + CRegion finalDamage; // damage used for funal off -> main - SRenderModifData renderModif; - float mouseZoomFactor = 1.f; - bool mouseZoomUseMouse = true; // true by default - bool useNearestNeighbor = false; - bool forceIntrospection = false; // cleaned in ::end() - bool blockScreenShader = false; - bool simplePass = false; + SRenderModifData renderModif; + float mouseZoomFactor = 1.f; + bool mouseZoomUseMouse = true; // true by default + bool useNearestNeighbor = false; + bool forceIntrospection = false; // cleaned in ::end() + bool blockScreenShader = false; + bool simplePass = false; - Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); - Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); + Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); + Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); - CBox clipBox = {}; // scaled coordinates + CBox clipBox = {}; // scaled coordinates - uint32_t discardMode = DISCARD_OPAQUE; - float discardOpacity = 0.f; + uint32_t discardMode = DISCARD_OPAQUE; + float discardOpacity = 0.f; }; class CEGLSync { From 2a052c69f36a71fb473262f57039b8ac81518ad3 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 25 Sep 2024 10:36:43 +0100 Subject: [PATCH 0060/1803] core: add a --systeminfo parameter to gather systeminfo without running --- src/debug/HyprCtl.cpp | 11 +++++++---- src/debug/HyprCtl.hpp | 3 +++ src/main.cpp | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 178e9ba8..0229a803 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -943,11 +943,14 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; result += "plugins:\n"; - for (auto const& pl : g_pPluginSystem->getAllPlugins()) { - result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); - } + if (g_pPluginSystem) { + for (auto const& pl : g_pPluginSystem->getAllPlugins()) { + result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); + } + } else + result += "\tunknown: not runtime\n"; - if (g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) { + if (g_pHyprCtl && g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) { result += "\n======Config-Start======\n"; result += g_pConfigManager->getConfigString(); result += "\n======Config-End========\n"; diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index cbacd7cb..d68bf14f 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -5,6 +5,9 @@ #include "../helpers/MiscFunctions.hpp" #include +// exposed for main.cpp +std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request); + class CHyprCtl { public: CHyprCtl(); diff --git a/src/main.cpp b/src/main.cpp index ba6fe505..279e1ce1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "Compositor.hpp" #include "config/ConfigManager.hpp" #include "init/initHelpers.hpp" +#include "debug/HyprCtl.hpp" #include using namespace Hyprutils::String; @@ -133,6 +134,10 @@ int main(int argc, char** argv) { std::cout << result; return 0; + } else if (it->compare("--systeminfo") == 0) { + const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""); + std::cout << SYSINFO << "\n"; + return 0; } else { std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; help(); From 8b86ee8bf08eaf8b57d0a7f12af876216323cc3d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 25 Sep 2024 10:37:58 +0100 Subject: [PATCH 0061/1803] github: encourage usage of --systeminfo if Hyprland won't launch --- .github/ISSUE_TEMPLATE/bug.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 7d402904..ce6d9d3e 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -29,10 +29,10 @@ body: attributes: label: System Info and Version description: | - Paste the output of `hyprctl systeminfo -c` here (If you are on a - version that shows you help menu, omit the `-c` and attach config files - to the issue). If you have configs outside of the main config shown - here, please attach. + Paste the output of `hyprctl systeminfo -c` here. If you can't + launch Hyprland, paste the output of `Hyprland --systeminfo`. + If `Hyprland --systeminfo` errors out (added in 0.44.0), find + and paste the Hyprland version manually. value: "
System/Version info From 49713fab045f7bd41466ddedd83ad5cb81142853 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Sep 2024 23:15:36 +0100 Subject: [PATCH 0062/1803] pointermgr: avoid hogging CMonitor refs --- src/managers/PointerManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 3dcee431..736b629c 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -17,10 +17,8 @@ CPointerManager::CPointerManager() { onMonitorLayoutChange(); - PMONITOR->events.modeChanged.registerStaticListener( - [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); - PMONITOR->events.disconnect.registerStaticListener( - [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( [this](void* owner, std::any data) { if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) From 22746b304614b313a78d740f4536e809a4df90e2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Sep 2024 23:38:11 +0100 Subject: [PATCH 0063/1803] hyprctl: use the getMonitorData helper everywhere --- src/debug/HyprCtl.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 0229a803..d9274727 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -160,16 +160,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { if (!m->output || m->ID == -1) continue; - result += std::format( - "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" - "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: A {} H {}\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->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), - m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, - (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), - (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), m->tearingState.activelyTearing, !m->m_bEnabled, - formatToString(m->output->state->state().drmFormat), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + result += CHyprCtl::getMonitorData(m, format); } } From b1ad2d806634edff656cb5ddc9850ae2c73324e8 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Thu, 26 Sep 2024 04:08:50 +0500 Subject: [PATCH 0064/1803] dispatchers: fixup dpms toggle (#7875) now toggles every monitor individually --- src/managers/KeybindManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 02e2f5e7..48c4517a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2403,9 +2403,7 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { bool enable = arg.starts_with("on"); std::string port = ""; - if (arg.starts_with("toggle")) - enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off - + bool isToggle = arg.starts_with("toggle"); if (arg.find_first_of(' ') != std::string::npos) port = arg.substr(arg.find_first_of(' ') + 1); @@ -2414,6 +2412,9 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { if (!port.empty() && m->szName != port) continue; + if (isToggle) + enable = !m->dpmsStatus; + m->output->state->resetExplicitFences(); m->output->state->setEnabled(enable); From caaa9b11e4763ed0367f81bf97ceaad5175806fc Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:10:53 +0100 Subject: [PATCH 0065/1803] wlr-output-configuration: Improve output configuration (#7571) --- src/config/ConfigManager.cpp | 66 ++++++++++++++--- src/config/ConfigManager.hpp | 2 +- src/helpers/Monitor.cpp | 4 +- src/managers/KeybindManager.cpp | 2 +- src/protocols/OutputManagement.cpp | 115 +++++++++++++++++++---------- src/protocols/OutputManagement.hpp | 69 +++++++++++------ 6 files changed, 181 insertions(+), 77 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 21a3a21e..ab5905c2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -7,6 +7,7 @@ #include "helpers/varlist/VarList.hpp" #include "../protocols/LayerShell.hpp" #include "../xwayland/XWayland.hpp" +#include "../protocols/OutputManagement.hpp" #include #include @@ -1079,28 +1080,69 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s return VAL; } -SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { +SMonitorRule CConfigManager::getMonitorRuleFor(const SP PMONITOR) { + auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule { + const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR); + + if (!CONFIG) + return rule; + + Debug::log(LOG, "CConfigManager::getMonitorRuleFor: found a wlr_output_manager override for {}", PMONITOR->szName); + + Debug::log(LOG, " > overriding enabled: {} -> {}", !rule.disabled, !CONFIG->enabled); + rule.disabled = !CONFIG->enabled; + + if ((CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_MODE) || (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE)) { + Debug::log(LOG, " > overriding mode: {:.0f}x{:.0f}@{:.2f}Hz -> {:.0f}x{:.0f}@{:.2f}Hz", rule.resolution.x, rule.resolution.y, rule.refreshRate, CONFIG->resolution.x, + CONFIG->resolution.y, CONFIG->refresh / 1000.F); + rule.resolution = CONFIG->resolution; + rule.refreshRate = CONFIG->refresh / 1000.F; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) { + Debug::log(LOG, " > overriding offset: {:.0f}, {:.0f} -> {:.0f}, {:.0f}", rule.offset.x, rule.offset.y, CONFIG->position.x, CONFIG->position.y); + rule.offset = CONFIG->position; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) { + Debug::log(LOG, " > overriding transform: {} -> {}", (uint8_t)rule.transform, (uint8_t)CONFIG->transform); + rule.transform = CONFIG->transform; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) { + Debug::log(LOG, " > overriding scale: {} -> {}", (uint8_t)rule.scale, (uint8_t)CONFIG->scale); + rule.scale = CONFIG->scale; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) { + Debug::log(LOG, " > overriding vrr: {} -> {}", rule.vrr.value_or(0), CONFIG->adaptiveSync); + rule.vrr = (int)CONFIG->adaptiveSync; + } + + return rule; + }; + for (auto const& r : m_dMonitorRules | std::views::reverse) { - if (PMONITOR.matchesStaticSelector(r.name)) { - return r; + if (PMONITOR->matchesStaticSelector(r.name)) { + return applyWlrOutputConfig(r); } } - Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName); + Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR->szName); for (auto const& r : m_dMonitorRules) { if (r.name.empty()) { - return r; + return applyWlrOutputConfig(r); } } Debug::log(WARN, "No rules configured. Using the default hardcoded one."); - return SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT, - .name = "", - .resolution = Vector2D(0, 0), - .offset = Vector2D(-INT32_MAX, -INT32_MAX), - .scale = -1}; // 0, 0 is preferred and -1, -1 is auto + return applyWlrOutputConfig(SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT, + .name = "", + .resolution = Vector2D(0, 0), + .offset = Vector2D(-INT32_MAX, -INT32_MAX), + .scale = -1}); // 0, 0 is preferred and -1, -1 is auto } SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) { @@ -1459,7 +1501,7 @@ void CConfigManager::performMonitorReload() { if (!m->output || m->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(*m); + auto rule = getMonitorRuleFor(m); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) { overAgain = true; @@ -1516,7 +1558,7 @@ void CConfigManager::ensureMonitorStatus() { if (!rm->output || rm->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(*rm); + auto rule = getMonitorRuleFor(rm); if (rule.disabled == rm->m_bEnabled) g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index da450e39..2134acf4 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -169,7 +169,7 @@ class CConfigManager { static std::string getMainConfigPath(); const std::string getConfigString(); - SMonitorRule getMonitorRuleFor(const CMonitor&); + SMonitorRule getMonitorRuleFor(const SP); SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a2d4c504..a9569699 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -114,7 +114,7 @@ void CMonitor::onConnect(bool noRule) { createdByUser = true; // should be true. WL and Headless backends should be addable / removable // get monitor rule that matches - SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this); + SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(self.lock()); // if it's disabled, disable and ignore if (monitorRule.disabled) { @@ -489,7 +489,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { pMirrorOf = nullptr; // set rule - const auto RULE = g_pConfigManager->getMonitorRuleFor(*this); + const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock()); vecPosition = RULE.offset; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 48c4517a..cd47bf71 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1943,7 +1943,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) { if (!m->output) continue; - auto rule = g_pConfigManager->getMonitorRuleFor(*m); + auto rule = g_pConfigManager->getMonitorRuleFor(m); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) { overAgain = true; break; diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 09552b19..dcc7a62d 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -307,10 +307,15 @@ COutputConfiguration::COutputConfiguration(SP resour LOGM(LOG, "disableHead on {}", PMONITOR->szName); - PMONITOR->activeMonitorRule.disabled = true; - if (!g_pConfigManager->replaceMonitorRule(PMONITOR->activeMonitorRule)) - g_pConfigManager->appendMonitorRule(PMONITOR->activeMonitorRule); - g_pHyprRenderer->applyMonitorRule(PMONITOR, &PMONITOR->activeMonitorRule, false); + SWlrManagerSavedOutputState newState; + if (owner->monitorStates.contains(PMONITOR->szName)) + newState = owner->monitorStates.at(PMONITOR->szName); + + newState.enabled = false; + + g_pConfigManager->m_bWantsMonitorReload = true; + + owner->monitorStates[PMONITOR->szName] = newState; }); resource->setTest([this](CZwlrOutputConfigurationV1* r) { @@ -346,6 +351,11 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { LOGM(LOG, "Applying configuration"); + if (!owner) { + LOGM(ERR, "applyTestConfiguration: no owner?!"); + return false; + } + for (auto const& headw : heads) { auto head = headw.lock(); @@ -357,41 +367,59 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { if (!PMONITOR) continue; - LOGM(LOG, "Applying config for monitor {}", PMONITOR->szName); + LOGM(LOG, "Saving config for monitor {}", PMONITOR->szName); - SMonitorRule newRule = PMONITOR->activeMonitorRule; - newRule.name = PMONITOR->szName; - newRule.disabled = false; + SWlrManagerSavedOutputState newState; + if (owner->monitorStates.contains(PMONITOR->szName)) + newState = owner->monitorStates.at(PMONITOR->szName); - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) { - newRule.resolution = head->state.mode->getMode()->pixelSize; - newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F; - } else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) { - newRule.resolution = head->state.customMode.size; - newRule.refreshRate = head->state.customMode.refresh / 1000.F; + newState.enabled = true; + + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) { + newState.resolution = head->state.mode->getMode()->pixelSize; + newState.refresh = head->state.mode->getMode()->refreshRate; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE; + LOGM(LOG, " > Mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh); + } else if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) { + newState.resolution = head->state.customMode.size; + newState.refresh = head->state.customMode.refresh; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE; + LOGM(LOG, " > Custom mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh); } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION) - newRule.offset = head->state.position; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION) { + newState.position = head->state.position; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION; + LOGM(LOG, " > Position: {:.0f}, {:.0f}", head->state.position.x, head->state.position.y); + } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) - newRule.vrr = head->state.adaptiveSync; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) { + newState.adaptiveSync = head->state.adaptiveSync; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC; + LOGM(LOG, " > vrr: {}", newState.adaptiveSync); + } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE) - newRule.scale = head->state.scale; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE) { + newState.scale = head->state.scale; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE; + LOGM(LOG, " > scale: {:.2f}", newState.scale); + } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM) - newRule.transform = head->state.transform; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM) { + newState.transform = head->state.transform; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM; + LOGM(LOG, " > transform: {}", (uint8_t)newState.transform); + } // reset properties for next set. - head->committedProperties = 0; + head->state.committedProperties = 0; - if (!g_pConfigManager->replaceMonitorRule(newRule)) - g_pConfigManager->appendMonitorRule(newRule); g_pConfigManager->m_bWantsMonitorReload = true; + + owner->monitorStates[PMONITOR->szName] = newState; } - LOGM(LOG, "Applied configuration"); + LOGM(LOG, "Saved configuration"); return true; } @@ -417,12 +445,12 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } - committedProperties |= OUTPUT_HEAD_COMMITTED_MODE; + state.committedProperties |= OUTPUT_HEAD_COMMITTED_MODE; state.mode = MODE; LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate); @@ -434,7 +462,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -444,7 +472,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, w, h, refresh); @@ -456,12 +484,12 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } - committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION; + state.committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION; state.position = {x, y}; LOGM(LOG, " | configHead for {}: set pos to {}, {}", pMonitor->szName, x, y); @@ -473,7 +501,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -483,7 +511,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, transform); @@ -495,7 +523,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -507,7 +535,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, scale); @@ -519,7 +547,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -529,7 +557,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, as); @@ -601,3 +629,14 @@ SP COutputManagementProtocol::modeFromResource(wl_resource* r) { return nullptr; } + +SP COutputManagementProtocol::getOutputStateFor(SP pMonitor) { + for (auto const& m : m_vManagers) { + if (!m->monitorStates.contains(pMonitor->szName)) + continue; + + return makeShared(m->monitorStates.at(pMonitor->szName)); + } + + return nullptr; +} diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index 36478d0b..f4a84475 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "WaylandProtocol.hpp" #include "wlr-output-management-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" @@ -13,6 +14,43 @@ class CMonitor; class COutputHead; class COutputMode; +struct SMonitorRule; + +enum eWlrOutputCommittedProperties : uint32_t { + OUTPUT_HEAD_COMMITTED_MODE = (1 << 0), + OUTPUT_HEAD_COMMITTED_CUSTOM_MODE = (1 << 1), + OUTPUT_HEAD_COMMITTED_POSITION = (1 << 2), + OUTPUT_HEAD_COMMITTED_TRANSFORM = (1 << 3), + OUTPUT_HEAD_COMMITTED_SCALE = (1 << 4), + OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC = (1 << 5), +}; + +struct SWlrManagerOutputState { + uint32_t committedProperties = 0; + + WP mode; + struct { + Vector2D size; + uint32_t refresh = 0; + } customMode; + Vector2D position; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + float scale = 1.F; + bool adaptiveSync = false; + bool enabled = true; +}; + +struct SWlrManagerSavedOutputState { + uint32_t committedProperties = 0; + Vector2D resolution; + uint32_t refresh = 0; + Vector2D position; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + float scale = 1.F; + bool adaptiveSync = false; + bool enabled = true; +}; + class COutputManager { public: COutputManager(SP resource_); @@ -21,6 +59,9 @@ class COutputManager { void ensureMonitorSent(CMonitor* pMonitor); void sendDone(); + // holds the states for this manager. + std::unordered_map monitorStates; + private: SP resource; bool stopped = false; @@ -80,30 +121,9 @@ class COutputConfigurationHead { public: COutputConfigurationHead(SP resource_, CMonitor* pMonitor_); - bool good(); + bool good(); - enum eCommittedProperties : uint32_t { - OUTPUT_HEAD_COMMITTED_MODE = (1 << 0), - OUTPUT_HEAD_COMMITTED_CUSTOM_MODE = (1 << 1), - OUTPUT_HEAD_COMMITTED_POSITION = (1 << 2), - OUTPUT_HEAD_COMMITTED_TRANSFORM = (1 << 3), - OUTPUT_HEAD_COMMITTED_SCALE = (1 << 4), - OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC = (1 << 5), - }; - - uint32_t committedProperties = 0; - - struct { - WP mode; - struct { - Vector2D size; - uint32_t refresh = 0; - } customMode; - Vector2D position; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - float scale = 1.F; - bool adaptiveSync = false; - } state; + SWlrManagerOutputState state; private: SP resource; @@ -136,6 +156,9 @@ class COutputManagementProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + // doesn't have to return one + SP getOutputStateFor(SP pMonitor); + private: void destroyResource(COutputManager* resource); void destroyResource(COutputHead* resource); From 32a8caf7e7a0609629eb08c91de9f9b23a10c455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 6 Jun 2024 10:07:53 +0200 Subject: [PATCH 0066/1803] Nix: also test cross build --- flake.nix | 10 ++++++++++ nix/default.nix | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index ef48b2d1..eca45675 100644 --- a/flake.nix +++ b/flake.nix @@ -67,6 +67,15 @@ hyprland-extras ]; }); + pkgsCrossFor = eachSystem (system: crossSystem: + import nixpkgs { + localSystem = system; + crossSystem = crossSystem; + overlays = with self.overlays; [ + hyprland-packages + hyprland-extras + ]; + }); in { overlays = import ./nix/overlays.nix {inherit self lib inputs;}; @@ -92,6 +101,7 @@ xdg-desktop-portal-hyprland ; + hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland; }); devShells = eachSystem (system: { diff --git a/nix/default.nix b/nix/default.nix index 40675d9a..be7394e4 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -102,7 +102,6 @@ in ninja pkg-config python3 # for udis86 - wayland-scanner ]; outputs = [ @@ -130,6 +129,7 @@ in tomlplusplus wayland wayland-protocols + wayland-scanner xorg.libXcursor ] (optionals customStdenv.hostPlatform.isMusl [libexecinfo]) From 7b56ce6521e5ad3b0a2dab6f79a045e79c7aeb82 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 11 Jun 2024 18:49:12 +0300 Subject: [PATCH 0067/1803] CI/Nix: add cross build --- .github/workflows/nix-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 50823629..6351216f 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -12,6 +12,7 @@ jobs: matrix: package: - hyprland + - hyprland-cross - xdg-desktop-portal-hyprland runs-on: ubuntu-latest From 77f2a01304f33a2dc7c9002ca9fb20a7653e6ae1 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 26 Sep 2024 16:52:02 +0300 Subject: [PATCH 0068/1803] flake.lock: update nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index a1f0d88d..4ebdc734 100644 --- a/flake.lock +++ b/flake.lock @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726755586, - "narHash": "sha256-PmUr/2GQGvFTIJ6/Tvsins7Q43KTMvMFhvG6oaYK+Wk=", + "lastModified": 1727122398, + "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c04d5652cfa9742b1d519688f65d1bbccea9eb7e", + "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093", "type": "github" }, "original": { From 14942bca60cc7d85e8238a151bd444112601ebe6 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 21:19:09 +0300 Subject: [PATCH 0069/1803] Nix: re-add hyprland-protocols --- flake.lock | 26 +++++++++++++++++++++++++- flake.nix | 6 ++++++ nix/default.nix | 2 ++ nix/overlays.nix | 1 + 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 4ebdc734..7e0f093e 100644 --- a/flake.lock +++ b/flake.lock @@ -56,6 +56,29 @@ } }, "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1721326555, + "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprland-protocols_2": { "inputs": { "nixpkgs": [ "xdph", @@ -172,6 +195,7 @@ "inputs": { "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", + "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", @@ -197,7 +221,7 @@ }, "xdph": { "inputs": { - "hyprland-protocols": "hyprland-protocols", + "hyprland-protocols": "hyprland-protocols_2", "hyprlang": [ "hyprlang" ], diff --git a/flake.nix b/flake.nix index eca45675..ee5af6a1 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,12 @@ inputs.hyprlang.follows = "hyprlang"; }; + hyprland-protocols = { + url = "github:hyprwm/hyprland-protocols"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + }; + hyprlang = { url = "github:hyprwm/hyprlang"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/default.nix b/nix/default.nix index be7394e4..85a3105d 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -13,6 +13,7 @@ cairo, git, hyprcursor, + hyprland-protocols, hyprlang, hyprutils, hyprwayland-scanner, @@ -116,6 +117,7 @@ in cairo git hyprcursor + hyprland-protocols hyprlang hyprutils libdrm diff --git a/nix/overlays.nix b/nix/overlays.nix index d6e078fa..71b5f59f 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -22,6 +22,7 @@ in { # Dependencies inputs.aquamarine.overlays.default inputs.hyprcursor.overlays.default + inputs.hyprland-protocols.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default From 27211c71e92e1bacf111d8a815e958f80969ce6e Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 21:20:35 +0300 Subject: [PATCH 0070/1803] Meson: try to find udis86 through pkgconfig, fallback to subproject Only the fork provides a .pc file, so there's no risk of linking the wrong lib version. If pkg-config can't find it (most cases), fall back to using the subproject through the wrap file. --- meson.build | 4 ---- nix/default.nix | 8 ++------ nix/overlays.nix | 17 +++++++++++++++++ src/meson.build | 6 +++++- subprojects/udis86.wrap | 5 +++++ 5 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 subprojects/udis86.wrap diff --git a/meson.build b/meson.build index 9449c241..42ed519d 100644 --- a/meson.build +++ b/meson.build @@ -43,10 +43,6 @@ xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) gio_dep = dependency('gio-2.0', required: true) -cmake = import('cmake') -udis = cmake.subproject('udis86') -udis86 = udis.dependency('libudis86') - if not xcb_dep.found() add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif diff --git a/nix/default.nix b/nix/default.nix index 85a3105d..df270f28 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -6,7 +6,6 @@ pkgconf, makeWrapper, meson, - cmake, ninja, aquamarine, binutils, @@ -17,7 +16,6 @@ hyprlang, hyprutils, hyprwayland-scanner, - jq, libGL, libdrm, libexecinfo, @@ -27,9 +25,9 @@ mesa, pango, pciutils, - python3, systemd, tomlplusplus, + udis86-hyprland, wayland, wayland-protocols, wayland-scanner, @@ -96,13 +94,10 @@ in nativeBuildInputs = [ hyprwayland-scanner - jq makeWrapper meson - cmake ninja pkg-config - python3 # for udis86 ]; outputs = [ @@ -129,6 +124,7 @@ in pango pciutils tomlplusplus + udis86-hyprland wayland wayland-protocols wayland-scanner diff --git a/nix/overlays.nix b/nix/overlays.nix index 71b5f59f..2b2788e7 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -26,6 +26,7 @@ in { inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default + self.overlays.udis86 # Hyprland packages themselves (final: prev: let @@ -64,4 +65,20 @@ in { hyprland-extras = lib.composeManyExtensions [ inputs.xdph.overlays.xdg-desktop-portal-hyprland ]; + + # udis86 from nixpkgs is too old, and also does not provide a .pc file + # this version is the one used in the git submodule, and allows us to + # fetch the source without '?submodules=1' + udis86 = final: prev: { + udis86-hyprland = prev.udis86.overrideAttrs (self: super: { + src = final.fetchFromGitHub { + owner = "canihavesomecoffee"; + repo = "udis86"; + rev = "5336633af70f3917760a6d441ff02d93477b0c86"; + hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g="; + }; + + patches = []; + }); + }; } diff --git a/src/meson.build b/src/meson.build index da46c38c..7c71a735 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,7 +31,11 @@ executable( backtrace_dep, epoll_dep, gio_dep, - udis86, + + # Try to find canihavesomecoffee's udis86 using pkgconfig + # vmt/udis86 does not provide a .pc file and won't be detected this way + # Falls back to using the subproject through udis86.wrap + dependency('udis86'), dependency('pixman-1'), dependency('gl', 'opengl'), diff --git a/subprojects/udis86.wrap b/subprojects/udis86.wrap new file mode 100644 index 00000000..dfb63984 --- /dev/null +++ b/subprojects/udis86.wrap @@ -0,0 +1,5 @@ +[wrap-file] +method = cmake + +[provide] +udis86 = libudis86_dep From 89d945aabe632387f113ac500bfee573d51cc4f7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 18:00:02 +0300 Subject: [PATCH 0071/1803] CMake: use hyprland-protocols from pkg-config, fallback to subproject protocolnew: fix external path, which may not be in $CMAKE_SOURCE_DIR --- CMakeLists.txt | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8055271e..08eb93cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,7 +230,7 @@ add_custom_target(generate-protocol-headers) function(protocolnew protoPath protoName external) if(external) - set(path ${CMAKE_SOURCE_DIR}/${protoPath}) + set(path ${protoPath}) else() set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) endif() @@ -261,11 +261,20 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads libudis86) -protocolnew("subprojects/hyprland-protocols/protocols" - "hyprland-global-shortcuts-v1" true) +pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0) +if(hyprland_protocols_dep_FOUND) + pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) + message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") +else() + set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols") + message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}") +endif() + +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1" + true) protocolnew("unstable/text-input" "text-input-unstable-v1" false) -protocolnew("subprojects/hyprland-protocols/protocols" - "hyprland-toplevel-export-v1" true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1" + true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) @@ -276,8 +285,7 @@ protocolnew("protocols" "input-method-unstable-v2" true) protocolnew("protocols" "wlr-output-management-unstable-v1" true) protocolnew("protocols" "kde-server-decoration" true) protocolnew("protocols" "wlr-data-control-unstable-v1" true) -protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1" - true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) protocolnew("protocols" "wayland-drm" true) protocolnew("staging/tearing-control" "tearing-control-v1" false) From be96787ed086f751455cf713739296b5c6e3a235 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 18:01:44 +0300 Subject: [PATCH 0072/1803] CMake: use udis86 from pkg-config, fallback to subproject Only canihavesomecoffee's fork (the one the subproject uses) provides a .pc file, so we either find the correct version or we use the subproject. --- CMakeLists.txt | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08eb93cf..8115d01c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,18 @@ message(STATUS "Gathering git info") execute_process(COMMAND ./scripts/generateVersion.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -# udis -add_subdirectory("subprojects/udis86") +find_package(PkgConfig REQUIRED) + +# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not +# provide a .pc file and won't be detected this way +pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2) + +# Fallback to subproject +if(NOT udis_dep_FOUND) + add_subdirectory("subprojects/udis86") + include_directories("subprojects/udis86") + message(STATUS "udis86 dependency not found, falling back to subproject") +endif() if(CMAKE_BUILD_TYPE) string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) @@ -47,8 +57,6 @@ else() set(BUILDTYPE_LOWER "release") endif() -find_package(PkgConfig REQUIRED) - pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir) @@ -63,7 +71,8 @@ else() message(STATUS "Configuring Hyprland in Release with CMake") endif() -include_directories(. "src/" "subprojects/udis86/" "protocols/") +include_directories(. "src/" "protocols/") + set(CMAKE_CXX_STANDARD 26) add_compile_options( -Wall @@ -224,6 +233,11 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps) +if(udis_dep_FOUND) + target_link_libraries(Hyprland PkgConfig::udis_dep) +else() + target_link_libraries(Hyprland libudis86) +endif() # used by `make installheaders`, to ensure the headers are generated add_custom_target(generate-protocol-headers) @@ -258,8 +272,7 @@ function(protocolWayland) PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp) endfunction() -target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads - libudis86) +target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0) if(hyprland_protocols_dep_FOUND) From f75f8efb1be227e586cc0ba2ce6153ce56e04314 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 20:53:34 +0300 Subject: [PATCH 0073/1803] Meson: add tracy dependency --- meson.build | 6 ++++++ meson_options.txt | 1 + nix/default.nix | 7 +++++-- src/meson.build | 1 + subprojects/tracy.wrap | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 subprojects/tracy.wrap diff --git a/meson.build b/meson.build index 42ed519d..3545f46a 100644 --- a/meson.build +++ b/meson.build @@ -73,6 +73,12 @@ foreach file : headers install_headers(file, subdir: 'hyprland', preserve_path: true) endforeach +tracy = dependency('tracy', static: true, required: get_option('tracy_enable')) + +if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized' + warning('Profiling builds should set -- buildtype = debugoptimized') +endif + subdir('protocols') subdir('src') subdir('hyprctl') diff --git a/meson_options.txt b/meson_options.txt index 16a34a54..d8c9d5e6 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,3 +1,4 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer') +option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') diff --git a/nix/default.nix b/nix/default.nix index df270f28..6f086ccc 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -144,7 +144,7 @@ in mesonBuildType = if debug - then "debug" + then "debugoptimized" else "release"; # we want as much debug info as possible @@ -156,7 +156,10 @@ in "legacy_renderer" = legacyRenderer; "systemd" = withSystemd; }) - (mesonBool "b_pch" false) + (mapAttrsToList mesonBool { + "b_pch" = false; + "tracy_enable" = false; + }) ]; postInstall = '' diff --git a/src/meson.build b/src/meson.build index 7c71a735..2dbe2f44 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,6 +31,7 @@ executable( backtrace_dep, epoll_dep, gio_dep, + tracy, # Try to find canihavesomecoffee's udis86 using pkgconfig # vmt/udis86 does not provide a .pc file and won't be detected this way diff --git a/subprojects/tracy.wrap b/subprojects/tracy.wrap new file mode 100644 index 00000000..11b21787 --- /dev/null +++ b/subprojects/tracy.wrap @@ -0,0 +1 @@ +[wrap-file] From b2143a98e2719012f8c36211a066f8ebccc950b8 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 26 Sep 2024 23:00:20 +0300 Subject: [PATCH 0074/1803] CI/Nix: no longer build with submodules --- .github/workflows/nix-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 6351216f..73adb497 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -25,4 +25,4 @@ jobs: name: hyprland authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}&submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" + - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" From e20aef7d53fcde1470e8d7672e6a03d814fca97f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 26 Sep 2024 22:34:33 +0100 Subject: [PATCH 0075/1803] opengl: remove debug log --- src/render/OpenGL.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ff3d52e4..4f22d6aa 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1384,8 +1384,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - Debug::log(LOG, "internal:\nmat: {},\nglmat: {}", matrix.toString(), glMatrix.toString()); - if (waitTimeline != nullptr) { if (!waitForTimelinePoint(waitTimeline, waitPoint)) { Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint); From 58669fef77ac17ea205ce3570f48e17de736111f Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 27 Sep 2024 18:35:29 +0300 Subject: [PATCH 0076/1803] flake.lock: update --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 7e0f093e..5adaa350 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1726665257, - "narHash": "sha256-rEzEZtd3iyVo5RJ1OGujOlnywNf3gsrOnjAn1NLciD4=", + "lastModified": 1727261104, + "narHash": "sha256-rxDI7WrxIRV9it9mDCHcLa7xQykf1JloXnoXr5xQ8zI=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "752d0fbd141fabb5a1e7f865199b80e6e76f8d8e", + "rev": "b82fdaff917582a9d568969e15e61b398c71e990", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1721326555, - "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", + "lastModified": 1727451107, + "narHash": "sha256-qV9savtHwmZUa0eJE294WYJjKPGB2+bJhwByFShsVyo=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", + "rev": "6b3261ee13a6d2b99de79a31d352f6996e35bde3", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1727219120, - "narHash": "sha256-wmT+JpnDk6EjgASU2VGfS0nnu6oKA4Cw25o5fzpDD/Q=", + "lastModified": 1727300645, + "narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "db956287d3aa194dda91d05c8eb286de2a569edf", + "rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c", "type": "github" }, "original": { @@ -162,11 +162,11 @@ ] }, "locked": { - "lastModified": 1726840673, - "narHash": "sha256-HIPEXyRRVZoqD6U+lFS1B0tsIU7p83FaB9m7KT/x6mQ=", + "lastModified": 1726874836, + "narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "b68dab23fc922eae99306988133ee80a40b39ca5", + "rev": "500c81a9e1a76760371049a8d99e008ea77aa59e", "type": "github" }, "original": { From 2cf6e7862a844ad96aa060d63f6774df7e2234a6 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 27 Sep 2024 20:49:40 -0400 Subject: [PATCH 0077/1803] dwindle: add config option `split_bias` (#7920) If `default_split_ratio` is greater than 1.0, `split_bias` will give the bigger half to a specific window: 0 - positional (default) 1 - current window 2 - opening window --- src/config/ConfigManager.cpp | 1 + src/layout/DwindleLayout.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ab5905c2..ad6e1871 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -446,6 +446,7 @@ CConfigManager::CConfigManager() { 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:split_bias", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:smart_split", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:smart_resizing", Hyprlang::INT{1}); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c936d59c..69b044b4 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -1,7 +1,7 @@ #include "DwindleLayout.hpp" -#include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" +#include "../render/decorations/CHyprGroupBarDecoration.hpp" void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { if (children[0]) { @@ -459,6 +459,12 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir } } + // split in favor of a specific window + const auto first = NEWPARENT->children[0]; + static auto PSPLITBIAS = CConfigValue("dwindle:split_bias"); + if ((*PSPLITBIAS == 1 && first == PNODE) || (*PSPLITBIAS == 2 && first == OPENINGON)) + NEWPARENT->splitRatio = 2.f - NEWPARENT->splitRatio; + // and update the previous parent if it exists if (OPENINGON->pParent) { if (OPENINGON->pParent->children[0] == OPENINGON) { From 6f313de952311282e82461a342c74ea702d9f13a Mon Sep 17 00:00:00 2001 From: bivsk <141476105+bivsk@users.noreply.github.com> Date: Sat, 28 Sep 2024 08:46:31 -0400 Subject: [PATCH 0078/1803] core: Fix Musl builds (#7934) Musl does not include the internal type `__time_t`. Use `time_t` instead. --- src/protocols/PresentationTime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index e1ff52cd..71f74cd5 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -58,8 +58,8 @@ void CPresentationFeedback::sendQueued(SP data, timespe if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; - __time_t tv_sec = 0; - if (sizeof(__time_t) > 4) + time_t tv_sec = 0; + if (sizeof(time_t) > 4) tv_sec = when->tv_sec >> 32; if (data->wasPresented) From d73c14751ad40fd54d93baac2226f550142b0e74 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 28 Sep 2024 21:53:08 +0300 Subject: [PATCH 0079/1803] CI/Nix: git+https -> github --- .github/workflows/nix-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 73adb497..d1f47ee4 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -25,4 +25,4 @@ jobs: name: hyprland authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" + - run: nix build 'github:hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" From 9e418671e12549156d0735a6b23732f66d5647c7 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Sun, 29 Sep 2024 09:42:10 -0400 Subject: [PATCH 0080/1803] config: add descriptions for dwindle and master layout options (#7933) --- src/config/ConfigDescriptions.hpp | 160 ++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 84ac1a41..3a91a808 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1372,4 +1372,164 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + + /* + * dwindle: + */ + + SConfigOptionDescription{ + .value = "dwindle:pseudotile", + .description = "enable pseudotiling. Pseudotiled windows retain their floating size when tiled.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:force_split", + .description = "0 -> split follows mouse, 1 -> always split to the left (new = left or top) 2 -> always split to the right (new = right or bottom)", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "follow mouse,left or top,right or bottom"}, + }, + SConfigOptionDescription{ + .value = "dwindle:preserve_split", + .description = "if enabled, the split (side/top) will not change regardless of what happens to the container.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:smart_split", + .description = "if enabled, allows a more precise control over the window split direction based on the cursor's position. The window is conceptually divided into four " + "triangles, and cursor's triangle determines the split direction. This feature also turns on preserve_split.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:smart_resizing", + .description = + "if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "dwindle:permanent_direction_override", + .description = "if enabled, makes the preselect direction persist until either this mode is turned off, another direction is specified, or a non-direction is specified " + "(anything other than l,r,u/t,d/b)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:special_scale_factor", + .description = "specifies the scale factor of windows on the special workspace [0 - 1]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "dwindle:split_width_multiplier", + .description = "specifies the auto-split width multiplier", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0.1, 3}, + }, + SConfigOptionDescription{ + .value = "dwindle:no_gaps_when_only", + .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, + }, + SConfigOptionDescription{ + .value = "dwindle:use_active_for_splits", + .description = "whether to prefer the active window or the mouse position for splits", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "dwindle:default_split_ratio", + .description = "the default split ratio on window open. 1 means even 50/50 split. [0.1 - 1.9]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0.1, 1.9}, + }, + SConfigOptionDescription{ + .value = "dwindle:split_bias", + .description = "specifies which window will receive the larger half of a split. positional - 0, current window - 1, opening window - 2 [0/1/2]", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "positional,current,opening"}, + }, + + /* + * master: + */ + + SConfigOptionDescription{ + .value = "master:allow_small_split", + .description = "enable adding additional master windows in a horizontal split style", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "master:special_scale_factor", + .description = "the scale of the special workspace windows. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "master:mfact", + .description = + "the size as a percentage of the master window, for example `mfact = 0.70` would mean 70% of the screen will be the master window, and 30% the slave [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.55, 0, 1}, + }, + SConfigOptionDescription{ + .value = "master:new_status", + .description = "`master`: new window becomes master; `slave`: new windows are added to slave stack; `inherit`: inherit from focused window", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"slave"}, + }, + SConfigOptionDescription{ + .value = "master:new_on_top", + .description = "whether a newly open window should be on the top of the stack", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "master:new_on_active", + .description = "`before`, `after`: place new window relative to the focused window; `none`: place new window according to the value of `new_on_top`. ", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"none"}, + }, + SConfigOptionDescription{ + .value = "master:no_gaps_when_only", + .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, + }, + SConfigOptionDescription{ + .value = "master:orientation", + .description = "default placement of the master area, can be left, right, top, bottom or center", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"left"}, + }, + SConfigOptionDescription{ + .value = "master:inherit_fullscreen", + .description = "inherit fullscreen status when cycling/swapping to another window (e.g. monocle layout)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "master:always_center_master", + .description = "when using orientation=center, keep the master window centered, even when it is the only window in the workspace.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "master:smart_resizing", + .description = + "if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "master:drop_at_cursor", + .description = "when enabled, dragging and dropping windows will put them at the cursor position. Otherwise, when dropped at the stack side, they will go to the " + "top/bottom of the stack depending on new_on_top.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, }; From 4b00cba319dc44294567d06df7c378cf5e4e5338 Mon Sep 17 00:00:00 2001 From: Luke Chen <3363954+LukeXuan@users.noreply.github.com> Date: Sun, 29 Sep 2024 09:47:59 -0400 Subject: [PATCH 0081/1803] dwindle: add movetoroot method to layout messages (#7903) --- src/layout/DwindleLayout.cpp | 42 ++++++++++++++++++++++++++++++++++++ src/layout/DwindleLayout.hpp | 1 + 2 files changed, 43 insertions(+) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 69b044b4..ed47fa44 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -998,6 +998,10 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str toggleSplit(header.pWindow); } else if (ARGS[0] == "swapsplit") { swapSplit(header.pWindow); + } else if (ARGS[0] == "movetoroot") { + const auto WINDOW = ARGS[1].empty() ? header.pWindow : g_pCompositor->getWindowByRegex(ARGS[1]); + const auto STABLE = ARGS[2].empty() || ARGS[2] != "unstable"; + moveToRoot(WINDOW, STABLE); } else if (ARGS[0] == "preselect") { std::string direction = ARGS[1]; @@ -1065,6 +1069,44 @@ void CHyprDwindleLayout::swapSplit(PHLWINDOW pWindow) { PNODE->pParent->recalcSizePosRecursive(); } +// goal: maximize the chosen window within current dwindle layout +// impl: swap the selected window with the other sub-tree below root +void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) { + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE || !PNODE->pParent) + return; + + if (pWindow->isFullscreen()) + return; + + // already at root + if (!PNODE->pParent->pParent) + return; + + auto& pNode = PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[0] : PNODE->pParent->children[1]; + + // instead of [getMasterNodeOnWorkspace], we walk back to root since we need + // to know which children of root is our ancestor + auto pAncestor = PNODE, pRoot = PNODE->pParent; + while (pRoot->pParent) { + pAncestor = pRoot; + pRoot = pRoot->pParent; + } + + auto& pSwap = pRoot->children[0] == pAncestor ? pRoot->children[1] : pRoot->children[0]; + std::swap(pNode, pSwap); + std::swap(pNode->pParent, pSwap->pParent); + + // [stable] in that the focused window occupies same side of screen + if (stable) + std::swap(pRoot->children[0], pRoot->children[1]); + + // if the workspace is visible, recalculate layout + if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + pRoot->recalcSizePosRecursive(); +} + void CHyprDwindleLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) { const auto PNODE = getNodeFromWindow(from); diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index bbd511c2..953ba3a2 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -87,6 +87,7 @@ class CHyprDwindleLayout : public IHyprLayout { void toggleSplit(PHLWINDOW); void swapSplit(PHLWINDOW); + void moveToRoot(PHLWINDOW, bool stable = true); eDirection overrideDirection = DIRECTION_DEFAULT; From 6649255d54f45a7e2fedd9b4be85fe5d11229c04 Mon Sep 17 00:00:00 2001 From: Gliczy <129636582+Gliczy@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:45:19 +0200 Subject: [PATCH 0082/1803] flake.lock: update --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 5adaa350..2579dd11 100644 --- a/flake.lock +++ b/flake.lock @@ -42,11 +42,11 @@ ] }, "locked": { - "lastModified": 1722623071, - "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=", + "lastModified": 1727532803, + "narHash": "sha256-ZaZ7h7PY8mQc4vtGmVqWLAq9CAO02gHMyNR5yY8zDmM=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "912d56025f03d41b1ad29510c423757b4379eb1c", + "rev": "b98726e431d4d3ed58bd58bee1047cdb81cec69f", "type": "github" }, "original": { @@ -177,11 +177,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1727122398, - "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=", + "lastModified": 1727348695, + "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093", + "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1727109343, - "narHash": "sha256-1PFckA8Im7wMSl26okwOKqBZeCFLD3LvZZFaxswDhbY=", + "lastModified": 1727524473, + "narHash": "sha256-1DGktDtSWIJpnDbVoj/qpvJSH5zg6JbOfuh6xqZMap0=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "4adb6c4c41ee5014bfe608123bfeddb26e5f5cea", + "rev": "7e500e679ede40e79cf2d89b5f5fa3e34923bd26", "type": "github" }, "original": { From 488efab63654a643d76df4997cd932d6fddd8faf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 00:57:51 +0100 Subject: [PATCH 0083/1803] single-pixel-buffer: new protocol impl fixes #6624 --- CMakeLists.txt | 1 + src/helpers/Color.hpp | 3 +- src/managers/ProtocolManager.cpp | 2 + src/protocols/SinglePixel.cpp | 125 +++++++++++++++++++++++++++++++ src/protocols/SinglePixel.hpp | 79 +++++++++++++++++++ 5 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 src/protocols/SinglePixel.cpp create mode 100644 src/protocols/SinglePixel.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8115d01c..ee9cd2e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) +protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) protocolwayland() diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 8abfe748..32ed39ee 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -8,8 +8,9 @@ class CColor { CColor(float r, float g, float b, float a); CColor(uint64_t); - float r = 0, g = 0, b = 0, a = 1.f; + float r = 0, g = 0, b = 0, a = 1.f; + // AR32 uint32_t getAsHex() const; CColor operator-(const CColor& c2) const { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6b6d5acf..8bcc857a 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -44,6 +44,7 @@ #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/XDGDialog.hpp" +#include "../protocols/SinglePixel.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -152,6 +153,7 @@ CProtocolManager::CProtocolManager() { PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); + PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp new file mode 100644 index 00000000..7dd3748f --- /dev/null +++ b/src/protocols/SinglePixel.cpp @@ -0,0 +1,125 @@ +#include "SinglePixel.hpp" +#include + +CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { + LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); + + color = col_.getAsHex(); + + g_pHyprRenderer->makeEGLCurrent(); + + opaque = col_.a >= 1.F; + + texture = makeShared(DRM_FORMAT_ARGB8888, (uint8_t*)&color, 4, Vector2D{1, 1}); + + resource = CWLBufferResource::create(makeShared(client, 1, id)); + + success = texture->m_iTexID; + + if (!success) + Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); +} + +CSinglePixelBuffer::~CSinglePixelBuffer() { + ; +} + +Aquamarine::eBufferCapability CSinglePixelBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +Aquamarine::eBufferType CSinglePixelBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +bool CSinglePixelBuffer::isSynchronous() { + return true; +} + +void CSinglePixelBuffer::update(const CRegion& damage) { + ; +} + +Aquamarine::SDMABUFAttrs CSinglePixelBuffer::dmabuf() { + return {.success = false}; +} + +std::tuple CSinglePixelBuffer::beginDataPtr(uint32_t flags) { + return {(uint8_t*)&color, DRM_FORMAT_ARGB8888, 4}; +} + +void CSinglePixelBuffer::endDataPtr() { + ; +} + +bool CSinglePixelBuffer::good() { + return resource->good(); +} + +CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) { + buffer = makeShared(id, client, color); + + if (!buffer->good()) + return; + + buffer->resource->buffer = buffer; + + listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) { + listeners.bufferResourceDestroy.reset(); + PROTO::singlePixel->destroyResource(this); + }); +} + +CSinglePixelBufferResource::~CSinglePixelBufferResource() { + ; +} + +bool CSinglePixelBufferResource::good() { + return buffer->good(); +} + +CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); + resource->setOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); + + resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { + CColor color{r / (float)std::numeric_limits::max(), g / (float)std::numeric_limits::max(), b / (float)std::numeric_limits::max(), + a / (float)std::numeric_limits::max()}; + const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared(id, resource->client(), color)); + + if (!RESOURCE->good()) { + res->noMemory(); + PROTO::singlePixel->m_vBuffers.pop_back(); + return; + } + }); +} + +bool CSinglePixelBufferManagerResource::good() { + return resource->resource(); +} + +CSinglePixelProtocol::CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CSinglePixelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CSinglePixelProtocol::destroyResource(CSinglePixelBufferManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CSinglePixelProtocol::destroyResource(CSinglePixelBufferResource* surf) { + std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == surf; }); +} diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp new file mode 100644 index 00000000..ab74825c --- /dev/null +++ b/src/protocols/SinglePixel.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "single-pixel-buffer-v1.hpp" +#include "types/Buffer.hpp" + +class CSinglePixelBuffer : public IHLBuffer { + public: + CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col); + virtual ~CSinglePixelBuffer(); + + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual bool isSynchronous(); + virtual void update(const CRegion& damage); + virtual Aquamarine::SDMABUFAttrs dmabuf(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + // + bool good(); + bool success = false; + + private: + uint32_t color = 0x00000000; + + struct { + CHyprSignalListener resourceDestroy; + } listeners; +}; + +class CSinglePixelBufferResource { + public: + CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color); + ~CSinglePixelBufferResource(); + + bool good(); + + private: + SP buffer; + + struct { + CHyprSignalListener bufferResourceDestroy; + } listeners; +}; + +class CSinglePixelBufferManagerResource { + public: + CSinglePixelBufferManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CSinglePixelProtocol : public IWaylandProtocol { + public: + CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CSinglePixelBufferManagerResource* resource); + void destroyResource(CSinglePixelBufferResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vBuffers; + + friend class CSinglePixelBufferManagerResource; + friend class CSinglePixelBufferResource; +}; + +namespace PROTO { + inline UP singlePixel; +}; \ No newline at end of file From 968f6a6013409a6e6eab1545b28cd5e0cc49ce87 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Sun, 29 Sep 2024 23:52:58 -0500 Subject: [PATCH 0084/1803] meson: fix arch build with new protocol --- protocols/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/meson.build b/protocols/meson.build index d686bacd..6990b5a7 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -63,6 +63,7 @@ protocols = [ wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', + wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', ] wl_protocols = [] From f6387536f62454f82039b42f641cd8c44153ad47 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Mon, 30 Sep 2024 00:15:25 -0500 Subject: [PATCH 0085/1803] protocol: fix missing include --- src/protocols/SinglePixel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 7dd3748f..0595cce5 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -1,5 +1,6 @@ #include "SinglePixel.hpp" #include +#include "render/Renderer.hpp" CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); From 3ddb16bd5bb7146d125a7d68e4e9f3b54c381a20 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:25:39 +0100 Subject: [PATCH 0086/1803] compositor/wayland: up the max buffer size to avoid disconnects when app hangs --- CMakeLists.txt | 2 +- src/Compositor.cpp | 4 +++ src/helpers/ByteOperations.hpp | 52 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/helpers/ByteOperations.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ee9cd2e2..3440af4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ pkg_check_modules( IMPORTED_TARGET xkbcommon uuid - wayland-server + wayland-server>=1.22.90 wayland-protocols cairo pango diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 232ba4a6..25d73db0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -28,6 +28,7 @@ #include "desktop/LayerSurface.hpp" #include "render/Renderer.hpp" #include "xwayland/XWayland.hpp" +#include "helpers/ByteOperations.hpp" #include #include @@ -229,6 +230,9 @@ void CCompositor::initServer(std::string socketName, int socketFd) { if (envEnabled("HYPRLAND_TRACE")) Debug::trace = true; + // set the buffer size to 1MB to avoid disconnects due to an app hanging for a short while + wl_display_set_default_max_buffer_size(m_sWLDisplay, 1_MB); + Aquamarine::SBackendOptions options; options.logFunction = aqLog; diff --git a/src/helpers/ByteOperations.hpp b/src/helpers/ByteOperations.hpp new file mode 100644 index 00000000..6d9507ff --- /dev/null +++ b/src/helpers/ByteOperations.hpp @@ -0,0 +1,52 @@ +#pragma once + +#define ULL unsigned long long +#define LD long double + +constexpr ULL operator""_kB(const ULL BYTES) { + return BYTES * 1024; +} +constexpr ULL operator""_MB(const ULL BYTES) { + return BYTES * 1024 * 1024; +} +constexpr ULL operator""_GB(const ULL BYTES) { + return BYTES * 1024 * 1024 * 1024; +} +constexpr ULL operator""_TB(const ULL BYTES) { + return BYTES * 1024 * 1024 * 1024 * 1024; +} +constexpr LD operator""_kB(const LD BYTES) { + return BYTES * 1024; +} +constexpr LD operator""_MB(const LD BYTES) { + return BYTES * 1024 * 1024; +} +constexpr LD operator""_GB(const LD BYTES) { + return BYTES * 1024 * 1024 * 1024; +} +constexpr LD operator""_TB(const LD BYTES) { + return BYTES * 1024 * 1024 * 1024 * 1024; +} + +template +using __acceptable_byte_operation_type = typename std::enable_if::value || std::is_trivially_constructible::value>::type; + +template > +constexpr X kBtoBytes(const X kB) { + return kB * 1024; +} +template > +constexpr X MBtoBytes(const X MB) { + return MB * 1024 * 1024; +} +template > +constexpr X GBtoBytes(const X GB) { + return GB * 1024 * 1024 * 1024; +} +template > +constexpr X TBtoBytes(const X TB) { + return TB * 1024 * 1024 * 1024 * 1024; +} + +#undef ULL +#undef LD \ No newline at end of file From 68fd32c81013541f237e2046779185b41db1538e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:27:10 +0100 Subject: [PATCH 0087/1803] byteoperations: add missing header --- src/helpers/ByteOperations.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/ByteOperations.hpp b/src/helpers/ByteOperations.hpp index 6d9507ff..13e98500 100644 --- a/src/helpers/ByteOperations.hpp +++ b/src/helpers/ByteOperations.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #define ULL unsigned long long #define LD long double From 6bd339714160505ab1c4aade659eca6fe426fea5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:40:38 +0100 Subject: [PATCH 0088/1803] wlr-output-management: accept 0 refresh rates fixes #7879 --- src/protocols/OutputManagement.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index dcc7a62d..3fd0cf6c 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -467,11 +467,16 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_CUSTOM_MODE, "Invalid mode"); return; } + if (refresh == 0) { + LOGM(LOG, " | configHead for {}: refreshRate 0, using old refresh rate of {:.2f}Hz", pMonitor->szName, pMonitor->refreshRate); + refresh = std::round(pMonitor->refreshRate * 1000.F); + } + state.committedProperties |= OUTPUT_HEAD_COMMITTED_CUSTOM_MODE; state.customMode = {{w, h}, (uint32_t)refresh}; From 5c6c300abfea2539ffad9bcbf857325eec5ab765 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:42:36 +0100 Subject: [PATCH 0089/1803] wayland/output: send geometry in updateState --- src/protocols/core/Output.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 394dc8e2..7b88e0a8 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -21,8 +21,6 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni PROTO::outputs.at(monitor->szName)->destroyResource(this); }); - resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), - monitor->output->model.c_str(), monitor->transform); if (resource->version() >= 4) { resource->sendName(monitor->szName.c_str()); resource->sendDescription(monitor->szDescription.c_str()); @@ -57,6 +55,9 @@ void CWLOutputResource::updateState() { resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); + resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), + monitor->output->model.c_str(), monitor->transform); + if (resource->version() >= 2) resource->sendDone(); } From e2426942e5716a742ea353d2a1de7d7760fbbb41 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 2 Oct 2024 11:22:19 +0200 Subject: [PATCH 0090/1803] layout: add auto_group to control default grouping (#7883) --- src/config/ConfigDescriptions.hpp | 6 +++ src/config/ConfigManager.cpp | 1 + src/events/Windows.cpp | 2 +- src/layout/DwindleLayout.cpp | 21 +-------- src/layout/IHyprLayout.cpp | 73 ++++++++++++++++++++++++------- src/layout/IHyprLayout.hpp | 1 + src/layout/MasterLayout.cpp | 20 --------- 7 files changed, 68 insertions(+), 56 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 3a91a808..385d4e59 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -772,6 +772,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_GRADIENT, .data = SConfigOptionDescription::SGradientData{"0x66775500"}, }, + SConfigOptionDescription{ + .value = "group:auto_group", + .description = "automatically group new windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ad6e1871..2ce07ff0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -377,6 +377,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 544483b1..1c2c7cfa 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -322,7 +322,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->updateWindowData(); if (PWINDOW->m_bIsFloating) { - g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW); + g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; // size and move rules diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index ed47fa44..04cbf21d 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -340,26 +340,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir return; } - // if it's a group, add the window - if (OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group - && pWindow->canBeGroupedInto(OPENINGON->pWindow.lock()) && !m_vOverrideFocalPoint) { // we are not moving window - m_lDwindleNodesData.remove(*PNODE); - - static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); - - return; - } - - // If it's not, get the node under our cursor + // get the node under our cursor m_lDwindleNodesData.push_back(SDwindleNodeData()); const auto NEWPARENT = &m_lDwindleNodesData.back(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c5a5373c..0fb78d02 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -9,23 +9,25 @@ #include "../xwayland/XSurface.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { - if (pWindow->m_bIsFloating) { + CBox desiredGeometry = {}; + g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); + + if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; + } else + pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); + + pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; + + bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow); + if (autoGrouped) + return; + + if (pWindow->m_bIsFloating) onWindowCreatedFloating(pWindow); - } else { - CBox desiredGeometry = {}; - g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - - if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; - } else { - pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); - } - - pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; - + else onWindowCreatedTiling(pWindow, direction); - } } void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) { @@ -178,6 +180,47 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } } +bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { + static auto AUTOGROUP = CConfigValue("group:auto_group"); + if ((*AUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. + && g_pCompositor->m_pLastWindow.lock() // check if a focused window exists. + && g_pCompositor->m_pLastWindow != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && g_pCompositor->m_pLastWindow->m_pWorkspace == + pWindow + ->m_pWorkspace // fix for multimonitor: when there is a focused group in monitor 1 and monitor 2 is empty, this enables adding the first window of monitor 2 when using the mouse to focus it. + && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow.lock() // check if the focused window is a group + && pWindow->canBeGroupedInto(g_pCompositor->m_pLastWindow.lock()) // check if the new window can be grouped into the focused group + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + + switch (pWindow->m_bIsFloating) { + case false: + if (g_pCompositor->m_pLastWindow->m_bIsFloating) + pWindow->m_bIsFloating = true; + break; + + case true: + if (!g_pCompositor->m_pLastWindow->m_bIsFloating) + pWindow->m_bIsFloating = false; + break; + } + + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? g_pCompositor->m_pLastWindow : g_pCompositor->m_pLastWindow->getGroupTail())->insertWindowToGroup(pWindow); + + g_pCompositor->m_pLastWindow->setGroupCurrent(pWindow); + pWindow->applyGroupRules(); + pWindow->updateWindowDecos(); + recalculateWindow(pWindow); + + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + + return true; + } + + return false; +} + void IHyprLayout::onBeginDragWindow() { const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 7e0d5704..f9e2de0d 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -47,6 +47,7 @@ class IHyprLayout { virtual void onWindowCreated(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT) = 0; virtual void onWindowCreatedFloating(PHLWINDOW); + virtual bool onWindowCreatedAutoGroup(PHLWINDOW); /* Return tiled status diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8fa324b0..04a6ea29 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -116,26 +116,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire return; } - // if it's a group, add the window - if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group - && pWindow->canBeGroupedInto(OPENINGON->pWindow.lock())) { - - m_lMasterNodesData.remove(*PNODE); - - static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); - - return; - } - pWindow->applyGroupRules(); static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); From de68e065fe861d7ca01eca267df4c305bc6e73c2 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 2 Oct 2024 22:25:25 +0200 Subject: [PATCH 0091/1803] layout: fix dragging a window into a group after e242694 (#7976) --- src/layout/IHyprLayout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 0fb78d02..4b5c9d4f 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -552,10 +552,10 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vLastFloatingSize = PSAVEDSIZE; - // move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back. + // move to narnia because we don't wanna find our own node. onWindowCreated should apply the coords back. pWindow->m_vPosition = Vector2D(-999999, -999999); - onWindowCreatedTiling(pWindow); + onWindowCreated(pWindow); pWindow->m_vRealPosition.setValue(PSAVEDPOS); pWindow->m_vRealSize.setValue(PSAVEDSIZE); From aed529f695bc62f5fa45dc94c545275ebb49bc48 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 3 Oct 2024 22:00:44 +0000 Subject: [PATCH 0092/1803] renderer: fix uvBR calculation (#7975) --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 417a3ff8..b081fd81 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1134,7 +1134,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPcurrent.size.y; const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y)); - uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); + uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y)); uvTL = uvTL + TOADDTL; // TODO: make this passed to the func. Might break in the future. From 1ed925b69c2854a3f345cbeb7dca29a6286ca926 Mon Sep 17 00:00:00 2001 From: Theo Paris Date: Fri, 4 Oct 2024 01:41:27 -0700 Subject: [PATCH 0093/1803] internal: fix missing include directive (#7984) This should fix building with clang. --- src/helpers/SdDaemon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/SdDaemon.cpp b/src/helpers/SdDaemon.cpp index 48c23e6b..80944794 100644 --- a/src/helpers/SdDaemon.cpp +++ b/src/helpers/SdDaemon.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace Systemd { From 8e237b006fa7dd348a58c85f1aa46a8a835533c2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 00:43:59 +0100 Subject: [PATCH 0094/1803] xdg-output: minor cleanups --- src/protocols/XDGOutput.cpp | 32 ++++++++++++++------------------ src/protocols/XDGOutput.hpp | 6 +++--- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 5d620667..0cdadd43 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -29,29 +29,20 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver return; } - RESOURCE->setDestroy([this](CZxdgOutputManagerV1* res) { this->onManagerResourceDestroy(res->resource()); }); - RESOURCE->setOnDestroy([this](CZxdgOutputManagerV1* res) { this->onManagerResourceDestroy(res->resource()); }); - RESOURCE->setGetXdgOutput([this](CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* output) { this->onManagerGetXDGOutput(mgr, id, output); }); + RESOURCE->setDestroy([this](CZxdgOutputManagerV1* res) { onManagerResourceDestroy(res->resource()); }); + RESOURCE->setOnDestroy([this](CZxdgOutputManagerV1* res) { onManagerResourceDestroy(res->resource()); }); + RESOURCE->setGetXdgOutput([this](CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* output) { onManagerGetXDGOutput(mgr, id, output); }); } CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); static auto P2 = g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); - static auto P3 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - const auto PMONITOR = std::any_cast(param); - for (auto const& o : m_vXDGOutputs) { - if (o->monitor == PMONITOR) - o->monitor = nullptr; - } - }); } void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource) { - const auto OUTPUT = CWLOutputResource::fromResource(outputResource); - - const auto PMONITOR = OUTPUT->monitor.get(); - - const auto CLIENT = mgr->client(); + const auto OUTPUT = CWLOutputResource::fromResource(outputResource); + const auto PMONITOR = OUTPUT->monitor.lock(); + const auto CLIENT = mgr->client(); CXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique(makeShared(CLIENT, mgr->version(), id), PMONITOR)).get(); #ifndef NO_XWAYLAND @@ -66,8 +57,12 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 return; } - if (!PMONITOR) + if (!PMONITOR) { + LOGM(ERR, "New xdg_output from client {:x} ({}) has no CMonitor?!", (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland"); return; + } + + LOGM(LOG, "New xdg_output for {}: client {:x} ({})", PMONITOR->szName, (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland"); const auto XDGVER = pXDGOutput->resource->version(); @@ -84,8 +79,9 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 } void CXDGOutputProtocol::updateAllOutputs() { - for (auto const& o : m_vXDGOutputs) { + LOGM(LOG, "updating all xdg_output heads"); + for (auto const& o : m_vXDGOutputs) { if (!o->monitor) continue; @@ -97,7 +93,7 @@ void CXDGOutputProtocol::updateAllOutputs() { // -CXDGOutput::CXDGOutput(SP resource_, CMonitor* monitor_) : monitor(monitor_), resource(resource_) { +CXDGOutput::CXDGOutput(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { if (!resource->resource()) return; diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 73e7d53e..15d86cc7 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -9,12 +9,12 @@ class CXDGOutputProtocol; class CXDGOutput { public: - CXDGOutput(SP resource, CMonitor* monitor_); + CXDGOutput(SP resource, SP monitor_); void sendDetails(); private: - CMonitor* monitor = nullptr; + WP monitor; SP resource; std::optional overridePosition; @@ -30,12 +30,12 @@ class CXDGOutputProtocol : public IWaylandProtocol { CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void updateAllOutputs(); private: void onManagerResourceDestroy(wl_resource* res); void onOutputResourceDestroy(wl_resource* res); void onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource); - void updateAllOutputs(); // std::vector> m_vManagerResources; From 3a5052a714e2a6a2b002dddcac1204960b298f8b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 00:44:16 +0100 Subject: [PATCH 0095/1803] compositor: update all xdg outputs on arrange --- src/Compositor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 25d73db0..b4d10c88 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -23,6 +23,7 @@ #include "protocols/PointerConstraints.hpp" #include "protocols/LayerShell.hpp" #include "protocols/XDGShell.hpp" +#include "protocols/XDGOutput.hpp" #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" @@ -2869,6 +2870,8 @@ void CCompositor::arrangeMonitors() { else m->xwaylandScale = 1.f; } + + PROTO::xdgOutput->updateAllOutputs(); } void CCompositor::enterUnsafeState() { From a815b14bf1b69b92f82bd09f6845fbdbb2fbe516 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 00:44:30 +0100 Subject: [PATCH 0096/1803] monitor: cleanup and modernize scheduleDone --- src/helpers/Monitor.cpp | 25 ++++++++++++++----------- src/helpers/Monitor.hpp | 6 +++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a9569699..03a1d92b 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -12,6 +12,7 @@ #include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../protocols/core/Compositor.hpp" #include "sync/SyncTimeline.hpp" #include @@ -789,20 +790,22 @@ CBox CMonitor::logicalBox() { return {vecPosition, vecSize}; } -static void onDoneSource(void* data) { - auto pMonitor = (CMonitor*)data; - - if (!PROTO::outputs.contains(pMonitor->szName)) - return; - - PROTO::outputs.at(pMonitor->szName)->sendDone(); -} - void CMonitor::scheduleDone() { - if (doneSource) + if (doneScheduled) return; - doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this); + doneScheduled = true; + + g_pEventLoopManager->doLater([M = self] { + if (!M) // if M is gone, we got destroyed, doesn't matter. + return; + + if (!PROTO::outputs.contains(M->szName)) + return; + + PROTO::outputs.at(M->szName)->sendDone(); + M->doneScheduled = false; + }); } bool CMonitor::attemptDirectScanout() { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 97d9f8ab..2a2edab6 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -190,10 +190,10 @@ class CMonitor { } private: - void setupDefaultWS(const SMonitorRule&); - WORKSPACEID findAvailableDefaultWS(); + void setupDefaultWS(const SMonitorRule&); + WORKSPACEID findAvailableDefaultWS(); - wl_event_source* doneSource = nullptr; + bool doneScheduled = false; struct { CHyprSignalListener frame; From 595eb89f6e16df0e19916e3c02bf5ceac5a61c57 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:52:53 +0100 Subject: [PATCH 0097/1803] renderer: Fix resize artifacts (stretching, bumps) (#7499) --- src/desktop/WLSurface.cpp | 2 +- src/render/OpenGL.cpp | 3 +++ src/render/Renderer.cpp | 42 +++++++++++++++++++++++---------------- src/render/Renderer.hpp | 33 +++++++++++++++--------------- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 45050e35..5e88f507 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -62,7 +62,7 @@ bool CWLSurface::small() const { const auto O = m_pWindowOwner.lock(); - return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1; + return O->m_vReportedSize.x > m_pResource->current.size.x + 1 || O->m_vReportedSize.y > m_pResource->current.size.y + 1; } Vector2D CWLSurface::correctSmallVec() const { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 4f22d6aa..a16c2d62 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1423,6 +1423,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_iTarget, tex->m_iTexID); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_S, 0x2900 /* GL_CLAMP */); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_T, 0x2900); + if (m_RenderData.useNearestNeighbor) { glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(tex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b081fd81..310d45af 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -150,7 +150,7 @@ static void renderSurface(SP surface, int x, int y, void* da const auto& TEXTURE = surface->current.texture; const auto RDATA = (SRenderData*)data; - const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; + const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; // this is bad, probably has been logged elsewhere. Means the texture failed // uploading to the GPU. @@ -180,6 +180,7 @@ static void renderSurface(SP surface, int x, int y, void* da // however, if surface buffer w / h < box, we need to adjust them const auto PWINDOW = PSURFACE ? PSURFACE->getWindow() : nullptr; + // center the surface if it's smaller than the viewport we assign it if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees PWINDOW */) { const auto CORRECT = PSURFACE->correctSmallVec(); const auto SIZE = PSURFACE->getViewporterCorrectedSize(); @@ -195,17 +196,6 @@ static void renderSurface(SP surface, int x, int y, void* da } } - if (!INTERACTIVERESIZEINPROGRESS && PSURFACE && PWINDOW && PWINDOW->m_vRealSize.goal().floor() > 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((float)surface->current.size.x, 2.F), std::max((float)surface->current.size.y, 2.F)}; if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) { @@ -231,6 +221,8 @@ static void renderSurface(SP surface, int x, int y, void* da return; // invisible } + const auto PROJSIZEUNSCALED = windowBox.size(); + windowBox.scale(RDATA->pMonitor->scale); windowBox.round(); @@ -239,7 +231,7 @@ static void renderSurface(SP surface, int x, int y, void* da DELTALESSTHAN(windowBox.height, surface->current.bufferSize.y, 3) /* off by one-or-two */ && (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; - g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface, windowBox.size(), MISALIGNEDFSV1); + g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->pMonitor->self.lock(), RDATA->surface == surface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); // check for fractional scale surfaces misaligning the buffer size // in those cases it's better to just force nearest neighbor @@ -1083,7 +1075,8 @@ void CHyprRenderer::renderSessionLockMissing(CMonitor* pMonitor) { g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } -void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) { +void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, SP pMonitor, bool main, const Vector2D& projSize, + const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { Vector2D uvTL; Vector2D uvBR = Vector2D(1, 1); @@ -1112,6 +1105,22 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPscale); + const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; + const auto EXPECTED_SIZE = + ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) + .round(); + if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { + // this will not work with shm AFAIK, idk why. + // NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much + const auto FIX = projSize / EXPECTED_SIZE; + uvBR = uvBR * FIX; + } + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR; @@ -1127,7 +1136,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_pXDGSurface->current.geometry; // ignore X and Y, adjust uv - if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) { + if (geom.x != 0 || geom.y != 0 || geom.width > projSizeUnscaled.x || geom.height > projSizeUnscaled.y) { const auto XPERC = (double)geom.x / (double)pSurface->current.size.x; const auto YPERC = (double)geom.y / (double)pSurface->current.size.y; const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.size.x; @@ -1137,8 +1146,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_vRealSize.value(); + auto maxSize = projSizeUnscaled; if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall) maxSize = pWindow->m_pWLSurface->getViewporterCorrectedSize(); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index b730d589..7d1ae4b1 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -49,22 +49,23 @@ class CHyprRenderer { CHyprRenderer(); ~CHyprRenderer(); - void renderMonitor(CMonitor* pMonitor); - void arrangeLayersForMonitor(const MONITORID&); - void damageSurface(SP, double, double, double scale = 1.0); - void damageWindow(PHLWINDOW, bool forceFull = false); - void damageBox(CBox*, bool skipFrameSchedule = false); - void damageBox(const int& x, const int& y, const int& w, const int& h); - void damageRegion(const CRegion&); - void damageMonitor(CMonitor*); - void damageMirrorsWith(CMonitor*, const CRegion&); - bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); - bool shouldRenderWindow(PHLWINDOW, CMonitor*); - bool shouldRenderWindow(PHLWINDOW); - void ensureCursorRenderingMode(); - bool shouldRenderCursor(); - void setCursorHidden(bool hide); - void calculateUVForSurface(PHLWINDOW, SP, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false); + void renderMonitor(CMonitor* pMonitor); + void arrangeLayersForMonitor(const MONITORID&); + void damageSurface(SP, double, double, double scale = 1.0); + void damageWindow(PHLWINDOW, bool forceFull = false); + void damageBox(CBox*, bool skipFrameSchedule = false); + void damageBox(const int& x, const int& y, const int& w, const int& h); + void damageRegion(const CRegion&); + void damageMonitor(CMonitor*); + void damageMirrorsWith(CMonitor*, const CRegion&); + bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); + bool shouldRenderWindow(PHLWINDOW, CMonitor*); + bool shouldRenderWindow(PHLWINDOW); + void ensureCursorRenderingMode(); + bool shouldRenderCursor(); + void setCursorHidden(bool hide); + void calculateUVForSurface(PHLWINDOW, SP, SP pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, + bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry); void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace); From 46bf87c8d1f053284a266d5f0b470073a48a92f6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:37:12 +0100 Subject: [PATCH 0098/1803] monitor: use a scope guard for disconnect events --- src/helpers/Monitor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 03a1d92b..f105ea66 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -229,6 +229,12 @@ void CMonitor::onConnect(bool noRule) { } void CMonitor::onDisconnect(bool destroy) { + CScopeGuard x = {[this]() { + if (g_pCompositor->m_bIsShuttingDown) + return; + g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); + EMIT_HOOK_EVENT("monitorRemoved", this); + }}; if (renderTimer) { wl_event_source_remove(renderTimer); @@ -341,9 +347,6 @@ void CMonitor::onDisconnect(bool destroy) { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } std::erase_if(g_pCompositor->m_vMonitors, [&](SP& el) { return el.get() == this; }); - - g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); - EMIT_HOOK_EVENT("monitorRemoved", this); } void CMonitor::addDamage(const pixman_region32_t* rg) { From 6fbfeefc7119ff86411b765aa26b4bffbaa825ec Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:40:03 +0100 Subject: [PATCH 0099/1803] protocolmgr: don't expose the fallback output --- src/managers/ProtocolManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 8bcc857a..157fa76c 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -86,7 +86,8 @@ CProtocolManager::CProtocolManager() { // ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after // this event is emitted iirc. - if (M->isMirror()) + // also ignore the fallback + if (M->isMirror() || M == g_pCompositor->m_pUnsafeOutput) return; if (PROTO::outputs.contains(M->szName)) From 52c09196219313aec2ec1d3d543669bff834d746 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:41:44 +0100 Subject: [PATCH 0100/1803] monitor: arrange monitors on connect and disconnect --- src/helpers/Monitor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index f105ea66..c6cef41f 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -36,6 +36,7 @@ CMonitor::~CMonitor() { } void CMonitor::onConnect(bool noRule) { + CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; if (output->supportsExplicit) { inTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); @@ -234,6 +235,7 @@ void CMonitor::onDisconnect(bool destroy) { return; g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); EMIT_HOOK_EVENT("monitorRemoved", this); + g_pCompositor->arrangeMonitors(); }}; if (renderTimer) { From 3ca699debffbb97085888835a33f20d0c542128d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:57:18 +0100 Subject: [PATCH 0101/1803] opengl: use GL_CLAMP_TO_EDGE instead of GL_CLAMP avoid error spam on select hw --- src/render/OpenGL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a16c2d62..833e2ccb 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1423,8 +1423,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_iTarget, tex->m_iTexID); - glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_S, 0x2900 /* GL_CLAMP */); - glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_T, 0x2900); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (m_RenderData.useNearestNeighbor) { glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); From 0ec6072a290051a03ab66cfb9bc616b2f5540e64 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 16:36:57 +0100 Subject: [PATCH 0102/1803] single-pixel: set buffer size to 1,1 --- src/protocols/SinglePixel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 0595cce5..d800539d 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -17,6 +17,8 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor co success = texture->m_iTexID; + size = {1, 1}; + if (!success) Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); } From 0c7a7e2d569eeed9d6025f3eef4ea0690d90845d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 6 Oct 2024 12:04:13 +0100 Subject: [PATCH 0103/1803] version: bump to 0.44.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8298bb08..a8ab6c96 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.43.0 +0.44.0 From da86aac0f5c5c3604351961b901f62cdf7186a10 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 6 Oct 2024 14:07:07 +0100 Subject: [PATCH 0104/1803] security-context: implement protocol fixes #7318 --- CMakeLists.txt | 1 + protocols/meson.build | 1 + src/Compositor.cpp | 12 ++ src/managers/ProtocolManager.cpp | 55 ++++++++ src/managers/ProtocolManager.hpp | 2 + src/protocols/SecurityContext.cpp | 214 ++++++++++++++++++++++++++++++ src/protocols/SecurityContext.hpp | 83 ++++++++++++ src/protocols/TextInputV1.hpp | 2 +- src/protocols/WaylandProtocol.cpp | 4 + src/protocols/WaylandProtocol.hpp | 1 + 10 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 src/protocols/SecurityContext.cpp create mode 100644 src/protocols/SecurityContext.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3440af4a..1bac29ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,6 +331,7 @@ protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) +protocolnew("staging/security-context" "security-context-v1" false) protocolwayland() diff --git a/protocols/meson.build b/protocols/meson.build index 6990b5a7..3fa2ef2f 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -64,6 +64,7 @@ protocols = [ wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', + wayland_protocol_dir / 'staging/security-context/security-context-v1.xml', ] wl_protocols = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b4d10c88..f00e1e34 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -24,6 +24,7 @@ #include "protocols/LayerShell.hpp" #include "protocols/XDGShell.hpp" #include "protocols/XDGOutput.hpp" +#include "protocols/SecurityContext.hpp" #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" @@ -210,11 +211,22 @@ void CCompositor::setRandomSplash() { static std::vector> pendingOutputs; +// + +static bool filterGlobals(const wl_client* client, const wl_global* global, void* data) { + if (!PROTO::securityContext->isClientSandboxed(client)) + return true; + + return !g_pProtocolManager || !g_pProtocolManager->isGlobalPrivileged(global); +} + // void CCompositor::initServer(std::string socketName, int socketFd) { m_sWLDisplay = wl_display_create(); + wl_display_set_global_filter(m_sWLDisplay, ::filterGlobals, nullptr); + m_sWLEventLoop = wl_display_get_event_loop(m_sWLDisplay); // register crit signal handler diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 157fa76c..6366eefe 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -45,6 +45,7 @@ #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/XDGDialog.hpp" #include "../protocols/SinglePixel.hpp" +#include "../protocols/SecurityContext.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -155,6 +156,7 @@ CProtocolManager::CProtocolManager() { PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); + PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) @@ -225,9 +227,62 @@ CProtocolManager::~CProtocolManager() { PROTO::toplevelExport.reset(); PROTO::globalShortcuts.reset(); PROTO::xdgDialog.reset(); + PROTO::singlePixel.reset(); + PROTO::securityContext.reset(); PROTO::lease.reset(); PROTO::sync.reset(); PROTO::mesaDRM.reset(); PROTO::linuxDma.reset(); } + +bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { + if (!global) + return false; + + for (auto& [k, v] : PROTO::outputs) { + if (global == v->getGlobal()) + return false; + } + + // this is a static whitelist of allowed protocols, + // outputs are dynamic so we checked them above + // clang-format off + static const std::vector ALLOWED_WHITELIST = { + PROTO::seat->getGlobal(), + PROTO::data->getGlobal(), + PROTO::compositor->getGlobal(), + PROTO::subcompositor->getGlobal(), + PROTO::shm->getGlobal(), + PROTO::viewport->getGlobal(), + PROTO::tearing->getGlobal(), + PROTO::fractional->getGlobal(), + PROTO::cursorShape->getGlobal(), + PROTO::idleInhibit->getGlobal(), + PROTO::relativePointer->getGlobal(), + PROTO::xdgDecoration->getGlobal(), + PROTO::alphaModifier->getGlobal(), + PROTO::pointerGestures->getGlobal(), + PROTO::shortcutsInhibit->getGlobal(), + PROTO::textInputV1->getGlobal(), + PROTO::textInputV3->getGlobal(), + PROTO::constraints->getGlobal(), + PROTO::activation->getGlobal(), + PROTO::idle->getGlobal(), + PROTO::ime->getGlobal(), + PROTO::virtualKeyboard->getGlobal(), + PROTO::virtualPointer->getGlobal(), + PROTO::serverDecorationKDE->getGlobal(), + PROTO::tablet->getGlobal(), + PROTO::presentation->getGlobal(), + PROTO::xdgShell->getGlobal(), + PROTO::xdgDialog->getGlobal(), + PROTO::singlePixel->getGlobal(), + PROTO::sync ? PROTO::sync->getGlobal() : nullptr, + PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, + PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, + }; + // clang-format on + + return std::find(ALLOWED_WHITELIST.begin(), ALLOWED_WHITELIST.end(), global) == ALLOWED_WHITELIST.end(); +} diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 1b6d31b6..d5629e9e 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -11,6 +11,8 @@ class CProtocolManager { CProtocolManager(); ~CProtocolManager(); + bool isGlobalPrivileged(const wl_global* global); + private: std::unordered_map m_mModeChangeListeners; diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp new file mode 100644 index 00000000..b93ef448 --- /dev/null +++ b/src/protocols/SecurityContext.cpp @@ -0,0 +1,214 @@ +#include "SecurityContext.hpp" +#include "../Compositor.hpp" +#include + +static int onListenFdEvent(int fd, uint32_t mask, void* data) { + auto sc = (CSecurityContext*)data; + sc->onListen(mask); + return 0; +} + +static int onCloseFdEvent(int fd, uint32_t mask, void* data) { + auto sc = (CSecurityContext*)data; + sc->onClose(mask); + return 0; +} + +SP CSecurityContextSandboxedClient::create(int clientFD) { + auto p = SP(new CSecurityContextSandboxedClient(clientFD)); + if (!p->client) + return nullptr; + return p; +} + +static void onSecurityContextClientDestroy(wl_listener* l, void* d) { + CSecurityContextSandboxedClient* client = wl_container_of(l, client, destroyListener); + client->onDestroy(); +} + +CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD) { + client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD); + if (!client) + return; + + destroyListener.notify = ::onSecurityContextClientDestroy; + wl_client_add_destroy_late_listener(client, &destroyListener); +} + +CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { + wl_list_remove(&destroyListener.link); +} + +void CSecurityContextSandboxedClient::onDestroy() { + std::erase_if(PROTO::securityContext->m_vSandboxedClients, [this](const auto& e) { return e.get() == this; }); +} + +CSecurityContext::CSecurityContext(SP resource_, int listenFD_, int closeFD_) : listenFD(listenFD_), closeFD(closeFD_), resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSecurityContextV1* r) { + LOGM(LOG, "security_context at 0x{:x}: resource destroyed, keeping context until fd hangup", (uintptr_t)this); + resource = nullptr; + }); + resource->setOnDestroy([this](CWpSecurityContextV1* r) { + LOGM(LOG, "security_context at 0x{:x}: resource destroyed, keeping context until fd hangup", (uintptr_t)this); + resource = nullptr; + }); + + LOGM(LOG, "New security_context at 0x{:x}", (uintptr_t)this); + + resource->setSetSandboxEngine([this](CWpSecurityContextV1* r, const char* engine) { + if (!sandboxEngine.empty()) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox engine already set"); + return; + } + + if (committed) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); + return; + } + + sandboxEngine = engine ? engine : "(null)"; + LOGM(LOG, "security_context at 0x{:x} sets engine to {}", (uintptr_t)this, sandboxEngine); + }); + + resource->setSetAppId([this](CWpSecurityContextV1* r, const char* appid) { + if (!appID.empty()) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox appid already set"); + return; + } + + if (committed) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); + return; + } + + appID = appid ? appid : "(null)"; + LOGM(LOG, "security_context at 0x{:x} sets appid to {}", (uintptr_t)this, appID); + }); + + resource->setSetInstanceId([this](CWpSecurityContextV1* r, const char* instance) { + if (!instanceID.empty()) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox instance already set"); + return; + } + + if (committed) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); + return; + } + + instanceID = instance ? instance : "(null)"; + LOGM(LOG, "security_context at 0x{:x} sets instance to {}", (uintptr_t)this, instanceID); + }); + + resource->setCommit([this](CWpSecurityContextV1* r) { + committed = true; + + LOGM(LOG, "security_context at 0x{:x} commits", (uintptr_t)this); + + listenSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, listenFD, WL_EVENT_READABLE, ::onListenFdEvent, this); + closeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, closeFD, 0, ::onCloseFdEvent, this); + + if (!listenSource || !closeSource) { + r->noMemory(); + return; + } + }); +} + +CSecurityContext::~CSecurityContext() { + if (listenSource) + wl_event_source_remove(listenSource); + if (closeSource) + wl_event_source_remove(closeSource); +} + +bool CSecurityContext::good() { + return resource->resource(); +} + +void CSecurityContext::onListen(uint32_t mask) { + if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { + LOGM(ERR, "security_context at 0x{:x} got an error in listen", (uintptr_t)this); + PROTO::securityContext->destroyContext(this); + return; + } + + if (!(mask & WL_EVENT_READABLE)) + return; + + int clientFD = accept(listenFD, nullptr, nullptr); + if (clientFD < 0) { + LOGM(ERR, "security_context at 0x{:x} couldn't accept", (uintptr_t)this); + return; + } + + auto newClient = CSecurityContextSandboxedClient::create(clientFD); + if (!newClient) { + LOGM(ERR, "security_context at 0x{:x} couldn't create a client", (uintptr_t)this); + close(clientFD); + return; + } + + PROTO::securityContext->m_vSandboxedClients.emplace_back(newClient); + + LOGM(LOG, "security_context at 0x{:x} got a new wl_client 0x{:x}", (uintptr_t)this, (uintptr_t)newClient->client); +} + +void CSecurityContext::onClose(uint32_t mask) { + if (!(mask & (WL_EVENT_ERROR | WL_EVENT_HANGUP))) + return; + + PROTO::securityContext->destroyContext(this); +} + +CSecurityContextManagerResource::CSecurityContextManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSecurityContextManagerV1* r) { PROTO::securityContext->destroyResource(this); }); + resource->setOnDestroy([this](CWpSecurityContextManagerV1* r) { PROTO::securityContext->destroyResource(this); }); + + resource->setCreateListener([](CWpSecurityContextManagerV1* r, uint32_t id, int32_t lfd, int32_t cfd) { + const auto RESOURCE = + PROTO::securityContext->m_vContexts.emplace_back(makeShared(makeShared(r->client(), r->version(), id), lfd, cfd)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::securityContext->m_vContexts.pop_back(); + return; + } + }); +} + +bool CSecurityContextManagerResource::good() { + return resource->resource(); +} + +CSecurityContextProtocol::CSecurityContextProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CSecurityContextProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CSecurityContextProtocol::destroyResource(CSecurityContextManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CSecurityContextProtocol::destroyContext(CSecurityContext* context) { + std::erase_if(m_vContexts, [&](const auto& other) { return other.get() == context; }); +} + +bool CSecurityContextProtocol::isClientSandboxed(const wl_client* client) { + return std::find_if(m_vSandboxedClients.begin(), m_vSandboxedClients.end(), [client](const auto& e) { return e->client == client; }) != m_vSandboxedClients.end(); +} diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp new file mode 100644 index 00000000..bcbb69b2 --- /dev/null +++ b/src/protocols/SecurityContext.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "security-context-v1.hpp" + +class CSecurityContext { + public: + CSecurityContext(SP resource_, int listenFD_, int closeFD_); + ~CSecurityContext(); + + bool good(); + + std::string sandboxEngine, appID, instanceID; + int listenFD = -1, closeFD = -1; + + void onListen(uint32_t mask); + void onClose(uint32_t mask); + + private: + SP resource; + + wl_event_source * listenSource = nullptr, *closeSource = nullptr; + + bool committed = false; +}; + +class CSecurityContextManagerResource { + public: + CSecurityContextManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CSecurityContextSandboxedClient { + public: + static SP create(int clientFD); + ~CSecurityContextSandboxedClient(); + + void onDestroy(); + + wl_listener destroyListener; + + private: + CSecurityContextSandboxedClient(int clientFD); + + wl_client* client = nullptr; + + friend class CSecurityContextProtocol; + friend class CSecurityContext; +}; + +class CSecurityContextProtocol : public IWaylandProtocol { + public: + CSecurityContextProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + bool isClientSandboxed(const wl_client* client); + + private: + void destroyResource(CSecurityContextManagerResource* resource); + + void destroyContext(CSecurityContext* context); + + // + std::vector> m_vManagers; + std::vector> m_vContexts; + std::vector> m_vSandboxedClients; + + friend class CSecurityContextManagerResource; + friend class CSecurityContext; + friend class CSecurityContextSandboxedClient; +}; + +namespace PROTO { + inline UP securityContext; +}; \ No newline at end of file diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index 9bee452c..d3b0d71b 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -60,7 +60,7 @@ class CTextInputV1 { friend class CTextInputV1Protocol; }; -class CTextInputV1Protocol : IWaylandProtocol { +class CTextInputV1Protocol : public IWaylandProtocol { public: CTextInputV1Protocol(const wl_interface* iface, const int& ver, const std::string& name); diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp index 0782d323..00b112b0 100644 --- a/src/protocols/WaylandProtocol.cpp +++ b/src/protocols/WaylandProtocol.cpp @@ -40,3 +40,7 @@ IWaylandProtocol::~IWaylandProtocol() { void IWaylandProtocol::removeGlobal() { wl_global_remove(m_pGlobal); } + +wl_global* IWaylandProtocol::getGlobal() { + return m_pGlobal; +} diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index 87c75ed8..056322ac 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -53,6 +53,7 @@ class IWaylandProtocol { virtual void onDisplayDestroy(); virtual void removeGlobal(); + virtual wl_global* getGlobal(); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0; From 4e41cda27ed4176005082436cb35878335e63fae Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 6 Oct 2024 15:08:26 +0100 Subject: [PATCH 0105/1803] security-context: close client fds after disconnect --- src/protocols/SecurityContext.cpp | 7 ++++--- src/protocols/SecurityContext.hpp | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index b93ef448..b42c3a97 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -14,8 +14,8 @@ static int onCloseFdEvent(int fd, uint32_t mask, void* data) { return 0; } -SP CSecurityContextSandboxedClient::create(int clientFD) { - auto p = SP(new CSecurityContextSandboxedClient(clientFD)); +SP CSecurityContextSandboxedClient::create(int clientFD_) { + auto p = SP(new CSecurityContextSandboxedClient(clientFD_)); if (!p->client) return nullptr; return p; @@ -26,7 +26,7 @@ static void onSecurityContextClientDestroy(wl_listener* l, void* d) { client->onDestroy(); } -CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD) { +CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) : clientFD(clientFD_) { client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD); if (!client) return; @@ -37,6 +37,7 @@ CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD) { CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { wl_list_remove(&destroyListener.link); + close(clientFD); } void CSecurityContextSandboxedClient::onDestroy() { diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp index bcbb69b2..76313bcf 100644 --- a/src/protocols/SecurityContext.hpp +++ b/src/protocols/SecurityContext.hpp @@ -47,9 +47,10 @@ class CSecurityContextSandboxedClient { wl_listener destroyListener; private: - CSecurityContextSandboxedClient(int clientFD); + CSecurityContextSandboxedClient(int clientFD_); - wl_client* client = nullptr; + wl_client* client = nullptr; + int clientFD = -1; friend class CSecurityContextProtocol; friend class CSecurityContext; From 97444ed7a8a83406970fcc05907db1110435b59b Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 7 Oct 2024 14:22:55 +0200 Subject: [PATCH 0106/1803] layout: fix auto group when opening a new window in a non-focused workspace using window rules (#8006) --- src/layout/IHyprLayout.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 4b5c9d4f..f090e87d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -181,33 +181,34 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { - static auto AUTOGROUP = CConfigValue("group:auto_group"); - if ((*AUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. - && g_pCompositor->m_pLastWindow.lock() // check if a focused window exists. - && g_pCompositor->m_pLastWindow != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. - && g_pCompositor->m_pLastWindow->m_pWorkspace == - pWindow - ->m_pWorkspace // fix for multimonitor: when there is a focused group in monitor 1 and monitor 2 is empty, this enables adding the first window of monitor 2 when using the mouse to focus it. - && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow.lock() // check if the focused window is a group - && pWindow->canBeGroupedInto(g_pCompositor->m_pLastWindow.lock()) // check if the new window can be grouped into the focused group - && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + static auto PAUTOGROUP = CConfigValue("group:auto_group"); + PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? + g_pCompositor->m_pLastWindow.lock() : + g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + + if ((*PAUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. + && OPENINGON // check if OPENINGON exists. + && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group + && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. switch (pWindow->m_bIsFloating) { case false: - if (g_pCompositor->m_pLastWindow->m_bIsFloating) + if (OPENINGON->m_bIsFloating) pWindow->m_bIsFloating = true; break; case true: - if (!g_pCompositor->m_pLastWindow->m_bIsFloating) + if (!OPENINGON->m_bIsFloating) pWindow->m_bIsFloating = false; break; } static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? g_pCompositor->m_pLastWindow : g_pCompositor->m_pLastWindow->getGroupTail())->insertWindowToGroup(pWindow); + (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); - g_pCompositor->m_pLastWindow->setGroupCurrent(pWindow); + OPENINGON->setGroupCurrent(pWindow); pWindow->applyGroupRules(); pWindow->updateWindowDecos(); recalculateWindow(pWindow); From 5bf7b1e1fadf743f41ec765f7545370e3d7ccf96 Mon Sep 17 00:00:00 2001 From: Timon Schelling Date: Mon, 7 Oct 2024 15:44:03 +0000 Subject: [PATCH 0107/1803] flake.nix: add xdph follows fixes a duplicate hyprland-protocols instance sometimes being created due to xdph not following hyprlands instance --- flake.lock | 29 +++-------------------------- flake.nix | 5 +++-- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/flake.lock b/flake.lock index 2579dd11..2f9fbbc6 100644 --- a/flake.lock +++ b/flake.lock @@ -78,31 +78,6 @@ "type": "github" } }, - "hyprland-protocols_2": { - "inputs": { - "nixpkgs": [ - "xdph", - "nixpkgs" - ], - "systems": [ - "xdph", - "systems" - ] - }, - "locked": { - "lastModified": 1721326555, - "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", - "type": "github" - } - }, "hyprlang": { "inputs": { "hyprutils": [ @@ -221,7 +196,9 @@ }, "xdph": { "inputs": { - "hyprland-protocols": "hyprland-protocols_2", + "hyprland-protocols": [ + "hyprland-protocols" + ], "hyprlang": [ "hyprlang" ], diff --git a/flake.nix b/flake.nix index ee5af6a1..cfd003f8 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,7 @@ url = "github:hyprwm/xdg-desktop-portal-hyprland"; inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; + inputs.hyprland-protocols.follows = "hyprland-protocols"; inputs.hyprlang.follows = "hyprlang"; inputs.hyprutils.follows = "hyprutils"; inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; @@ -98,13 +99,13 @@ inherit (pkgsFor.${system}) # hyprland-packages - + hyprland hyprland-debug hyprland-legacy-renderer hyprland-unwrapped # hyprland-extras - + xdg-desktop-portal-hyprland ; hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland; From 46d990f1b632dc52a667d876a32cffb24ef72bd8 Mon Sep 17 00:00:00 2001 From: Artur Manuel Date: Mon, 7 Oct 2024 19:49:19 +0100 Subject: [PATCH 0108/1803] feat: add a custom made treewide formatter (#7992) --- .gitignore | 4 +++ flake.lock | 77 +++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 22 ++++++++++++-- nix/default.nix | 2 +- nix/formatter.nix | 64 +++++++++++++++++++++++++++++++++++++++ nix/overlays.nix | 4 +-- 6 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 nix/formatter.nix diff --git a/.gitignore b/.gitignore index 2e158a4e..a7934790 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ _deps build/ result* +/.pre-commit-config.yaml /.vscode/ /.idea/ .envrc @@ -39,3 +40,6 @@ PKGBUILD src/version.h hyprpm/Makefile hyprctl/Makefile + +**/.#*.* +**/#*.*# diff --git a/flake.lock b/flake.lock index 2f9fbbc6..85069a74 100644 --- a/flake.lock +++ b/flake.lock @@ -29,6 +29,43 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "hyprcursor": { "inputs": { "hyprlang": [ @@ -166,6 +203,45 @@ "type": "github" } }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1720386169, + "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1728092656, + "narHash": "sha256-eMeCTJZ5xBeQ0f9Os7K8DThNVSo9gy4umZLDfF5q6OM=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "1211305a5b237771e13fcca0c51e60ad47326a9a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "aquamarine": "aquamarine", @@ -175,6 +251,7 @@ "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks", "systems": "systems", "xdph": "xdph" } diff --git a/flake.nix b/flake.nix index cfd003f8..e3419ef8 100644 --- a/flake.nix +++ b/flake.nix @@ -56,6 +56,11 @@ inputs.hyprutils.follows = "hyprutils"; inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; }; + + pre-commit-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = inputs @ { @@ -77,7 +82,7 @@ pkgsCrossFor = eachSystem (system: crossSystem: import nixpkgs { localSystem = system; - crossSystem = crossSystem; + inherit crossSystem; overlays = with self.overlays; [ hyprland-packages hyprland-extras @@ -92,6 +97,18 @@ self.packages.${system}) // { inherit (self.packages.${system}) xdg-desktop-portal-hyprland; + pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + hyprland-treewide-formatter = { + enable = true; + entry = "${self.formatter.${system}}/bin/hyprland-treewide-formatter"; + pass_filenames = false; + excludes = ["subprojects"]; + always_run = true; + }; + }; + }; }); packages = eachSystem (system: { @@ -120,10 +137,11 @@ hardeningDisable = ["fortify"]; inputsFrom = [pkgsFor.${system}.hyprland]; packages = [pkgsFor.${system}.clang-tools]; + inherit (self.checks.${system}.pre-commit-check) shellHook; }; }); - formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra); + formatter = eachSystem (system: pkgsFor.${system}.callPackage ./nix/formatter.nix {}); nixosModules.default = import ./nix/module.nix inputs; homeManagerModules.default = import ./nix/hm-module.nix self; diff --git a/nix/default.nix b/nix/default.nix index 6f086ccc..d463e271 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -68,7 +68,7 @@ in inherit version; src = cleanSourceWith { - filter = name: type: let + filter = name: _type: let baseName = baseNameOf (toString name); in ! (hasSuffix ".nix" baseName); diff --git a/nix/formatter.nix b/nix/formatter.nix new file mode 100644 index 00000000..66721c2c --- /dev/null +++ b/nix/formatter.nix @@ -0,0 +1,64 @@ +{ + writeShellApplication, + deadnix, + statix, + alejandra, + llvmPackages_19, + fd, +}: +writeShellApplication { + name = "hyprland-treewide-formatter"; + runtimeInputs = [ + deadnix + statix + alejandra + llvmPackages_19.clang-tools + fd + ]; + text = '' + # shellcheck disable=SC2148 + + # common excludes + excludes="subprojects" + + nix_format() { + if [ "$*" = 0 ]; then + fd '.*\.nix' . -E "$excludes" -x statix fix -- {} \; + fd '.*\.nix' . -E "$excludes" -X deadnix -e -- {} \; -X alejandra {} \; + elif [ -d "$1" ]; then + fd '.*\.nix' "$1" -E "$excludes" -i -x statix fix -- {} \; + fd '.*\.nix' "$1" -E "$excludes" -i -X deadnix -e -- {} \; -X alejandra {} \; + else + statix fix -- "$1" + deadnix -e "$1" + alejandra "$1" + fi + } + + cpp_format() { + if [ "$*" = 0 ] || [ "$1" = "." ]; then + fd '.*\.cpp' . -E "$excludes" | xargs clang-format --verbose -i + elif [ -d "$1" ]; then + fd '.*\.cpp' "$1" -E "$excludes" | xargs clang-format --verbose -i + else + clang-format --verbose -i "$1" + fi + } + + for i in "$@"; do + case ''${i##*.} in + "nix") + nix_format "$i" + ;; + "cpp") + cpp_format "$i" + ;; + *) + nix_format "$i" + cpp_format "$i" + ;; + esac + + done + ''; +} diff --git a/nix/overlays.nix b/nix/overlays.nix index 2b2788e7..a78f3003 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -29,7 +29,7 @@ in { self.overlays.udis86 # Hyprland packages themselves - (final: prev: let + (final: _prev: let date = mkDate (self.lastModifiedDate or "19700101"); in { hyprland = final.callPackage ./default.nix { @@ -70,7 +70,7 @@ in { # this version is the one used in the git submodule, and allows us to # fetch the source without '?submodules=1' udis86 = final: prev: { - udis86-hyprland = prev.udis86.overrideAttrs (self: super: { + udis86-hyprland = prev.udis86.overrideAttrs (_self: _super: { src = final.fetchFromGitHub { owner = "canihavesomecoffee"; repo = "udis86"; From a364df4c9e9a73f0460665463028539e3abe4a8b Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:52:49 +0000 Subject: [PATCH 0109/1803] internal: use clampWindowSize to unify min/maxsize handling (#8014) modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp --- src/desktop/Window.cpp | 20 ++++++++++++++------ src/desktop/Window.hpp | 1 + src/events/Windows.cpp | 22 ++-------------------- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index feced807..fa85dc07 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -736,9 +736,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority); - m_vRealSize = - Vector2D(std::min((double)m_sWindowData.maxSize.value().x, m_vRealSize.goal().x), std::min((double)m_sWindowData.maxSize.value().y, m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal()); + clampWindowSize(std::nullopt, m_sWindowData.maxSize.value()); + } catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule.starts_with("minsize")) { try { @@ -751,9 +750,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } m_sWindowData.minSize = CWindowOverridableVar(VEC, priority); - m_vRealSize = - Vector2D(std::max((double)m_sWindowData.minSize.value().x, m_vRealSize.goal().x), std::max((double)m_sWindowData.minSize.value().y, m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal()); + clampWindowSize(m_sWindowData.minSize.value(), std::nullopt); + if (m_sGroupData.pNextWindow.expired()) setHidden(false); } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } @@ -1253,6 +1251,16 @@ int CWindow::surfacesCount() { return no; } +void CWindow::clampWindowSize(const std::optional minSize, const std::optional maxSize) { + const Vector2D REALSIZE = m_vRealSize.goal(); + const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{0.f, 0.f}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); + const Vector2D DELTA = REALSIZE - NEWSIZE; + + m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0; + m_vRealSize = NEWSIZE; + g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE); +} + bool CWindow::isFullscreen() { return m_sFullscreenState.internal != FSMODE_NONE; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index d14248c5..9baf57c4 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -429,6 +429,7 @@ class CWindow { bool onSpecialWorkspace(); void activate(bool force = false); int surfacesCount(); + void clampWindowSize(const std::optional minSize, const std::optional maxSize); bool isFullscreen(); bool isEffectiveInternalFSMode(const eFullscreenMode); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 1c2c7cfa..37f29130 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -751,26 +751,8 @@ void Events::listener_commitWindow(void* owner, void* data) { const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize; const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize; - if (MAXSIZE > Vector2D{1, 1}) { - const auto REALSIZE = PWINDOW->m_vRealSize.goal(); - Vector2D newSize = REALSIZE; - - if (MAXSIZE.x < newSize.x) - newSize.x = MAXSIZE.x; - if (MAXSIZE.y < newSize.y) - newSize.y = MAXSIZE.y; - if (MINSIZE.x > newSize.x) - newSize.x = MINSIZE.x; - if (MINSIZE.y > newSize.y) - newSize.y = MINSIZE.y; - - const Vector2D DELTA = REALSIZE - newSize; - - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0; - PWINDOW->m_vRealSize = newSize; - g_pXWaylandManager->setWindowSize(PWINDOW, newSize); - g_pHyprRenderer->damageWindow(PWINDOW); - } + PWINDOW->clampWindowSize(MINSIZE, MAXSIZE > Vector2D{1, 1} ? std::optional{MAXSIZE} : std::nullopt); + g_pHyprRenderer->damageWindow(PWINDOW); } if (!PWINDOW->m_pWorkspace->m_bVisible) From 0d70c442538ba0d1efc63558c859c184367c95ad Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:23:48 -0500 Subject: [PATCH 0110/1803] screencopy: fix screencopy frames not being cleaned up (#8017) --------- Co-authored-by: Vaxry --- src/protocols/Screencopy.cpp | 13 ++++++++----- src/protocols/Screencopy.hpp | 4 ++-- src/protocols/ToplevelExport.cpp | 16 +++++++++++----- src/protocols/ToplevelExport.hpp | 4 ++-- subprojects/hyprland-protocols | 2 +- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 63024541..1b06a1fa 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -394,12 +394,12 @@ void CScreencopyProtocol::bindManager(wl_client* client, void* data, uint32_t ve void CScreencopyProtocol::destroyResource(CScreencopyClient* client) { std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other->client.get() == client; }); } void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) { std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { @@ -412,8 +412,11 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { // share frame if correct output for (auto const& f : m_vFramesAwaitingWrite) { + if (!f) + continue; + if (!f->pMonitor || !f->buffer) { - framesToRemove.push_back(f); + framesToRemove.emplace_back(f); continue; } @@ -425,10 +428,10 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { f->client->lastFrame.reset(); ++f->client->frameCounter; - framesToRemove.push_back(f); + framesToRemove.emplace_back(f); } for (auto const& f : framesToRemove) { - destroyResource(f.get()); + std::erase(m_vFramesAwaitingWrite, f); } } diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index cbc56edb..e121d0fd 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -54,7 +54,7 @@ class CScreencopyFrame { bool good(); - SP self; + WP self; WP client; private: @@ -92,7 +92,7 @@ class CScreencopyProtocol : public IWaylandProtocol { private: std::vector> m_vFrames; - std::vector> m_vFramesAwaitingWrite; + std::vector> m_vFramesAwaitingWrite; std::vector> m_vClients; SP m_pSoftwareCursorTimer; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index b28a827a..66df5926 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -354,12 +354,12 @@ void CToplevelExportProtocol::bindManager(wl_client* client, void* data, uint32_ void CToplevelExportProtocol::destroyResource(CToplevelExportClient* client) { std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other->client.get() == client; }); } void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) { std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { @@ -370,11 +370,17 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { // share frame if correct output for (auto const& f : m_vFramesAwaitingWrite) { - if (!f->pWindow || !validMapped(f->pWindow)) { - framesToRemove.push_back(f); + if (!f) + continue; + + if (!validMapped(f->pWindow)) { + framesToRemove.emplace_back(f); continue; } + if (!f->pWindow) + continue; + const auto PWINDOW = f->pWindow; if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) @@ -394,7 +400,7 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { } for (auto const& f : framesToRemove) { - destroyResource(f.get()); + std::erase(m_vFramesAwaitingWrite, f); } } diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 638b69f0..9686431b 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -45,7 +45,7 @@ class CToplevelExportFrame { bool good(); - SP self; + WP self; WP client; private: @@ -85,7 +85,7 @@ class CToplevelExportProtocol : IWaylandProtocol { private: std::vector> m_vClients; std::vector> m_vFrames; - std::vector> m_vFramesAwaitingWrite; + std::vector> m_vFramesAwaitingWrite; void shareFrame(CToplevelExportFrame* frame); bool copyFrameDmabuf(CToplevelExportFrame* frame, timespec* now); diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index e06482e0..c7c3f4cd 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit e06482e0e611130cd1929f75e8c1cf679e57d161 +Subproject commit c7c3f4cd0faed21fc90ba6bd06fe4f3e0e057ea8 From 4711796d3800f1a6673eccbd50e8e8a02bb0fd85 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 09:54:25 +0100 Subject: [PATCH 0111/1803] config: give simple help for super+q not working only on default config :P --- src/config/ConfigManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2ce07ff0..018deaa7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -867,8 +867,10 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { if (result.error && !std::any_cast(m_pConfig->getConfigValue("debug:suppress_errors"))) g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) - g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", - CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); + g_pHyprError->queueCreate( + "Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + + " )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland", + CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); else if (*PENABLEEXPLICIT != prevEnabledExplicit) g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); else From 45e82199fb29f422ebbbfe06ce03022dfb6d645e Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 8 Oct 2024 12:20:41 +0200 Subject: [PATCH 0112/1803] layout: add drag_into_group to control merging dragging windows (#8004) --- src/config/ConfigDescriptions.hpp | 6 ++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 65 +++++++++++++------ .../decorations/CHyprGroupBarDecoration.cpp | 16 +++-- 4 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 385d4e59..2ca230be 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -778,6 +778,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:drag_into_group", + .description = "whether dragging a window into a unlocked group will merge them. Options: 0 (disabled), 1 (enabled), 2 (only when dragging into the groupbar)", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "disabled,enabled,only when dragging into the groupbar"}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 018deaa7..9a5283fa 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -378,6 +378,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f090e87d..f249d2b5 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -193,17 +193,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. - switch (pWindow->m_bIsFloating) { - case false: - if (OPENINGON->m_bIsFloating) - pWindow->m_bIsFloating = true; - break; - - case true: - if (!OPENINGON->m_bIsFloating) - pWindow->m_bIsFloating = false; - break; - } + pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); @@ -335,21 +325,47 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->currentlyDraggedWindow.reset(); g_pInputManager->m_bWasDraggingWindow = true; - if (DRAGGINGWINDOW->m_bDraggingTiled) { - DRAGGINGWINDOW->m_bIsFloating = false; - g_pInputManager->refocus(); - changeWindowFloatingMode(DRAGGINGWINDOW); - DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; - } else if (g_pInputManager->dragMode == MBIND_MOVE) { + if (g_pInputManager->dragMode == MBIND_MOVE) { g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING | FLOATING_ONLY, DRAGGINGWINDOW); + PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, DRAGGINGWINDOW); if (pWindow) { if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW)) return; - if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) { + bool denied = false; + if (!pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled) + denied = true; + + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !denied) { + if (DRAGGINGWINDOW->m_bDraggingTiled) { + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + DRAGGINGWINDOW->m_bDraggingTiled = false; + } + + if (DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock()) { + std::vector members; + PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); + do { + members.push_back(curr); + curr = curr->m_sGroupData.pNextWindow.lock(); + } while (curr != members[0]); + + for (auto it = members.begin(); it != members.end(); ++it) { + (*it)->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members + if (pWindow->m_bIsFloating) + (*it)->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + } + } + + DRAGGINGWINDOW->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of the window + + if (pWindow->m_bIsFloating) + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window + static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); pWindow->setGroupCurrent(DRAGGINGWINDOW); @@ -361,6 +377,13 @@ void IHyprLayout::onEndDragWindow() { } } + if (DRAGGINGWINDOW->m_bDraggingTiled) { + DRAGGINGWINDOW->m_bIsFloating = false; + g_pInputManager->refocus(); + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + } + g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); g_pCompositor->focusWindow(DRAGGINGWINDOW); @@ -553,10 +576,10 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vLastFloatingSize = PSAVEDSIZE; - // move to narnia because we don't wanna find our own node. onWindowCreated should apply the coords back. + // move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back. pWindow->m_vPosition = Vector2D(-999999, -999999); - onWindowCreated(pWindow); + onWindowCreatedTiling(pWindow); pWindow->m_vRealPosition.setValue(PSAVEDPOS); pWindow->m_vRealSize.setValue(PSAVEDSIZE); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4cdb9043..ef6c81e6 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -402,8 +402,9 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock())) + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2)) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; @@ -435,6 +436,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND // restores the group for (auto it = members.begin(); it != members.end(); ++it) { + (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members + if (pWindowInsertAfter->m_bIsFloating) + (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members if (std::next(it) != members.end()) (*it)->m_sGroupData.pNextWindow = *std::next(it); else @@ -442,9 +446,13 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND } members[0]->m_sGroupData.head = true; members[0]->m_sGroupData.locked = WASLOCKED; - } else { + } else g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); - } + + pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window + + if (pWindowInsertAfter->m_bIsFloating) + g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize.goal()); // match the size of the window pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); From b3a7e3109bf2b7b4422424471130197dc08baeb1 Mon Sep 17 00:00:00 2001 From: davc0n Date: Tue, 8 Oct 2024 12:42:51 +0200 Subject: [PATCH 0113/1803] misc: refactor version command (#8027) Fixes a minor spacing issue if git status is not dirty. Additionally now should be easier to extend it eventually. --- src/main.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 279e1ce1..57bb5507 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -116,11 +116,20 @@ int main(int argc, char** argv) { return 0; } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { + auto result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH; + auto dirty = std::string(GIT_DIRTY); + if (!dirty.empty()) + result += " " + dirty; + auto commitMsg = trim(GIT_COMMIT_MESSAGE); std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); - std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + - "\n\nflags: (if any)\n"; + result += " (" + commitMsg + ")."; + + result += "\nDate: " + std::string(GIT_COMMIT_DATE); + result += "\nTag: " + std::string(GIT_TAG) + ", commits: " + std::string(GIT_COMMITS); + result += "\nbuilt against aquamarine " + std::string(AQUAMARINE_VERSION); + + result += "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; From e0cfbec66b97edb2957508152f32e77a1b181afc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 8 Oct 2024 13:15:53 +0100 Subject: [PATCH 0114/1803] keybinds: fixup xkb_states for resolve_by_sym fixes #7750 --- src/devices/IKeyboard.cpp | 10 ++++++++++ src/devices/IKeyboard.hpp | 5 +++-- src/managers/KeybindManager.cpp | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 13440169..3300f252 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -178,13 +178,18 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { if (xkbState) xkb_state_unref(xkbState); + if (xkbSymState) + xkb_state_unref(xkbSymState); + xkbState = nullptr; xkbStaticState = nullptr; + xkbSymState = nullptr; if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); xkbStaticState = xkb_state_new(keymap); xkbState = xkb_state_new(keymap); + xkbSymState = xkb_state_new(keymap); return; } @@ -230,6 +235,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { xkbState = xkb_state_new(KEYMAP); xkbStaticState = xkb_state_new(KEYMAP); + xkbSymState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -252,6 +258,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { xkbState = xkb_state_new(NEWKEYMAP); xkbStaticState = xkb_state_new(NEWKEYMAP); + xkbSymState = xkb_state_new(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP); xkb_context_unref(PCONTEXT); @@ -332,6 +339,9 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group); + if (xkbSymState) + xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, group); + if (!updateModifiersState()) return; diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 759b2f58..76d2c31b 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -82,8 +82,9 @@ class IKeyboard : public IHID { bool keymapOverridden = false; xkb_layout_index_t activeLayout = 0; - xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr; - xkb_keymap* xkbKeymap = nullptr; + xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr, + *xkbSymState = nullptr /* Same as static but gets layouts */; + xkb_keymap* xkbKeymap = nullptr; struct { uint32_t depressed = 0, latched = 0, locked = 0, group = 0; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cd47bf71..d893e258 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -376,7 +376,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbState : m_pXKBTranslationState, KEYCODE); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE); const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) From 1bf63dfdcd76c09137b4647f9af2c5ebc9fc6e34 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:59:15 +0100 Subject: [PATCH 0115/1803] protocols: Add support for hyprland-ctm-control-v1 (#8023) * initial ctm support * flake.lock: update * Meson: bump required versions and add ctm proto --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 6 ++- flake.lock | 36 ++++++------- meson.build | 2 +- protocols/meson.build | 3 +- src/helpers/Monitor.cpp | 6 +++ src/helpers/Monitor.hpp | 5 ++ src/managers/ProtocolManager.cpp | 3 ++ src/protocols/CTMControl.cpp | 86 ++++++++++++++++++++++++++++++++ src/protocols/CTMControl.hpp | 44 ++++++++++++++++ src/render/Renderer.cpp | 5 ++ 10 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 src/protocols/CTMControl.cpp create mode 100644 src/protocols/CTMControl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bac29ab..4de449dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,7 +100,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) -pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine) +pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") @@ -274,7 +274,7 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) -pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0) +pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.0) if(hyprland_protocols_dep_FOUND) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") @@ -301,6 +301,8 @@ protocolnew("protocols" "wlr-data-control-unstable-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) protocolnew("protocols" "wayland-drm" true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) + protocolnew("staging/tearing-control" "tearing-control-v1" false) protocolnew("staging/fractional-scale" "fractional-scale-v1" false) protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false) diff --git a/flake.lock b/flake.lock index 85069a74..de9a4dce 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1727261104, - "narHash": "sha256-rxDI7WrxIRV9it9mDCHcLa7xQykf1JloXnoXr5xQ8zI=", + "lastModified": 1728326504, + "narHash": "sha256-dQXAj+4d6neY7ldCiH6gNym3upP49PVxRzEPxXlD9Aw=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "b82fdaff917582a9d568969e15e61b398c71e990", + "rev": "65dd97b5d21e917295159bbef1d52e06963f4eb0", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1727532803, - "narHash": "sha256-ZaZ7h7PY8mQc4vtGmVqWLAq9CAO02gHMyNR5yY8zDmM=", + "lastModified": 1727821604, + "narHash": "sha256-hNw5J6xatedqytYowx0mJKgctjA4lQARZFdgnzM2RpM=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "b98726e431d4d3ed58bd58bee1047cdb81cec69f", + "rev": "d60e1e01e6e6633ef1c87148b9137cc1dd39263d", "type": "github" }, "original": { @@ -102,11 +102,11 @@ ] }, "locked": { - "lastModified": 1727451107, - "narHash": "sha256-qV9savtHwmZUa0eJE294WYJjKPGB2+bJhwByFShsVyo=", + "lastModified": 1728345020, + "narHash": "sha256-xGbkc7U/Roe0/Cv3iKlzijIaFBNguasI31ynL2IlEoM=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "6b3261ee13a6d2b99de79a31d352f6996e35bde3", + "rev": "a7c183800e74f337753de186522b9017a07a8cee", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1725997860, - "narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=", + "lastModified": 1728168612, + "narHash": "sha256-AnB1KfiXINmuiW7BALYrKqcjCnsLZPifhb/7BsfPbns=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876", + "rev": "f054f2e44d6a0b74607a6bc0f52dba337a3db38e", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1727348695, - "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", + "lastModified": 1728018373, + "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", + "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", "type": "github" }, "original": { @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1727524473, - "narHash": "sha256-1DGktDtSWIJpnDbVoj/qpvJSH5zg6JbOfuh6xqZMap0=", + "lastModified": 1728166987, + "narHash": "sha256-w6dVTguAn9zJ+7aPOhBQgDz8bn6YZ7b56cY8Kg5HJRI=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "7e500e679ede40e79cf2d89b5f5fa3e34923bd26", + "rev": "fb9c8d665af0588bb087f97d0f673ddf0d501787", "type": "github" }, "original": { diff --git a/meson.build b/meson.build index 3545f46a..e9bbb99d 100644 --- a/meson.build +++ b/meson.build @@ -30,7 +30,7 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif -aquamarine = dependency('aquamarine') +aquamarine = dependency('aquamarine', version: '>=0.4.2') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') xcb_dep = dependency('xcb', required: get_option('xwayland')) diff --git a/protocols/meson.build b/protocols/meson.build index 3fa2ef2f..2c0d06d1 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -7,7 +7,7 @@ wayland_protos = dependency( hyprland_protos = dependency( 'hyprland-protocols', - version: '>=0.2', + version: '>=0.4', fallback: 'hyprland-protocols', ) @@ -36,6 +36,7 @@ protocols = [ hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml', wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index c6cef41f..f3e7de4e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -813,6 +813,12 @@ void CMonitor::scheduleDone() { }); } +void CMonitor::setCTM(const Mat3x3& ctm_) { + ctm = ctm_; + ctmUpdated = true; + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME); +} + bool CMonitor::attemptDirectScanout() { if (!mirrors.empty() || isMirror() || g_pHyprRenderer->m_bDirectScanoutBlocked) return false; // do not DS if this monitor is being mirrored. Will break the functionality. diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2a2edab6..f5068dba 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -131,6 +131,10 @@ class CMonitor { CMonitor* pMirrorOf = nullptr; std::vector mirrors; + // ctm + Mat3x3 ctm = Mat3x3::identity(); + bool ctmUpdated = false; + // for tearing PHLWINDOWREF solitaryClient; @@ -179,6 +183,7 @@ class CMonitor { CBox logicalBox(); void scheduleDone(); bool attemptDirectScanout(); + void setCTM(const Mat3x3& ctm); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6366eefe..25a34657 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -46,6 +46,7 @@ #include "../protocols/XDGDialog.hpp" #include "../protocols/SinglePixel.hpp" #include "../protocols/SecurityContext.hpp" +#include "../protocols/CTMControl.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -157,6 +158,7 @@ CProtocolManager::CProtocolManager() { PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); + PROTO::ctm = std::make_unique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) @@ -229,6 +231,7 @@ CProtocolManager::~CProtocolManager() { PROTO::xdgDialog.reset(); PROTO::singlePixel.reset(); PROTO::securityContext.reset(); + PROTO::ctm.reset(); PROTO::lease.reset(); PROTO::sync.reset(); diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp new file mode 100644 index 00000000..f2a54c6f --- /dev/null +++ b/src/protocols/CTMControl.cpp @@ -0,0 +1,86 @@ +#include "CTMControl.hpp" +#include "../Compositor.hpp" +#include "core/Output.hpp" + +CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); }); + resource->setOnDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); }); + + resource->setSetCtmForOutput([this](CHyprlandCtmControlManagerV1* r, wl_resource* output, wl_fixed_t mat0, wl_fixed_t mat1, wl_fixed_t mat2, wl_fixed_t mat3, wl_fixed_t mat4, + wl_fixed_t mat5, wl_fixed_t mat6, wl_fixed_t mat7, wl_fixed_t mat8) { + const auto OUTPUTRESOURCE = CWLOutputResource::fromResource(output); + + if (!OUTPUTRESOURCE) + return; // ?! + + const auto PMONITOR = OUTPUTRESOURCE->monitor.lock(); + + if (!PMONITOR) + return; // ?!?! + + const std::array MAT = {wl_fixed_to_double(mat0), wl_fixed_to_double(mat1), wl_fixed_to_double(mat2), wl_fixed_to_double(mat3), wl_fixed_to_double(mat4), + wl_fixed_to_double(mat5), wl_fixed_to_double(mat6), wl_fixed_to_double(mat7), wl_fixed_to_double(mat8)}; + + for (auto& el : MAT) { + if (el < 0.F) { + resource->error(HYPRLAND_CTM_CONTROL_MANAGER_V1_ERROR_INVALID_MATRIX, "a matrix component was < 0"); + return; + } + } + + ctms[PMONITOR->szName] = MAT; + + LOGM(LOG, "CTM set for output {}: {}", PMONITOR->szName, ctms.at(PMONITOR->szName).toString()); + }); + + resource->setCommit([this](CHyprlandCtmControlManagerV1* r) { + LOGM(LOG, "Committing ctms to outputs"); + + for (auto& m : g_pCompositor->m_vMonitors) { + if (!ctms.contains(m->szName)) { + PROTO::ctm->setCTM(m, Mat3x3::identity()); + continue; + } + + PROTO::ctm->setCTM(m, ctms.at(m->szName)); + } + }); +} + +CHyprlandCTMControlResource::~CHyprlandCTMControlResource() { + for (auto& m : g_pCompositor->m_vMonitors) { + PROTO::ctm->setCTM(m, Mat3x3::identity()); + } +} + +bool CHyprlandCTMControlResource::good() { + return resource->resource(); +} + +CHyprlandCTMControlProtocol::CHyprlandCTMControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } + + LOGM(LOG, "New CTM Manager at 0x{:x}", (uintptr_t)RESOURCE.get()); +} + +void CHyprlandCTMControlProtocol::destroyResource(CHyprlandCTMControlResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CHyprlandCTMControlProtocol::setCTM(SP monitor, const Mat3x3& ctm) { + monitor->setCTM(ctm); +} diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp new file mode 100644 index 00000000..08f1b0e8 --- /dev/null +++ b/src/protocols/CTMControl.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "hyprland-ctm-control-v1.hpp" +#include + +class CMonitor; + +class CHyprlandCTMControlResource { + public: + CHyprlandCTMControlResource(SP resource_); + ~CHyprlandCTMControlResource(); + + bool good(); + + private: + SP resource; + + std::unordered_map ctms; +}; + +class CHyprlandCTMControlProtocol : public IWaylandProtocol { + public: + CHyprlandCTMControlProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CHyprlandCTMControlResource* resource); + + void setCTM(SP monitor, const Mat3x3& ctm); + + // + std::vector> m_vManagers; + + friend class CHyprlandCTMControlResource; +}; + +namespace PROTO { + inline UP ctm; +}; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 310d45af..f388ec37 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1498,6 +1498,11 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { if (inFD >= 0) pMonitor->output->state->setExplicitInFence(inFD); + if (pMonitor->ctmUpdated) { + pMonitor->ctmUpdated = false; + pMonitor->output->state->setCTM(pMonitor->ctm); + } + bool ok = pMonitor->state.commit(); if (!ok) { if (inFD >= 0) { From 57b632ead88b4558a53e52aa9c098d48362ee768 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 17:02:55 +0100 Subject: [PATCH 0116/1803] pointer: expand sw cursor damage box fixes #8031 just a bit, rounding errors I guess --- src/managers/PointerManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 736b629c..cc9deec7 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -657,7 +657,7 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { } void CPointerManager::damageIfSoftware() { - auto b = getCursorBoxGlobal(); + auto b = getCursorBoxGlobal().expand(4); static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); From e4a26f4f1d9d30569b9e7e6c265fccfd42fa5d72 Mon Sep 17 00:00:00 2001 From: JManch <61563764+JManch@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:50:06 +0100 Subject: [PATCH 0117/1803] dispatchers: allow leading whitespace in window parameter (#8016) --- src/Compositor.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f00e1e34..459aca11 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2445,13 +2445,31 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor, IOutput::scheduleF pMonitor->output->scheduleFrame(reason); } -PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { +PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) { + auto regexp = trim(regexp_); + if (regexp.starts_with("active")) return m_pLastWindow.lock(); + else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) { + // first floating on the current ws + if (!valid(m_pLastWindow)) + return nullptr; + + const bool FLOAT = regexp.starts_with("floating"); + + for (auto const& w : m_vWindows) { + if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden()) + continue; + + return w; + } + + return nullptr; + } eFocusWindowMode mode = MODE_CLASS_REGEX; - std::regex regexCheck(regexp); + std::regex regexCheck(regexp_); std::string matchCheck; if (regexp.starts_with("class:")) { regexCheck = std::regex(regexp.substr(6)); @@ -2470,21 +2488,6 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { } else if (regexp.starts_with("pid:")) { mode = MODE_PID; matchCheck = regexp.substr(4); - } else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) { - // first floating on the current ws - if (!valid(m_pLastWindow)) - return nullptr; - - const bool FLOAT = regexp.starts_with("floating"); - - for (auto const& w : m_vWindows) { - if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden()) - continue; - - return w; - } - - return nullptr; } for (auto const& w : g_pCompositor->m_vWindows) { From 613eac4603f4a15868c88a47a8ee8dcb84ee2dd3 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 8 Oct 2024 20:31:15 +0200 Subject: [PATCH 0118/1803] layout: remove unnecessary check after 45e8219 (#8037) --- src/layout/IHyprLayout.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f249d2b5..24ee13f4 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -186,12 +186,12 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { g_pCompositor->m_pLastWindow.lock() : g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); - if ((*PAUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. - && OPENINGON // check if OPENINGON exists. - && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. - && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group - && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON - && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + if (*PAUTOGROUP // check if auto_group is enabled. + && OPENINGON // check if OPENINGON exists. + && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group + && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state From 60308a2bb576413cbc787d4bde4f8d0e3fa3c9d6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 20:28:30 +0100 Subject: [PATCH 0119/1803] defaultConfig: add a nofocus rule for weird X windows ref #6543 --- example/hyprland.conf | 6 +++++- src/config/defaultConfig.hpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 4adc2d40..3478bcff 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -255,4 +255,8 @@ bindl = , XF86AudioPrev, exec, playerctl previous # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ -windowrulev2 = suppressevent maximize, class:.* # You'll probably like this. +# Ignore maximize requests from apps. You'll probably like this. +windowrulev2 = suppressevent maximize, class:.* + +# Fix some dragging issues with XWayland +windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 5843caa3..54ce6642 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -268,5 +268,9 @@ bindl = , XF86AudioPrev, exec, playerctl previous # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ -windowrulev2 = suppressevent maximize, class:.* # You'll probably like this. +# Ignore maximize requests from apps. You'll probably like this. +windowrulev2 = suppressevent maximize, class:.* + +# Fix some dragging issues with XWayland +windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 )#"; From 91299f7039d80b25b3f0296d3d0f4d2059d41869 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 8 Oct 2024 21:20:25 +0100 Subject: [PATCH 0120/1803] hyprerror: make hyprerror reserve space (#8040) --- src/hyprerror/HyprError.cpp | 20 ++++++++++++++++++++ src/hyprerror/HyprError.hpp | 12 ++++++++---- src/render/Renderer.cpp | 17 +++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index bbc3a006..5f63de24 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -3,6 +3,9 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" +#include +using namespace Hyprutils::Utils; + CHyprError::CHyprError() { m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE); m_fFadeOpacity.registerVar(); @@ -130,6 +133,8 @@ void CHyprError::createQueued() { } m_szQueued = ""; + m_fLastHeight = yoffset + PAD + 1; + pango_font_description_free(pangoFD); g_object_unref(layoutText); @@ -158,6 +163,8 @@ void CHyprError::createQueued() { m_cQueued = CColor(); g_pHyprRenderer->damageMonitor(PMONITOR); + + g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID); } void CHyprError::draw() { @@ -174,6 +181,11 @@ void CHyprError::draw() { m_pTexture->destroyTexture(); m_bIsCreated = false; m_szQueued = ""; + + for (auto& m : g_pCompositor->m_vMonitors) { + g_pHyprRenderer->arrangeLayersForMonitor(m->ID); + } + return; } else { m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); @@ -203,3 +215,11 @@ void CHyprError::destroy() { else m_szQueued = ""; } + +bool CHyprError::active() { + return m_bIsCreated; +} + +float CHyprError::height() { + return m_fLastHeight; +} diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index 8dbb4521..a553614c 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -11,9 +11,12 @@ class CHyprError { CHyprError(); ~CHyprError(); - void queueCreate(std::string message, const CColor& color); - void draw(); - void destroy(); + void queueCreate(std::string message, const CColor& color); + void draw(); + void destroy(); + + bool active(); + float height(); // logical private: void createQueued(); @@ -23,7 +26,8 @@ class CHyprError { bool m_bIsCreated = false; SP m_pTexture; CAnimatedVariable m_fFadeOpacity; - CBox m_bDamageBox = {0, 0, 0, 0}; + CBox m_bDamageBox = {0, 0, 0, 0}; + float m_fLastHeight = 0.F; bool m_bMonitorChanged = false; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f388ec37..61f94014 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -97,6 +97,16 @@ CHyprRenderer::CHyprRenderer() { ensureCursorRenderingMode(); }); + static auto P3 = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { + g_pEventLoopManager->doLater([this]() { + if (!g_pHyprError->active()) + return; + for (auto& m : g_pCompositor->m_vMonitors) { + arrangeLayersForMonitor(m->ID); + } + }); + }); + m_pCursorTicker = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, cursorTicker, nullptr); wl_event_source_timer_update(m_pCursorTicker, 500); @@ -1757,6 +1767,13 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + if (g_pHyprError->active() && g_pCompositor->m_pLastMonitor == PMONITOR->self) { + const auto HEIGHT = g_pHyprError->height(); + PMONITOR->vecReservedTopLeft.y = HEIGHT; + usableArea.y += HEIGHT; + usableArea.h -= HEIGHT; + } + for (auto& la : PMONITOR->m_aLayerSurfaceLayers) { std::stable_sort(la.begin(), la.end(), [](const PHLLSREF& a, const PHLLSREF& b) { return a->order > b->order; }); } From 8cced091f53c92bc8de97b9d3dac20b31980af70 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 21:58:40 +0100 Subject: [PATCH 0121/1803] renderer: reserve space for error at the bottom if that's set ref #8040 --- src/render/Renderer.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 61f94014..bc95abc6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1756,7 +1756,9 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgetMonitorFromID(monitor); + const auto PMONITOR = g_pCompositor->getMonitorFromID(monitor); + + static auto BAR_POSITION = CConfigValue("debug:error_position"); if (!PMONITOR) return; @@ -1768,10 +1770,15 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; if (g_pHyprError->active() && g_pCompositor->m_pLastMonitor == PMONITOR->self) { - const auto HEIGHT = g_pHyprError->height(); - PMONITOR->vecReservedTopLeft.y = HEIGHT; - usableArea.y += HEIGHT; - usableArea.h -= HEIGHT; + const auto HEIGHT = g_pHyprError->height(); + if (*BAR_POSITION == 0) { + PMONITOR->vecReservedTopLeft.y = HEIGHT; + usableArea.y += HEIGHT; + usableArea.h -= HEIGHT; + } else { + PMONITOR->vecReservedBottomRight.y = HEIGHT; + usableArea.h -= HEIGHT; + } } for (auto& la : PMONITOR->m_aLayerSurfaceLayers) { From ac658500fbebe607f2db83f11c37f0a3a05ef734 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 23:33:10 +0100 Subject: [PATCH 0122/1803] keyboard: update group state on change for the sym resolve state fixes #8038 --- src/devices/IKeyboard.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 3300f252..d1119772 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -392,6 +392,9 @@ void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); if (updateModifiersState()) { + if (xkbSymState) + xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, modifiersState.group); + keyboardEvents.modifiers.emit(SModifiersEvent{ .depressed = modifiersState.depressed, .latched = modifiersState.latched, From bc299928ad5571300180eb8edb6742ed3bbf0282 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 9 Oct 2024 00:26:40 +0100 Subject: [PATCH 0123/1803] output/xdg-output: avoid sending events to released globals ref #6835 --- src/protocols/XDGOutput.cpp | 4 +++- src/protocols/XDGOutput.hpp | 2 ++ src/protocols/core/Output.cpp | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 0cdadd43..0598e713 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -51,6 +51,8 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 #endif pXDGOutput->client = CLIENT; + pXDGOutput->outputProto = OUTPUT->owner; + if (!pXDGOutput->resource->resource()) { m_vXDGOutputs.pop_back(); mgr->noMemory(); @@ -104,7 +106,7 @@ CXDGOutput::CXDGOutput(SP resource_, SP monitor_) : mon void CXDGOutput::sendDetails() { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - if (!monitor) + if (!monitor || !outputProto || outputProto->isDefunct()) return; const auto POS = isXWayland ? monitor->vecXWaylandPosition : monitor->vecPosition; diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 15d86cc7..520f3aaa 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -6,6 +6,7 @@ class CMonitor; class CXDGOutputProtocol; +class CWLOutputProtocol; class CXDGOutput { public: @@ -16,6 +17,7 @@ class CXDGOutput { private: WP monitor; SP resource; + WP outputProto; std::optional overridePosition; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 7b88e0a8..4047774a 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -47,7 +47,7 @@ SP CWLOutputResource::getResource() { } void CWLOutputResource::updateState() { - if (!monitor || (owner && owner->defunct)) + if (!monitor || !owner || owner->defunct) return; if (resource->version() >= 2) @@ -119,6 +119,9 @@ bool CWLOutputProtocol::isDefunct() { } void CWLOutputProtocol::sendDone() { + if (defunct) + return; + for (auto const& r : m_vOutputs) { r->resource->sendDone(); } From 6ce07ee86453e8ef01faa7b4e1eb8f09475f32b7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 9 Oct 2024 12:00:43 +0300 Subject: [PATCH 0124/1803] CI/release: remove script backup line --- .github/workflows/release.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1f52b4ff..d5ff1aa0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,7 +20,6 @@ jobs: run: | git fetch --unshallow || echo "failed unshallowing" bash -c scripts/generateVersion.sh - mv scripts/generateVersion.sh scripts/generateVersion.sh.bak - name: Create tarball with submodules id: tar From 223dcc8bac7fee90aa6aa7596d9379e56b526e62 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Wed, 9 Oct 2024 04:24:05 -0500 Subject: [PATCH 0125/1803] output: update state even if no owner exists (#8044) --- src/protocols/core/Output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 4047774a..3e68937f 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -47,7 +47,7 @@ SP CWLOutputResource::getResource() { } void CWLOutputResource::updateState() { - if (!monitor || !owner || owner->defunct) + if (!monitor || (owner && owner->defunct)) return; if (resource->version() >= 2) From 3d28879c2640cdb6e8426127692240100793bfef Mon Sep 17 00:00:00 2001 From: JManch <61563764+JManch@users.noreply.github.com> Date: Wed, 9 Oct 2024 10:24:35 +0100 Subject: [PATCH 0126/1803] hyprerror: fix height calc with bottom bar (#8043) --- src/hyprerror/HyprError.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 5f63de24..4044bcc9 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -133,7 +133,7 @@ void CHyprError::createQueued() { } m_szQueued = ""; - m_fLastHeight = yoffset + PAD + 1; + m_fLastHeight = yoffset + PAD + 1 - (TOPBAR ? 0 : Y - PAD); pango_font_description_free(pangoFD); g_object_unref(layoutText); From 6ae89940c761d4ed4317df0af29e8df41d472091 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 9 Oct 2024 11:58:49 +0200 Subject: [PATCH 0127/1803] layout: add merge_floated_into_tiled_on_groupbar (#8042) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/render/decorations/CHyprGroupBarDecoration.cpp | 12 +++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 2ca230be..d684e44a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -784,6 +784,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_CHOICE, .data = SConfigOptionDescription::SChoiceData{0, "disabled,enabled,only when dragging into the groupbar"}, }, + SConfigOptionDescription{ + .value = "group:merge_floated_into_tiled_on_groupbar", + .description = "whether dragging a floating window into a tiled window groupbar will merge them", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 9a5283fa..e973f1ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -377,6 +377,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index ef6c81e6..eca3f2cb 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -402,9 +402,15 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2)) + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); + + bool denied = false; + if (!m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) + denied = true; + + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || denied) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; From c4eb1940336cd88ca65ba65582ce104e49dfc7c9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 9 Oct 2024 22:00:06 +0100 Subject: [PATCH 0128/1803] gammactrl: guard pMonitor in setGamma --- src/protocols/GammaControl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 077d6e2f..e794e543 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -46,6 +46,13 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out resource->setOnDestroy([this](CZwlrGammaControlV1* gamma) { PROTO::gamma->destroyGammaControl(this); }); resource->setSetGamma([this](CZwlrGammaControlV1* gamma, int32_t fd) { + if (!pMonitor) { + LOGM(ERR, "setGamma for a dead monitor"); + resource->sendFailed(); + close(fd); + return; + } + LOGM(LOG, "setGamma for {}", pMonitor->szName); int fdFlags = fcntl(fd, F_GETFL, 0); From b65773bea9b912a41cfcbc789fb2e60a07e3d0c1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 10 Oct 2024 11:01:13 +0100 Subject: [PATCH 0129/1803] hyprpm: disallow shallow on unknown branch --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 669789b4..612995dc 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -436,7 +436,7 @@ bool CPluginManager::updateHeaders(bool force) { progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); - const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow; + const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow; // let us give a bit of leg-room for shallowing // due to timezones, etc. From d655a10381f01212635f2eadd69e1f22930f8f06 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:56:19 +0100 Subject: [PATCH 0130/1803] config/layout: nuke no_gaps_when_only (#8072) --- src/config/ConfigDescriptions.hpp | 12 ------------ src/config/ConfigManager.cpp | 2 -- src/layout/DwindleLayout.cpp | 30 ++++-------------------------- src/layout/MasterLayout.cpp | 30 +++++------------------------- src/managers/input/Touch.cpp | 1 - 5 files changed, 9 insertions(+), 66 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index d684e44a..bef5ee53 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1446,12 +1446,6 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_FLOAT, .data = SConfigOptionDescription::SFloatData{1, 0.1, 3}, }, - SConfigOptionDescription{ - .value = "dwindle:no_gaps_when_only", - .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", - .type = CONFIG_OPTION_CHOICE, - .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, - }, SConfigOptionDescription{ .value = "dwindle:use_active_for_splits", .description = "whether to prefer the active window or the mouse position for splits", @@ -1512,12 +1506,6 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_STRING_SHORT, .data = SConfigOptionDescription::SStringData{"none"}, }, - SConfigOptionDescription{ - .value = "master:no_gaps_when_only", - .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", - .type = CONFIG_OPTION_CHOICE, - .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, - }, SConfigOptionDescription{ .value = "master:orientation", .description = "default placement of the master area, can be left, right, top, bottom or center", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e973f1ab..6ec63d4c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -446,7 +446,6 @@ CConfigManager::CConfigManager() { 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", 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:split_bias", Hyprlang::INT{0}); @@ -459,7 +458,6 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_active", {"none"}); 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", Hyprlang::INT{1}); m_pConfig->addConfigValue("master:allow_small_split", Hyprlang::INT{0}); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 04cbf21d..76b26af1 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -142,11 +142,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - 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(); + 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); @@ -156,27 +155,6 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->m_vSize = nodeBox.size(); PWINDOW->m_vPosition = nodeBox.pos(); - const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->workspaceID()); - - if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (NODESONWORKSPACE == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) { - - PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noRounding = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noShadow = CWindowOverridableVar(true, PRIORITY_LAYOUT); - - PWINDOW->updateWindowDecos(); - - const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - - 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.goal()); - - return; - } - PWINDOW->updateWindowDecos(); auto calcPos = PWINDOW->m_vPosition; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 04a6ea29..8fde960d 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -631,12 +631,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - 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(); + 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); @@ -649,25 +648,6 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_vSize = pNode->size; PWINDOW->m_vPosition = pNode->position; - if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) { - - PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noRounding = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noShadow = CWindowOverridableVar(true, PRIORITY_LAYOUT); - - PWINDOW->updateWindowDecos(); - - const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - - 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.goal()); - - return; - } - PWINDOW->updateWindowDecos(); auto calcPos = PWINDOW->m_vPosition; diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 9b03168e..0333648a 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -39,7 +39,6 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { const auto PWORKSPACE = PMONITOR->activeWorkspace; const bool VERTANIMS = PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); - // TODO: support no_gaps_when_only? const double TARGETLEFT = ((VERTANIMS ? gapsOut.top : gapsOut.left) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x); const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.bottom : gapsOut.right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x)); const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x); From 178a300eeaf006fed4c8c9a599657b4530f65559 Mon Sep 17 00:00:00 2001 From: Jasson Date: Fri, 11 Oct 2024 07:07:25 -0400 Subject: [PATCH 0131/1803] xwayland: minor cleanups and fixes (#8076) --- src/managers/XWaylandManager.cpp | 110 +++++++++++++++---------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index fad7e451..8b63d37e 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -5,14 +5,13 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../xwayland/XWayland.hpp" +#include #define OUTPUT_MANAGER_VERSION 3 #define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3 #define OUTPUT_DESCRIPTION_MUTABLE_SINCE_VERSION 3 -CHyprXWaylandManager::CHyprXWaylandManager() { - ; -} +CHyprXWaylandManager::CHyprXWaylandManager() = default; CHyprXWaylandManager::~CHyprXWaylandManager() { #ifndef NO_XWAYLAND @@ -21,7 +20,7 @@ CHyprXWaylandManager::~CHyprXWaylandManager() { } SP CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) { - return pWindow->m_pWLSurface->resource(); + return pWindow ? pWindow->m_pWLSurface->resource() : nullptr; } void CHyprXWaylandManager::activateSurface(SP pSurface, bool activate) { @@ -40,27 +39,31 @@ void CHyprXWaylandManager::activateSurface(SP pSurface, bool return; } - if (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface) { - if (activate) { - PWINDOW->m_pXWaylandSurface->setMinimized(false); - PWINDOW->m_pXWaylandSurface->restackToTop(); + if (PWINDOW->m_bIsX11) { + if (PWINDOW->m_pXWaylandSurface) { + if (activate) { + PWINDOW->m_pXWaylandSurface->setMinimized(false); + PWINDOW->m_pXWaylandSurface->restackToTop(); + } + PWINDOW->m_pXWaylandSurface->activate(activate); } - PWINDOW->m_pXWaylandSurface->activate(activate); - } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) + } else if (PWINDOW->m_pXDGSurface) PWINDOW->m_pXDGSurface->toplevel->setActive(activate); } void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { - setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos if (activate) { + setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); + if (!pWindow->isX11OverrideRedirect()) pWindow->m_pXWaylandSurface->restackToTop(); } pWindow->m_pXWaylandSurface->activate(activate); + } else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel) pWindow->m_pXDGSurface->toplevel->setActive(activate); @@ -74,6 +77,9 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { } void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { + if (!pWindow) + return; + if (pWindow->m_bIsX11) { const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); @@ -83,7 +89,10 @@ void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { pbox->x = pWindow->m_pXWaylandSurface->geometry.x; pbox->y = pWindow->m_pXWaylandSurface->geometry.y; - if ((SIZEHINTS->flags & 0x2 /* ICCCM USSize */) || (SIZEHINTS->flags & 0x8 /* ICCCM PSize */)) { + constexpr int ICCCM_USSize = 0x2; + constexpr int ICCCM_PSize = 0x8; + + if ((SIZEHINTS->flags & ICCCM_USSize) || (SIZEHINTS->flags & ICCCM_PSize)) { pbox->w = SIZEHINTS->base_width; pbox->h = SIZEHINTS->base_height; } else { @@ -117,34 +126,34 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool Vector2D windowPos = pWindow->m_vRealPosition.value(); if (pWindow->m_bIsX11 && PMONITOR) { - windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor + windowPos -= PMONITOR->vecPosition; // normalize to monitor if (*PXWLFORCESCALEZERO) - windowPos = windowPos * PMONITOR->scale; // scale if applicable - windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland + windowPos *= PMONITOR->scale; // scale if applicable + windowPos += PMONITOR->vecXWaylandPosition; // move to correct position for xwayland } - if (!force && ((pWindow->m_vPendingReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vPendingReportedSize == size && !pWindow->m_bIsX11))) + if (!force && pWindow->m_vPendingReportedSize == size && (windowPos == pWindow->m_vReportedPosition || !pWindow->m_bIsX11)) return; pWindow->m_vReportedPosition = windowPos; pWindow->m_vPendingReportedSize = size; - pWindow->m_fX11SurfaceScaledBy = 1.f; + pWindow->m_fX11SurfaceScaledBy = 1.0f; if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) { - size = size * PMONITOR->scale; + size *= PMONITOR->scale; pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; } if (pWindow->m_bIsX11) pWindow->m_pXWaylandSurface->configure({windowPos, size}); else if (pWindow->m_pXDGSurface->toplevel) - pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor())); + pWindow->m_vPendingSizeAcks.emplace_back(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor()); } bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { if (pWindow->m_bIsX11) { - for (auto const& a : pWindow->m_pXWaylandSurface->atoms) + for (const auto& a : pWindow->m_pXWaylandSurface->atoms) if (a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] || @@ -157,16 +166,8 @@ bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { return true; } - if (pWindow->isModal()) - return true; - - if (pWindow->m_pXWaylandSurface->transient) - return true; - - if (pWindow->m_pXWaylandSurface->role.contains("task_dialog") || pWindow->m_pXWaylandSurface->role.contains("pop-up")) - return true; - - if (pWindow->m_pXWaylandSurface->overrideRedirect) + if (pWindow->isModal() || pWindow->m_pXWaylandSurface->transient || + (pWindow->m_pXWaylandSurface->role.contains("task_dialog") || pWindow->m_pXWaylandSurface->role.contains("pop-up")) || pWindow->m_pXWaylandSurface->overrideRedirect) return true; const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); @@ -203,6 +204,9 @@ void CHyprXWaylandManager::checkBorders(PHLWINDOW pWindow) { } void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscreen) { + if (!pWindow) + return; + if (pWindow->m_bIsX11) pWindow->m_pXWaylandSurface->setFullscreen(fullscreen); else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel) @@ -210,37 +214,33 @@ void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscree } Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) { - if (!validMapped(pWindow)) - return Vector2D(99999, 99999); + constexpr int NO_MAX_SIZE_LIMIT = 99999; + if (!validMapped(pWindow) || + ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || + pWindow->m_sWindowData.noMaxSize.valueOrDefault())) + return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); - if ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || - pWindow->m_sWindowData.noMaxSize.valueOrDefault()) - return Vector2D(99999, 99999); + Vector2D maxSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : + pWindow->m_pXDGSurface->toplevel->current.maxSize; - auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : - pWindow->m_pXDGSurface->toplevel->current.maxSize; + if (maxSize.x < 5) + maxSize.x = NO_MAX_SIZE_LIMIT; + if (maxSize.y < 5) + maxSize.y = NO_MAX_SIZE_LIMIT; - if (MAXSIZE.x < 5) - MAXSIZE.x = 99999; - if (MAXSIZE.y < 5) - MAXSIZE.y = 99999; - - return MAXSIZE; + return maxSize; } Vector2D CHyprXWaylandManager::getMinSizeForWindow(PHLWINDOW pWindow) { - if (!validMapped(pWindow)) + if (!validMapped(pWindow) || ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel))) return Vector2D(0, 0); - if ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel)) - return Vector2D(0, 0); + Vector2D minSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->min_width, pWindow->m_pXWaylandSurface->sizeHints->min_height) : + pWindow->m_pXDGSurface->toplevel->current.minSize; - auto MINSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->min_width, pWindow->m_pXWaylandSurface->sizeHints->min_height) : - pWindow->m_pXDGSurface->toplevel->current.minSize; + minSize = minSize.clamp({1, 1}); - MINSIZE = MINSIZE.clamp({1, 1}); - - return MINSIZE; + return minSize; } Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { @@ -249,7 +249,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { CMonitor* pMonitor = nullptr; double bestDistance = __FLT_MAX__; - for (auto const& m : g_pCompositor->m_vMonitors) { + for (const auto& m : g_pCompositor->m_vMonitors) { const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; double distance = @@ -268,9 +268,9 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { Vector2D result = coord - pMonitor->vecXWaylandPosition; // if scaled, unscale if (*PXWLFORCESCALEZERO) - result = result / pMonitor->scale; + result /= pMonitor->scale; // add pos - result = result + pMonitor->vecPosition; + result += pMonitor->vecPosition; return result; -} +} \ No newline at end of file From 7564b26b7d386d248eaa47c1a481c09eefd8e3ca Mon Sep 17 00:00:00 2001 From: Toni500github <88878648+Toni500github@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:19:16 +0200 Subject: [PATCH 0132/1803] internal: improve version query and define HYPRLAND_VERSION (#8034) --- CMakeLists.txt | 2 ++ hyprpm/src/core/PluginManager.cpp | 3 +-- meson.build | 1 + src/debug/HyprCtl.cpp | 23 +++++++++++++-------- src/debug/HyprCtl.hpp | 1 + src/main.cpp | 34 +++++-------------------------- 6 files changed, 25 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4de449dc..df919d76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,8 @@ else() message(STATUS "Configuring Hyprland in Release with CMake") endif() +add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}") + include_directories(. "src/" "protocols/") set(CMAKE_CXX_STANDARD 26) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 612995dc..96ec60ad 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -440,8 +440,7 @@ bool CPluginManager::updateHeaders(bool force) { // let us give a bit of leg-room for shallowing // due to timezones, etc. - const std::string SHALLOW_DATE = - trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'"); + const std::string SHALLOW_DATE = trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+%a %b %d %H:%M:%S %Y'"); if (m_bVerbose && bShallow) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE); diff --git a/meson.build b/meson.build index e9bbb99d..33e8fdbe 100644 --- a/meson.build +++ b/meson.build @@ -21,6 +21,7 @@ add_project_arguments( '-Wno-missing-field-initializers', '-Wno-narrowing', '-Wno-pointer-arith', datarootdir, + '-DHYPRLAND_VERSION="' + meson.project_version() + '"', ], language: 'cpp', ) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index d9274727..e0bb2b83 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -853,26 +853,33 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + - "\n\nflags: (if any)\n"; + std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" + "Date: {}\n" + "Tag: {}, commits: {}\n" + "built against aquamarine {}\n\n\n", + HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION); +#if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND)) + result += "no flags were set\n"; +#else + result += "flags set:\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; #endif -#ifndef ISDEBUG +#ifdef ISDEBUG result += "debug\n"; #endif #ifdef NO_XWAYLAND result += "no xwayland\n"; #endif - +#endif return result; } else { std::string result = std::format( R"#({{ "branch": "{}", "commit": "{}", + "version": "{}", "dirty": {}, "commit_message": "{}", "commit_date": "{}", @@ -880,13 +887,13 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "commits": "{}", "buildAquamarine": "{}", "flags": [)#", - GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, - AQUAMARINE_VERSION); + GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, + GIT_COMMITS, AQUAMARINE_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; #endif -#ifndef ISDEBUG +#ifdef ISDEBUG result += "\"debug\","; #endif #ifdef NO_XWAYLAND diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index d68bf14f..c1bf51ca 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -7,6 +7,7 @@ // exposed for main.cpp std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request); +std::string versionRequest(eHyprCtlOutputFormat format, std::string request); class CHyprCtl { public: diff --git a/src/main.cpp b/src/main.cpp index 57bb5507..45f212d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ void help() { std::cout << " --config FILE -c FILE - Specify config file to use\n"; std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; + std::cout << " --systeminfo - Prints system infos\n"; std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; std::cout << " --version -v - Print this binary's version\n"; } @@ -33,9 +34,9 @@ int main(int argc, char** argv) { throwError("XDG_RUNTIME_DIR is not set!"); // export HYPRLAND_CMD - std::string cmd = ""; - for (auto i = 0; i < argc; ++i) - cmd += std::string(i == 0 ? "" : " ") + argv[i]; + std::string cmd = argv[0]; + for (int i = 1; i < argc; ++i) + cmd += std::string(" ") + argv[i]; setenv("HYPRLAND_CMD", cmd.c_str(), 1); setenv("XDG_BACKEND", "wayland", 1); @@ -116,32 +117,7 @@ int main(int argc, char** argv) { return 0; } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { - auto result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH; - auto dirty = std::string(GIT_DIRTY); - if (!dirty.empty()) - result += " " + dirty; - - auto commitMsg = trim(GIT_COMMIT_MESSAGE); - std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); - result += " (" + commitMsg + ")."; - - result += "\nDate: " + std::string(GIT_COMMIT_DATE); - result += "\nTag: " + std::string(GIT_TAG) + ", commits: " + std::string(GIT_COMMITS); - result += "\nbuilt against aquamarine " + std::string(AQUAMARINE_VERSION); - - result += "\n\nflags: (if any)\n"; - -#ifdef LEGACY_RENDERER - result += "legacyrenderer\n"; -#endif -#ifndef ISDEBUG - result += "debug\n"; -#endif -#ifdef NO_XWAYLAND - result += "no xwayland\n"; -#endif - - std::cout << result; + std::cout << versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "") << std::endl; return 0; } else if (it->compare("--systeminfo") == 0) { const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""); From f5db4839730643169b7e8b7fb6ae2fbb8743ebe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgars=20C=C4=ABrulis?= Date: Sat, 12 Oct 2024 03:12:07 +0300 Subject: [PATCH 0133/1803] drm-timeline: Add check for conflicting acquire and release points (#8083) Signed-off-by: Edgars Cirulis --- src/protocols/DRMSyncobj.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 4993f1a4..a7f242ee 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -55,8 +55,13 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP= pending.releasePoint) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, "Acquire and release points are on the same timeline, and acquire >= release"); + surface->pending.rejected = true; + return; + } + } // wait for the acquire timeline to materialize auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); From ee8116ac5dc412dce924a0163074ce7988dd0cfc Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sat, 12 Oct 2024 03:29:51 +0300 Subject: [PATCH 0134/1803] input: Fix VRR for constrained cursors (#6877) --- src/Compositor.cpp | 4 +++ src/events/Windows.cpp | 19 +++++++++++-- src/helpers/Monitor.cpp | 8 +++++- src/helpers/Monitor.hpp | 2 ++ src/helpers/Timer.cpp | 5 ++-- src/helpers/Timer.hpp | 2 +- src/managers/AnimationManager.cpp | 2 +- src/managers/PointerManager.cpp | 43 +++++++++++++++++++++++++---- src/managers/PointerManager.hpp | 7 +++++ src/managers/SeatManager.hpp | 3 ++ src/managers/input/InputManager.cpp | 21 ++++++++++++-- src/managers/input/InputManager.hpp | 1 + 12 files changed, 100 insertions(+), 17 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 459aca11..dcc6422d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1,4 +1,5 @@ #include "Compositor.hpp" +#include "debug/Log.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" #include "managers/CursorManager.hpp" @@ -1380,6 +1381,9 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { if (!validMapped(pWindow)) return; + if (pWindow == (top ? m_vWindows.back() : m_vWindows.front())) + return; + auto moveToZ = [&](PHLWINDOW pw, bool top) -> void { if (top) { for (auto it = m_vWindows.begin(); it != m_vWindows.end(); ++it) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 37f29130..e549907e 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -12,6 +12,7 @@ #include "../protocols/core/Compositor.hpp" #include "../protocols/ToplevelExport.hpp" #include "../xwayland/XSurface.hpp" +#include "managers/PointerManager.hpp" #include using namespace Hyprutils::String; @@ -758,8 +759,21 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_pWorkspace->m_bVisible) return; - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, - PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + + PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); + if (g_pSeatManager->isPointerFrameCommit) { + g_pSeatManager->isPointerFrameSkipped = false; + g_pSeatManager->isPointerFrameCommit = false; + } else + g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, + PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); + + if (g_pSeatManager->isPointerFrameSkipped) { + g_pPointerManager->sendStoredMovement(); + g_pSeatManager->sendPointerFrame(); + g_pSeatManager->isPointerFrameCommit = true; + } if (!PWINDOW->m_bIsX11) { PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces(); @@ -767,7 +781,6 @@ void Events::listener_commitWindow(void* owner, void* data) { } // 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.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.texture) { CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index f3e7de4e..091745df 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -16,6 +16,7 @@ #include "../protocols/core/Compositor.hpp" #include "sync/SyncTimeline.hpp" #include +#include "debug/Log.hpp" #include #include using namespace Hyprutils::String; @@ -384,7 +385,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; // keep requested minimum refresh rate - if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { + if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000.0f / *PMINRR) { // damage whole screen because some previous cursor box damages were skipped damage.damageEntire(); return false; @@ -933,6 +934,11 @@ bool CMonitor::attemptDirectScanout() { return true; } +void CMonitor::debugLastPresentation(const std::string& message) { + Debug::log(TRACE, "{} (last presentation {} - {} fps)", message, lastPresentationTimer.getMillis(), + lastPresentationTimer.getMillis() > 0 ? 1000.0f / lastPresentationTimer.getMillis() : 0.0f); +} + CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f5068dba..ad8a823b 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -185,6 +185,8 @@ class CMonitor { bool attemptDirectScanout(); void setCTM(const Mat3x3& ctm); + void debugLastPresentation(const std::string& message); + bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp index 7b1726df..e00c5918 100644 --- a/src/helpers/Timer.cpp +++ b/src/helpers/Timer.cpp @@ -1,4 +1,5 @@ #include "Timer.hpp" +#include void CTimer::reset() { m_tpLastReset = std::chrono::steady_clock::now(); @@ -8,8 +9,8 @@ std::chrono::steady_clock::duration CTimer::getDuration() { return std::chrono::steady_clock::now() - m_tpLastReset; } -long CTimer::getMillis() { - return std::chrono::duration_cast(getDuration()).count(); +float CTimer::getMillis() { + return std::chrono::duration_cast(getDuration()).count() / 1000.f; } float CTimer::getSeconds() { diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp index 827e7625..a58225d0 100644 --- a/src/helpers/Timer.hpp +++ b/src/helpers/Timer.hpp @@ -6,7 +6,7 @@ class CTimer { public: void reset(); float getSeconds(); - long getMillis(); + float getMillis(); const std::chrono::steady_clock::time_point& chrono() const; private: diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 092d9721..0ff94f1f 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -259,7 +259,7 @@ void CAnimationManager::tick() { // manually schedule a frame if (PMONITOR) - g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION); } // do it here, because if this alters the animation vars deque we would be in trouble above. diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index cc9deec7..8c2a1bad 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/PointerGestures.hpp" +#include "../protocols/RelativePointer.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/IdleNotify.hpp" #include "../protocols/core/Compositor.hpp" @@ -328,7 +329,7 @@ void CPointerManager::onCursorMoved() { continue; const auto CURSORPOS = getCursorPosForMonitor(m); - m->output->moveCursor(CURSORPOS); + m->output->moveCursor(CURSORPOS, m->shouldSkipScheduleFrameOnMouseEvent()); } if (recalc) @@ -342,7 +343,7 @@ bool CPointerManager::attemptHardwareCursor(SPmonitor.lock()); - state->monitor->output->moveCursor(CURSORPOS); + state->monitor->output->moveCursor(CURSORPOS, state->monitor->shouldSkipScheduleFrameOnMouseEvent()); auto texture = getCurrentCursorTexture(); @@ -385,7 +386,8 @@ bool CPointerManager::setHWCursorBuffer(SP state, SPcursorFrontBuffer = buf; - g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + if (!state->monitor->shouldSkipScheduleFrameOnMouseEvent()) + g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } @@ -676,8 +678,11 @@ void CPointerManager::warpTo(const Vector2D& logical) { damageIfSoftware(); pointerPos = closestValid(logical); - recheckEnteredOutputs(); - onCursorMoved(); + + if (!g_pInputManager->isLocked()) { + recheckEnteredOutputs(); + onCursorMoved(); + } damageIfSoftware(); } @@ -859,7 +864,14 @@ void CPointerManager::attachPointer(SP pointer) { }); listener->frame = pointer->pointerEvents.frame.registerListener([this] (std::any e) { - g_pSeatManager->sendPointerFrame(); + bool shouldSkip = false; + if (!g_pSeatManager->mouse.expired() && g_pInputManager->isLocked()) { + auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); + shouldSkip = PMONITOR && PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); + } + g_pSeatManager->isPointerFrameSkipped = shouldSkip; + if (!g_pSeatManager->isPointerFrameSkipped) + g_pSeatManager->sendPointerFrame(); }); listener->swipeBegin = pointer->pointerEvents.swipeBegin.registerListener([this] (std::any e) { @@ -1080,3 +1092,22 @@ void CPointerManager::damageCursor(SP pMonitor) { Vector2D CPointerManager::cursorSizeLogical() { return currentCursorImage.size / currentCursorImage.scale; } + +void CPointerManager::storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) { + storedTime = time; + storedDelta += delta; + storedUnaccel += deltaUnaccel; +} + +void CPointerManager::setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) { + storedTime = time; + storedDelta = delta; + storedUnaccel = deltaUnaccel; +} + +void CPointerManager::sendStoredMovement() { + PROTO::relativePointer->sendRelativeMotion((uint64_t)storedTime * 1000, storedDelta, storedUnaccel); + storedTime = 0; + storedDelta = Vector2D{}; + storedUnaccel = Vector2D{}; +} diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 4a4c4f61..6b89eb16 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -61,6 +61,9 @@ class CPointerManager { // Vector2D position(); Vector2D cursorSizeLogical(); + void storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel); + void setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel); + void sendStoredMovement(); void recheckEnteredOutputs(); @@ -154,6 +157,10 @@ class CPointerManager { Vector2D pointerPos = {0, 0}; + uint64_t storedTime = 0; + Vector2D storedDelta = {0, 0}; + Vector2D storedUnaccel = {0, 0}; + struct SMonitorPointerState { SMonitorPointerState(SP m) : monitor(m) {} ~SMonitorPointerState() {} diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index 5cc7eee0..e50f123f 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -128,6 +128,9 @@ class CSeatManager { void setGrab(SP grab); // nullptr removes SP seatGrab; + bool isPointerFrameSkipped = false; + bool isPointerFrameCommit = false; + private: struct SSeatResourceContainer { SSeatResourceContainer(SP); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 03c72919..eef5e040 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -87,6 +87,11 @@ void CInputManager::onMouseMoved(IPointer::SMotionEvent e) { const auto DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta; + if (g_pSeatManager->isPointerFrameSkipped) + g_pPointerManager->storeMovement((uint64_t)e.timeMs, DELTA, e.unaccel); + else + g_pPointerManager->setStoredMovement((uint64_t)e.timeMs, DELTA, e.unaccel); + PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel); g_pPointerManager->move(DELTA); @@ -167,7 +172,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_vLastCursorPosFloored = MOUSECOORDSFLOORED; - const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); + const auto PMONITOR = isLocked() && g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor.get() : g_pCompositor->getMonitorFromCursor(); // this can happen if there are no displays hooked up to Hyprland if (PMONITOR == nullptr) @@ -184,9 +189,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // constraints if (!g_pSeatManager->mouse.expired() && isConstrained()) { const auto SURF = CWLSurface::fromResource(g_pCompositor->m_pLastFocus.lock()); - const auto CONSTRAINT = SURF->constraint(); + const auto CONSTRAINT = SURF ? SURF->constraint() : nullptr; - if (SURF && CONSTRAINT) { + if (CONSTRAINT) { if (CONSTRAINT->isLocked()) { const auto HINT = CONSTRAINT->logicPositionHint(); g_pCompositor->warpCursorTo(HINT, true); @@ -1428,6 +1433,16 @@ bool CInputManager::isConstrained() { return false; } +bool CInputManager::isLocked() { + if (!isConstrained()) + return false; + + const auto SURF = CWLSurface::fromResource(g_pCompositor->m_pLastFocus.lock()); + const auto CONSTRAINT = SURF ? SURF->constraint() : nullptr; + + return CONSTRAINT && CONSTRAINT->isLocked(); +} + void CInputManager::updateCapabilities() { uint32_t caps = 0; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index ebf00b2d..d5634796 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -108,6 +108,7 @@ class CInputManager { void unconstrainMouse(); bool isConstrained(); + bool isLocked(); Vector2D getMouseCoordsInternal(); void refocus(); From c3f7c9bbb52b9ad3d24ccfcc5c552ed16c9985a5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 12 Oct 2024 15:18:34 +0100 Subject: [PATCH 0135/1803] xcursor: don't crash on broken permissions in X themes ref #8079 --- src/managers/XCursorManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 1e7ca535..93ee7965 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -117,9 +117,11 @@ void CXCursorManager::loadTheme(std::string const& name, int size, float scale) cursors = loadStandardCursors(themeName, lastLoadSize); } else { for (auto const& p : paths) { - auto dirCursors = loadAllFromDir(p, lastLoadSize); - std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(cursors), - [this](auto const& p) { return std::none_of(cursors.begin(), cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); }); + try { + auto dirCursors = loadAllFromDir(p, lastLoadSize); + std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(cursors), + [this](auto const& p) { return std::none_of(cursors.begin(), cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); }); + } catch (std::exception& e) { Debug::log(ERR, "XCursor path {} can't be loaded: threw error {}", p, e.what()); } } } From 1822707c7e7394ce8c7572f2fe890763a307f499 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 12 Oct 2024 17:56:46 +0100 Subject: [PATCH 0136/1803] drm-syncobj: fix crash on missing timelines fixes #8092 --- src/protocols/DRMSyncobj.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index a7f242ee..1da4baaf 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -55,6 +55,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP= pending.releasePoint) { resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, "Acquire and release points are on the same timeline, and acquire >= release"); From e79d3cd2ef5632e2e6b3b20fd0b5dc4d2843f956 Mon Sep 17 00:00:00 2001 From: Toni500git Date: Sun, 13 Oct 2024 14:23:33 +0200 Subject: [PATCH 0137/1803] hyprpm: convert std::cout and std::cerr to std::println() --- hyprpm/src/core/DataState.cpp | 6 +- hyprpm/src/core/PluginManager.cpp | 267 ++++++++++++++------------- hyprpm/src/core/PluginManager.hpp | 3 +- hyprpm/src/helpers/StringUtils.hpp | 32 ++++ hyprpm/src/main.cpp | 35 ++-- hyprpm/src/progress/CProgressBar.cpp | 16 +- hyprpm/src/progress/CProgressBar.hpp | 2 +- 7 files changed, 202 insertions(+), 159 deletions(-) create mode 100644 hyprpm/src/helpers/StringUtils.hpp diff --git a/hyprpm/src/core/DataState.cpp b/hyprpm/src/core/DataState.cpp index 05c63f4e..fb8679d6 100644 --- a/hyprpm/src/core/DataState.cpp +++ b/hyprpm/src/core/DataState.cpp @@ -1,6 +1,6 @@ #include "DataState.hpp" #include -#include +#include #include #include #include "PluginManager.hpp" @@ -8,7 +8,7 @@ std::string DataState::getDataStatePath() { const auto HOME = getenv("HOME"); if (!HOME) { - std::cerr << "DataState: no $HOME\n"; + std::println(stderr, "DataState: no $HOME"); throw std::runtime_error("no $HOME"); return ""; } @@ -242,4 +242,4 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) { } return false; -} \ No newline at end of file +} diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 96ec60ad..359b2c78 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -1,12 +1,15 @@ #include "PluginManager.hpp" #include "../helpers/Colors.hpp" +#include "../helpers/StringUtils.hpp" #include "../progress/CProgressBar.hpp" #include "Manifest.hpp" #include "DataState.hpp" +#include #include #include #include +#include #include #include #include @@ -31,6 +34,7 @@ static std::string execAndGet(std::string cmd) { if (!pipe) return ""; + result.reserve(buffer.size()); while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { result += buffer.data(); } @@ -47,10 +51,10 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { once = true; const auto HLVERCALL = execAndGet("hyprctl version"); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "version returned: " << HLVERCALL << "\n"; + std::println("{}", verboseString("version returned: {}", HLVERCALL)); if (!HLVERCALL.contains("Tag:")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " You don't seem to be running Hyprland."; + std::println(stderr, "\n{}", failureString("You don't seem to be running Hyprland.")); return SHyprlandVersion{}; } @@ -76,7 +80,7 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { } catch (...) { ; } if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "parsed commit " << hlcommit << " at branch " << hlbranch << " on " << hldate << ", commits " << commits << "\n"; + std::println("{}", verboseString("parsed commit {} at branch {} on {}, commits {}", hlcommit, hlbranch, hldate, commits)); ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits}; return ver; @@ -102,20 +106,21 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n"; + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); return false; } if (DataState::pluginRepoExists(url)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n"; + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Repository already installed.")); return false; } auto GLOBALSTATE = DataState::getGlobalState(); if (!GLOBALSTATE.dontWarnInstall) { - std::cout << Colors::YELLOW << "!" << Colors::RED << " Disclaimer:\n " << Colors::RESET - << "plugins, especially not official, have no guarantee of stability, availablity or security.\n Run them at your own risk.\n " - << "This message will not appear again.\n"; + std::println("{}!{} Disclaimer: {}", Colors::YELLOW, Colors::RED, Colors::RESET); + std::println("plugins, especially not official, have no guarantee of stability, availablity or security.\n" + "Run them at your own risk.\n" + "This message will not appear again."); GLOBALSTATE.dontWarnInstall = true; DataState::updateGlobalState(GLOBALSTATE); } @@ -129,7 +134,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::getline(std::cin, input); if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') { - std::cout << "Aborting.\n"; + std::println(stderr, "Aborting."); return false; } @@ -144,7 +149,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::filesystem::create_directory("/tmp/hyprpm"); std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); } else if (!std::filesystem::is_directory("/tmp/hyprpm")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hyprpm\n"; + std::println(stderr, "\n{}", failureString("Could not prepare working dir for hyprpm")); return false; } @@ -153,59 +158,59 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; if (!createSafeDirectory(m_szWorkingPluginDirectory)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for repo\n"; + std::println(stderr, "\n{}", failureString("Could not prepare working dir for repo")); return false; } - progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url); + progress.printMessageAbove(infoString("Cloning {}", url)); std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n"; + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret)); return false; } if (!rev.empty()) { std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " 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"; + std::println(stderr, "\n{}", failureString("Could not check out revision {}. shell returned:\n{}", rev, ret)); return false; } ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init"); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n"; + std::println("{}", verboseString("git submodule update --init returned: {}", ret)); } progress.m_iSteps = 1; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); + progress.printMessageAbove(successString("cloned")); progress.m_szCurrentMessage = "Reading the manifest"; progress.print(); std::unique_ptr pManifest; if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); + progress.printMessageAbove(successString("found hyprpm manifest")); pManifest = std::make_unique(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml"); } else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); + progress.printMessageAbove(successString("found hyprload manifest")); pManifest = std::make_unique(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml"); } if (!pManifest) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest")); return false; } if (!pManifest->m_bGood) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest")); return false; } progress.m_iSteps = 2; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"); + progress.printMessageAbove(successString("parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:")); for (auto const& pl : pManifest->m_vPlugins) { - std::string message = std::string{Colors::RESET} + " → " + pl.name + " by "; + std::string message = "→ " + pl.name + " by "; for (auto const& a : pl.authors) { message += a + ", "; } @@ -220,19 +225,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& if (!pManifest->m_sRepository.commitPins.empty()) { // check commit pins - progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); + progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size())); for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) { if (hl != HLVER.hash) continue; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); + progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin)); execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init"); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n"; + std::println("{}", verboseString("git submodule update --init returned: {}", ret)); break; } @@ -244,12 +249,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& const auto HEADERSSTATUS = headersValid(); if (HEADERSSTATUS != HEADERS_OK) { - std::cerr << "\n" << headerError(HEADERSSTATUS); + std::println("\n{}", headerError(HEADERSSTATUS)); return false; } progress.m_iSteps = 3; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " Hyprland headers OK"); + progress.printMessageAbove(successString("Hyprland headers OK")); progress.m_szCurrentMessage = "Building plugin(s)"; progress.print(); @@ -257,35 +262,36 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::string out; if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n"); + progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name)); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); + progress.printMessageAbove(infoString("Building {}", p.name)); for (auto const& bs : p.buildSteps) { - std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); + const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; + std::println("{}", verboseString("shell returned: " + out)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" + - " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update " - "first.\n Try re-running with -v to see " - "more verbose output.\n"); + progress.printMessageAbove(failureString("Plugin {} failed to build.\n" + " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n" + " If you are on -git, update first\n" + " Try re-running with -v to see more verbose output.\n", + p.name)); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); + progress.printMessageAbove(successString("built {} into {}", p.name, p.output)); } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " all plugins built"); + progress.printMessageAbove(successString("all plugins built")); progress.m_iSteps = 4; progress.m_szCurrentMessage = "Installing repository"; progress.print(); @@ -304,13 +310,13 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& } DataState::addNewPluginRepo(repo); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed repository"); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " you can now enable the plugin(s) with hyprpm enable"); + progress.printMessageAbove(successString("installed repository")); + progress.printMessageAbove(successString("you can now enable the plugin(s) with hyprpm enable")); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Done!"; progress.print(); - std::cout << "\n"; + std::print("\n"); // remove build files std::filesystem::remove_all(m_szWorkingPluginDirectory); @@ -320,7 +326,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& bool CPluginManager::removePluginRepo(const std::string& urlOrName) { if (!DataState::pluginRepoExists(urlOrName)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not remove the repository. Repository is not installed.\n"; + std::println(stderr, "\n{}", failureString("Could not remove the repository. Repository is not installed.")); return false; } @@ -331,7 +337,7 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) { std::getline(std::cin, input); if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') { - std::cout << "Aborting.\n"; + std::println("Aborting."); return false; } @@ -347,15 +353,15 @@ eHeadersErrors CPluginManager::headersValid() { return HEADERS_MISSING; // find headers commit - std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath()); - auto headers = execAndGet(cmd.c_str()); + const std::string& cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath()); + auto headers = execAndGet(cmd.c_str()); if (!headers.contains("-I/")) return HEADERS_MISSING; headers.pop_back(); // pop newline - std::string verHeader = ""; + std::string verHeader; while (!headers.empty()) { const auto PATH = headers.substr(0, headers.find(" -I/", 3)); @@ -406,7 +412,7 @@ bool CPluginManager::updateHeaders(bool force) { const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n"; + std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); return false; } @@ -416,7 +422,7 @@ bool CPluginManager::updateHeaders(bool force) { } if (!force && headersValid() == HEADERS_OK) { - std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n"; + std::println("\n{}", successString("Headers up to date.")); return true; } @@ -430,11 +436,11 @@ bool CPluginManager::updateHeaders(bool force) { const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME; if (!createSafeDirectory(WORKINGDIR)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hl\n"; + std::println("\n{}", failureString("Could not prepare working dir for hl")); return false; } - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); + progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/hyprwm/Hyprland, this might take a moment.")); const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow; @@ -443,60 +449,60 @@ bool CPluginManager::updateHeaders(bool force) { const std::string SHALLOW_DATE = trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+%a %b %d %H:%M:%S %Y'"); if (m_bVerbose && bShallow) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE); + progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE)); std::string ret = - execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")); + execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")); if (!std::filesystem::exists(WORKINGDIR)) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Clone failed. Retrying without shallow."); + progress.printMessageAbove(failureString("Clone failed. Retrying without shallow.")); ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME); } if (!std::filesystem::exists(WORKINGDIR + "/.git")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n"; + std::println(stderr, "\n{}", failureString("Could not clone the Hyprland repository. shell returned:\n{}", ret)); return false; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); + progress.printMessageAbove(successString("Hyprland cloned")); progress.m_iSteps = 2; progress.m_szCurrentMessage = "Checking out sources"; progress.print(); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); + progress.printMessageAbove(verboseString("will run: cd {} && git checkout {} 2>&1", WORKINGDIR, HLVER.hash)); ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); if (ret.contains("fatal: unable to read tree")) { - std::cerr << "\n" - << Colors::RED << "✖" << Colors::RESET - << " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n"; + std::println(stderr, "\n{}", + failureString("Could not checkout the running Hyprland commit. If you are on -git, try updating.\n" + "You can also try re-running hyprpm update with --no-shallow.")); return false; } if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret); + progress.printMessageAbove(verboseString("git returned (co): {}", ret)); ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret); + progress.printMessageAbove(verboseString("git returned (rs): {}", ret)); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " checked out to running ver"); + progress.printMessageAbove(successString("checked out to running ver")); progress.m_iSteps = 3; progress.m_szCurrentMessage = "Building Hyprland"; progress.print(); - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland"); + progress.printMessageAbove(statusString("!", Colors::YELLOW, "configuring Hyprland")); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath()); + progress.printMessageAbove(verboseString("setting PREFIX for cmake to {}", DataState::getHeadersPath())); ret = execAndGet(std::format("cd {} && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", WORKINGDIR, DataState::getHeadersPath())); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret); + progress.printMessageAbove(verboseString("cmake returned: {}", ret)); if (ret.contains("CMake Error at")) { // missing deps, let the user know. @@ -505,48 +511,46 @@ bool CPluginManager::updateHeaders(bool force) { missing = missing.substr(0, missing.find("-- Configuring incomplete")); missing = missing.substr(0, missing.find_last_of('\n')); - std::cerr << "\n" - << Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n" - << missing << "\n\nThis likely means that you are missing the above dependencies or they are out of date.\n"; + std::println(stderr, "\n{}", + failureString("Could not configure the hyprland source, cmake complained:\n{}\n\n" + "This likely means that you are missing the above dependencies or they are out of date.", + missing)); return false; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland"); + progress.printMessageAbove(successString("configured Hyprland")); progress.m_iSteps = 4; progress.m_szCurrentMessage = "Installing sources"; progress.print(); - std::string cmd = + const std::string& cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" {}/Makefile && cd {} && make installheaders", DataState::getHeadersPath(), WORKINGDIR, WORKINGDIR); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd); + progress.printMessageAbove(verboseString("installation will run: {}", cmd)); ret = execAndGet(cmd); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n"; + std::println("{}", verboseString("installer returned: {}", ret)); // remove build files std::filesystem::remove_all(WORKINGDIR); auto HEADERSVALID = headersValid(); if (HEADERSVALID == HEADERS_OK) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed headers"); + progress.printMessageAbove(successString("installed headers")); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Done!"; progress.print(); - std::cout << "\n"; + std::print("\n"); } else { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" + - headerErrorShort(HEADERSVALID) + ")"); + progress.printMessageAbove(failureString("failed to install headers with error code {} ({})", (int)HEADERSVALID, headerErrorShort(HEADERSVALID))); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Failed"; progress.print(); - std::cout << "\n"; - - std::cerr << "\n" << headerError(HEADERSVALID); + std::print(stderr, "\n\n{}", headerError(HEADERSVALID)); return false; } @@ -556,14 +560,14 @@ bool CPluginManager::updateHeaders(bool force) { bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (headersValid() != HEADERS_OK) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n"; + std::println("{}", failureString("headers are not up-to-date, please run hyprpm update.")); return false; } const auto REPOS = DataState::getAllRepositories(); if (REPOS.size() < 1) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " No repos to update.\n"; + std::println("{}", failureString("No repos to update.")); return true; } @@ -585,25 +589,26 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.m_szCurrentMessage = "Updating " + repo.name; progress.print(); - progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name); + progress.printMessageAbove(infoString("checking for updates for {}", repo.name)); createSafeDirectory(m_szWorkingPluginDirectory); - progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url); + progress.printMessageAbove(infoString("Cloning {}", repo.url)); std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret; + std::println("{}", failureString("could not clone repo: shell returned: {}", ret)); return false; } if (!repo.rev.empty()) { - progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev); + progress.printMessageAbove(infoString("Plugin has revision set, resetting: {}", repo.rev)); std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " 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; + std::println(stderr, "\n{}", failureString("could not check out revision {}: shell returned:\n{}", repo.rev, ret)); + return false; } } @@ -619,7 +624,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (!update) { std::filesystem::remove_all(m_szWorkingPluginDirectory); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date."); + progress.printMessageAbove(successString("repository {} is up-to-date.", repo.name)); progress.m_iSteps++; progress.print(); continue; @@ -627,41 +632,41 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { // we need to update - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " has updates."); - progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + repo.name); + progress.printMessageAbove(successString("repository {} has updates.", repo.name)); + progress.printMessageAbove(infoString("Building {}", repo.name)); progress.m_iSteps++; progress.print(); std::unique_ptr pManifest; if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); + progress.printMessageAbove(successString("found hyprpm manifest")); pManifest = std::make_unique(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml"); } else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); + progress.printMessageAbove(successString("found hyprload manifest")); pManifest = std::make_unique(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml"); } if (!pManifest) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest")); continue; } if (!pManifest->m_bGood) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest")); continue; } 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"); + progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size())); for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) { if (hl != HLVER.hash) continue; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); + progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin)); execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); } @@ -671,32 +676,33 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { std::string out; if (p.since > HLVER.commits && HLVER.commits >= 1000 /* for shallow clones, we can't check this. 1000 is an arbitrary number I chose. */) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n"); + progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name)); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); + progress.printMessageAbove(infoString("Building {}", p.name)); for (auto const& bs : p.buildSteps) { - std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); + const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; + std::println("{}", verboseString("shell returned: {}", out)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { - std::cerr << "\n" - << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n" - << " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try " - "re-running with -v to see more verbose " - "output.\n"; + std::println(stderr, + "\n{}\n" + " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n" + "If you are on -git, update first.\n" + "Try re-running with -v to see more verbose output.", + failureString("Plugin {} failed to build.")); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); + progress.printMessageAbove(successString("built {} into {}", p.name, p.output)); } // add repo toml to DataState @@ -717,7 +723,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { std::filesystem::remove_all(m_szWorkingPluginDirectory); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name); + progress.printMessageAbove(successString("updated {}", repo.name)); } progress.m_iSteps++; @@ -732,7 +738,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.m_szCurrentMessage = "Done!"; progress.print(); - std::cout << "\n"; + std::print("\n"); return true; } @@ -740,27 +746,27 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { bool CPluginManager::enablePlugin(const std::string& name) { bool ret = DataState::setPluginEnabled(name, true); if (ret) - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Enabled " << name << "\n"; + std::println("{}", successString("Enabled {}", name)); return ret; } bool CPluginManager::disablePlugin(const std::string& name) { bool ret = DataState::setPluginEnabled(name, false); if (ret) - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Disabled " << name << "\n"; + std::println("{}", successString("Disabled {}", name)); return ret; } ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { if (headersValid() != HEADERS_OK) { - std::cerr << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n"; + std::println(stderr, "\n{}", failureString("headers are not up-to-date, please run hyprpm update.")); return LOADSTATE_HEADERS_OUTDATED; } const auto HOME = getenv("HOME"); const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE"); if (!HOME || !HIS) { - std::cerr << "PluginManager: no $HOME or HIS\n"; + std::println(stderr, "PluginManager: no $HOME or HIS"); return LOADSTATE_FAIL; } const auto HYPRPMPATH = DataState::getDataStatePath() + "/"; @@ -769,14 +775,14 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { std::vector loadedPlugins; - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Ensuring plugin load state\n"; + std::println("{}", successString("Ensuring plugin load state")); // iterate line by line while (!pluginLines.empty()) { - auto plLine = pluginLines.substr(0, pluginLines.find("\n")); + auto plLine = pluginLines.substr(0, pluginLines.find('\n')); - if (pluginLines.find("\n") != std::string::npos) - pluginLines = pluginLines.substr(pluginLines.find("\n") + 1); + if (pluginLines.find('\n') != std::string::npos) + pluginLines = pluginLines.substr(pluginLines.find('\n') + 1); else pluginLines = ""; @@ -819,7 +825,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { if (!enabled(p)) { // unload loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false); - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Unloaded " << p << "\n"; + std::println("{}", successString("Unloaded {}", p)); } } @@ -833,11 +839,11 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { continue; loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true); - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Loaded " << p.name << "\n"; + std::println("{}", successString("Loaded {}"), p.name); } } - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Plugin load state ensured\n"; + std::println("{}", successString("Plugin load state ensured")); return LOADSTATE_OK; } @@ -855,16 +861,17 @@ void CPluginManager::listAllPlugins() { const auto REPOS = DataState::getAllRepositories(); for (auto const& r : REPOS) { - std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n"; + std::println("{}", infoString("Repository {}:", r.name)); for (auto const& p : r.plugins) { - - std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name; + std::println(" │ Plugin {}", p.name); if (!p.failed) - std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n"; + std::println(" └─ enabled: {}", (p.enabled ? std::string{Colors::GREEN} + "true" : std::string{Colors::RED} + "false")); else - std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n"; + std::println(" └─ enabled: {}Plugin failed to build", Colors::RED); + + std::println("{}", Colors::RESET); } } } @@ -875,19 +882,19 @@ void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int duratio std::string CPluginManager::headerError(const eHeadersErrors err) { switch (err) { - case HEADERS_CORRUPTED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers corrupted. Please run hyprpm update to fix those.\n"; - case HEADERS_MISMATCHED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers version mismatch. Please run hyprpm update to fix those.\n"; - case HEADERS_NOT_HYPRLAND: return std::string{Colors::RED} + "✖" + Colors::RESET + " It doesn't seem you are running on hyprland.\n"; - case HEADERS_MISSING: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers missing. Please run hyprpm update to fix those.\n"; + case HEADERS_CORRUPTED: return failureString("Headers corrupted. Please run hyprpm update to fix those.\n"); + case HEADERS_MISMATCHED: return failureString("Headers version mismatch. Please run hyprpm update to fix those.\n"); + case HEADERS_NOT_HYPRLAND: return failureString("It doesn't seem you are running on hyprland.\n"); + case HEADERS_MISSING: return failureString("Headers missing. Please run hyprpm update to fix those.\n"); case HEADERS_DUPLICATED: { - return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers duplicated!!! This is a very bad sign.\n" + - " This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" + - " If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n"; + return failureString("Headers duplicated!!! This is a very bad sign.\n" + "This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" + "If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n"); } default: break; } - return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n"; + return failureString("Unknown header error. Please run hyprpm update to fix those.\n"); } std::string CPluginManager::headerErrorShort(const eHeadersErrors err) { diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index c16a9d0f..d4603084 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -2,6 +2,7 @@ #include #include +#include enum eHeadersErrors { HEADERS_OK = 0, @@ -68,7 +69,7 @@ class CPluginManager { std::string headerError(const eHeadersErrors err); std::string headerErrorShort(const eHeadersErrors err); - std::string m_szWorkingPluginDirectory = ""; + std::string m_szWorkingPluginDirectory; }; inline std::unique_ptr g_pPluginManager; diff --git a/hyprpm/src/helpers/StringUtils.hpp b/hyprpm/src/helpers/StringUtils.hpp new file mode 100644 index 00000000..c1a5fd98 --- /dev/null +++ b/hyprpm/src/helpers/StringUtils.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include "Colors.hpp" + +template +std::string statusString(const std::string_view emoji, const std::string_view color, const std::string_view fmt, Args&&... args) { + std::string ret = std::format("{}{}{} ", color, emoji, Colors::RESET); + ret += std::vformat(fmt, std::make_format_args(args...)); + return ret; +} + +template +std::string successString(const std::string_view fmt, Args&&... args) { + return statusString("✔", Colors::GREEN, fmt, args...); +} + +template +std::string failureString(const std::string_view fmt, Args&&... args) { + return statusString("✖", Colors::RED, fmt, args...); +} + +template +std::string verboseString(const std::string_view fmt, Args&&... args) { + return statusString("[v]", Colors::BLUE, fmt, args...); +} + +template +std::string infoString(const std::string_view fmt, Args&&... args) { + return statusString("→", Colors::RESET, fmt, args...); +} diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index 4f00f708..67f14aed 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -1,15 +1,16 @@ -#include "progress/CProgressBar.hpp" #include "helpers/Colors.hpp" +#include "helpers/StringUtils.hpp" #include "core/PluginManager.hpp" #include "core/DataState.hpp" -#include +#include #include #include +#include #include #include -const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager +constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┃ ┣ add [url] [git rev] → Install a new plugin repository from git. Git revision ┃ is optional, when set, commit locks are ignored. @@ -30,14 +31,14 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┗ )#"; -int main(int argc, char** argv, char** envp) { +int main(int argc, char** argv, char** envp) { std::vector ARGS{argc}; for (int i = 0; i < argc; ++i) { ARGS[i] = std::string{argv[i]}; } if (ARGS.size() < 2) { - std::cout << HELP; + std::println(stderr, "{}", HELP); return 1; } @@ -47,7 +48,7 @@ int main(int argc, char** argv, char** envp) { for (int i = 1; i < argc; ++i) { if (ARGS[i].starts_with("-")) { if (ARGS[i] == "--help" || ARGS[i] == "-h") { - std::cout << HELP; + std::println("{}", HELP); return 0; } else if (ARGS[i] == "--notify" || ARGS[i] == "-n") { notify = true; @@ -57,9 +58,9 @@ int main(int argc, char** argv, char** envp) { noShallow = true; } else if (ARGS[i] == "--force" || ARGS[i] == "-f") { force = true; - std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n"; + std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing.")); } else { - std::cerr << "Unrecognized option " << ARGS[i] << "\n"; + std::println(stderr, "Unrecognized option {}", ARGS[i]); return 1; } } else { @@ -68,7 +69,7 @@ int main(int argc, char** argv, char** envp) { } if (command.empty()) { - std::cout << HELP; + std::println(stderr, "{}", HELP); return 0; } @@ -78,7 +79,7 @@ int main(int argc, char** argv, char** envp) { if (command[0] == "add") { if (command.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for add.\n"; + std::println(stderr, "{}", failureString("Not enough args for add.")); return 1; } @@ -90,7 +91,7 @@ int main(int argc, char** argv, char** envp) { 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"; + std::println(stderr, "{}", failureString("Not enough args for remove.")); return 1; } @@ -116,12 +117,12 @@ int main(int argc, char** argv, char** envp) { g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers"); } else if (command[0] == "enable") { if (ARGS.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for enable.\n"; + std::println(stderr, "{}", failureString("Not enough args for enable.")); return 1; } if (!g_pPluginManager->enablePlugin(command[1])) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't enable plugin (missing?)\n"; + std::println(stderr, "{}", failureString("Couldn't enable plugin (missing?)")); return 1; } @@ -130,12 +131,12 @@ int main(int argc, char** argv, char** envp) { return 1; } else if (command[0] == "disable") { if (command.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for disable.\n"; + std::println(stderr, "{}", failureString("Not enough args for disable.")); return 1; } if (!g_pPluginManager->disablePlugin(command[1])) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't disable plugin (missing?)\n"; + std::println(stderr, "{}", failureString("Couldn't disable plugin (missing?)")); return 1; } @@ -160,9 +161,9 @@ int main(int argc, char** argv, char** envp) { } else if (command[0] == "list") { g_pPluginManager->listAllPlugins(); } else { - std::cout << HELP; + std::println(stderr, "{}", HELP); return 1; } return 0; -} \ No newline at end of file +} diff --git a/hyprpm/src/progress/CProgressBar.cpp b/hyprpm/src/progress/CProgressBar.cpp index 45602f82..9f2df08a 100644 --- a/hyprpm/src/progress/CProgressBar.cpp +++ b/hyprpm/src/progress/CProgressBar.cpp @@ -1,11 +1,11 @@ #include "CProgressBar.hpp" -#include +#include #include #include #include -#include +#include #include #include @@ -16,11 +16,12 @@ void CProgressBar::printMessageAbove(const std::string& msg) { ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); std::string spaces; + spaces.reserve(w.ws_col); for (size_t i = 0; i < w.ws_col; ++i) { spaces += ' '; } - std::cout << "\r" << spaces << "\r" << msg << "\n"; + std::println("\r{}\r{}", spaces, msg); print(); } @@ -29,15 +30,16 @@ void CProgressBar::print() { ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); if (m_bFirstPrint) - std::cout << "\n"; + std::print("\n"); m_bFirstPrint = false; std::string spaces; + spaces.reserve(w.ws_col); for (size_t i = 0; i < w.ws_col; ++i) { spaces += ' '; } - std::cout << "\r" << spaces << "\r"; + std::print("\r{}\r", spaces); std::string message = ""; @@ -74,7 +76,7 @@ void CProgressBar::print() { message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " "; // draw message - std::cout << message + " " + m_szCurrentMessage; + std::print("{} {}", message, m_szCurrentMessage); std::fflush(stdout); -} \ No newline at end of file +} diff --git a/hyprpm/src/progress/CProgressBar.hpp b/hyprpm/src/progress/CProgressBar.hpp index 6ac18f21..dfcb36f7 100644 --- a/hyprpm/src/progress/CProgressBar.hpp +++ b/hyprpm/src/progress/CProgressBar.hpp @@ -14,4 +14,4 @@ class CProgressBar { private: bool m_bFirstPrint = true; -}; \ No newline at end of file +}; From b61d4c363679a880e8577a3d983d73dbab367a9d Mon Sep 17 00:00:00 2001 From: Toni500git Date: Sun, 13 Oct 2024 14:23:56 +0200 Subject: [PATCH 0138/1803] hyprctl: convert std::cout and std::cerr to std::println() --- hyprctl/Strings.hpp | 2 ++ hyprctl/main.cpp | 37 +++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/hyprctl/Strings.hpp b/hyprctl/Strings.hpp index 17725e77..f77626a5 100644 --- a/hyprctl/Strings.hpp +++ b/hyprctl/Strings.hpp @@ -1,5 +1,7 @@ #pragma once +#include + const std::string_view USAGE = R"#(usage: hyprctl [flags] [args...|--help] commands: diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 1ad189b7..1f7f8d74 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -44,11 +45,11 @@ struct SInstanceData { bool valid = true; }; -void log(std::string str) { +void log(const std::string& str) { if (quiet) return; - std::cout << str << "\n"; + std::println("{}", str); } std::string getRuntimeDir() { @@ -105,7 +106,7 @@ std::vector instances() { static volatile bool sigintReceived = false; void intHandler(int sig) { sigintReceived = true; - std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl; + std::println("[hyprctl] SIGINT received, closing connection"); } int rollingRead(const int socket) { @@ -115,12 +116,12 @@ int rollingRead(const int socket) { constexpr size_t BUFFER_SIZE = 8192; std::array buffer = {0}; long sizeWritten = 0; - std::cout << "[hyprctl] reading from socket following up log:" << std::endl; + std::println("[hyprctl] reading from socket following up log:"); while (!sigintReceived) { sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); if (sizeWritten < 0 && errno != EAGAIN) { if (errno != EINTR) - std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl; + std::println("Couldn't read (5): {}: {}", strerror(errno), errno); close(socket); return 5; } @@ -129,7 +130,7 @@ int rollingRead(const int socket) { break; if (sizeWritten > 0) { - std::cout << std::string(buffer.data(), sizeWritten); + std::println("{}", std::string(buffer.data(), sizeWritten)); buffer.fill('\0'); } @@ -323,7 +324,7 @@ int main(int argc, char** argv) { bool parseArgs = true; if (argc < 2) { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -360,7 +361,7 @@ int main(int argc, char** argv) { ++i; if (i >= ARGS.size()) { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -371,24 +372,24 @@ int main(int argc, char** argv) { const std::string& cmd = ARGS[0]; if (cmd == "hyprpaper") { - std::cout << HYPRPAPER_HELP << std::endl; + std::println("{}", HYPRPAPER_HELP); } else if (cmd == "notify") { - std::cout << NOTIFY_HELP << std::endl; + std::println("{}", NOTIFY_HELP); } else if (cmd == "output") { - std::cout << OUTPUT_HELP << std::endl; + std::println("{}", OUTPUT_HELP); } else if (cmd == "plugin") { - std::cout << PLUGIN_HELP << std::endl; + std::println("{}", PLUGIN_HELP); } else if (cmd == "setprop") { - std::cout << SETPROP_HELP << std::endl; + std::println("{}", SETPROP_HELP); } else if (cmd == "switchxkblayout") { - std::cout << SWITCHXKBLAYOUT_HELP << std::endl; + std::println("{}", SWITCHXKBLAYOUT_HELP); } else { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); } return 1; } else { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -399,7 +400,7 @@ int main(int argc, char** argv) { } if (fullRequest.empty()) { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -476,7 +477,7 @@ int main(int argc, char** argv) { else if (fullRequest.contains("/decorations")) exitStatus = request(fullRequest, 1); else if (fullRequest.contains("/--help")) - std::cout << USAGE << std::endl; + std::println("{}", USAGE); else if (fullRequest.contains("/rollinglog") && needRoll) exitStatus = request(fullRequest, 0, true); else { From 05a5e0b4f1ced12f2a0330132f37b0081d7a5e4d Mon Sep 17 00:00:00 2001 From: Toni500git Date: Sun, 13 Oct 2024 14:24:10 +0200 Subject: [PATCH 0139/1803] hyprland: convert std::cout and std::cerr to std::println() --- src/Compositor.cpp | 14 +++++++------ src/debug/Log.cpp | 4 ++-- src/main.cpp | 51 ++++++++++++++++++++++++---------------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index dcc6422d..fd4979b0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -9,7 +9,9 @@ #include "managers/eventLoop/EventLoopManager.hpp" #include #include +#include #include +#include #include #include #include @@ -138,37 +140,37 @@ CCompositor::CCompositor() { m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr"; if (m_szHyprTempDataRoot.starts_with("/hypr")) { - std::cout << "Bailing out, XDG_RUNTIME_DIR is invalid\n"; + std::println("Bailing out, $XDG_RUNTIME_DIR is invalid"); throw std::runtime_error("CCompositor() failed"); } if (!m_szHyprTempDataRoot.starts_with("/run/user")) - std::cout << "[!!WARNING!!] XDG_RUNTIME_DIR looks non-standard. Proceeding anyways...\n"; + std::println("[!!WARNING!!] XDG_RUNTIME_DIR looks non-standard. Proceeding anyways..."); std::random_device dev; std::mt19937 engine(dev()); std::uniform_int_distribution<> distribution(0, INT32_MAX); - m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL)) + "_" + std::to_string(distribution(engine)); + m_szInstanceSignature = std::format("{}_{}_{}", GIT_COMMIT_HASH, std::time(NULL), distribution(engine)); setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true); if (!std::filesystem::exists(m_szHyprTempDataRoot)) mkdir(m_szHyprTempDataRoot.c_str(), S_IRWXU); else if (!std::filesystem::is_directory(m_szHyprTempDataRoot)) { - std::cout << "Bailing out, " << m_szHyprTempDataRoot << " is not a directory\n"; + std::println("Bailing out, {} is not a directory", m_szHyprTempDataRoot); throw std::runtime_error("CCompositor() failed"); } m_szInstancePath = m_szHyprTempDataRoot + "/" + m_szInstanceSignature; if (std::filesystem::exists(m_szInstancePath)) { - std::cout << "Bailing out, " << m_szInstancePath << " exists??\n"; + std::println("Bailing out, {} exists??", m_szInstancePath); throw std::runtime_error("CCompositor() failed"); } if (mkdir(m_szInstancePath.c_str(), S_IRWXU) < 0) { - std::cout << "Bailing out, couldn't create " << m_szInstancePath << "\n"; + std::println("Bailing out, couldn't create {}", m_szInstancePath); throw std::runtime_error("CCompositor() failed"); } diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index a4c5b08e..5a314833 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -4,7 +4,7 @@ #include "RollingLogFollow.hpp" #include -#include +#include #include void Debug::init(const std::string& IS) { @@ -69,5 +69,5 @@ void Debug::log(LogLevel level, std::string str) { // log it to the stdout too. if (!disableStdout) - std::cout << ((coloredLogs && !**coloredLogs) ? str : coloredStr) << "\n"; + std::println("{}", ((coloredLogs && !**coloredLogs) ? str : coloredStr)); } diff --git a/src/main.cpp b/src/main.cpp index 45f212d3..6bbf73fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,9 @@ #include "init/initHelpers.hpp" #include "debug/HyprCtl.hpp" +#include #include +#include using namespace Hyprutils::String; #include @@ -17,15 +19,15 @@ using namespace Hyprutils::String; #include void help() { - std::cout << "usage: Hyprland [arg [...]].\n"; - std::cout << "\nArguments:\n"; - std::cout << " --help -h - Show this message again\n"; - std::cout << " --config FILE -c FILE - Specify config file to use\n"; - std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; - std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; - std::cout << " --systeminfo - Prints system infos\n"; - std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; - std::cout << " --version -v - Print this binary's version\n"; + std::println("usage: Hyprland [arg [...]].\n"); + std::println(R"(Arguments: + --help -h - Show this message again + --config FILE -c FILE - Specify config file to use + --socket NAME - Sets the Wayland socket name (for Wayland socket handover) + --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover) + --systeminfo - Prints system infos + --i-am-really-stupid - Omits root user privileges check (why would you do that?) + --version -v - Print this binary's version)"); } int main(int argc, char** argv) { @@ -53,7 +55,7 @@ int main(int argc, char** argv) { for (auto it = args.begin(); it != args.end(); it++) { if (it->compare("--i-am-really-stupid") == 0 && !ignoreSudo) { - std::cout << "[ WARNING ] Running Hyprland with superuser privileges might damage your system\n"; + std::println("[ WARNING ] Running Hyprland with superuser privileges might damage your system"); ignoreSudo = true; } else if (it->compare("--socket") == 0) { @@ -79,7 +81,7 @@ int main(int argc, char** argv) { if (fcntl(socketFd, F_GETFD) == -1) throw std::exception(); } catch (...) { - std::cerr << "[ ERROR ] Invalid Wayland FD!\n"; + std::println(stderr, "[ ERROR ] Invalid Wayland FD!"); help(); return 1; @@ -101,7 +103,7 @@ int main(int argc, char** argv) { throw std::exception(); } } catch (...) { - std::cerr << "[ ERROR ] Config file '" << configPath << "' doesn't exist!\n"; + std::println(stderr, "[ ERROR ] Config file '{}' doesn't exist!", configPath); help(); return 1; @@ -117,14 +119,13 @@ int main(int argc, char** argv) { return 0; } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { - std::cout << versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "") << std::endl; + std::println("{}", versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "")); return 0; } else if (it->compare("--systeminfo") == 0) { - const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""); - std::cout << SYSINFO << "\n"; + std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "")); return 0; } else { - std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; + std::println(stderr, "[ ERROR ] Unknown option '{}' !", it->c_str()); help(); return 1; @@ -132,30 +133,32 @@ int main(int argc, char** argv) { } if (!ignoreSudo && Init::isSudo()) { - std::cerr << "[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n"; - std::cerr << " Hint: Use the --i-am-really-stupid flag to omit that check.\n"; + std::println(stderr, + "[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n" + " Hint: Use the --i-am-really-stupid flag to omit that check."); return 1; } else if (ignoreSudo && Init::isSudo()) { - std::cout << "Superuser privileges check is omitted. I hope you know what you're doing.\n"; + std::println("Superuser privileges check is omitted. I hope you know what you're doing."); } if (socketName.empty() ^ (socketFd == -1)) { - std::cerr << "[ ERROR ] Hyprland was launched with only one of --socket and --wayland-fd.\n"; - std::cerr << " Hint: Pass both --socket and --wayland-fd to perform Wayland socket handover.\n"; + std::println(stderr, + "[ ERROR ] Hyprland was launched with only one of --socket and --wayland-fd.\n" + " Hint: Pass both --socket and --wayland-fd to perform Wayland socket handover."); return 1; } - std::cout << "Welcome to Hyprland!\n"; + std::println("Welcome to Hyprland!"); // let's init the compositor. // it initializes basic Wayland stuff in the constructor. try { g_pCompositor = std::make_unique(); g_pCompositor->explicitConfigPath = configPath; - } catch (std::exception& e) { - std::cout << "Hyprland threw in ctor: " << e.what() << "\nCannot continue.\n"; + } catch (const std::exception& e) { + std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what()); return 1; } From 5c3bd8e93d9f25be3e16a0445ba6fce8d30b6d73 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 13 Oct 2024 17:26:39 +0100 Subject: [PATCH 0140/1803] notif-overlay: add a bit of padding for icons --- src/debug/HyprNotificationOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 29da20c8..16f80ab6 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -37,7 +37,7 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() { 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->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text; PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->started.reset(); PNOTIF->timeMs = timeMs; From 8e51a36c7fd500e865e34f08ab4dc4331dca59cf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 14 Oct 2024 00:19:10 +0100 Subject: [PATCH 0141/1803] config/example: add optional smart gaps to the default config ref #8106 #8114 --- example/hyprland.conf | 7 +++++++ src/config/defaultConfig.hpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index 3478bcff..6d7bddb8 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -117,6 +117,13 @@ animations { animation = workspaces, 1, 6, default } +# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ +# "Smart gaps" / "No gaps when only" +# uncomment all three if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 54ce6642..5c8b0e68 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -130,6 +130,13 @@ animations { animation = workspaces, 1, 6, default } +# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ +# "Smart gaps" / "No gaps when only" +# uncomment all three if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below From abfd550ee228ea23058039790e792b45d2467c8d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 14 Oct 2024 00:24:32 +0100 Subject: [PATCH 0142/1803] xwm: avoid infinite parent lookup loop in lookupParentExists ref #8045 --- src/xwayland/XWM.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index dcb22eae..248813bf 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -150,10 +150,17 @@ void CXWM::handleUnmapNotify(xcb_unmap_notify_event_t* e) { } static bool lookupParentExists(SP XSURF, SP prospectiveChild) { + std::vector> visited; + while (XSURF->parent) { if (XSURF->parent == prospectiveChild) return true; + visited.emplace_back(XSURF); + XSURF = XSURF->parent.lock(); + + if (std::find(visited.begin(), visited.end(), XSURF) != visited.end()) + return false; } return false; From e7fd0f5aec85c11a8eaf5e1abf8504f0a6d0710e Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 13 Oct 2024 23:25:19 +0000 Subject: [PATCH 0143/1803] layout: deny auto-grouping a new floating window into a tiled group (#8108) --- src/layout/IHyprLayout.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 24ee13f4..80c9abff 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -186,12 +186,17 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { g_pCompositor->m_pLastWindow.lock() : g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); - if (*PAUTOGROUP // check if auto_group is enabled. - && OPENINGON // check if OPENINGON exists. - && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. - && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group - && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON - && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + bool denied = false; + if (pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating) + denied = true; + + if (*PAUTOGROUP // check if auto_group is enabled. + && OPENINGON // check if OPENINGON exists. + && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. + && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. + && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group a new window that should be floated. + && !denied) { // don't group a new floated window into a tiled group. pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state From ce62521883e217aab4da305d71e40e4a50567dfb Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 14 Oct 2024 05:37:42 -0500 Subject: [PATCH 0144/1803] drm-lease: fix crashes and implementation (#8116) --- src/protocols/DRMLease.cpp | 28 ++++++++++++++++++++-------- src/protocols/DRMLease.hpp | 3 ++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 37f2e2eb..d0114ce7 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -44,10 +44,6 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPleaseFD); - - resource->sendLeaseFd(aqlease->leaseFD); - lease = aqlease; for (auto const& m : requested) { @@ -61,8 +57,13 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPsendFinished(); + LOGM(LOG, "Revoking lease for fd {}", lease->leaseFD); }); + LOGM(LOG, "Granting lease, sending fd {}", lease->leaseFD); + + resource->sendLeaseFd(lease->leaseFD); + close(lease->leaseFD); } @@ -70,6 +71,12 @@ bool CDRMLeaseResource::good() { return resource->resource(); } +CDRMLeaseResource::~CDRMLeaseResource() { + // destroy in this order to ensure listener gets called + lease.reset(); + listeners.destroyLease.reset(); +} + CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP resource_) : resource(resource_) { if (!good()) return; @@ -100,7 +107,7 @@ CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP reso return; } - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), self.lock()); + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), self.lock()); if (!RESOURCE) { resource->noMemory(); return; @@ -185,7 +192,8 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc close(fd); for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) { - sendConnector(m.lock()); + if (m) + sendConnector(m.lock()); } resource->sendDone(); @@ -196,10 +204,10 @@ bool CDRMLeaseDeviceResource::good() { } void CDRMLeaseDeviceResource::sendConnector(SP monitor) { - if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e->monitor == monitor; }) != connectorsSent.end()) + if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e && !e->dead && e->monitor == monitor; }) != connectorsSent.end()) return; - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), monitor); + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), 0), monitor); if (!RESOURCE) { resource->noMemory(); return; @@ -267,6 +275,9 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseDeviceResource* resource) { } void CDRMLeaseProtocol::destroyResource(CDRMLeaseConnectorResource* resource) { + for (const auto& m : m_vManagers) { + std::erase_if(m->connectorsSent, [resource](const auto& e) { return e.expired() || e->dead || e.get() == resource; }); + } std::erase_if(m_vConnectors, [resource](const auto& e) { return e.get() == resource; }); } @@ -279,6 +290,7 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { } void CDRMLeaseProtocol::offer(SP monitor) { + std::erase_if(primaryDevice->offeredOutputs, [](const auto& e) { return e.expired(); }); if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) return; diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index 56eaa3db..3671cfce 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -22,12 +22,13 @@ class CDRMLeaseRequestResource; class CDRMLeaseResource { public: CDRMLeaseResource(SP resource_, SP request); + ~CDRMLeaseResource(); bool good(); WP parent; std::vector> requested; - WP lease; + SP lease; int leaseFD = -1; From f309681d4a78d1c12d8a04fe37075a50a750c2ec Mon Sep 17 00:00:00 2001 From: deadacute <6218316+deadacute@users.noreply.github.com> Date: Sun, 13 Oct 2024 20:40:09 +0200 Subject: [PATCH 0145/1803] example: update desktop file to include DesktopNames --- example/hyprland.desktop | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/example/hyprland.desktop b/example/hyprland.desktop index 57ad076f..bb2801a9 100644 --- a/example/hyprland.desktop +++ b/example/hyprland.desktop @@ -2,4 +2,6 @@ Name=Hyprland Comment=An intelligent dynamic tiling Wayland compositor Exec=Hyprland -Type=Application \ No newline at end of file +Type=Application +DesktopNames=Hyprland +Keywords=tiling;wayland;compositor; From 22b1370ae512c92d84bbcd4cff2a3f8a4496c994 Mon Sep 17 00:00:00 2001 From: "fanlumaster(Fany Full)" <1730976608@qq.com> Date: Tue, 15 Oct 2024 01:03:16 +0800 Subject: [PATCH 0146/1803] IME: Fixup IME popup candidate windows position when scale is not 1.0 (#8117) --- src/managers/input/InputMethodPopup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index a8757030..cf48f2a5 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -100,14 +100,14 @@ void CInputPopup::updateBox() { cursorBoxParent = {0, 0, (int)parentBox.w, (int)parentBox.h}; } - Vector2D currentPopupSize = surface->getViewporterCorrectedSize(); + Vector2D currentPopupSize = surface->getViewporterCorrectedSize() / surface->resource()->current.scale; CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); Vector2D popupOffset(0, 0); if (parentBox.y + cursorBoxParent.y + cursorBoxParent.height + currentPopupSize.y > pMonitor->vecPosition.y + pMonitor->vecSize.y) - popupOffset.y = -currentPopupSize.y; + popupOffset.y -= currentPopupSize.y; else popupOffset.y = cursorBoxParent.height; From 01c2ff34ddcb5995409c33c2b549e93b98b56d6b Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 14 Oct 2024 18:31:17 +0000 Subject: [PATCH 0147/1803] layout: simplify the conditions to autogroup (#8120) --- src/layout/IHyprLayout.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 80c9abff..fa3f8b8d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -191,14 +191,12 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { denied = true; if (*PAUTOGROUP // check if auto_group is enabled. - && OPENINGON // check if OPENINGON exists. - && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. - && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group a new window that should be floated. - && !denied) { // don't group a new floated window into a tiled group. + && !g_pXWaylandManager->shouldBeFloated(pWindow) // fixes the popups of XWayland programs running in a floating group. + && !denied) { // don't group a new floated window into a tiled group (for convenience). - pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state + pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state. Needed to autogroup a new tiled window into a floated group. static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); From ace803948aaed6328342ea57e81adc1a01236c71 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 16 Oct 2024 09:59:47 +0000 Subject: [PATCH 0148/1803] layout: enable group rules for new floating windows (#8122) * layout: enable group rules for new floating windows * fix comment * do not apply group rules to a new floating window if it shouldBeFloated. fixes child windows * comment --- src/layout/IHyprLayout.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index fa3f8b8d..892ed12c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -82,6 +82,8 @@ void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) { } void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { + if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows + pWindow->applyGroupRules(); CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); @@ -193,7 +195,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { if (*PAUTOGROUP // check if auto_group is enabled. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. - && !g_pXWaylandManager->shouldBeFloated(pWindow) // fixes the popups of XWayland programs running in a floating group. + && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. && !denied) { // don't group a new floated window into a tiled group (for convenience). pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state. Needed to autogroup a new tiled window into a floated group. From 0baf166d39260c6d1d422cf528fb5fedc3010cdb Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 16 Oct 2024 10:01:31 +0000 Subject: [PATCH 0149/1803] [gha] Nix: update inputs --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index de9a4dce..0a12fe0a 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1728326504, - "narHash": "sha256-dQXAj+4d6neY7ldCiH6gNym3upP49PVxRzEPxXlD9Aw=", + "lastModified": 1728902391, + "narHash": "sha256-44bnoY0nAvbBQ/lVjmn511yL39Sv7SknV0BDxn34P3Q=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "65dd97b5d21e917295159bbef1d52e06963f4eb0", + "rev": "9874e08eec85b5542ca22494e127b0cdce46b786", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1727821604, - "narHash": "sha256-hNw5J6xatedqytYowx0mJKgctjA4lQARZFdgnzM2RpM=", + "lastModified": 1728669738, + "narHash": "sha256-EDNAU9AYcx8OupUzbTbWE1d3HYdeG0wO6Msg3iL1muk=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "d60e1e01e6e6633ef1c87148b9137cc1dd39263d", + "rev": "0264e698149fcb857a66a53018157b41f8d97bb0", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1727300645, - "narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=", + "lastModified": 1728941256, + "narHash": "sha256-WRypmcZ2Bw94lLmcmxYokVOHPJSZ7T06V49QZ4tkZeQ=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c", + "rev": "fd4be8b9ca932f7384e454bcd923c5451ef2aa85", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1728018373, - "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", + "lastModified": 1728888510, + "narHash": "sha256-nsNdSldaAyu6PE3YUA+YQLqUDJh+gRbBooMMekZJwvI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", + "rev": "a3c0b3b21515f74fd2665903d4ce6bc4dc81c77c", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1728092656, - "narHash": "sha256-eMeCTJZ5xBeQ0f9Os7K8DThNVSo9gy4umZLDfF5q6OM=", + "lastModified": 1728778939, + "narHash": "sha256-WybK5E3hpGxtCYtBwpRj1E9JoiVxe+8kX83snTNaFHE=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "1211305a5b237771e13fcca0c51e60ad47326a9a", + "rev": "ff68f91754be6f3427e4986d7949e6273659be1d", "type": "github" }, "original": { From 781828a56e495439bfe9c0a701cb29f5e4e2df24 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 16 Oct 2024 21:59:29 +0100 Subject: [PATCH 0150/1803] output: send enter events on late wl_output binds fixes #6560 --- src/protocols/core/Compositor.cpp | 6 ++++++ src/protocols/core/Compositor.hpp | 2 ++ src/protocols/core/Output.cpp | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 37a4bdf1..3d4b63c1 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -589,3 +589,9 @@ void CWLCompositorProtocol::destroyResource(CWLSurfaceResource* resource) { void CWLCompositorProtocol::destroyResource(CWLRegionResource* resource) { std::erase_if(m_vRegions, [&](const auto& other) { return other.get() == resource; }); } + +void CWLCompositorProtocol::forEachSurface(std::function)> fn) { + for (auto& surf : m_vSurfaces) { + fn(surf); + } +} diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index dc1c851f..b3c067c9 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -169,6 +169,8 @@ class CWLCompositorProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void forEachSurface(std::function)> fn); + struct { CSignal newSurface; // SP } events; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 3e68937f..e9f35abc 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -1,4 +1,6 @@ #include "Output.hpp" +#include "Compositor.hpp" +#include "../../Compositor.hpp" #include "../../helpers/Monitor.hpp" CWLOutputResource::CWLOutputResource(SP resource_, SP pMonitor) : monitor(pMonitor), resource(resource_) { @@ -27,6 +29,25 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni } updateState(); + + PROTO::compositor->forEachSurface([](SP surf) { + auto HLSurf = CWLSurface::fromResource(surf); + + if (!HLSurf) + return; + + const auto GEOMETRY = HLSurf->getSurfaceBoxGlobal(); + + if (!GEOMETRY.has_value()) + return; + + for (auto& m : g_pCompositor->m_vMonitors) { + if (!m->logicalBox().overlaps(*GEOMETRY)) + continue; + + surf->enter(m); + } + }); } SP CWLOutputResource::fromResource(wl_resource* res) { From 86e9f69a69990feb880dadd0c2b8c067b2a96fa9 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 16 Oct 2024 21:13:35 +0000 Subject: [PATCH 0151/1803] layout: move applyGroupRules() to onWindowCreated() (#8139) --- src/layout/DwindleLayout.cpp | 4 ---- src/layout/IHyprLayout.cpp | 7 ++++--- src/layout/MasterLayout.cpp | 2 -- src/render/decorations/CHyprGroupBarDecoration.cpp | 1 - 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 76b26af1..8a7426eb 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -308,8 +308,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir applyNodeDataToWindow(PNODE); - pWindow->applyGroupRules(); - return; } @@ -450,8 +448,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride); recalculateMonitor(pWindow->m_iMonitorID); - - pWindow->applyGroupRules(); } void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 892ed12c..b8d92636 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -20,6 +20,9 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; + if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows + pWindow->applyGroupRules(); + bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow); if (autoGrouped) return; @@ -82,8 +85,6 @@ void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) { } void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { - if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows - pWindow->applyGroupRules(); CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); @@ -194,6 +195,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { if (*PAUTOGROUP // check if auto_group is enabled. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. + && OPENINGON != pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. && !denied) { // don't group a new floated window into a tiled group (for convenience). @@ -204,7 +206,6 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); OPENINGON->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); pWindow->updateWindowDecos(); recalculateWindow(pWindow); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8fde960d..f983770b 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -116,8 +116,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire return; } - pWindow->applyGroupRules(); - static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); eOrientation orientation = getDynamicOrientation(pWindow->m_pWorkspace); const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index eca3f2cb..74a1e2e9 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -466,7 +466,6 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND std::swap(pDraggedHead->m_sGroupData.head, pWindowInsertEnd->m_sGroupData.head); m_pWindow->setGroupCurrent(pDraggedWindow); - pDraggedWindow->applyGroupRules(); pDraggedWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow); From 09581d32fd465c5c4ff868090369ee67516c38a9 Mon Sep 17 00:00:00 2001 From: zakk4223 Date: Wed, 16 Oct 2024 16:13:59 -0500 Subject: [PATCH 0152/1803] hyprpm: Fix crashes due to misplaced fmt argument(s) (#8140) --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 359b2c78..57c67641 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -697,7 +697,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n" "If you are on -git, update first.\n" "Try re-running with -v to see more verbose output.", - failureString("Plugin {} failed to build.")); + failureString("Plugin {} failed to build.", p.name)); p.failed = true; continue; } @@ -839,7 +839,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { continue; loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true); - std::println("{}", successString("Loaded {}"), p.name); + std::println("{}", successString("Loaded {}", p.name)); } } From b57086aa4362117c1f1025246f618d760e44b026 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 16 Oct 2024 22:22:36 +0100 Subject: [PATCH 0153/1803] window: properly break cycles in X11TransientFor ref #8045 --- src/desktop/Window.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index fa85dc07..a393f361 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -451,15 +451,21 @@ PHLWINDOW CWindow::X11TransientFor() { if (!m_pXWaylandSurface || !m_pXWaylandSurface->parent) return nullptr; - auto s = m_pXWaylandSurface->parent; - auto oldParent = s; + auto s = m_pXWaylandSurface->parent; + std::vector> visited; while (s) { - // break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created? - if (!s->parent || s->parent == oldParent) + // break loops. Some X apps make them, and it seems like it's valid behavior?!?!?! + // TODO: we should reject loops being created in the first place. + if (std::find(visited.begin(), visited.end(), s) != visited.end()) break; + + visited.emplace_back(s.lock()); s = s->parent; } + if (s == m_pXWaylandSurface) + return nullptr; // dead-ass circle + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pXWaylandSurface != s) continue; From 495b92fb535f51a38e5130e6b89bd1fb01ce8cfb Mon Sep 17 00:00:00 2001 From: Behzad Date: Thu, 17 Oct 2024 17:50:18 +0330 Subject: [PATCH 0154/1803] makefile: fix typo (#8127) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 59efc0ef..98267eea 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ PREFIX = /usr/local legacyrenderer: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` legacyrendererdebug: From 5f30cb7753266316b85a460c6266995678187294 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:03:17 +0000 Subject: [PATCH 0155/1803] windowrules: allow specifying max size in size window rule (#8021) * allow specifying max size in size window rule modified: src/events/Windows.cpp * clean up modified: src/events/Windows.cpp --- src/events/Windows.cpp | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e549907e..d2d5bebf 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -330,24 +330,38 @@ void Events::listener_mapWindow(void* owner, void* data) { for (auto const& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("size")) { 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 MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) { + auto stringToPercentage = [](const std::string& VALUE, const float REL) { + if (VALUE.ends_with('%')) + return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100; + else + return std::stof(VALUE); + }; - const auto SIZEX = SIZEXSTR == "max" ? - std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : - (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x); - const auto SIZEY = SIZEYSTR == "max" ? - std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : - (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y); + if (VALUE.starts_with('<')) + return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL)); + else if (VALUE.starts_with('>')) + return std::max(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL)); + + return stringToPercentage(VALUE, REL); + }; + + 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 MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + + const float SIZEX = + SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); + + const float SIZEY = + SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size, applying to {}", PWINDOW); - PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY); - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal(); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->clampWindowSize(Vector2D{SIZEXSTR.starts_with("<") ? 0 : SIZEX, SIZEYSTR.starts_with("<") ? 0 : SIZEY}, Vector2D{SIZEX, SIZEY}); PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } From 0e630e9e74ad34683194a07cfe6afe55a2c0685f Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:05:55 +0000 Subject: [PATCH 0156/1803] session-lock: reset seat grab on a new session lock (#8147) --- src/managers/SessionLockManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 260a3992..4e05695a 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" +#include "../managers/SeatManager.hpp" #include #include @@ -84,6 +85,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { }); g_pCompositor->focusSurface(nullptr); + g_pSeatManager->setGrab(nullptr); } bool CSessionLockManager::isSessionLocked() { From e5d3a71263187feec6c2249b3f7b74de0a71f47c Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 19 Oct 2024 14:49:56 +0000 Subject: [PATCH 0157/1803] config: fix generateConfig loop (#8164) * config: fix generateConfig loop * config: cleanup getMainConfigPath --- src/config/ConfigManager.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 6ec63d4c..432b7faf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -688,14 +688,13 @@ std::string CConfigManager::getMainConfigPath() { if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV) return CFG_ENV; - Debug::log(TRACE, "Seems as if HYPRLAND_CONFIG isn't set, let's see what we can do with HOME."); - static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); - if (paths.first.has_value()) { - return paths.first.value(); - } else if (paths.second.has_value()) { - auto configPath = Hyprutils::Path::fullConfigPath(paths.second.value(), ISDEBUG ? "hyprlandd" : "hyprland"); - return generateConfig(configPath).value(); + const auto PATHS = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); + if (PATHS.first.has_value()) { + return PATHS.first.value(); + } else if (PATHS.second.has_value()) { + const auto CONFIGPATH = Hyprutils::Path::fullConfigPath(PATHS.second.value(), ISDEBUG ? "hyprlandd" : "hyprland"); + return generateConfig(CONFIGPATH).value(); } else throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME are set in the environment. Could not find config in XDG_CONFIG_DIRS or /etc/xdg."); } From 904f9b6aee6a4524fba554f76b32747f85f0609d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:09:39 +0100 Subject: [PATCH 0158/1803] foreign-toplevel: don't send updates to X11 OR windows --- src/protocols/ForeignToplevel.cpp | 29 ++++++++++++++++++++++++----- src/protocols/ForeignToplevel.hpp | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index 1f8cbcbe..38bb5e69 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -31,8 +31,8 @@ CForeignToplevelList::CForeignToplevelList(SP resourc }); for (auto const& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->m_bFadingOut) - continue; + if (!PROTO::foreignToplevel->windowValidForForeign(w)) + return; onMap(w); } @@ -112,20 +112,35 @@ bool CForeignToplevelList::good() { CForeignToplevelProtocol::CForeignToplevelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (!windowValidForForeign(window)) + return; + for (auto const& m : m_vManagers) { - m->onMap(std::any_cast(data)); + m->onMap(window); } }); static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (!windowValidForForeign(window)) + return; + for (auto const& m : m_vManagers) { - m->onUnmap(std::any_cast(data)); + m->onUnmap(window); } }); static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (!windowValidForForeign(window)) + return; + for (auto const& m : m_vManagers) { - m->onTitle(std::any_cast(data)); + m->onTitle(window); } }); } @@ -148,3 +163,7 @@ void CForeignToplevelProtocol::onManagerResourceDestroy(CForeignToplevelList* mg void CForeignToplevelProtocol::destroyHandle(CForeignToplevelHandle* handle) { std::erase_if(m_vHandles, [&](const auto& other) { return other.get() == handle; }); } + +bool CForeignToplevelProtocol::windowValidForForeign(PHLWINDOW pWindow) { + return validMapped(pWindow) && !pWindow->isX11OverrideRedirect(); +} diff --git a/src/protocols/ForeignToplevel.hpp b/src/protocols/ForeignToplevel.hpp index d95db41f..076bfd7c 100644 --- a/src/protocols/ForeignToplevel.hpp +++ b/src/protocols/ForeignToplevel.hpp @@ -50,6 +50,7 @@ class CForeignToplevelProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(CForeignToplevelList* mgr); void destroyHandle(CForeignToplevelHandle* handle); + bool windowValidForForeign(PHLWINDOW pWindow); // std::vector> m_vManagers; From 48bf32c5de5628a4a17387375ea997f738a4f807 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:09:46 +0100 Subject: [PATCH 0159/1803] foreign-toplevel-wlr: don't send updates to X11 OR windows --- src/protocols/ForeignToplevelWlr.cpp | 26 +++++++++++++++++++++++++- src/protocols/ForeignToplevelWlr.hpp | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 291969db..1163a5e7 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -180,7 +180,7 @@ CForeignToplevelWlrManager::CForeignToplevelWlrManager(SPm_vWindows) { - if (!w->m_bIsMapped || w->m_bFadingOut) + if (!PROTO::foreignToplevelWlr->windowValidForForeign(w)) continue; onMap(w); @@ -313,6 +313,10 @@ bool CForeignToplevelWlrManager::good() { CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onMap(PWINDOW); } @@ -320,6 +324,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onUnmap(PWINDOW); } @@ -327,6 +335,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onTitle(PWINDOW); } @@ -334,6 +346,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P3 = g_pHookSystem->hookDynamic("activeWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onNewFocus(PWINDOW); } @@ -348,6 +364,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P5 = g_pHookSystem->hookDynamic("fullscreen", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onFullscreen(PWINDOW); } @@ -383,3 +403,7 @@ PHLWINDOW CForeignToplevelWlrProtocol::windowFromHandleResource(wl_resource* res return nullptr; } + +bool CForeignToplevelWlrProtocol::windowValidForForeign(PHLWINDOW pWindow) { + return validMapped(pWindow) && !pWindow->isX11OverrideRedirect(); +} diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp index 99f63b47..e726707d 100644 --- a/src/protocols/ForeignToplevelWlr.hpp +++ b/src/protocols/ForeignToplevelWlr.hpp @@ -63,6 +63,7 @@ class CForeignToplevelWlrProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(CForeignToplevelWlrManager* mgr); void destroyHandle(CForeignToplevelHandleWlr* handle); + bool windowValidForForeign(PHLWINDOW pWindow); // std::vector> m_vManagers; From 62ee5cc2739d70570dbe143c9bd75d00a51db942 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:21:47 +0100 Subject: [PATCH 0160/1803] monitor: modernize/refactor last legacy-handled events --- src/Compositor.cpp | 2 +- src/events/Events.hpp | 8 --- src/events/Monitors.cpp | 105 ---------------------------------------- src/helpers/Monitor.cpp | 74 +++++++++++++++++++++++++++- src/helpers/Monitor.hpp | 1 + 5 files changed, 74 insertions(+), 116 deletions(-) delete mode 100644 src/events/Monitors.cpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fd4979b0..ca27f17a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -3057,5 +3057,5 @@ void CCompositor::onNewMonitor(SP output) { } g_pHyprRenderer->damageMonitor(PNEWMONITOR.get()); - Events::listener_monitorFrame(PNEWMONITOR.get(), nullptr); + PNEWMONITOR->onMonitorFrame(); } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 0af16f64..84565979 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -24,12 +24,4 @@ namespace Events { DYNLISTENFUNC(requestMaximize); DYNLISTENFUNC(setOverrideRedirect); DYNLISTENFUNC(ackConfigure); - - // Monitor part 2 the sequel - DYNLISTENFUNC(monitorFrame); - DYNLISTENFUNC(monitorStateRequest); - DYNLISTENFUNC(monitorDamage); - DYNLISTENFUNC(monitorNeedsFrame); - DYNLISTENFUNC(monitorCommit); - DYNLISTENFUNC(monitorBind); }; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp deleted file mode 100644 index 9d2210f6..00000000 --- a/src/events/Monitors.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" -#include "Events.hpp" -#include "../debug/HyprCtl.hpp" -#include "../config/ConfigValue.hpp" -#include "../protocols/Screencopy.hpp" -#include "../protocols/ToplevelExport.hpp" -#include - -// --------------------------------------------------------- // -// __ __ ____ _ _ _____ _______ ____ _____ _____ // -// | \/ |/ __ \| \ | |_ _|__ __/ __ \| __ \ / ____| // -// | \ / | | | | \| | | | | | | | | | |__) | (___ // -// | |\/| | | | | . ` | | | | | | | | | _ / \___ \ // -// | | | | |__| | |\ |_| |_ | | | |__| | | \ \ ____) | // -// |_| |_|\____/|_| \_|_____| |_| \____/|_| \_\_____/ // -// // -// --------------------------------------------------------- // - -void Events::listener_monitorFrame(void* owner, void* data) { - CMonitor* const PMONITOR = (CMonitor*)owner; - - if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { - Debug::log(WARN, "Attempted to render frame on inactive session!"); - - if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { - return m->output != g_pCompositor->m_pUnsafeOutput->output; - })) { - // restore from unsafe state - g_pCompositor->leaveUnsafeState(); - } - - return; // cannot draw on session inactive (different tty) - } - - if (!PMONITOR->m_bEnabled) - return; - - g_pHyprRenderer->recheckSolitaryForMonitor(PMONITOR); - - PMONITOR->tearingState.busy = false; - - if (PMONITOR->tearingState.activelyTearing && PMONITOR->solitaryClient.lock() /* can be invalidated by a recheck */) { - - if (!PMONITOR->tearingState.frameScheduledWhileBusy) - return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? - - PMONITOR->tearingState.nextRenderTorn = true; - PMONITOR->tearingState.frameScheduledWhileBusy = false; - } - - 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 (!PMONITOR->RATScheduled) { - // render - g_pHyprRenderer->renderMonitor(PMONITOR); - } - - PMONITOR->RATScheduled = false; - - const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR); - - 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 TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); - - if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) - g_pHyprRenderer->renderMonitor(PMONITOR); - else - wl_event_source_timer_update(PMONITOR->renderTimer, TIMETOSLEEP); - } else { - g_pHyprRenderer->renderMonitor(PMONITOR); - } -} - -void Events::listener_monitorNeedsFrame(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - - g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); -} - -void Events::listener_monitorCommit(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - - if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER - PROTO::screencopy->onOutputCommit(PMONITOR); - PROTO::toplevelExport->onOutputCommit(PMONITOR); - } -} - -void Events::listener_monitorBind(void* owner, void* data) { - ; -} diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 091745df..74471f62 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -11,6 +11,8 @@ #include "../protocols/DRMLease.hpp" #include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Output.hpp" +#include "../protocols/Screencopy.hpp" +#include "../protocols/ToplevelExport.hpp" #include "../managers/PointerManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" #include "../protocols/core/Compositor.hpp" @@ -44,8 +46,13 @@ void CMonitor::onConnect(bool noRule) { outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); } - listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); - listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); + listeners.frame = output->events.frame.registerListener([this](std::any d) { onMonitorFrame(); }); + listeners.commit = output->events.commit.registerListener([this](std::any d) { + if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER + PROTO::screencopy->onOutputCommit(this); + PROTO::toplevelExport->onOutputCommit(this); + } + }); listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); @@ -939,6 +946,69 @@ void CMonitor::debugLastPresentation(const std::string& message) { lastPresentationTimer.getMillis() > 0 ? 1000.0f / lastPresentationTimer.getMillis() : 0.0f); } +void CMonitor::onMonitorFrame() { + if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { + Debug::log(WARN, "Attempted to render frame on inactive session!"); + + if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { + return m->output != g_pCompositor->m_pUnsafeOutput->output; + })) { + // restore from unsafe state + g_pCompositor->leaveUnsafeState(); + } + + return; // cannot draw on session inactive (different tty) + } + + if (!m_bEnabled) + return; + + g_pHyprRenderer->recheckSolitaryForMonitor(this); + + tearingState.busy = false; + + if (tearingState.activelyTearing && solitaryClient.lock() /* can be invalidated by a recheck */) { + + if (!tearingState.frameScheduledWhileBusy) + return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? + + tearingState.nextRenderTorn = true; + tearingState.frameScheduledWhileBusy = false; + } + + static auto PENABLERAT = CConfigValue("misc:render_ahead_of_time"); + static auto PRATSAFE = CConfigValue("misc:render_ahead_safezone"); + + lastPresentationTimer.reset(); + + if (*PENABLERAT && !tearingState.nextRenderTorn) { + if (!RATScheduled) { + // render + g_pHyprRenderer->renderMonitor(this); + } + + RATScheduled = false; + + const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(this); + + if (max + *PRATSAFE > 1000.0 / refreshRate) + return; + + const auto MSLEFT = 1000.0 / refreshRate - lastPresentationTimer.getMillis(); + + RATScheduled = true; + + const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE); + const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); + + if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) + g_pHyprRenderer->renderMonitor(this); + else + wl_event_source_timer_update(renderTimer, TIMETOSLEEP); + } else + g_pHyprRenderer->renderMonitor(this); +} + CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index ad8a823b..ceb90232 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -186,6 +186,7 @@ class CMonitor { void setCTM(const Mat3x3& ctm); void debugLastPresentation(const std::string& message); + void onMonitorFrame(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; From 0eaf3581a340f2521d96fe46d7956913c72d7698 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:24:03 +0100 Subject: [PATCH 0161/1803] window: guard PMONITOR in commit listener ref #8170 --- src/events/Windows.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index d2d5bebf..37e5406c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -775,7 +775,9 @@ void Events::listener_commitWindow(void* owner, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); + if (PMONITOR) + PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); + if (g_pSeatManager->isPointerFrameCommit) { g_pSeatManager->isPointerFrameSkipped = false; g_pSeatManager->isPointerFrameCommit = false; From ce3ba798df6bca5be1da4396644a9ef08a2acab4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 17:03:22 +0100 Subject: [PATCH 0162/1803] defaultConfig: improve smart gaps --- example/hyprland.conf | 14 ++++++++++---- src/config/defaultConfig.hpp | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 6d7bddb8..012446f3 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -119,10 +119,16 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" -# uncomment all three if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 +# uncomment all if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0 +# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = f[1], gapsout:0, gapsin:0 +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] +# windowrulev2 = rounding 0, floating:0, onworkspace:f[1] # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 5c8b0e68..a5d759de 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -132,10 +132,16 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" -# uncomment all three if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 +# uncomment all if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0 +# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = f[1], gapsout:0, gapsin:0 +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] +# windowrulev2 = rounding 0, floating:0, onworkspace:f[1] # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { From f044e4c9514ec89c4c1fc8a523ca90b8cb907fb7 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 19 Oct 2024 23:03:29 +0100 Subject: [PATCH 0163/1803] internal: Move CMonitor to SP (#8178) * move monitors to sp * XD --- src/Compositor.cpp | 112 ++++++++--------- src/Compositor.hpp | 36 +++--- src/config/ConfigManager.cpp | 16 +-- src/config/ConfigManager.hpp | 4 +- src/debug/HyprCtl.cpp | 10 +- src/debug/HyprDebugOverlay.cpp | 18 +-- src/debug/HyprDebugOverlay.hpp | 24 ++-- src/debug/HyprNotificationOverlay.cpp | 6 +- src/debug/HyprNotificationOverlay.hpp | 8 +- src/desktop/DesktopTypes.hpp | 6 + src/desktop/LayerSurface.cpp | 6 +- src/desktop/Window.cpp | 2 +- src/desktop/Window.hpp | 2 +- src/events/Windows.cpp | 6 +- src/helpers/Monitor.cpp | 114 +++++++++--------- src/helpers/Monitor.hpp | 6 +- src/helpers/WLClasses.hpp | 20 +-- src/hyprerror/HyprError.cpp | 4 +- src/layout/DwindleLayout.cpp | 7 +- src/layout/MasterLayout.cpp | 7 +- src/managers/AnimationManager.cpp | 2 +- src/managers/CursorManager.cpp | 2 +- src/managers/KeybindManager.cpp | 16 +-- src/managers/KeybindManager.hpp | 2 +- src/managers/PointerManager.cpp | 34 ++---- src/managers/PointerManager.hpp | 2 - src/managers/ProtocolManager.cpp | 6 +- src/managers/ProtocolManager.hpp | 2 +- src/managers/SessionLockManager.cpp | 4 +- src/managers/XWaylandManager.cpp | 4 +- src/managers/input/InputManager.cpp | 10 +- src/managers/input/InputManager.hpp | 2 +- src/managers/input/InputMethodPopup.cpp | 6 +- src/managers/input/Swipe.cpp | 10 +- src/managers/input/Touch.cpp | 2 +- src/protocols/ForeignToplevelWlr.cpp | 4 +- src/protocols/ForeignToplevelWlr.hpp | 2 +- src/protocols/GammaControl.cpp | 8 +- src/protocols/GammaControl.hpp | 10 +- src/protocols/LayerShell.cpp | 6 +- src/protocols/LayerShell.hpp | 2 +- src/protocols/LinuxDMABUF.cpp | 4 +- src/protocols/OutputManagement.cpp | 22 ++-- src/protocols/OutputManagement.hpp | 24 ++-- src/protocols/OutputPower.cpp | 6 +- src/protocols/OutputPower.hpp | 4 +- src/protocols/PresentationTime.cpp | 4 +- src/protocols/Screencopy.cpp | 16 +-- src/protocols/Screencopy.hpp | 6 +- src/protocols/SessionLock.cpp | 8 +- src/protocols/SessionLock.hpp | 6 +- src/protocols/ToplevelExport.cpp | 2 +- src/protocols/ToplevelExport.hpp | 2 +- src/protocols/core/DataDevice.cpp | 2 +- src/protocols/core/DataDevice.hpp | 2 +- src/render/OpenGL.cpp | 22 ++-- src/render/OpenGL.hpp | 54 ++++----- src/render/Renderer.cpp | 62 +++++----- src/render/Renderer.hpp | 56 ++++----- .../decorations/CHyprBorderDecoration.cpp | 4 +- .../decorations/CHyprBorderDecoration.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 4 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.hpp | 2 +- .../decorations/IHyprWindowDecoration.hpp | 2 +- 66 files changed, 424 insertions(+), 446 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index ca27f17a..b23b3194 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -412,8 +412,8 @@ void CCompositor::initAllSignals() { m_bSessionActive = true; for (auto const& m : m_vMonitors) { - scheduleFrameForMonitor(m.get()); - g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); + scheduleFrameForMonitor(m); + g_pHyprRenderer->applyMonitorRule(m, &m->activeMonitorRule, true); } g_pConfigManager->m_bWantsMonitorReload = true; @@ -498,7 +498,7 @@ void CCompositor::cleanup() { m_vWindows.clear(); for (auto const& m : m_vMonitors) { - g_pHyprOpenGL->destroyMonitorResources(m.get()); + g_pHyprOpenGL->destroyMonitorResources(m); m->output->state->setEnabled(false); m->state.commit(); @@ -717,38 +717,38 @@ void CCompositor::startCompositor() { g_pEventLoopManager->enterLoop(); } -CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) { +PHLMONITOR CCompositor::getMonitorFromID(const MONITORID& id) { for (auto const& m : m_vMonitors) { if (m->ID == id) { - return m.get(); + return m; } } return nullptr; } -CMonitor* CCompositor::getMonitorFromName(const std::string& name) { +PHLMONITOR CCompositor::getMonitorFromName(const std::string& name) { for (auto const& m : m_vMonitors) { if (m->szName == name) { - return m.get(); + return m; } } return nullptr; } -CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) { +PHLMONITOR CCompositor::getMonitorFromDesc(const std::string& desc) { for (auto const& m : m_vMonitors) { if (m->szDescription.starts_with(desc)) - return m.get(); + return m; } return nullptr; } -CMonitor* CCompositor::getMonitorFromCursor() { +PHLMONITOR CCompositor::getMonitorFromCursor() { return getMonitorFromVector(g_pPointerManager->position()); } -CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { +PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) { SP mon; for (auto const& m : m_vMonitors) { if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) { @@ -772,13 +772,13 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { if (!pBestMon) { // ????? Debug::log(WARN, "getMonitorFromVector no close mon???"); - return m_vMonitors.front().get(); + return m_vMonitors.front(); } - return pBestMon.get(); + return pBestMon; } - return mon.get(); + return mon; } void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) { @@ -790,9 +790,9 @@ void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) { } } -bool CCompositor::monitorExists(CMonitor* pMonitor) { +bool CCompositor::monitorExists(PHLMONITOR pMonitor) { for (auto const& m : m_vRealMonitors) { - if (m.get() == pMonitor) + if (m == pMonitor) return true; } @@ -982,20 +982,20 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; } -CMonitor* CCompositor::getMonitorFromOutput(SP out) { +PHLMONITOR CCompositor::getMonitorFromOutput(SP out) { for (auto const& m : m_vMonitors) { if (m->output == out) { - return m.get(); + return m; } } return nullptr; } -CMonitor* CCompositor::getRealMonitorFromOutput(SP out) { +PHLMONITOR CCompositor::getRealMonitorFromOutput(SP out) { for (auto const& m : m_vRealMonitors) { if (m->output == out) { - return m.get(); + return m; } } @@ -1183,7 +1183,7 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo SURF->constraint()->activate(); } -SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { +SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) { if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) @@ -1779,7 +1779,7 @@ bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { return false; } -bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* pMonitor) { +bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR pMonitor) { const auto PMONITOR = pMonitor ? pMonitor : getMonitorFromVector(point); const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; @@ -1788,11 +1788,11 @@ bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* p return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y); } -CMonitor* CCompositor::getMonitorInDirection(const char& dir) { - return this->getMonitorInDirection(m_pLastMonitor.get(), dir); +PHLMONITOR CCompositor::getMonitorInDirection(const char& dir) { + return getMonitorInDirection(m_pLastMonitor.lock(), dir); } -CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const char& dir) { +PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const char& dir) { if (!pSourceMonitor) return nullptr; @@ -1800,7 +1800,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto SIZEA = pSourceMonitor->vecSize; auto longestIntersect = -1; - CMonitor* longestIntersectMonitor = nullptr; + PHLMONITOR longestIntersectMonitor = nullptr; for (auto const& m : m_vMonitors) { if (m == m_pLastMonitor) @@ -1814,7 +1814,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1823,7 +1823,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1833,7 +1833,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1843,7 +1843,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1990,7 +1990,7 @@ MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { return nextID; } -void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) { +void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitorB) { const auto PWORKSPACEA = pMonitorA->activeWorkspace; const auto PWORKSPACEB = pMonitorB->activeWorkspace; @@ -2077,16 +2077,16 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) EMIT_HOOK_EVENT("moveWorkspace", (std::vector{PWORKSPACEB, pMonitorA})); } -CMonitor* CCompositor::getMonitorFromString(const std::string& name) { +PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { if (name == "current") - return g_pCompositor->m_pLastMonitor.get(); + return g_pCompositor->m_pLastMonitor.lock(); else if (isDirection(name)) return getMonitorInDirection(name[0]); else if (name[0] == '+' || name[0] == '-') { // relative if (m_vMonitors.size() == 1) - return m_vMonitors.begin()->get(); + return *m_vMonitors.begin(); const auto OFFSET = name[0] == '-' ? name : name.substr(1); @@ -2119,7 +2119,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { currentPlace = std::clamp(currentPlace, 0, (int)m_vMonitors.size() - 1); } - return m_vMonitors[currentPlace].get(); + return m_vMonitors[currentPlace]; } else if (isNumber(name)) { // change by ID MONITORID monID = MONITOR_INVALID; @@ -2143,7 +2143,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { continue; if (m->matchesStaticSelector(name)) { - return m.get(); + return m; } } } @@ -2151,7 +2151,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { return nullptr; } -void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMonitor, bool noWarpCursor) { +void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) { // We trust the monitor to be correct. @@ -2226,7 +2226,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon } } - if (SWITCHINGISACTIVE && POLDMON == g_pCompositor->m_pLastMonitor.get()) { // if it was active, preserve its' status. If it wasn't, don't. + if (SWITCHINGISACTIVE && POLDMON == g_pCompositor->m_pLastMonitor) { // if it was active, preserve its' status. If it wasn't, don't. Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active {} -> {}", pMonitor->activeWorkspaceID(), pWorkspace->m_iID); if (valid(pMonitor->activeWorkspace)) { @@ -2438,7 +2438,7 @@ void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { } } -void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor, IOutput::scheduleFrameReason reason) { +void CCompositor::scheduleFrameForMonitor(PHLMONITOR pMonitor, IOutput::scheduleFrameReason reason) { if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) return; @@ -2555,7 +2555,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { if (*PNOWARPS && !force) { const auto PMONITORNEW = getMonitorFromVector(pos); - if (PMONITORNEW != m_pLastMonitor.get()) + if (PMONITORNEW != m_pLastMonitor) setActiveMonitor(PMONITORNEW); return; } @@ -2563,7 +2563,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { g_pPointerManager->warpTo(pos); const auto PMONITORNEW = getMonitorFromVector(pos); - if (PMONITORNEW != m_pLastMonitor.get()) + if (PMONITORNEW != m_pLastMonitor) setActiveMonitor(PMONITORNEW); } @@ -2690,8 +2690,8 @@ void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name g_pEventManager->postEvent({"renameworkspace", std::to_string(PWORKSPACE->m_iID) + "," + PWORKSPACE->m_szName}); } -void CCompositor::setActiveMonitor(CMonitor* pMonitor) { - if (m_pLastMonitor.get() == pMonitor) +void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { + if (m_pLastMonitor == pMonitor) return; if (!pMonitor) { @@ -2801,13 +2801,13 @@ PHLWINDOW CCompositor::getForceFocus() { } void CCompositor::arrangeMonitors() { - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); - std::vector toArrange; - std::vector arranged; + std::vector toArrange; + std::vector arranged; for (auto const& m : m_vMonitors) - toArrange.push_back(m.get()); + toArrange.push_back(m); Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size()); @@ -2906,7 +2906,7 @@ void CCompositor::enterUnsafeState() { m_bUnsafeState = true; - setActiveMonitor(m_pUnsafeOutput); + setActiveMonitor(m_pUnsafeOutput.lock()); } void CCompositor::leaveUnsafeState() { @@ -2917,10 +2917,10 @@ void CCompositor::leaveUnsafeState() { m_bUnsafeState = false; - CMonitor* pNewMonitor = nullptr; + PHLMONITOR pNewMonitor = nullptr; for (auto const& pMonitor : m_vMonitors) { if (pMonitor->output != m_pUnsafeOutput->output) { - pNewMonitor = pMonitor.get(); + pNewMonitor = pMonitor; break; } } @@ -2931,7 +2931,7 @@ void CCompositor::leaveUnsafeState() { m_pUnsafeOutput->onDisconnect(); for (auto const& m : m_vMonitors) { - scheduleFrameForMonitor(m.get()); + scheduleFrameForMonitor(m); } } @@ -3007,7 +3007,7 @@ static void checkDefaultCursorWarp(SP monitor) { } // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. - if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { + if (g_pCompositor->getMonitorFromCursor() == monitor) { g_pCompositor->warpCursorTo(POS, true); g_pInputManager->refocus(); } @@ -3017,7 +3017,7 @@ void CCompositor::onNewMonitor(SP output) { // add it to real auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared(output)); if (std::string("HEADLESS-1") == output->name) { - g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); + g_pCompositor->m_pUnsafeOutput = PNEWMONITOR; output->name = "FALLBACK"; // we are allowed to do this :) } @@ -3040,12 +3040,12 @@ void CCompositor::onNewMonitor(SP output) { // ready to process if we have a real monitor if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) - g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get(); + g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR; g_pCompositor->m_bReadyToProcess = true; g_pConfigManager->m_bWantsMonitorReload = true; - g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); + g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR, IOutput::AQ_SCHEDULE_NEW_MONITOR); checkDefaultCursorWarp(PNEWMONITOR); @@ -3056,6 +3056,6 @@ void CCompositor::onNewMonitor(SP output) { } } - g_pHyprRenderer->damageMonitor(PNEWMONITOR.get()); + g_pHyprRenderer->damageMonitor(PNEWMONITOR); PNEWMONITOR->onMonitorFrame(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index a57450f1..7fbd32e8 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -89,7 +89,7 @@ class CCompositor { bool m_bDPMSStateON = true; bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bNextIsUnsafe = false; - CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state + PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state bool m_bIsShuttingDown = false; bool m_bFinalRequests = false; bool m_bDesktopEnvSet = false; @@ -97,22 +97,22 @@ class CCompositor { // ------------------------------------------------- // - CMonitor* getMonitorFromID(const MONITORID&); - CMonitor* getMonitorFromName(const std::string&); - CMonitor* getMonitorFromDesc(const std::string&); - CMonitor* getMonitorFromCursor(); - CMonitor* getMonitorFromVector(const Vector2D&); + PHLMONITOR getMonitorFromID(const MONITORID&); + PHLMONITOR getMonitorFromName(const std::string&); + PHLMONITOR getMonitorFromDesc(const std::string&); + PHLMONITOR getMonitorFromCursor(); + PHLMONITOR getMonitorFromVector(const Vector2D&); void removeWindowFromVectorSafe(PHLWINDOW); void focusWindow(PHLWINDOW, SP pSurface = nullptr); void focusSurface(SP, PHLWINDOW pWindowOwner = nullptr); - bool monitorExists(CMonitor*); + bool monitorExists(PHLMONITOR); PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); SP vectorToLayerSurface(const Vector2D&, std::vector*, Vector2D*, PHLLS*); - SP vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*); + SP vectorToLayerPopupSurface(const Vector2D&, PHLMONITOR monitor, Vector2D*, PHLLS*); SP vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP); - CMonitor* getMonitorFromOutput(SP); - CMonitor* getRealMonitorFromOutput(SP); + PHLMONITOR getMonitorFromOutput(SP); + PHLMONITOR getRealMonitorFromOutput(SP); PHLWINDOW getWindowFromSurface(SP); PHLWINDOW getWindowFromHandle(uint32_t); bool isWorkspaceVisible(PHLWORKSPACE); @@ -138,16 +138,16 @@ class CCompositor { PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); WORKSPACEID getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); - bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); - CMonitor* getMonitorInDirection(const char&); - CMonitor* getMonitorInDirection(CMonitor*, const char&); + bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr); + PHLMONITOR getMonitorInDirection(const char&); + PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&); void updateAllWindowsAnimatedDecorationValues(); void updateWorkspaceWindows(const WORKSPACEID& id); void updateWindowAnimatedDecorationValues(PHLWINDOW); MONITORID getNextAvailableMonitorID(std::string const& name); - void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); - void swapActiveWorkspaces(CMonitor*, CMonitor*); - CMonitor* getMonitorFromString(const std::string&); + void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false); + void swapActiveWorkspaces(PHLMONITOR, PHLMONITOR); + PHLMONITOR getMonitorFromString(const std::string&); bool workspaceIDOutOfBounds(const WORKSPACEID&); void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); @@ -156,7 +156,7 @@ class CCompositor { void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON); void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); PHLWINDOW getX11Parent(PHLWINDOW); - void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); + void scheduleFrameForMonitor(PHLMONITOR, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); void addToFadingOutSafe(PHLLS); void removeFromFadingOutSafe(PHLLS); void addToFadingOutSafe(PHLWINDOW); @@ -169,7 +169,7 @@ class CCompositor { PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", bool isEmpty = true); // will be deleted next frame if left empty and unfocused! void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); - void setActiveMonitor(CMonitor*); + void setActiveMonitor(PHLMONITOR); bool isWorkspaceSpecial(const WORKSPACEID&); WORKSPACEID getNewSpecialID(); void performUserChecks(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 432b7faf..f16ebe46 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -943,9 +943,9 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { for (auto const& m : g_pCompositor->m_vMonitors) { // mark blur dirty - g_pHyprOpenGL->markBlurDirtyForMonitor(m.get()); + g_pHyprOpenGL->markBlurDirtyForMonitor(m); - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m); // Force the compositor to fully re-render all monitors m->forceFullFrames = 2; @@ -1506,7 +1506,7 @@ void CConfigManager::performMonitorReload() { auto rule = getMonitorRuleFor(m); - if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) { + if (!g_pHyprRenderer->applyMonitorRule(m, &rule)) { overAgain = true; break; } @@ -1564,14 +1564,14 @@ void CConfigManager::ensureMonitorStatus() { auto rule = getMonitorRuleFor(rm); if (rule.disabled == rm->m_bEnabled) - g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); + g_pHyprRenderer->applyMonitorRule(rm, &rule); } } -void CConfigManager::ensureVRR(CMonitor* pMonitor) { +void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { static auto PVRR = reinterpret_cast(getConfigValuePtr("misc:vrr")); - static auto ensureVRRForDisplay = [&](CMonitor* m) -> void { + static auto ensureVRRForDisplay = [&](PHLMONITOR m) -> void { if (!m->output || m->createdByUser) return; @@ -1641,7 +1641,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { } for (auto const& m : g_pCompositor->m_vMonitors) { - ensureVRRForDisplay(m.get()); + ensureVRRForDisplay(m); } } @@ -1653,7 +1653,7 @@ void CConfigManager::addParseError(const std::string& err) { g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); } -CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) { +PHLMONITOR CConfigManager::getBoundMonitorForWS(const std::string& wsname) { auto monitor = getBoundMonitorStringForWS(wsname); if (monitor.substr(0, 5) == "desc:") return g_pCompositor->getMonitorFromDesc(monitor.substr(5)); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 2134acf4..e9ed2d64 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -173,7 +173,7 @@ class CConfigManager { SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); - CMonitor* getBoundMonitorForWS(const std::string&); + PHLMONITOR getBoundMonitorForWS(const std::string&); std::string getBoundMonitorStringForWS(const std::string&); const std::deque& getAllWorkspaceRules(); @@ -198,7 +198,7 @@ class CConfigManager { void appendMonitorRule(const SMonitorRule&); bool replaceMonitorRule(const SMonitorRule&); void ensureMonitorStatus(); - void ensureVRR(CMonitor* pMonitor = nullptr); + void ensureVRR(PHLMONITOR pMonitor = nullptr); std::string parseKeyword(const std::string&, const std::string&); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index e0bb2b83..e09fb529 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -54,7 +54,7 @@ static std::string formatToString(uint32_t drmFormat) { return "Invalid"; } -static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { +static std::string availableModesForOutput(PHLMONITOR pMonitor, eHyprCtlOutputFormat format) { std::string result; for (auto const& m : pMonitor->output->modes) { @@ -117,7 +117,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(), (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), - availableModesForOutput(m.get(), format)); + availableModesForOutput(m, format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" @@ -128,7 +128,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m, format)); } return result; @@ -1030,7 +1030,7 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { // decorations will probably need a repaint if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { for (auto const& m : g_pCompositor->m_vMonitors) { - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } } @@ -1779,7 +1779,7 @@ std::string CHyprCtl::getReply(std::string request) { } for (auto const& m : g_pCompositor->m_vMonitors) { - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } } diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 2da64e63..9326cfe0 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -7,7 +7,7 @@ CHyprDebugOverlay::CHyprDebugOverlay() { m_pTexture = makeShared(); } -void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { +void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) { m_dLastRenderTimes.push_back(durationUs / 1000.f); if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate) @@ -17,7 +17,7 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) m_pMonitor = pMonitor; } -void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { +void CHyprMonitorDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) { m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f); if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate) @@ -27,7 +27,7 @@ void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float dur m_pMonitor = pMonitor; } -void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) { +void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) { m_dLastFrametimes.push_back(std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f); if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate) @@ -39,7 +39,7 @@ void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) { m_pMonitor = pMonitor; // anim data too - const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor.get(); + const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor.lock() : g_pCompositor->m_pLastMonitor.lock(); if (PMONITORFORTICKS) { if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate) m_dLastAnimationTicks.pop_front(); @@ -188,21 +188,21 @@ int CHyprMonitorDebugOverlay::draw(int offset) { return posY - offset; } -void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { +void CHyprDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) { m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs); } -void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { +void CHyprDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) { m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs); } -void CHyprDebugOverlay::frameData(CMonitor* pMonitor) { +void CHyprDebugOverlay::frameData(PHLMONITOR pMonitor) { m_mMonitorOverlays[pMonitor].frameData(pMonitor); } void CHyprDebugOverlay::draw() { - const auto PMONITOR = g_pCompositor->m_vMonitors.front().get(); + const auto PMONITOR = g_pCompositor->m_vMonitors.front(); if (!m_pCairoSurface || !m_pCairo) { m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); @@ -218,7 +218,7 @@ void CHyprDebugOverlay::draw() { // draw the things int offsetY = 0; for (auto const& m : g_pCompositor->m_vMonitors) { - offsetY += m_mMonitorOverlays[m.get()].draw(offsetY); + offsetY += m_mMonitorOverlays[m].draw(offsetY); offsetY += 5; // for padding between mons } diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index e7742b35..19b9120a 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -5,7 +5,7 @@ #include "../render/Texture.hpp" #include #include -#include +#include class CHyprRenderer; @@ -13,9 +13,9 @@ class CHyprMonitorDebugOverlay { public: int draw(int offset); - void renderData(CMonitor* pMonitor, float durationUs); - void renderDataNoOverlay(CMonitor* pMonitor, float durationUs); - void frameData(CMonitor* pMonitor); + void renderData(PHLMONITOR pMonitor, float durationUs); + void renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs); + void frameData(PHLMONITOR pMonitor); private: std::deque m_dLastFrametimes; @@ -23,7 +23,7 @@ class CHyprMonitorDebugOverlay { std::deque m_dLastRenderTimesNoOverlay; std::deque m_dLastAnimationTicks; std::chrono::high_resolution_clock::time_point m_tpLastFrame; - CMonitor* m_pMonitor = nullptr; + PHLMONITORREF m_pMonitor; CBox m_wbLastDrawnBox; friend class CHyprRenderer; @@ -33,17 +33,17 @@ class CHyprDebugOverlay { public: CHyprDebugOverlay(); void draw(); - void renderData(CMonitor*, float durationUs); - void renderDataNoOverlay(CMonitor*, float durationUs); - void frameData(CMonitor*); + void renderData(PHLMONITOR, float durationUs); + void renderDataNoOverlay(PHLMONITOR, float durationUs); + void frameData(PHLMONITOR); private: - std::unordered_map m_mMonitorOverlays; + std::map m_mMonitorOverlays; - cairo_surface_t* m_pCairoSurface = nullptr; - cairo_t* m_pCairo = nullptr; + cairo_surface_t* m_pCairoSurface = nullptr; + cairo_t* m_pCairo = nullptr; - SP m_pTexture; + SP m_pTexture; friend class CHyprMonitorDebugOverlay; friend class CHyprRenderer; diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 16f80ab6..e46999e6 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -45,7 +45,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC PNOTIF->fontSize = fontSize; for (auto const& m : g_pCompositor->m_vMonitors) { - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m); } } @@ -61,7 +61,7 @@ void CHyprNotificationOverlay::dismissNotifications(const int amount) { } } -CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { +CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) { static constexpr auto ANIM_DURATION_MS = 600.0; static constexpr auto ANIM_LAG_MS = 100.0; static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0; @@ -187,7 +187,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10}; } -void CHyprNotificationOverlay::draw(CMonitor* pMonitor) { +void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) { const auto MONSIZE = pMonitor->vecTransformedSize; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 352c44c9..0bba8b04 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -41,13 +41,13 @@ class CHyprNotificationOverlay { CHyprNotificationOverlay(); ~CHyprNotificationOverlay(); - void draw(CMonitor* pMonitor); + void draw(PHLMONITOR pMonitor); 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: - CBox drawNotifications(CMonitor* pMonitor); + CBox drawNotifications(PHLMONITOR pMonitor); CBox m_bLastDamage; std::deque> m_dNotifications; @@ -55,8 +55,8 @@ class CHyprNotificationOverlay { cairo_surface_t* m_pCairoSurface = nullptr; cairo_t* m_pCairo = nullptr; - CMonitor* m_pLastMonitor = nullptr; - Vector2D m_vecLastSize = Vector2D(-1, -1); + PHLMONITORREF m_pLastMonitor; + Vector2D m_vecLastSize = Vector2D(-1, -1); SP m_pTexture; }; diff --git a/src/desktop/DesktopTypes.hpp b/src/desktop/DesktopTypes.hpp index 4e40c4e0..7f812cc1 100644 --- a/src/desktop/DesktopTypes.hpp +++ b/src/desktop/DesktopTypes.hpp @@ -3,6 +3,7 @@ class CWorkspace; class CWindow; class CLayerSurface; +class CMonitor; /* Shared pointer to a workspace */ typedef SP PHLWORKSPACE; @@ -18,3 +19,8 @@ typedef WP PHLWINDOWREF; typedef SP PHLLS; /* Weak pointer to a layer surface */ typedef WP PHLLSREF; + +/* Shared pointer to a monitor */ +typedef SP PHLMONITOR; +/* Weak pointer to a monitor */ +typedef WP PHLMONITORREF; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 0e7e71b6..6c024ee0 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -6,9 +6,9 @@ #include "../managers/SeatManager.hpp" PHLLS CLayerSurface::create(SP resource) { - PHLLS pLS = SP(new CLayerSurface(resource)); + PHLLS pLS = SP(new CLayerSurface(resource)); - CMonitor* pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor); + auto pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor); pLS->surface->assign(resource->surface.lock(), pLS); @@ -18,7 +18,7 @@ PHLLS CLayerSurface::create(SP resource) { } if (pMonitor->pMirrorOf) - pMonitor = g_pCompositor->m_vMonitors.front().get(); + pMonitor = g_pCompositor->m_vMonitors.front(); pLS->self = pLS; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index a393f361..1297bb83 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1188,7 +1188,7 @@ void CWindow::setSuspended(bool suspend) { m_bSuspended = suspend; } -bool CWindow::visibleOnMonitor(CMonitor* pMonitor) { +bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) { CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()}; return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty(); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 9baf57c4..b2a8e763 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -424,7 +424,7 @@ class CWindow { float rounding(); bool canBeTorn(); void setSuspended(bool suspend); - bool visibleOnMonitor(CMonitor* pMonitor); + bool visibleOnMonitor(PHLMONITOR pMonitor); WORKSPACEID workspaceID(); bool onSpecialWorkspace(); void activate(bool force = false); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 37e5406c..21055f79 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -49,10 +49,10 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); - auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); + auto PMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!g_pCompositor->m_pLastMonitor) { g_pCompositor->setActiveMonitor(g_pCompositor->getMonitorFromVector({})); - PMONITOR = g_pCompositor->m_pLastMonitor.get(); + PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } auto PWORKSPACE = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; PWINDOW->m_iMonitorID = PMONITOR->ID; @@ -314,7 +314,7 @@ void Events::listener_mapWindow(void* owner, void* data) { else if (PMONITOR->activeWorkspaceID() != REQUESTEDWORKSPACEID) g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspaceName); - PMONITOR = g_pCompositor->m_pLastMonitor.get(); + PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } } else workspaceSilent = false; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 74471f62..6ded5ea4 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -25,7 +25,7 @@ using namespace Hyprutils::String; using namespace Hyprutils::Utils; int ratHandler(void* data) { - g_pHyprRenderer->renderMonitor((CMonitor*)data); + g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock()); return 1; } @@ -49,12 +49,12 @@ void CMonitor::onConnect(bool noRule) { listeners.frame = output->events.frame.registerListener([this](std::any d) { onMonitorFrame(); }); listeners.commit = output->events.commit.registerListener([this](std::any d) { if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER - PROTO::screencopy->onOutputCommit(this); - PROTO::toplevelExport->onOutputCommit(this); + PROTO::screencopy->onOutputCommit(self.lock()); + PROTO::toplevelExport->onOutputCommit(self.lock()); } }); listeners.needsFrame = - output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); + output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); listeners.presented = output->events.present.registerListener([this](std::any d) { auto E = std::any_cast(d); @@ -84,7 +84,7 @@ void CMonitor::onConnect(bool noRule) { return; Debug::log(LOG, "Reapplying monitor rule for {} from a state request", szName); - g_pHyprRenderer->applyMonitorRule(this, &activeMonitorRule, true); + g_pHyprRenderer->applyMonitorRule(self.lock(), &activeMonitorRule, true); return; } @@ -98,7 +98,7 @@ void CMonitor::onConnect(bool noRule) { SMonitorRule rule = activeMonitorRule; rule.resolution = SIZE; - g_pHyprRenderer->applyMonitorRule(this, &rule); + g_pHyprRenderer->applyMonitorRule(self.lock(), &rule); }); tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM; @@ -171,7 +171,7 @@ void CMonitor::onConnect(bool noRule) { // set mode, also applies if (!noRule) - g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); + g_pHyprRenderer->applyMonitorRule(self.lock(), &monitorRule, true); if (!state.commit()) Debug::log(WARN, "state.commit() failed in CMonitor::onCommit"); @@ -187,7 +187,7 @@ void CMonitor::onConnect(bool noRule) { continue; if (ws->m_szLastMonitor == szName || g_pCompositor->m_vMonitors.size() == 1 /* avoid lost workspaces on recover */) { - g_pCompositor->moveWorkspaceToMonitor(ws, this); + g_pCompositor->moveWorkspaceToMonitor(ws, self.lock()); ws->startAnim(true, true, true); ws->m_szLastMonitor = ""; } @@ -204,13 +204,13 @@ void CMonitor::onConnect(bool noRule) { setMirror(activeMonitorRule.mirrorOf); if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet - g_pCompositor->setActiveMonitor(this); + g_pCompositor->setActiveMonitor(self.lock()); g_pHyprRenderer->arrangeLayersForMonitor(ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); // ensure VRR (will enable if necessary) - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); // verify last mon valid bool found = false; @@ -222,19 +222,19 @@ void CMonitor::onConnect(bool noRule) { } if (!found) - g_pCompositor->setActiveMonitor(this); + g_pCompositor->setActiveMonitor(self.lock()); renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this); - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); - PROTO::gamma->applyGammaToState(this); + PROTO::gamma->applyGammaToState(self.lock()); events.connect.emit(); g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); - EMIT_HOOK_EVENT("monitorAdded", this); + EMIT_HOOK_EVENT("monitorAdded", self.lock()); } void CMonitor::onDisconnect(bool destroy) { @@ -242,7 +242,7 @@ void CMonitor::onDisconnect(bool destroy) { if (g_pCompositor->m_bIsShuttingDown) return; g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); - EMIT_HOOK_EVENT("monitorRemoved", this); + EMIT_HOOK_EVENT("monitorRemoved", self.lock()); g_pCompositor->arrangeMonitors(); }}; @@ -259,21 +259,21 @@ void CMonitor::onDisconnect(bool destroy) { events.disconnect.emit(); // Cleanup everything. Move windows back, snap cursor, shit. - CMonitor* BACKUPMON = nullptr; + PHLMONITOR BACKUPMON = nullptr; for (auto const& m : g_pCompositor->m_vMonitors) { if (m.get() != this) { - BACKUPMON = m.get(); + BACKUPMON = m; break; } } // remove mirror if (pMirrorOf) { - pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == self; })); // unlock software for mirrored monitor - g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); - pMirrorOf = nullptr; + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf.lock()); + pMirrorOf.reset(); } if (!mirrors.empty()) { @@ -340,16 +340,16 @@ void CMonitor::onDisconnect(bool destroy) { if (!state.commit()) Debug::log(WARN, "state.commit() failed in CMonitor::onDisconnect"); - if (g_pCompositor->m_pLastMonitor.get() == this) - g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput); + if (g_pCompositor->m_pLastMonitor == self) + g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput.lock()); - if (g_pHyprRenderer->m_pMostHzMonitor == this) { - int mostHz = 0; - CMonitor* pMonitorMostHz = nullptr; + if (g_pHyprRenderer->m_pMostHzMonitor == self) { + int mostHz = 0; + PHLMONITOR pMonitorMostHz = nullptr; for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->refreshRate > mostHz && m.get() != this) { - pMonitorMostHz = m.get(); + if (m->refreshRate > mostHz && m != self) { + pMonitorMostHz = m; mostHz = m->refreshRate; } } @@ -361,11 +361,11 @@ void CMonitor::onDisconnect(bool destroy) { void CMonitor::addDamage(const pixman_region32_t* rg) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); - if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { + if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } else if (damage.damage(rg)) - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } void CMonitor::addDamage(const CRegion* rg) { @@ -374,13 +374,13 @@ void CMonitor::addDamage(const CRegion* rg) { void CMonitor::addDamage(const CBox* box) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); - if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { + if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } if (damage.damage(*box)) - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { @@ -456,7 +456,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { if (PNEWWORKSPACE) { // workspace exists, move it to the newly connected monitor - g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this); + g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, self.lock()); activeWorkspace = PNEWWORKSPACE; g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); PNEWWORKSPACE->startAnim(true, true, true); @@ -485,7 +485,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { return; } - if (PMIRRORMON == this) { + if (PMIRRORMON == self) { Debug::log(ERR, "Cannot mirror self!"); return; } @@ -494,13 +494,13 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // disable mirroring if (pMirrorOf) { - pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == self; })); // unlock software for mirrored monitor - g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf.lock()); } - pMirrorOf = nullptr; + pMirrorOf.reset(); // set rule const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock()); @@ -528,12 +528,12 @@ void CMonitor::setMirror(const std::string& mirrorOf) { setupDefaultWS(RULE); - g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff + g_pHyprRenderer->applyMonitorRule(self.lock(), (SMonitorRule*)&RULE, true); // will apply the offset and stuff } else { - CMonitor* BACKUPMON = nullptr; + PHLMONITOR BACKUPMON = nullptr; for (auto const& m : g_pCompositor->m_vMonitors) { if (m.get() != this) { - BACKUPMON = m.get(); + BACKUPMON = m; break; } } @@ -557,14 +557,14 @@ void CMonitor::setMirror(const std::string& mirrorOf) { pMirrorOf = PMIRRORMON; - pMirrorOf->mirrors.push_back(this); + pMirrorOf->mirrors.push_back(self); // remove from mvmonitors - std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; }); + std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other == self; }); g_pCompositor->arrangeMonitors(); - g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get()); + g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front()); g_pCompositor->sanityCheckWorkspaces(); @@ -654,11 +654,11 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo EMIT_HOOK_EVENT("workspace", pWorkspace); } - g_pHyprRenderer->damageMonitor(this); + g_pHyprRenderer->damageMonitor(self.lock()); g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); g_pCompositor->updateSuspendedStates(); @@ -674,7 +674,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (activeSpecialWorkspace == pWorkspace) return; - g_pHyprRenderer->damageMonitor(this); + g_pHyprRenderer->damageMonitor(self.lock()); if (!pWorkspace) { // remove special if exists @@ -696,7 +696,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pCompositor->updateFullscreenFadeOnWorkspace(activeWorkspace); - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); g_pCompositor->updateSuspendedStates(); @@ -764,11 +764,11 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", pWorkspace->m_szName + "," + szName}); - g_pHyprRenderer->damageMonitor(this); + g_pHyprRenderer->damageMonitor(self.lock()); g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); g_pCompositor->updateSuspendedStates(); } @@ -824,7 +824,7 @@ void CMonitor::scheduleDone() { void CMonitor::setCTM(const Mat3x3& ctm_) { ctm = ctm_; ctmUpdated = true; - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME); } bool CMonitor::attemptDirectScanout() { @@ -963,7 +963,7 @@ void CMonitor::onMonitorFrame() { if (!m_bEnabled) return; - g_pHyprRenderer->recheckSolitaryForMonitor(this); + g_pHyprRenderer->recheckSolitaryForMonitor(self.lock()); tearingState.busy = false; @@ -984,12 +984,12 @@ void CMonitor::onMonitorFrame() { if (*PENABLERAT && !tearingState.nextRenderTorn) { if (!RATScheduled) { // render - g_pHyprRenderer->renderMonitor(this); + g_pHyprRenderer->renderMonitor(self.lock()); } RATScheduled = false; - const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(this); + const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(self.lock()); if (max + *PRATSAFE > 1000.0 / refreshRate) return; @@ -1002,11 +1002,11 @@ void CMonitor::onMonitorFrame() { const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) - g_pHyprRenderer->renderMonitor(this); + g_pHyprRenderer->renderMonitor(self.lock()); else wl_event_source_timer_update(renderTimer, TIMETOSLEEP); } else - g_pHyprRenderer->renderMonitor(this); + g_pHyprRenderer->renderMonitor(self.lock()); } CMonitorState::CMonitorState(CMonitor* owner) { @@ -1040,7 +1040,7 @@ bool CMonitorState::commit() { if (!updateSwapchain()) return false; - EMIT_HOOK_EVENT("preMonitorCommit", m_pOwner); + EMIT_HOOK_EVENT("preMonitorCommit", m_pOwner->self.lock()); ensureBufferPresent(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index ceb90232..f3d6d647 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -54,7 +54,7 @@ class CMonitorState { private: void ensureBufferPresent(); - CMonitor* m_pOwner; + CMonitor* m_pOwner = nullptr; }; class CMonitor { @@ -128,8 +128,8 @@ class CMonitor { WP self; // mirroring - CMonitor* pMirrorOf = nullptr; - std::vector mirrors; + PHLMONITORREF pMirrorOf; + std::vector mirrors; // ctm Mat3x3 ctm = Mat3x3::identity(); diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 51f90166..9f2836e7 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -18,9 +18,9 @@ class CWLSurfaceResource; AQUAMARINE_FORWARD(ISwitch); struct SRenderData { - CMonitor* pMonitor; - timespec* when; - double x, y; + PHLMONITORREF pMonitor; + timespec* when; + double x, y; // for iters void* data = nullptr; @@ -59,16 +59,16 @@ struct SRenderData { }; struct SSwipeGesture { - PHLWORKSPACE pWorkspaceBegin = nullptr; + PHLWORKSPACE pWorkspaceBegin = nullptr; - double delta = 0; + double delta = 0; - int initialDirection = 0; - float avgSpeed = 0; - int speedPoints = 0; - int touch_id = 0; + int initialDirection = 0; + float avgSpeed = 0; + int speedPoints = 0; + int touch_id = 0; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; }; struct SSwitchDevice { diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 4044bcc9..4761346e 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -14,7 +14,7 @@ CHyprError::CHyprError() { if (!m_bIsCreated) return; - g_pHyprRenderer->damageMonitor(g_pCompositor->m_pLastMonitor.get()); + g_pHyprRenderer->damageMonitor(g_pCompositor->m_pLastMonitor.lock()); m_bMonitorChanged = true; }); @@ -47,7 +47,7 @@ void CHyprError::createQueued() { m_fFadeOpacity.setValueAndWarp(0.f); m_fFadeOpacity = 1.f; - const auto PMONITOR = g_pCompositor->m_vMonitors.front().get(); + const auto PMONITOR = g_pCompositor->m_vMonitors.front(); const auto SCALE = PMONITOR->scale; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 8a7426eb..0fa57143 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -101,18 +101,17 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (pNode->isNode) return; - CMonitor* PMONITOR = nullptr; + PHLMONITOR PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { - PMONITOR = m.get(); + PMONITOR = m; break; } } - } else { + } else PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); - } if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index f983770b..95b5afdf 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -594,18 +594,17 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { - CMonitor* PMONITOR = nullptr; + PHLMONITOR PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { - PMONITOR = m.get(); + PMONITOR = m; break; } } - } else { + } else PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); - } if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 0ff94f1f..9ff7497d 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -85,7 +85,7 @@ void CAnimationManager::tick() { PHLWINDOW PWINDOW = av->m_pWindow.lock(); PHLWORKSPACE PWORKSPACE = av->m_pWorkspace.lock(); PHLLS PLAYER = av->m_pLayer.lock(); - CMonitor* PMONITOR = nullptr; + PHLMONITOR PMONITOR = nullptr; bool animationsDisabled = animGlobalDisabled; if (PWINDOW) { diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 6f8292f7..34084a49 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -309,7 +309,7 @@ void CCursorManager::updateTheme() { for (auto const& m : g_pCompositor->m_vMonitors) { m->forceFullFrames = 5; - g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + g_pCompositor->scheduleFrameForMonitor(m, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d893e258..9c22fb93 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -271,11 +271,11 @@ void updateRelativeCursorCoords() { g_pCompositor->m_pLastWindow->m_vRelativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_pLastWindow->m_vPosition; } -bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { +bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { if (!monitor) return false; - const auto LASTMONITOR = g_pCompositor->m_pLastMonitor.get(); + const auto LASTMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!LASTMONITOR) return false; if (LASTMONITOR == monitor) { @@ -1096,7 +1096,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); static auto PWORKSPACECENTERON = CConfigValue("binds:workspace_center_on"); - const auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); + const auto PMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!PMONITOR) return {.success = false, .error = "Last monitor not found"}; @@ -1260,7 +1260,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { } auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); - CMonitor* pMonitor = nullptr; + PHLMONITOR pMonitor = nullptr; const auto POLDWS = PWINDOW->m_pWorkspace; static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); @@ -1795,7 +1795,7 @@ SDispatchResult CKeybindManager::exitHyprland(std::string argz) { } SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { - CMonitor* PMONITOR = g_pCompositor->getMonitorFromString(args); + PHLMONITOR PMONITOR = g_pCompositor->getMonitorFromString(args); if (!PMONITOR) { Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"); @@ -1854,7 +1854,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; } - const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor.get(); + const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!PCURRMONITOR) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"); @@ -1944,7 +1944,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) { continue; auto rule = g_pConfigManager->getMonitorRuleFor(m); - if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) { + if (!g_pHyprRenderer->applyMonitorRule(m, &rule, true)) { overAgain = true; break; } @@ -2427,7 +2427,7 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { } if (enable) - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); m->events.dpmsChanged.emit(); } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index c81ca86f..8981dcaf 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -146,7 +146,7 @@ class CKeybindManager { void updateXKBTranslationState(); bool ensureMouseBindState(); - static bool tryMoveFocusToMonitor(CMonitor* monitor); + static bool tryMoveFocusToMonitor(PHLMONITOR monitor); static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 8c2a1bad..ae90349b 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -14,7 +14,7 @@ CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { - auto PMONITOR = std::any_cast(data)->self.lock(); + auto PMONITOR = std::any_cast(data); onMonitorLayoutChange(); @@ -29,7 +29,7 @@ CPointerManager::CPointerManager() { }); hooks.monitorPreRender = g_pHookSystem->hookDynamic("preMonitorCommit", [this](void* self, SCallbackInfo& info, std::any data) { - auto state = stateFor(std::any_cast(data)->self.lock()); + auto state = stateFor(std::any_cast(data)); if (!state) return; @@ -51,16 +51,7 @@ void CPointerManager::unlockSoftwareAll() { updateCursorBackend(); } -void CPointerManager::lockSoftwareForMonitor(CMonitor* Monitor) { - for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->ID == Monitor->ID) { - lockSoftwareForMonitor(m); - return; - } - } -} - -void CPointerManager::lockSoftwareForMonitor(SP mon) { +void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) { auto state = stateFor(mon); state->softwareLocks++; @@ -68,16 +59,7 @@ void CPointerManager::lockSoftwareForMonitor(SP mon) { updateCursorBackend(); } -void CPointerManager::unlockSoftwareForMonitor(CMonitor* Monitor) { - for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->ID == Monitor->ID) { - unlockSoftwareForMonitor(m); - return; - } - } -} - -void CPointerManager::unlockSoftwareForMonitor(SP mon) { +void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { auto state = stateFor(mon); state->softwareLocks--; if (state->softwareLocks < 0) @@ -387,7 +369,7 @@ bool CPointerManager::setHWCursorBuffer(SP state, SPcursorFrontBuffer = buf; if (!state->monitor->shouldSkipScheduleFrameOnMouseEvent()) - g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + g_pCompositor->scheduleFrameForMonitor(state->monitor.lock(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } @@ -446,7 +428,7 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); - g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); + g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor; auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); if (!RBO) { @@ -503,7 +485,7 @@ SP CPointerManager::renderHWCursorBuffer(SPbind(); - g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO); + g_pHyprOpenGL->beginSimple(state->monitor.lock(), damage, RBO); g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; @@ -514,7 +496,7 @@ SP CPointerManager::renderHWCursorBuffer(SPend(); glFlush(); - g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.pMonitor.reset(); g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 6b89eb16..aef2490d 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -45,8 +45,6 @@ class CPointerManager { void lockSoftwareForMonitor(SP pMonitor); void unlockSoftwareForMonitor(SP pMonitor); - void lockSoftwareForMonitor(CMonitor* pMonitor); - void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); bool softwareLockedFor(SP pMonitor); diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 25a34657..601e564d 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -62,7 +62,7 @@ #include #include -void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { +void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) { const bool ISMIRROR = pMonitor->isMirror(); // onModeChanged we check if the current mirror status matches the global. @@ -84,7 +84,7 @@ CProtocolManager::CProtocolManager() { // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { - auto M = std::any_cast(param); + auto M = std::any_cast(param); // ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after // this event is emitted iirc. @@ -103,7 +103,7 @@ CProtocolManager::CProtocolManager() { }); static auto P2 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - auto M = std::any_cast(param); + auto M = std::any_cast(param); if (!PROTO::outputs.contains(M->szName)) return; PROTO::outputs.at(M->szName)->remove(); diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index d5629e9e..69dadd0f 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -16,7 +16,7 @@ class CProtocolManager { private: std::unordered_map m_mModeChangeListeners; - void onMonitorModeChange(CMonitor* pMonitor); + void onMonitorModeChange(PHLMONITOR pMonitor); }; inline std::unique_ptr g_pProtocolManager; diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 4e05695a..1b28cc27 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -73,7 +73,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pInputManager->refocus(); for (auto const& m : g_pCompositor->m_vMonitors) - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); }); m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([this](std::any data) { @@ -81,7 +81,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pCompositor->focusSurface(nullptr); for (auto const& m : g_pCompositor->m_vMonitors) - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); }); g_pCompositor->focusSurface(nullptr); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 8b63d37e..7b3081a2 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -247,7 +247,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - CMonitor* pMonitor = nullptr; + PHLMONITOR pMonitor = nullptr; double bestDistance = __FLT_MAX__; for (const auto& m : g_pCompositor->m_vMonitors) { const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; @@ -257,7 +257,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { if (distance < bestDistance) { bestDistance = distance; - pMonitor = m.get(); + pMonitor = m; } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index eef5e040..196f0b71 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -172,7 +172,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_vLastCursorPosFloored = MOUSECOORDSFLOORED; - const auto PMONITOR = isLocked() && g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor.get() : g_pCompositor->getMonitorFromCursor(); + const auto PMONITOR = isLocked() && g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor.lock() : g_pCompositor->getMonitorFromCursor(); // this can happen if there are no displays hooked up to Hyprland if (PMONITOR == nullptr) @@ -212,7 +212,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF.get(), (uintptr_t)CONSTRAINT.get()); } - if (PMONITOR != g_pCompositor->m_pLastMonitor.get() && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired()) + if (PMONITOR != g_pCompositor->m_pLastMonitor && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired()) g_pCompositor->setActiveMonitor(PMONITOR); if (g_pSessionLockManager->isSessionLocked()) { @@ -370,7 +370,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.lock(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); // grabs if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(foundSurface)) { @@ -720,7 +720,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { // notify app if we didnt handle it g_pSeatManager->sendPointerButton(e.timeMs, e.button, e.state); - if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor.get() && PMON) + if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor && PMON) g_pCompositor->setActiveMonitor(PMON); if (g_pSeatManager->seatGrab && e.state == WL_POINTER_BUTTON_STATE_PRESSED) { @@ -1359,7 +1359,7 @@ void CInputManager::refocus() { mouseMoveUnified(0, true); } -void CInputManager::refocusLastWindow(CMonitor* pMonitor) { +void CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { if (!pMonitor) { refocus(); return; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index d5634796..10faff24 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -112,7 +112,7 @@ class CInputManager { Vector2D getMouseCoordsInternal(); void refocus(); - void refocusLastWindow(CMonitor* pMonitor); + void refocusLastWindow(PHLMONITOR pMonitor); void simulateMouseMovement(); void sendMotionEventsToFocused(); diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index cf48f2a5..ffb4edcc 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -100,11 +100,11 @@ void CInputPopup::updateBox() { cursorBoxParent = {0, 0, (int)parentBox.w, (int)parentBox.h}; } - Vector2D currentPopupSize = surface->getViewporterCorrectedSize() / surface->resource()->current.scale; + Vector2D currentPopupSize = surface->getViewporterCorrectedSize() / surface->resource()->current.scale; - CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); + PHLMONITOR pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); - Vector2D popupOffset(0, 0); + Vector2D popupOffset(0, 0); if (parentBox.y + cursorBoxParent.y + cursorBoxParent.height + currentPopupSize.y > pMonitor->vecPosition.y + pMonitor->vecSize.y) popupOffset.y -= currentPopupSize.y; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index aa1d3274..8f95c6c6 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -33,7 +33,7 @@ void CInputManager::beginWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE; m_sActiveSwipe.delta = 0; - m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor.get(); + m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor; m_sActiveSwipe.avgSpeed = 0; m_sActiveSwipe.speedPoints = 0; @@ -179,7 +179,7 @@ void CInputManager::endWorkspaceSwipe() { } m_sActiveSwipe.pWorkspaceBegin->rememberPrevWorkspace(pSwitchedTo); - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (PWORKSPACEL) PWORKSPACEL->m_bForceRendering = false; @@ -264,7 +264,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID || !PWORKSPACE) { if (*PSWIPENEW) { - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (VERTANIMS) m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); @@ -304,7 +304,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID || !PWORKSPACE) { if (*PSWIPENEW) { - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (VERTANIMS) m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); @@ -341,7 +341,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); } - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 0333648a..454391af 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -18,7 +18,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { auto PMONITOR = g_pCompositor->getMonitorFromName(!e.device->boundOutput.empty() ? e.device->boundOutput : ""); - PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor.get(); + PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 1163a5e7..ffc335c9 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -44,7 +44,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPm_pWorkspace != monitor->activeWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, monitor->activeWorkspace); - g_pCompositor->setActiveMonitor(monitor.get()); + g_pCompositor->setActiveMonitor(monitor); } } } @@ -116,7 +116,7 @@ wl_resource* CForeignToplevelHandleWlr::res() { return resource->resource(); } -void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) { +void CForeignToplevelHandleWlr::sendMonitor(PHLMONITOR pMonitor) { if (lastMonitorID == pMonitor->ID) return; diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp index e726707d..880b7a14 100644 --- a/src/protocols/ForeignToplevelWlr.hpp +++ b/src/protocols/ForeignToplevelWlr.hpp @@ -22,7 +22,7 @@ class CForeignToplevelHandleWlr { bool closed = false; MONITORID lastMonitorID = MONITOR_INVALID; - void sendMonitor(CMonitor* pMonitor); + void sendMonitor(PHLMONITOR pMonitor); void sendState(); friend class CForeignToplevelWlrManager; diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index e794e543..14c6596f 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -143,11 +143,11 @@ void CGammaControl::applyToMonitor() { pMonitor->output->state->setGammaLut({}); } - g_pHyprRenderer->damageMonitor(pMonitor.get()); + g_pHyprRenderer->damageMonitor(pMonitor.lock()); } -CMonitor* CGammaControl::getMonitor() { - return pMonitor ? pMonitor.get() : nullptr; +PHLMONITOR CGammaControl::getMonitor() { + return pMonitor ? pMonitor.lock() : nullptr; } void CGammaControl::onMonitorDestroy() { @@ -186,7 +186,7 @@ void CGammaControlProtocol::onGetGammaControl(CZwlrGammaControlManagerV1* pMgr, } } -void CGammaControlProtocol::applyGammaToState(CMonitor* pMonitor) { +void CGammaControlProtocol::applyGammaToState(PHLMONITOR pMonitor) { for (auto const& g : m_vGammaControllers) { if (g->getMonitor() != pMonitor) continue; diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp index bbdc0139..5cfcd60a 100644 --- a/src/protocols/GammaControl.hpp +++ b/src/protocols/GammaControl.hpp @@ -14,13 +14,13 @@ class CGammaControl { CGammaControl(SP resource_, wl_resource* output); ~CGammaControl(); - bool good(); - void applyToMonitor(); - CMonitor* getMonitor(); + bool good(); + void applyToMonitor(); + PHLMONITOR getMonitor(); private: SP resource; - WP pMonitor; + PHLMONITORREF pMonitor; size_t gammaSize = 0; bool gammaTableSet = false; std::vector gammaTable; // [r,g,b]+ @@ -39,7 +39,7 @@ class CGammaControlProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void applyGammaToState(CMonitor* pMonitor); + void applyGammaToState(PHLMONITOR pMonitor); private: void onManagerResourceDestroy(wl_resource* res); diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index c02d23f3..5ceae5f2 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -14,8 +14,8 @@ void CLayerShellResource::SState::reset() { margin = {0, 0, 0, 0}; } -CLayerShellResource::CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer) : - layerNamespace(namespace_), surface(surf_), resource(resource_) { +CLayerShellResource::CLayerShellResource(SP resource_, SP surf_, std::string namespace_, PHLMONITOR pMonitor, + zwlrLayerShellV1Layer layer) : layerNamespace(namespace_), surface(surf_), resource(resource_) { if (!good()) return; @@ -218,7 +218,7 @@ void CLayerShellProtocol::destroyResource(CLayerShellResource* surf) { void CLayerShellProtocol::onGetLayerSurface(CZwlrLayerShellV1* pMgr, uint32_t id, wl_resource* surface, wl_resource* output, zwlrLayerShellV1Layer layer, std::string namespace_) { const auto CLIENT = pMgr->client(); - const auto PMONITOR = output ? CWLOutputResource::fromResource(output)->monitor.get() : nullptr; + const auto PMONITOR = output ? CWLOutputResource::fromResource(output)->monitor.lock() : nullptr; auto SURF = CWLSurfaceResource::fromResource(surface); if (!SURF) { diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 801bdfd6..ad6c1a75 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -26,7 +26,7 @@ class CLayerShellRole : public ISurfaceRole { }; class CLayerShellResource { public: - CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer); + CLayerShellResource(SP resource_, SP surf_, std::string namespace_, PHLMONITOR pMonitor, zwlrLayerShellV1Layer layer); ~CLayerShellResource(); bool good(); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index d9dd1d01..8e26c74f 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -452,7 +452,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const } static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { - auto pMonitor = std::any_cast(param); + auto pMonitor = std::any_cast(param); auto mon = pMonitor->self.lock(); auto tranche = SDMABUFTranche{ .device = mainDevice, @@ -464,7 +464,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const }); static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - auto pMonitor = std::any_cast(param); + auto pMonitor = std::any_cast(param); auto mon = pMonitor->self.lock(); std::erase_if(formatTable->monitorTranches, [mon](std::pair, SDMABUFTranche> pair) { return pair.first == mon; }); resetFormatTable(); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 3fd0cf6c..77cedd41 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -29,12 +29,12 @@ COutputManager::COutputManager(SP resource_) : resource(re // send all heads at start for (auto const& m : g_pCompositor->m_vRealMonitors) { - if (m.get() == g_pCompositor->m_pUnsafeOutput) + if (m == g_pCompositor->m_pUnsafeOutput) continue; LOGM(LOG, " | sending output head for {}", m->szName); - makeAndSendNewHead(m.get()); + makeAndSendNewHead(m); } sendDone(); @@ -44,7 +44,7 @@ bool COutputManager::good() { return resource->resource(); } -void COutputManager::makeAndSendNewHead(CMonitor* pMonitor) { +void COutputManager::makeAndSendNewHead(PHLMONITOR pMonitor) { if (stopped) return; @@ -63,7 +63,7 @@ void COutputManager::makeAndSendNewHead(CMonitor* pMonitor) { RESOURCE->sendAllData(); } -void COutputManager::ensureMonitorSent(CMonitor* pMonitor) { +void COutputManager::ensureMonitorSent(PHLMONITOR pMonitor) { if (pMonitor == g_pCompositor->m_pUnsafeOutput) return; @@ -86,7 +86,7 @@ void COutputManager::sendDone() { resource->sendDone(wl_display_next_serial(g_pCompositor->m_sWLDisplay)); } -COutputHead::COutputHead(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { +COutputHead::COutputHead(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!good()) return; @@ -105,7 +105,7 @@ COutputHead::COutputHead(SP resource_, CMonitor* pMonitor_) : m->resource->sendFinished(); } - pMonitor = nullptr; + pMonitor.reset(); for (auto const& m : PROTO::outputManagement->m_vManagers) { m->sendDone(); } @@ -221,8 +221,8 @@ void COutputHead::makeAndSendNewMode(SP mode) { RESOURCE->sendAllData(); } -CMonitor* COutputHead::monitor() { - return pMonitor; +PHLMONITOR COutputHead::monitor() { + return pMonitor.lock(); } COutputMode::COutputMode(SP resource_, SP mode_) : resource(resource_), mode(mode_) { @@ -424,14 +424,12 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { return true; } -COutputConfigurationHead::COutputConfigurationHead(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { +COutputConfigurationHead::COutputConfigurationHead(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!good()) return; resource->setOnDestroy([this](CZwlrOutputConfigurationHeadV1* r) { PROTO::outputManagement->destroyResource(this); }); - listeners.monitorDestroy = pMonitor->events.destroy.registerListener([this](std::any d) { pMonitor = nullptr; }); - resource->setSetMode([this](CZwlrOutputConfigurationHeadV1* r, wl_resource* outputMode) { const auto MODE = PROTO::outputManagement->modeFromResource(outputMode); @@ -612,7 +610,7 @@ void COutputManagementProtocol::destroyResource(COutputConfigurationHead* resour void COutputManagementProtocol::updateAllOutputs() { for (auto const& m : g_pCompositor->m_vRealMonitors) { for (auto const& mgr : m_vManagers) { - mgr->ensureMonitorSent(m.get()); + mgr->ensureMonitorSent(m); } } } diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index f4a84475..6deab017 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -56,7 +56,7 @@ class COutputManager { COutputManager(SP resource_); bool good(); - void ensureMonitorSent(CMonitor* pMonitor); + void ensureMonitorSent(PHLMONITOR pMonitor); void sendDone(); // holds the states for this manager. @@ -70,7 +70,7 @@ class COutputManager { std::vector> heads; - void makeAndSendNewHead(CMonitor* pMonitor); + void makeAndSendNewHead(PHLMONITOR pMonitor); friend class COutputManagementProtocol; }; @@ -92,16 +92,16 @@ class COutputMode { class COutputHead { public: - COutputHead(SP resource_, CMonitor* pMonitor_); + COutputHead(SP resource_, PHLMONITOR pMonitor_); - bool good(); - void sendAllData(); // this has to be separate as we need to send the head first, then set the data - void updateMode(); - CMonitor* monitor(); + bool good(); + void sendAllData(); // this has to be separate as we need to send the head first, then set the data + void updateMode(); + PHLMONITOR monitor(); private: SP resource; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; void makeAndSendNewMode(SP mode); void sendCurrentMode(); @@ -119,7 +119,7 @@ class COutputHead { class COutputConfigurationHead { public: - COutputConfigurationHead(SP resource_, CMonitor* pMonitor_); + COutputConfigurationHead(SP resource_, PHLMONITOR pMonitor_); bool good(); @@ -127,11 +127,7 @@ class COutputConfigurationHead { private: SP resource; - CMonitor* pMonitor = nullptr; - - struct { - CHyprSignalListener monitorDestroy; - } listeners; + PHLMONITORREF pMonitor; friend class COutputConfiguration; }; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index 0c324bf0..257155e4 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -2,7 +2,7 @@ #include "../Compositor.hpp" #include "core/Output.hpp" -COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { +COutputPower::COutputPower(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!resource->resource()) return; @@ -24,7 +24,7 @@ COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_ resource->sendMode(pMonitor->dpmsStatus ? ZWLR_OUTPUT_POWER_V1_MODE_ON : ZWLR_OUTPUT_POWER_V1_MODE_OFF); listeners.monitorDestroy = pMonitor->events.destroy.registerListener([this](std::any v) { - pMonitor = nullptr; + pMonitor.reset(); resource->sendFailed(); }); @@ -68,7 +68,7 @@ void COutputPowerProtocol::onGetOutputPower(CZwlrOutputPowerManagerV1* pMgr, uin } const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.get())).get(); + const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.lock())).get(); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/OutputPower.hpp b/src/protocols/OutputPower.hpp index 410742ca..91f2c5f3 100644 --- a/src/protocols/OutputPower.hpp +++ b/src/protocols/OutputPower.hpp @@ -11,14 +11,14 @@ class CMonitor; class COutputPower { public: - COutputPower(SP resource_, CMonitor* pMonitor); + COutputPower(SP resource_, PHLMONITOR pMonitor); bool good(); private: SP resource; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; struct { CHyprSignalListener monitorDestroy; diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 71f74cd5..b66694bf 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -73,8 +73,8 @@ void CPresentationFeedback::sendQueued(SP data, timespe CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - const auto PMONITOR = std::any_cast(param); - std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor.get() == PMONITOR; }); + const auto PMONITOR = std::any_cast(param); + std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); }); } diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 1b06a1fa..780c081d 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -19,7 +19,7 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t return; overlayCursor = !!overlay_cursor; - pMonitor = CWLOutputResource::fromResource(output)->monitor.get(); + pMonitor = CWLOutputResource::fromResource(output)->monitor; if (!pMonitor) { LOGM(ERR, "Client requested sharing of a monitor that doesnt exist"); @@ -38,7 +38,7 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t g_pHyprRenderer->makeEGLCurrent(); - shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor); + shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor.lock()); if (shmFormat == DRM_FORMAT_INVALID) { LOGM(ERR, "No format supported by renderer in capture output"); resource->sendFailed(); @@ -87,7 +87,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ return; } - if (!g_pCompositor->monitorExists(pMonitor)) { + if (!g_pCompositor->monitorExists(pMonitor.lock())) { LOGM(ERR, "Client requested sharing of a monitor that is gone"); resource->sendFailed(); PROTO::screencopy->destroyResource(this); @@ -165,7 +165,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ } if (!withDamage) - g_pHyprRenderer->damageMonitor(pMonitor); + g_pHyprRenderer->damageMonitor(pMonitor.lock()); } void CScreencopyFrame::share() { @@ -205,7 +205,7 @@ bool CScreencopyFrame::copyDmabuf() { CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock(), nullptr, true)) { + if (!g_pHyprRenderer->beginRender(pMonitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock(), nullptr, true)) { LOGM(ERR, "Can't copy: failed to begin rendering to dma frame"); return false; } @@ -240,7 +240,7 @@ bool CScreencopyFrame::copyShm() { CFramebuffer fb; fb.alloc(box.w, box.h, pMonitor->output->state->state().drmFormat); - if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { + if (!g_pHyprRenderer->beginRender(pMonitor.lock(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { LOGM(ERR, "Can't copy: failed to begin rendering"); return false; } @@ -288,7 +288,7 @@ bool CScreencopyFrame::copyShm() { } } - g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.pMonitor.reset(); LOGM(TRACE, "Copied frame via shm"); @@ -402,7 +402,7 @@ void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) { std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } -void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { +void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (m_vFramesAwaitingWrite.empty()) { g_pHyprRenderer->m_bDirectScanoutBlocked = false; return; // nothing to share diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index e121d0fd..62c9f8b8 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -60,7 +60,7 @@ class CScreencopyFrame { private: SP resource; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; bool overlayCursor = false; bool withDamage = false; bool lockedSWCursors = false; @@ -88,7 +88,7 @@ class CScreencopyProtocol : public IWaylandProtocol { void destroyResource(CScreencopyClient* resource); void destroyResource(CScreencopyFrame* resource); - void onOutputCommit(CMonitor* pMonitor); + void onOutputCommit(PHLMONITOR pMonitor); private: std::vector> m_vFrames; @@ -98,7 +98,7 @@ class CScreencopyProtocol : public IWaylandProtocol { SP m_pSoftwareCursorTimer; bool m_bTimerArmed = false; - void shareAllFrames(CMonitor* pMonitor); + void shareAllFrames(PHLMONITOR pMonitor); void shareFrame(CScreencopyFrame* frame); void sendFrameDamage(CScreencopyFrame* frame); bool copyFrameDmabuf(CScreencopyFrame* frame); diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index b1f701bf..642a5b89 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -5,7 +5,7 @@ #include "core/Compositor.hpp" #include "core/Output.hpp" -CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_) : +CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_) : resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { if (!resource->resource()) return; @@ -82,8 +82,8 @@ bool CSessionLockSurface::inert() { return sessionLock.expired(); } -CMonitor* CSessionLockSurface::monitor() { - return pMonitor; +PHLMONITOR CSessionLockSurface::monitor() { + return pMonitor.lock(); } SP CSessionLockSurface::surface() { @@ -184,7 +184,7 @@ void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id LOGM(LOG, "New sessionLockSurface with id {}", id); auto PSURFACE = CWLSurfaceResource::fromResource(surface); - auto PMONITOR = CWLOutputResource::fromResource(output)->monitor.get(); + auto PMONITOR = CWLOutputResource::fromResource(output)->monitor.lock(); SP sessionLock; for (auto const& l : m_vLocks) { diff --git a/src/protocols/SessionLock.hpp b/src/protocols/SessionLock.hpp index a0c67e88..a1df6fcf 100644 --- a/src/protocols/SessionLock.hpp +++ b/src/protocols/SessionLock.hpp @@ -13,12 +13,12 @@ class CWLSurfaceResource; class CSessionLockSurface { public: - CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_); + CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_); ~CSessionLockSurface(); bool good(); bool inert(); - CMonitor* monitor(); + PHLMONITOR monitor(); SP surface(); struct { @@ -31,7 +31,7 @@ class CSessionLockSurface { SP resource; WP sessionLock; WP pSurface; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; bool ackdConfigure = false; bool committed = false; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 66df5926..8b6208be 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -362,7 +362,7 @@ void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) { std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } -void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { +void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (m_vFramesAwaitingWrite.empty()) return; // nothing to share diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 9686431b..bcfa161c 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -80,7 +80,7 @@ class CToplevelExportProtocol : IWaylandProtocol { void destroyResource(CToplevelExportFrame* frame); void onWindowUnmap(PHLWINDOW pWindow); - void onOutputCommit(CMonitor* pMonitor); + void onOutputCommit(PHLMONITOR pMonitor); private: std::vector> m_vClients; diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 5644f243..056a72c4 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -681,7 +681,7 @@ void CWLDataDeviceProtocol::abortDrag() { g_pSeatManager->resendEnterEvents(); } -void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { +void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, timespec* when) { if (!dnd.dndSurface || !dnd.dndSurface->current.texture) return; diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 50e9ac61..81ca1b11 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -131,7 +131,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); // renders and damages the dnd icon, if present - void renderDND(CMonitor* pMonitor, timespec* when); + void renderDND(PHLMONITOR pMonitor, timespec* when); // for inputmgr to force refocus // TODO: move handling to seatmgr bool dndActive(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 833e2ccb..fc2d1012 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -340,7 +340,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { initAssets(); - static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); + static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); @@ -625,7 +625,7 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return shader; } -bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { +bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) { // passes requiring introspection are the ones that need to render blur, // or when we are rendering to a multigpu target @@ -731,7 +731,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; } -void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { +void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { m_RenderData.pMonitor = pMonitor; #ifndef GLES2 @@ -783,7 +783,7 @@ void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP< m_RenderData.simplePass = true; } -void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional finalDamage) { +void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional finalDamage) { m_RenderData.pMonitor = pMonitor; static auto PFORCEINTROSPECTION = CConfigValue("opengl:force_introspection"); @@ -929,7 +929,7 @@ void CHyprOpenGLImpl::end() { } // reset our data - m_RenderData.pMonitor = nullptr; + m_RenderData.pMonitor.reset(); m_RenderData.mouseZoomFactor = 1.f; m_RenderData.mouseZoomUseMouse = true; m_RenderData.forceIntrospection = false; @@ -1858,11 +1858,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o return currentRenderToFB; } -void CHyprOpenGLImpl::markBlurDirtyForMonitor(CMonitor* pMonitor) { +void CHyprOpenGLImpl::markBlurDirtyForMonitor(PHLMONITOR pMonitor) { m_mMonitorRenderResources[pMonitor].blurFBDirty = true; } -void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { +void CHyprOpenGLImpl::preRender(PHLMONITOR pMonitor) { static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); static auto PBLURXRAY = CConfigValue("decoration:blur:xray"); static auto PBLUR = CConfigValue("decoration:blur:enabled"); @@ -2728,7 +2728,7 @@ void CHyprOpenGLImpl::initAssets() { CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); } -void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { +void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); Debug::log(LOG, "Creating a texture for BGTex"); @@ -2860,7 +2860,7 @@ void CHyprOpenGLImpl::clearWithTex() { auto TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor); if (TEXIT == m_mMonitorBGFBs.end()) { - createBGTextureForMonitor(m_RenderData.pMonitor); + createBGTextureForMonitor(m_RenderData.pMonitor.lock()); TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor); } @@ -2872,7 +2872,7 @@ void CHyprOpenGLImpl::clearWithTex() { } } -void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { +void CHyprOpenGLImpl::destroyMonitorResources(PHLMONITOR pMonitor) { g_pHyprRenderer->makeEGLCurrent(); if (!g_pHyprOpenGL) @@ -2935,7 +2935,7 @@ void CHyprOpenGLImpl::setRenderModifEnabled(bool enabled) { m_RenderData.renderModif.enabled = enabled; } -uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { +uint32_t CHyprOpenGLImpl::getPreferredReadFormat(PHLMONITOR pMonitor) { return pMonitor->output->state->state().drmFormat; } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 0d1c267b..04f69d49 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -94,7 +94,7 @@ struct SMonitorRenderData { }; struct SCurrentRenderData { - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; PHLWORKSPACE pWorkspace = nullptr; Mat3x3 projection; Mat3x3 savedProjection; @@ -149,8 +149,8 @@ class CHyprOpenGLImpl { CHyprOpenGLImpl(); ~CHyprOpenGLImpl(); - void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(CMonitor*, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); + void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); + void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); void end(); void renderRect(CBox*, const CColor&, int round = 0); @@ -186,13 +186,13 @@ class CHyprOpenGLImpl { void scissor(const pixman_box32*, bool transform = true); void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(CMonitor*); + void destroyMonitorResources(PHLMONITOR); - void markBlurDirtyForMonitor(CMonitor*); + void markBlurDirtyForMonitor(PHLMONITOR); void preWindowPass(); bool preBlurQueued(); - void preRender(CMonitor*); + void preRender(PHLMONITOR); void saveBufferForMirror(CBox*); void renderMirrored(); @@ -205,31 +205,31 @@ class CHyprOpenGLImpl { void setDamage(const CRegion& damage, std::optional finalDamage = {}); - uint32_t getPreferredReadFormat(CMonitor* pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window - PHLLS m_pCurrentLayer; // hack to get the current rendered layer + PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window + PHLLS m_pCurrentLayer; // hack to get the current rendered layer - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; - std::unordered_map m_mMonitorRenderResources; - std::unordered_map m_mMonitorBGFBs; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; + std::unordered_map m_mMonitorRenderResources; + std::unordered_map m_mMonitorBGFBs; struct { PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; @@ -282,7 +282,7 @@ class CHyprOpenGLImpl { void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); GLuint compileShader(const GLuint&, std::string, bool dynamic = false); - void createBGTextureForMonitor(CMonitor*); + void createBGTextureForMonitor(PHLMONITOR); void initShaders(); void initDRMFormats(); void initEGL(bool gbm); @@ -304,7 +304,7 @@ class CHyprOpenGLImpl { void preBlurForCurrentMonitor(); - bool passRequiresIntrospection(CMonitor* pMonitor); + bool passRequiresIntrospection(PHLMONITOR pMonitor); friend class CHyprRenderer; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bc95abc6..1165b197 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -295,7 +295,7 @@ static void renderSurface(SP surface, int x, int y, void* da RDATA->surfaceCounter++; } -bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { +bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { if (!pWindow->visibleOnMonitor(pMonitor)) return false; @@ -389,7 +389,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { return false; } -void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { +void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { PHLWINDOW pWorkspaceWindow = nullptr; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); @@ -479,7 +479,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK } } -void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { +void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { PHLWINDOW lastWindow; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); @@ -551,7 +551,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor } } -void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) { +void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) { if (pWindow->isHidden()) return; @@ -766,7 +766,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec g_pHyprOpenGL->m_RenderData.clipBox = CBox(); } -void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time, bool popups) { +void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* time, bool popups) { if (!pLayer) return; @@ -835,7 +835,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time g_pHyprOpenGL->m_RenderData.discardOpacity = DA; } -void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, CMonitor* pMonitor, timespec* time) { +void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, timespec* time) { const auto POS = pPopup->globalBox().pos(); SRenderData renderdata = {pMonitor, time, POS.x, POS.y}; @@ -851,7 +851,7 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, CMonitor* pMonitor, time SURF->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); } -void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMonitor* pMonitor, timespec* time) { +void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, PHLMONITOR pMonitor, timespec* time) { SRenderData renderdata = {pMonitor, time, pMonitor->vecPosition.x, pMonitor->vecPosition.y}; renderdata.blur = false; @@ -863,7 +863,7 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon renderdata.surface->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); } -void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { +void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { static auto PDIMSPECIAL = CConfigValue("decoration:dim_special"); static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); static auto PBLUR = CConfigValue("decoration:blur:enabled"); @@ -1036,7 +1036,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC g_pHyprOpenGL->m_RenderData.renderModif = {}; } -void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry) { +void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry) { TRACY_GPU_ZONE("RenderLockscreen"); if (g_pSessionLockManager->isSessionLocked()) { @@ -1052,7 +1052,7 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB } } -void CHyprRenderer::renderSessionLockMissing(CMonitor* pMonitor) { +void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); CBox monbox = {{}, pMonitor->vecPixelSize}; @@ -1181,7 +1181,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_pLastMonitor.get()) { + if (pMonitor == g_pCompositor->m_pLastMonitor) { g_pHyprNotificationOverlay->draw(pMonitor); g_pHyprError->draw(); } // for drawing the debug overlay - if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { + if (pMonitor == g_pCompositor->m_vMonitors.front() && *PDEBUGOVERLAY == 1) { renderStartOverlay = std::chrono::high_resolution_clock::now(); g_pDebugOverlay->draw(); endRenderOverlay = std::chrono::high_resolution_clock::now(); @@ -1491,7 +1491,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pDebugOverlay->renderData(pMonitor, durationUs); if (*PDEBUGOVERLAY == 1) { - if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { + if (pMonitor == g_pCompositor->m_vMonitors.front()) { const float noOverlayUs = durationUs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; g_pDebugOverlay->renderDataNoOverlay(pMonitor, noOverlayUs); } else { @@ -1500,7 +1500,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } -bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { +bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { // apply timelines for explicit sync // save inFD otherwise reset will reset it auto inFD = pMonitor->output->state->state().explicitInFence; @@ -1565,7 +1565,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { return ok; } -void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { +void CHyprRenderer::renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { Vector2D translate = {geometry.x, geometry.y}; float scale = (float)geometry.width / pMonitor->vecPixelSize.x; @@ -1582,7 +1582,7 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, g_pHyprOpenGL->m_RenderData.pWorkspace = nullptr; } -void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { +void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface->resource()) continue; @@ -1670,7 +1670,7 @@ static void applyExclusive(CBox& usableArea, uint32_t anchor, int32_t exclusive, } } -void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector& layerSurfaces, bool exclusiveZone, CBox* usableArea) { +void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vector& layerSurfaces, bool exclusiveZone, CBox* usableArea) { CBox full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; for (auto const& ls : layerSurfaces) { @@ -1865,7 +1865,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { windowBox.translate(pWindow->m_vFloatingOffset); for (auto const& m : g_pCompositor->m_vMonitors) { - if (forceFull || g_pHyprRenderer->shouldRenderWindow(pWindow, m.get())) { // only damage if window is rendered on monitor + if (forceFull || g_pHyprRenderer->shouldRenderWindow(pWindow, m)) { // only damage if window is rendered on monitor CBox fixedDamageBox = {windowBox.x - m->vecPosition.x, windowBox.y - m->vecPosition.y, windowBox.width, windowBox.height}; fixedDamageBox.scale(m->scale); m->addDamage(&fixedDamageBox); @@ -1881,7 +1881,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { Debug::log(LOG, "Damage: Window ({}): xy: {}, {} wh: {}, {}", pWindow->m_szTitle, windowBox.x, windowBox.y, windowBox.width, windowBox.height); } -void CHyprRenderer::damageMonitor(CMonitor* pMonitor) { +void CHyprRenderer::damageMonitor(PHLMONITOR pMonitor) { if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror()) return; @@ -1925,7 +1925,7 @@ void CHyprRenderer::damageRegion(const CRegion& rg) { } } -void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion) { +void CHyprRenderer::damageMirrorsWith(PHLMONITOR pMonitor, const CRegion& pRegion) { for (auto const& mirror : pMonitor->mirrors) { // transform the damage here, so it won't get clipped by the monitor damage ring @@ -1946,11 +1946,11 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion mirror->addDamage(&transformed); - g_pCompositor->scheduleFrameForMonitor(mirror, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(mirror.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } } -void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) { +void CHyprRenderer::renderDragIcon(PHLMONITOR pMonitor, timespec* time) { PROTO::data->renderDND(pMonitor, time); } @@ -1965,7 +1965,7 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& return DAMAGE_TRACKING_INVALID; } -bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) { +bool CHyprRenderer::applyMonitorRule(PHLMONITOR pMonitor, SMonitorRule* pMonitorRule, bool force) { static auto PDISABLESCALECHECKS = CConfigValue("debug:disable_scale_checks"); @@ -2436,7 +2436,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (!g_pPointerManager->softwareLockedFor(m)) continue; - g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? + g_pHyprRenderer->damageMonitor(m); // TODO: maybe just damage the cursor area? } setCursorHidden(true); @@ -2448,7 +2448,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (!g_pPointerManager->softwareLockedFor(m)) continue; - g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? + g_pHyprRenderer->damageMonitor(m); // TODO: maybe just damage the cursor area? } setCursorHidden(false); @@ -2479,7 +2479,7 @@ bool CHyprRenderer::shouldRenderCursor() { return !m_bCursorHidden && m_bCursorHasSurface; } -std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor) { +std::tuple CHyprRenderer::getRenderTimes(PHLMONITOR pMonitor) { const auto POVERLAY = &g_pDebugOverlay->m_mMonitorOverlays[pMonitor]; float avgRenderTime = 0; @@ -2590,7 +2590,7 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWork region.subtract(rg); } -bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { +bool CHyprRenderer::canSkipBackBufferClear(PHLMONITOR pMonitor) { for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { if (!ls->layerSurface) continue; @@ -2616,7 +2616,7 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { return false; } -void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { +void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { pMonitor->solitaryClient.reset(); // reset it, if we find one it will be set. if (g_pHyprNotificationOverlay->hasAny() || g_pSessionLockManager->isSessionLocked()) @@ -2704,7 +2704,7 @@ void CHyprRenderer::unsetEGL() { eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } -bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { +bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { makeEGLCurrent(); @@ -2777,7 +2777,7 @@ void CHyprRenderer::endRender() { if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); else { - g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.pMonitor.reset(); g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = true; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 7d1ae4b1..41f40b5a 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -49,29 +49,29 @@ class CHyprRenderer { CHyprRenderer(); ~CHyprRenderer(); - void renderMonitor(CMonitor* pMonitor); + void renderMonitor(PHLMONITOR pMonitor); void arrangeLayersForMonitor(const MONITORID&); void damageSurface(SP, double, double, double scale = 1.0); void damageWindow(PHLWINDOW, bool forceFull = false); void damageBox(CBox*, bool skipFrameSchedule = false); void damageBox(const int& x, const int& y, const int& w, const int& h); void damageRegion(const CRegion&); - void damageMonitor(CMonitor*); - void damageMirrorsWith(CMonitor*, const CRegion&); - bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); - bool shouldRenderWindow(PHLWINDOW, CMonitor*); + void damageMonitor(PHLMONITOR); + void damageMirrorsWith(PHLMONITOR, const CRegion&); + bool applyMonitorRule(PHLMONITOR, SMonitorRule*, bool force = false); + bool shouldRenderWindow(PHLWINDOW, PHLMONITOR); bool shouldRenderWindow(PHLWINDOW); void ensureCursorRenderingMode(); bool shouldRenderCursor(); void setCursorHidden(bool hide); void calculateUVForSurface(PHLWINDOW, SP, SP pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, bool fixMisalignedFSV1 = false); - std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min - void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry); + std::tuple getRenderTimes(PHLMONITOR pMonitor); // avg max min + void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry); void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace); void setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace); // TODO: merge occlusion methods - bool canSkipBackBufferClear(CMonitor* pMonitor); - void recheckSolitaryForMonitor(CMonitor* pMonitor); + bool canSkipBackBufferClear(PHLMONITOR pMonitor); + void recheckSolitaryForMonitor(PHLMONITOR pMonitor); void setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force = false); void setCursorFromName(const std::string& name, bool force = false); void onRenderbufferDestroy(CRenderbuffer* rb); @@ -84,13 +84,13 @@ class CHyprRenderer { // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. - bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); - void endRender(); + bool beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); + void endRender(); - bool m_bBlockSurfaceFeedback = false; - bool m_bRenderingSnapshot = false; - CMonitor* m_pMostHzMonitor = nullptr; - bool m_bDirectScanoutBlocked = false; + bool m_bBlockSurfaceFeedback = false; + bool m_bRenderingSnapshot = false; + PHLMONITORREF m_pMostHzMonitor; + bool m_bDirectScanoutBlocked = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); @@ -115,20 +115,20 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(PHLWINDOW, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); - void renderLayer(PHLLS, CMonitor*, timespec*, bool popups = false); - void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); - void renderDragIcon(CMonitor*, timespec*); - void renderIMEPopup(CInputPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); - void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything - void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - void renderSessionLockMissing(CMonitor* pMonitor); + void arrangeLayerArray(PHLMONITOR, const std::vector&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderLayer(PHLLS, PHLMONITOR, timespec*, bool popups = false); + void renderSessionLockSurface(SSessionLockSurface*, PHLMONITOR, timespec*); + void renderDragIcon(PHLMONITOR, timespec*); + void renderIMEPopup(CInputPopup*, PHLMONITOR, timespec*); + void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); + void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything + void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + void renderSessionLockMissing(PHLMONITOR pMonitor); - bool commitPendingAndDoExplicitSync(CMonitor* pMonitor); + bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); bool m_bCursorHidden = false; bool m_bCursorHasSurface = false; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 1eaaa0af..68325a9c 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -46,7 +46,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() { return box.translate(WORKSPACEOFFSET); } -void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a) { +void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float a) { if (doesntWantBorders()) return; @@ -119,7 +119,7 @@ void CHyprBorderDecoration::damageEntire() { borderRegion.subtract(surfaceBoxShrunkRounding); for (auto const& m : g_pCompositor->m_vMonitors) { - if (!g_pHyprRenderer->shouldRenderWindow(m_pWindow.lock(), m.get())) { + if (!g_pHyprRenderer->shouldRenderWindow(m_pWindow.lock(), m)) { const CRegion monitorRegion({m->vecPosition, m->vecSize}); borderRegion.subtract(monitorRegion); } diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 0e196565..5d248a81 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -11,7 +11,7 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(CMonitor*, float a); + virtual void draw(PHLMONITOR, float a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 628a579a..a4388a67 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -67,7 +67,7 @@ void CHyprDropShadowDecoration::damageEntire() { } for (auto const& m : g_pCompositor->m_vMonitors) { - if (!g_pHyprRenderer->shouldRenderWindow(PWINDOW, m.get())) { + if (!g_pHyprRenderer->shouldRenderWindow(PWINDOW, m)) { const CRegion monitorRegion({m->vecPosition, m->vecSize}); shadowRegion.subtract(monitorRegion); } @@ -86,7 +86,7 @@ void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) { m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); } -void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) { +void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float a) { const auto PWINDOW = m_pWindow.lock(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index ecd5a47b..fce9a7c7 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -11,7 +11,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(CMonitor*, float a); + virtual void draw(PHLMONITOR, float a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 74a1e2e9..4219a5a8 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -94,7 +94,7 @@ void CHyprGroupBarDecoration::damageEntire() { g_pHyprRenderer->damageBox(&box); } -void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) { +void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float a) { // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index bfb15d5c..e388fa38 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -31,7 +31,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(CMonitor*, float a); + virtual void draw(PHLMONITOR, float a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index a58560f3..99698a56 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -39,7 +39,7 @@ class IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply) = 0; - virtual void draw(CMonitor*, float a) = 0; + virtual void draw(PHLMONITOR, float a) = 0; virtual eDecorationType getDecorationType() = 0; From 6a5c342063814ca7e3d181f324c71305bcd656a0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 23:45:51 +0100 Subject: [PATCH 0164/1803] layersurface: round geom in arrangeLayerArray fixes #8171 --- src/render/Renderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1165b197..1946d5a2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1742,7 +1742,9 @@ void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vectorgeometry = box; applyExclusive(*usableArea, PSTATE->anchor, PSTATE->exclusive, PSTATE->exclusiveEdge, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); From a17850e41cabb455880b43032cf65041cd77ef25 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 23:47:28 +0100 Subject: [PATCH 0165/1803] layersurface: fixup brace style --- src/render/Renderer.cpp | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1946d5a2..5df0c070 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1693,51 +1693,51 @@ void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vectordesiredSize}; // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - if (box.width == 0) { + if (box.width == 0) box.x = bounds.x; - } else if ((PSTATE->anchor & both_horiz) == both_horiz) { + else if ((PSTATE->anchor & both_horiz) == both_horiz) box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) box.x = bounds.x; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) box.x = bounds.x + (bounds.width - box.width); - } else { + else box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); - } + // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; - if (box.height == 0) { + if (box.height == 0) box.y = bounds.y; - } else if ((PSTATE->anchor & both_vert) == both_vert) { + else if ((PSTATE->anchor & both_vert) == both_vert) box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) box.y = bounds.y; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) box.y = bounds.y + (bounds.height - box.height); - } else { + else box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); - } + // Margin if (box.width == 0) { box.x += PSTATE->margin.left; box.width = bounds.width - (PSTATE->margin.left + PSTATE->margin.right); - } else if ((PSTATE->anchor & both_horiz) == both_horiz) { - // don't apply margins - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + } else if ((PSTATE->anchor & both_horiz) == both_horiz) + ; // don't apply margins + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) box.x += PSTATE->margin.left; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) box.x -= PSTATE->margin.right; - } + if (box.height == 0) { box.y += PSTATE->margin.top; box.height = bounds.height - (PSTATE->margin.top + PSTATE->margin.bottom); - } else if ((PSTATE->anchor & both_vert) == both_vert) { - // don't apply margins - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + } else if ((PSTATE->anchor & both_vert) == both_vert) + ; // don't apply margins + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) box.y += PSTATE->margin.top; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) box.y -= PSTATE->margin.bottom; - } + if (box.width <= 0 || box.height <= 0) { Debug::log(ERR, "LayerSurface {:x} has a negative/zero w/h???", (uintptr_t)ls.get()); continue; From 08cc063e175e48cea44d26b7e3762f4b8611f0c5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 23:48:25 +0100 Subject: [PATCH 0166/1803] monitor: avoid crash on released buffer in surf --- src/helpers/Monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 6ded5ea4..d8889585 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -845,7 +845,7 @@ bool CMonitor::attemptDirectScanout() { return false; // we can't scanout shm buffers. - if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */) + if (!PSURFACE->current.buffer || !PSURFACE->current.buffer->buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */) return false; Debug::log(TRACE, "attemptDirectScanout: surface {:x} passed, will attempt", (uintptr_t)PSURFACE.get()); From 4093b993a2c79ce576702641134d745ab97c6b2c Mon Sep 17 00:00:00 2001 From: Mike Will Date: Mon, 21 Oct 2024 11:08:25 -0400 Subject: [PATCH 0167/1803] input: add snapping to floating windows (#8088) * add snapping to floating windows Works for both moving and resizing of windows. It comes with 3 options: `general:snap:enabled` - whether it's enabled, off by default `general:snap:window_gap` - minimum gap in pixels between windows before snapping. Setting to 0 effectively turns off this method of snapping. `general:snap:monitor_gap` - minimum gap in pixels between window and monitor edges before snapping. Again, setting it to 0 effectively turns it off. * snap: add more ignore criteria and change if clause into a guard * snap: refactor code * snap: new refactoring approach and account for border size * snap: do corner snapping after all edge snapping is done The approach of performing corner snaps after each individual edge snap results in far fewer scenarios where snapping can occur. After trying it out for a while, I found that I prefer an approach that's more prone to snapping. * snap: combine snapWindows and snapMonitor into a single function * snap: add forced aspect ratio functionality * snap: avoid directly referring to border_size config value * snap: address vaxerski feedback - add new line between functions - use std::function typedef for SnapFn and make snap functions static - avoid uninitialized variable declarations. - change ignore condition m_bIsX11 to isX11OverrideRedirect() - use braces for CBox and Vector2D declarations. - add SNAP_INVALID to eSnapEdge enum - use bitshift notation for eSnapEdge and eRectCorner - make performSnap a non-member function. * snap: add corner-snapping to forced aspect ratio mode --- src/config/ConfigDescriptions.hpp | 18 ++++ src/config/ConfigManager.cpp | 3 + src/layout/IHyprLayout.cpp | 155 +++++++++++++++++++++++++++++- src/layout/IHyprLayout.hpp | 18 +++- 4 files changed, 185 insertions(+), 9 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index bef5ee53..7e2dd1be 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -104,6 +104,24 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{0, 0, 4}, }, + SConfigOptionDescription{ + .value = "general:snap:enabled", + .description = "enable snapping for floating windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "general:snap:window_gap", + .description = "minimum gap in pixels between windows before snapping", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{10, 0, 100}, + }, + SConfigOptionDescription{ + .value = "general:snap:monitor_gap", + .description = "minimum gap in pixels between window and monitor edges before snapping", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{10, 0, 100}, + }, /* * decoration: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f16ebe46..1dbd248d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -341,6 +341,9 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("general:layout", {"dwindle"}); m_pConfig->addConfigValue("general:allow_tearing", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:resize_corner", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:snap:enabled", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:snap:window_gap", Hyprlang::INT{10}); + m_pConfig->addConfigValue("general:snap:monitor_gap", Hyprlang::INT{10}); m_pConfig->addConfigValue("misc:disable_hyprland_logo", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_splash_rendering", Hyprlang::INT{0}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index b8d92636..95919c65 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -396,6 +396,138 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->m_bWasDraggingWindow = false; } +static inline bool canSnap(const double sideA, const double sideB, const double gap) { + return std::abs(sideA - sideB) < gap; +} + +static void snapMoveLeft(double& pos, double& len, const double p) { + pos = p; +} + +static void snapMoveRight(double& pos, double& len, const double p) { + pos = p - len; +} + +static void snapResizeLeft(double& pos, double& len, const double p) { + len += pos - p; + pos = p; +} + +static void snapResizeRight(double& pos, double& len, const double p) { + len = p - pos; +} + +typedef std::function SnapFn; + +static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { + static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); + static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); + + const SnapFn snapRight = (mode == MBIND_MOVE) ? snapMoveRight : snapResizeRight; + const SnapFn snapLeft = (mode == MBIND_MOVE) ? snapMoveLeft : snapResizeLeft; + const SnapFn snapDown = snapRight; + const SnapFn snapUp = snapLeft; + int snaps = 0; + + if (*SNAPWINDOWGAP) { + const auto PID = DRAGGINGWINDOW->getPID(); + const auto WSID = DRAGGINGWINDOW->workspaceID(); + const int BORD = DRAGGINGWINDOW->getRealBorderSize(); + + for (auto& other : g_pCompositor->m_vWindows) { + if (other->workspaceID() != WSID || other->getPID() == PID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) + continue; + + const int bord = std::max(BORD, other->getRealBorderSize()); + const double gap = *SNAPWINDOWGAP + bord; + + const CBox box = other->getWindowMainSurfaceBox(); + const CBox ob = {box.x, box.y, box.x + box.w, box.y + box.h}; + const CBox bb = {ob.x - bord, ob.y - bord, ob.w + bord, ob.h + bord}; + const Vector2D end = {pos.x + size.x, pos.y + size.y}; + + // only snap windows if their ranges intersect in the opposite axis + if (pos.y <= bb.h && bb.y <= end.y) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, bb.w, gap)) { + snapLeft(pos.x, size.x, bb.w); + snaps |= SNAP_LEFT; + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, bb.x, gap)) { + snapRight(pos.x, size.x, bb.x); + snaps |= SNAP_RIGHT; + } + } + if (pos.x <= bb.w && bb.x <= end.x) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, bb.h, gap)) { + snapUp(pos.y, size.y, bb.h); + snaps |= SNAP_UP; + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, bb.y, gap)) { + snapDown(pos.y, size.y, bb.y); + snaps |= SNAP_DOWN; + } + } + + // corner snapping + if (pos.x == bb.w || bb.x == pos.x + size.x) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, ob.y, gap)) { + snapUp(pos.y, size.y, ob.y); + snaps |= SNAP_UP; + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, ob.h, gap)) { + snapDown(pos.y, size.y, ob.h); + snaps |= SNAP_DOWN; + } + } + if (pos.y == bb.h || bb.y == pos.y + size.y) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, ob.x, gap)) { + snapLeft(pos.x, size.x, ob.x); + snaps |= SNAP_LEFT; + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, ob.w, gap)) { + snapRight(pos.x, size.x, ob.w); + snaps |= SNAP_RIGHT; + } + } + } + } + + if (*SNAPMONITORGAP) { + const auto MON = g_pCompositor->getMonitorFromID(DRAGGINGWINDOW->m_iMonitorID); + const CBox mon = {MON->vecPosition.x, MON->vecPosition.y, MON->vecPosition.x + MON->vecSize.x, MON->vecPosition.y + MON->vecSize.y}; + const double gap = *SNAPMONITORGAP; + + if (canSnap(pos.x, mon.x, gap)) { + snapLeft(pos.x, size.x, mon.x); + snaps |= SNAP_LEFT; + } + if (canSnap(pos.x + size.x, mon.w, gap)) { + snapRight(pos.x, size.x, mon.w); + snaps |= SNAP_RIGHT; + } + if (canSnap(pos.y, mon.y, gap)) { + snapUp(pos.y, size.y, mon.y); + snaps |= SNAP_UP; + } + if (canSnap(pos.y + size.y, mon.h, gap)) { + snapDown(pos.y, size.y, mon.h); + snaps |= SNAP_DOWN; + } + } + + if (mode == MBIND_RESIZE_FORCE_RATIO) { + const double RATIO = beginSize.y / beginSize.x; + + if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { + const double sizeY = size.x * RATIO; + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) + pos.y += size.y - sizeY; + size.y = sizeY; + } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { + const double sizeX = size.y / RATIO; + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) + pos.x += size.x - sizeX; + size.x = sizeX; + } + } +} + void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->currentlyDraggedWindow.expired()) return; @@ -418,6 +550,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { static auto PANIMATEMOUSE = CConfigValue("misc:animate_mouse_windowdragging"); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); + static auto SNAPENABLED = CConfigValue("general:snap:enabled"); + 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; @@ -448,7 +582,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->dragMode == MBIND_MOVE) { - CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goal()}; + Vector2D newPos = m_vBeginDragPositionXY + DELTA; + Vector2D newSize = DRAGGINGWINDOW->m_vRealSize.goal(); + + if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled) + performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY); + + CBox wb = {newPos, newSize}; wb.round(); if (*PANIMATEMOUSE) @@ -479,9 +619,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) newSize = newSize + Vector2D(-DELTA.x, DELTA.y); - if ((m_vBeginDragSizeXY.x >= 1 && m_vBeginDragSizeXY.y >= 1) && - (g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || - (!(g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) && DRAGGINGWINDOW->m_sWindowData.keepAspectRatio.valueOrDefault()))) { + eMouseBindMode mode = g_pInputManager->dragMode; + if (DRAGGINGWINDOW->m_sWindowData.keepAspectRatio.valueOrDefault() && mode != MBIND_RESIZE_BLOCK_RATIO) + mode = MBIND_RESIZE_FORCE_RATIO; + + if (m_vBeginDragSizeXY.x >= 1 && m_vBeginDragSizeXY.y >= 1 && mode == MBIND_RESIZE_FORCE_RATIO) { const float RATIO = m_vBeginDragSizeXY.y / m_vBeginDragSizeXY.x; @@ -510,6 +652,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0.0); + if (*SNAPENABLED) { + performSnap(newPos, newSize, DRAGGINGWINDOW, mode, m_eGrabbedCorner, m_vBeginDragSizeXY); + newSize = newSize.clamp(MINSIZE, MAXSIZE); + } + CBox wb = {newPos, newSize}; wb.round(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index f9e2de0d..f1659ccd 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -18,11 +18,19 @@ struct SLayoutMessageHeader { enum eFullscreenMode : int8_t; enum eRectCorner { - CORNER_NONE = 0, - CORNER_TOPLEFT, - CORNER_TOPRIGHT, - CORNER_BOTTOMRIGHT, - CORNER_BOTTOMLEFT + CORNER_NONE = 0, + CORNER_TOPLEFT = (1 << 0), + CORNER_TOPRIGHT = (1 << 1), + CORNER_BOTTOMRIGHT = (1 << 2), + CORNER_BOTTOMLEFT = (1 << 3), +}; + +enum eSnapEdge { + SNAP_INVALID = 0, + SNAP_UP = (1 << 0), + SNAP_DOWN = (1 << 1), + SNAP_LEFT = (1 << 2), + SNAP_RIGHT = (1 << 3), }; enum eDirection { From 9df0f0b66c66706c9ce8cf9f80e834d5abfc1e96 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:09:14 -0500 Subject: [PATCH 0168/1803] renderer: fix floating window damage (#8182) --- src/events/Windows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 21055f79..57a28948 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -687,6 +687,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); + g_pHyprRenderer->damageWindow(PWINDOW); + // do this after onWindowRemoved because otherwise it'll think the window is invalid PWINDOW->m_bIsMapped = false; @@ -726,8 +728,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { 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.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it From 5e96d738e698f22969ca502d042d5751711c6d8a Mon Sep 17 00:00:00 2001 From: KAGEYAM4 <75798544+KAGEYAM4@users.noreply.github.com> Date: Tue, 22 Oct 2024 04:58:42 +0530 Subject: [PATCH 0169/1803] hyprpm: Add option to notify on fail and keep original notify (#8167) * Only generate notification on fail Hyprpm fail/pass notification are mutually exclusive. * Add option to notify on fail and keep original notify (#1) * Add option to notify on fail and keep original notify --------- Co-authored-by: KAGEYAM4 <75798544+KAGEYAM4@users.noreply.github.com> --------- Co-authored-by: littleblack111 --- hyprpm/src/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index 67f14aed..55fb57e2 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -23,7 +23,8 @@ constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┃ ┣ Flags: ┃ -┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail) +┣ --notify | -n → Send a hyprland notification for important events (including both successes and fail events) +┣ --notify-fail | -nn → Send a hyprland notification for fail events only ┣ --help | -h → Show this menu ┣ --verbose | -v → Enable too much logging ┣ --force | -f → Force an operation ignoring checks (e.g. update -f) @@ -43,7 +44,7 @@ int main(int argc, char** argv, char** envp) { } std::vector command; - bool notify = false, verbose = false, force = false, noShallow = false; + bool notify = false, notifyFail = false, verbose = false, force = false, noShallow = false; for (int i = 1; i < argc; ++i) { if (ARGS[i].starts_with("-")) { @@ -52,6 +53,8 @@ int main(int argc, char** argv, char** envp) { return 0; } else if (ARGS[i] == "--notify" || ARGS[i] == "-n") { notify = true; + } else if (ARGS[i] == "--notify-fail" || ARGS[i] == "-nn") { + notifyFail = notify = true; } else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") { verbose = true; } else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") { @@ -155,7 +158,7 @@ int main(int argc, char** argv, char** envp) { break; default: break; } - } else if (notify) { + } else if (notify && !notifyFail) { g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins"); } } else if (command[0] == "list") { From 29997ef4ba8ef0a80390e80199998d1390177454 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 22 Oct 2024 21:34:15 +0100 Subject: [PATCH 0170/1803] default/config: improve default animations objectively better --- example/hyprland.conf | 30 ++++++++++++++++++++++-------- src/config/defaultConfig.hpp | 30 ++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 012446f3..f94cb1d1 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -103,18 +103,32 @@ decoration { # https://wiki.hyprland.org/Configuring/Variables/#animations animations { - enabled = true + enabled = yes, please :) # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more - bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + bezier = easeOutQuint,0.23,1,0.32,1 + bezier = easeInOutCubic,0.65,0.05,0.36,1 + bezier = linear,0,0,1,1 + bezier = almostLinear,0.5,0.5,0.75,1.0 + bezier = quick,0.15,0,0.1,1 - animation = windows, 1, 7, myBezier - animation = windowsOut, 1, 7, default, popin 80% - animation = border, 1, 10, default - animation = borderangle, 1, 8, default - animation = fade, 1, 7, default - animation = workspaces, 1, 6, default + animation = global, 1, 10, default + animation = border, 1, 5.39, easeOutQuint + animation = windows, 1, 4.79, easeOutQuint + animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% + animation = windowsOut, 1, 1.49, linear, popin 87% + animation = fadeIn, 1, 1.73, almostLinear + animation = fadeOut, 1, 1.46, almostLinear + animation = fade, 1, 3.03, quick + animation = layers, 1, 3.81, easeOutQuint + animation = layersIn, 1, 4, easeOutQuint, fade + animation = layersOut, 1, 1.5, linear, fade + animation = fadeLayersIn, 1, 1.79, almostLinear + animation = fadeLayersOut, 1, 1.39, almostLinear + animation = workspaces, 1, 1.94, almostLinear, fade + animation = workspacesIn, 1, 1.21, almostLinear, fade + animation = workspacesOut, 1, 1.94, almostLinear, fade } # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index a5d759de..4a33ec91 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -116,18 +116,32 @@ decoration { # https://wiki.hyprland.org/Configuring/Variables/#animations animations { - enabled = true + enabled = yes, please :) # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more - bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + bezier = easeOutQuint,0.23,1,0.32,1 + bezier = easeInOutCubic,0.65,0.05,0.36,1 + bezier = linear,0,0,1,1 + bezier = almostLinear,0.5,0.5,0.75,1.0 + bezier = quick,0.15,0,0.1,1 - animation = windows, 1, 7, myBezier - animation = windowsOut, 1, 7, default, popin 80% - animation = border, 1, 10, default - animation = borderangle, 1, 8, default - animation = fade, 1, 7, default - animation = workspaces, 1, 6, default + animation = global, 1, 10, default + animation = border, 1, 5.39, easeOutQuint + animation = windows, 1, 4.79, easeOutQuint + animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% + animation = windowsOut, 1, 1.49, linear, popin 87% + animation = fadeIn, 1, 1.73, almostLinear + animation = fadeOut, 1, 1.46, almostLinear + animation = fade, 1, 3.03, quick + animation = layers, 1, 3.81, easeOutQuint + animation = layersIn, 1, 4, easeOutQuint, fade + animation = layersOut, 1, 1.5, linear, fade + animation = fadeLayersIn, 1, 1.79, almostLinear + animation = fadeLayersOut, 1, 1.39, almostLinear + animation = workspaces, 1, 1.94, almostLinear, fade + animation = workspacesIn, 1, 1.21, almostLinear, fade + animation = workspacesOut, 1, 1.94, almostLinear, fade } # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ From 2b6ff6837e81a3b459f2f3cc366830c420a7a62e Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 22 Oct 2024 23:51:25 +0000 Subject: [PATCH 0171/1803] groups: add group_on_movetoworkspace (#8159) --- src/Compositor.cpp | 51 +++++++++++++++++++++++-------- src/config/ConfigDescriptions.hpp | 6 ++++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 5 +-- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b23b3194..313d57ac 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -34,6 +34,7 @@ #include "render/Renderer.hpp" #include "xwayland/XWayland.hpp" #include "helpers/ByteOperations.hpp" +#include "render/decorations/CHyprGroupBarDecoration.hpp" #include #include @@ -2748,21 +2749,47 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FSMODE_NONE); - if (!pWindow->m_bIsFloating) { + const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); + const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true); + const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; + const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + + if (!pWindow->m_bIsFloating) g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); - pWindow->moveToWorkspace(pWorkspace); - pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; - g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); + + pWindow->moveToWorkspace(pWorkspace); + pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; + + static auto PGROUPONMOVETOWORKSPACE = CConfigValue("group:group_on_movetoworkspace"); + if (*PGROUPONMOVETOWORKSPACE && visibleWindowsOnWorkspace == 1 && pFirstWindowOnWorkspace && pFirstWindowOnWorkspace != pWindow && + pFirstWindowOnWorkspace->m_sGroupData.pNextWindow.lock() && pWindow->canBeGroupedInto(pFirstWindowOnWorkspace)) { + + pWindow->m_bIsFloating = pFirstWindowOnWorkspace->m_bIsFloating; // match the floating state. Needed to group tiled into floated and vice versa. + if (!pWindow->m_sGroupData.pNextWindow.expired()) { + PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock(); + while (next != pWindow) { + next->m_bIsFloating = pFirstWindowOnWorkspace->m_bIsFloating; // match the floating state of group members + next = next->m_sGroupData.pNextWindow.lock(); + } + } + + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? pFirstWindowOnWorkspace : pFirstWindowOnWorkspace->getGroupTail())->insertWindowToGroup(pWindow); + + pFirstWindowOnWorkspace->setGroupCurrent(pWindow); + pWindow->updateWindowDecos(); + g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); + + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + } else { - const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; + if (!pWindow->m_bIsFloating) + g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); - const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); - - pWindow->moveToWorkspace(pWorkspace); - pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; - - pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; + if (pWindow->m_bIsFloating) + pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; } pWindow->updateToplevel(); diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 7e2dd1be..7910e865 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -808,6 +808,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "group:group_on_movetoworkspace", + .description = "whether using movetoworkspace[silent] will merge the window into the workspace's solitary unlocked group", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1dbd248d..8237fd44 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -383,6 +383,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:group_on_movetoworkspace", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 95919c65..655f2341 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -194,8 +194,9 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { denied = true; if (*PAUTOGROUP // check if auto_group is enabled. - && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. + && OPENINGON // this shouldn't be 0, but honestly, better safe than sorry. && OPENINGON != pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. && !denied) { // don't group a new floated window into a tiled group (for convenience). @@ -352,7 +353,7 @@ void IHyprLayout::onEndDragWindow() { DRAGGINGWINDOW->m_bDraggingTiled = false; } - if (DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock()) { + if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { std::vector members; PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); do { From 6e0aadc585c6d9fdaaebfa5853adbf9610897c82 Mon Sep 17 00:00:00 2001 From: chitoroagad Date: Tue, 22 Oct 2024 18:05:30 +0100 Subject: [PATCH 0172/1803] updated flake.lock --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 0a12fe0a..beb56b5c 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1728902391, - "narHash": "sha256-44bnoY0nAvbBQ/lVjmn511yL39Sv7SknV0BDxn34P3Q=", + "lastModified": 1729527199, + "narHash": "sha256-D5/YksfRga8Akd04ZtIkuYSIOjXVrAzQIQBSeplokzU=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "9874e08eec85b5542ca22494e127b0cdce46b786", + "rev": "8d732fa8aff8b12ef2b1e2f00fc8153e41312b72", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1728888510, - "narHash": "sha256-nsNdSldaAyu6PE3YUA+YQLqUDJh+gRbBooMMekZJwvI=", + "lastModified": 1729413321, + "narHash": "sha256-I4tuhRpZFa6Fu6dcH9Dlo5LlH17peT79vx1y1SpeKt0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a3c0b3b21515f74fd2665903d4ce6bc4dc81c77c", + "rev": "1997e4aa514312c1af7e2bda7fad1644e778ff26", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1728778939, - "narHash": "sha256-WybK5E3hpGxtCYtBwpRj1E9JoiVxe+8kX83snTNaFHE=", + "lastModified": 1729104314, + "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "ff68f91754be6f3427e4986d7949e6273659be1d", + "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6", "type": "github" }, "original": { From cdac64970e894c3211d94da8925fbf905b52a594 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Thu, 24 Oct 2024 01:32:39 +0500 Subject: [PATCH 0173/1803] Makefile: fix legacyrendererdebug typo (#8214) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 98267eea..7cf21119 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ legacyrenderer: legacyrendererdebug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build - cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` release: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build From f603a22af0c8890b9742d761d44f0b595740f5b1 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:12:41 +0500 Subject: [PATCH 0174/1803] internal: Remove some unused lambda captures (#8218) --- src/devices/Tablet.cpp | 2 +- src/managers/TokenManager.cpp | 4 ++-- src/managers/input/InputManager.cpp | 2 +- src/protocols/DataDeviceWlr.cpp | 4 ++-- src/protocols/PrimarySelection.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp index 71ca8991..99e436fb 100644 --- a/src/devices/Tablet.cpp +++ b/src/devices/Tablet.cpp @@ -197,7 +197,7 @@ CTabletPad::CTabletPad(SP pad_) : pad(pad_) { }); }); - listeners.attach = pad->events.attach.registerListener([this](std::any d) { + listeners.attach = pad->events.attach.registerListener([](std::any d) { ; // TODO: this doesn't do anything in aq atm }); diff --git a/src/managers/TokenManager.cpp b/src/managers/TokenManager.cpp index cee97c1c..5efa2eb8 100644 --- a/src/managers/TokenManager.cpp +++ b/src/managers/TokenManager.cpp @@ -34,7 +34,7 @@ SP CTokenManager::getToken(const std::string& uuid) { // cleanup expired tokens const auto NOW = std::chrono::steady_clock::now(); - std::erase_if(m_mTokens, [this, &NOW](const auto& el) { return el.second->expiresAt < NOW; }); + std::erase_if(m_mTokens, [&NOW](const auto& el) { return el.second->expiresAt < NOW; }); if (!m_mTokens.contains(uuid)) return {}; @@ -46,4 +46,4 @@ void CTokenManager::removeToken(SP token) { if (!token) return; m_mTokens.erase(token->uuid); -} \ No newline at end of file +} diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 196f0b71..6f7d8017 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -905,7 +905,7 @@ void CInputManager::setupKeyboard(SP keeb) { keeb.get()); keeb->keyboardEvents.keymap.registerStaticListener( - [this](void* owner, std::any data) { + [](void* owner, std::any data) { auto PKEEB = ((IKeyboard*)owner)->self.lock(); const auto LAYOUT = PKEEB->getActiveLayout(); diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index 69e28772..baf0a299 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -112,7 +112,7 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : resourc resource->setDestroy([this](CZwlrDataControlDeviceV1* r) { PROTO::dataWlr->destroyResource(this); }); resource->setOnDestroy([this](CZwlrDataControlDeviceV1* r) { PROTO::dataWlr->destroyResource(this); }); - resource->setSetSelection([this](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { + resource->setSetSelection([](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { auto source = sourceR ? CWLRDataSource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "wlr reset selection received"); @@ -129,7 +129,7 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : resourc g_pSeatManager->setCurrentSelection(source); }); - resource->setSetPrimarySelection([this](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { + resource->setSetPrimarySelection([](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { auto source = sourceR ? CWLRDataSource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "wlr reset primary selection received"); diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index f1db2d65..7602a466 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -113,7 +113,7 @@ CPrimarySelectionDevice::CPrimarySelectionDevice(SPsetDestroy([this](CZwpPrimarySelectionDeviceV1* r) { PROTO::primarySelection->destroyResource(this); }); resource->setOnDestroy([this](CZwpPrimarySelectionDeviceV1* r) { PROTO::primarySelection->destroyResource(this); }); - resource->setSetSelection([this](CZwpPrimarySelectionDeviceV1* r, wl_resource* sourceR, uint32_t serial) { + resource->setSetSelection([](CZwpPrimarySelectionDeviceV1* r, wl_resource* sourceR, uint32_t serial) { static auto PPRIMARYSEL = CConfigValue("misc:middle_click_paste"); if (!*PPRIMARYSEL) { From 7f46680ab16e8f67000a09d20fc7ba41e211f3ef Mon Sep 17 00:00:00 2001 From: czlabinger <118806077+czlabinger@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:01:08 +0200 Subject: [PATCH 0175/1803] hyprctl: add caps/num lock state for keyboards (#8145) --------- Co-authored-by: Behzad --- src/debug/HyprCtl.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index e09fb529..82290f94 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -549,6 +549,15 @@ std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { std::string result = ""; + auto getModState = [](SP keyboard, const char* xkbModName) -> bool { + auto IDX = xkb_keymap_mod_get_index(keyboard->xkbKeymap, xkbModName); + + if (IDX == XKB_MOD_INVALID) + return false; + + return (keyboard->modifiersState.locked & (1 << IDX)) > 0; + }; + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "{\n"; result += "\"mice\": [\n"; @@ -580,11 +589,13 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "variant": "{}", "options": "{}", "active_keymap": "{}", + "capsLock": {}, + "numLock": {}, "main": {} }},)#", (uintptr_t)k.get(), escapeJSONStrings(k->hlName), escapeJSONStrings(k->currentRules.rules), escapeJSONStrings(k->currentRules.model), escapeJSONStrings(k->currentRules.layout), escapeJSONStrings(k->currentRules.variant), escapeJSONStrings(k->currentRules.options), escapeJSONStrings(KM), - (k->active ? "true" : "false")); + (getModState(k, XKB_MOD_NAME_CAPS) ? "true" : "false"), (getModState(k, XKB_MOD_NAME_NUM) ? "true" : "false"), (k->active ? "true" : "false")); } trimTrailingComma(result); @@ -668,9 +679,11 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { for (auto const& k : g_pInputManager->m_vKeyboards) { const auto KM = k->getActiveLayout(); - result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n", - (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, - k->currentRules.options, KM, (k->active ? "yes" : "no")); + result += + std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tcapsLock: " + "{}\n\t\t\tnumLock: {}\n\t\t\tmain: {}\n", + (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, k->currentRules.options, + KM, (getModState(k, XKB_MOD_NAME_CAPS) ? "yes" : "no"), (getModState(k, XKB_MOD_NAME_NUM) ? "yes" : "no"), (k->active ? "yes" : "no")); } result += "\n\nTablets:\n"; From 3cec45d82113051d35e846e5d80719d8ea0f7002 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:50:53 +0500 Subject: [PATCH 0176/1803] Improve hyprland-session.service (#8225) --- example/hyprland-session.service | 1 + 1 file changed, 1 insertion(+) diff --git a/example/hyprland-session.service b/example/hyprland-session.service index 7d33f5b3..b6f0b55b 100644 --- a/example/hyprland-session.service +++ b/example/hyprland-session.service @@ -10,5 +10,6 @@ After=graphical-session-pre.target Type=notify ExecStart=/usr/bin/Hyprland ExecStop=/usr/bin/hyprctl dispatch exit +ExecStopPost=/usr/bin/systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP Restart=on-failure Slice=session.slice From f0e023bff2f2a25ffe5ed3166f55f7274d17c6bc Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 25 Oct 2024 12:26:48 +0200 Subject: [PATCH 0177/1803] security-context: avoid UB in C macro (#8229) to safely use wl_container_of with a class the class has to be no virtual functions, no inheritance, and uniform access control (e.g all public) work around this by putting this into a destroywrapper struct. --- src/protocols/SecurityContext.cpp | 12 ++++++++---- src/protocols/SecurityContext.hpp | 12 +++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index b42c3a97..13428b91 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -22,7 +22,8 @@ SP CSecurityContextSandboxedClient::create(int } static void onSecurityContextClientDestroy(wl_listener* l, void* d) { - CSecurityContextSandboxedClient* client = wl_container_of(l, client, destroyListener); + CSecurityContextSandboxedClientDestroyWrapper* wrap = wl_container_of(l, wrap, listener); + CSecurityContextSandboxedClient* client = wrap->parent; client->onDestroy(); } @@ -31,12 +32,15 @@ CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) if (!client) return; - destroyListener.notify = ::onSecurityContextClientDestroy; - wl_client_add_destroy_late_listener(client, &destroyListener); + wl_list_init(&destroyListener.listener.link); + destroyListener.listener.notify = ::onSecurityContextClientDestroy; + destroyListener.parent = this; + wl_client_add_destroy_late_listener(client, &destroyListener.listener); } CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { - wl_list_remove(&destroyListener.link); + wl_list_remove(&destroyListener.listener.link); + wl_list_init(&destroyListener.listener.link); close(clientFD); } diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp index 76313bcf..63f58bde 100644 --- a/src/protocols/SecurityContext.hpp +++ b/src/protocols/SecurityContext.hpp @@ -37,14 +37,20 @@ class CSecurityContextManagerResource { SP resource; }; +class CSecurityContextSandboxedClient; +struct CSecurityContextSandboxedClientDestroyWrapper { + wl_listener listener; + CSecurityContextSandboxedClient* parent = nullptr; +}; + class CSecurityContextSandboxedClient { public: static SP create(int clientFD); ~CSecurityContextSandboxedClient(); - void onDestroy(); + void onDestroy(); - wl_listener destroyListener; + CSecurityContextSandboxedClientDestroyWrapper destroyListener; private: CSecurityContextSandboxedClient(int clientFD_); @@ -81,4 +87,4 @@ class CSecurityContextProtocol : public IWaylandProtocol { namespace PROTO { inline UP securityContext; -}; \ No newline at end of file +}; From e5384774a8258e44cc7f7b690ce4f6ad1f92b562 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Sat, 26 Oct 2024 01:38:59 +0500 Subject: [PATCH 0178/1803] example/hyprland-session.service: add support for xdg autostart (#8230) --- example/hyprland-session.service | 1 + 1 file changed, 1 insertion(+) diff --git a/example/hyprland-session.service b/example/hyprland-session.service index b6f0b55b..3089a961 100644 --- a/example/hyprland-session.service +++ b/example/hyprland-session.service @@ -3,6 +3,7 @@ Description=Hyprland - Tiling compositor with the looks Documentation=man:Hyprland(1) BindsTo=graphical-session.target Before=graphical-session.target +Wants=xdg-desktop-autostart.target Wants=graphical-session-pre.target After=graphical-session-pre.target From d5689bb53935ff1adbbfc9fdf5b1f542ce39efb2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 26 Oct 2024 02:06:13 +0100 Subject: [PATCH 0179/1803] internal: cleanup CMonitor usage and fix a few ref hogs ref #8221 --- src/Compositor.cpp | 8 +++---- src/Compositor.hpp | 6 ++--- src/config/ConfigManager.cpp | 2 +- src/config/ConfigManager.hpp | 2 +- src/debug/HyprDebugOverlay.hpp | 8 +++---- src/helpers/Monitor.cpp | 8 +++---- src/helpers/Monitor.hpp | 2 +- src/managers/PointerManager.cpp | 16 ++++++------- src/managers/PointerManager.hpp | 22 +++++++++--------- src/protocols/CTMControl.cpp | 2 +- src/protocols/CTMControl.hpp | 2 +- src/protocols/DRMLease.cpp | 6 ++--- src/protocols/DRMLease.hpp | 10 ++++----- src/protocols/LinuxDMABUF.cpp | 20 ++++++++--------- src/protocols/LinuxDMABUF.hpp | 12 +++++----- src/protocols/OutputManagement.cpp | 2 +- src/protocols/OutputManagement.hpp | 2 +- src/protocols/PresentationTime.cpp | 6 ++--- src/protocols/PresentationTime.hpp | 6 ++--- src/protocols/VirtualPointer.cpp | 4 ++-- src/protocols/VirtualPointer.hpp | 12 +++++----- src/protocols/XDGOutput.cpp | 2 +- src/protocols/XDGOutput.hpp | 4 ++-- src/protocols/core/Compositor.cpp | 6 ++--- src/protocols/core/Compositor.hpp | 8 +++---- src/protocols/core/Output.cpp | 4 ++-- src/protocols/core/Output.hpp | 8 +++---- src/render/OpenGL.hpp | 36 +++++++++++++++--------------- src/render/Renderer.cpp | 4 ++-- src/render/Renderer.hpp | 4 ++-- 30 files changed, 116 insertions(+), 118 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 313d57ac..743895aa 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -750,7 +750,7 @@ PHLMONITOR CCompositor::getMonitorFromCursor() { } PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) { - SP mon; + PHLMONITOR mon; for (auto const& m : m_vMonitors) { if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) { mon = m; @@ -759,8 +759,8 @@ PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) { } if (!mon) { - float bestDistance = 0.f; - SP pBestMon; + float bestDistance = 0.f; + PHLMONITOR pBestMon; for (auto const& m : m_vMonitors) { float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize); @@ -3008,7 +3008,7 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } -static void checkDefaultCursorWarp(SP monitor) { +static void checkDefaultCursorWarp(PHLMONITOR monitor) { static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); static bool cursorDefaultDone = false; static bool firstLaunch = true; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7fbd32e8..208b6ecf 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -59,8 +59,8 @@ class CCompositor { std::string m_szInstancePath = ""; std::string m_szCurrentSplash = "error"; - std::vector> m_vMonitors; - std::vector> m_vRealMonitors; // for all monitors, even those turned off + std::vector m_vMonitors; + std::vector m_vRealMonitors; // for all monitors, even those turned off std::vector m_vWindows; std::vector m_vLayers; std::vector m_vWorkspaces; @@ -80,7 +80,7 @@ class CCompositor { WP m_pLastFocus; PHLWINDOWREF m_pLastWindow; - WP m_pLastMonitor; + PHLMONITORREF m_pLastMonitor; std::vector m_vWindowFocusHistory; // first element is the most recently focused. diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8237fd44..e2dc4b0f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1087,7 +1087,7 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s return VAL; } -SMonitorRule CConfigManager::getMonitorRuleFor(const SP PMONITOR) { +SMonitorRule CConfigManager::getMonitorRuleFor(const PHLMONITOR PMONITOR) { auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule { const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index e9ed2d64..cf053daa 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -169,7 +169,7 @@ class CConfigManager { static std::string getMainConfigPath(); const std::string getConfigString(); - SMonitorRule getMonitorRuleFor(const SP); + SMonitorRule getMonitorRuleFor(const PHLMONITOR); SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index 19b9120a..89d1d606 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -38,12 +38,12 @@ class CHyprDebugOverlay { void frameData(PHLMONITOR); private: - std::map m_mMonitorOverlays; + std::map m_mMonitorOverlays; - cairo_surface_t* m_pCairoSurface = nullptr; - cairo_t* m_pCairo = nullptr; + cairo_surface_t* m_pCairoSurface = nullptr; + cairo_t* m_pCairo = nullptr; - SP m_pTexture; + SP m_pTexture; friend class CHyprMonitorDebugOverlay; friend class CHyprRenderer; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index d8889585..41290b7d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -71,7 +71,7 @@ void CMonitor::onConnect(bool noRule) { Debug::log(LOG, "Removing monitor {} from realMonitors", szName); - std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == this; }); + std::erase_if(g_pCompositor->m_vRealMonitors, [&](PHLMONITOR& el) { return el.get() == this; }); }); listeners.state = output->events.state.registerListener([this](std::any d) { @@ -149,7 +149,7 @@ void CMonitor::onConnect(bool noRule) { return; } - SP* thisWrapper = nullptr; + PHLMONITOR* thisWrapper = nullptr; // find the wrap for (auto& m : g_pCompositor->m_vRealMonitors) { @@ -356,7 +356,7 @@ void CMonitor::onDisconnect(bool destroy) { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } - std::erase_if(g_pCompositor->m_vMonitors, [&](SP& el) { return el.get() == this; }); + std::erase_if(g_pCompositor->m_vMonitors, [&](PHLMONITOR& el) { return el.get() == this; }); } void CMonitor::addDamage(const pixman_region32_t* rg) { @@ -509,7 +509,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // push to mvmonitors - SP* thisWrapper = nullptr; + PHLMONITOR* thisWrapper = nullptr; // find the wrap for (auto& m : g_pCompositor->m_vRealMonitors) { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f3d6d647..dce44b4a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -125,7 +125,7 @@ class CMonitor { SP outTimeline; uint64_t commitSeq = 0; - WP self; + PHLMONITORREF self; // mirroring PHLMONITORREF pMirrorOf; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index ae90349b..0d6e0206 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -69,7 +69,7 @@ void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { updateCursorBackend(); } -bool CPointerManager::softwareLockedFor(SP mon) { +bool CPointerManager::softwareLockedFor(PHLMONITOR mon) { auto state = stateFor(mon); return state->softwareLocks > 0 || state->hardwareFailed; } @@ -82,7 +82,7 @@ bool CPointerManager::hasCursor() { return currentCursorImage.pBuffer || currentCursorImage.surface; } -SP CPointerManager::stateFor(SP mon) { +SP CPointerManager::stateFor(PHLMONITOR mon) { auto it = std::find_if(monitorStates.begin(), monitorStates.end(), [mon](const auto& other) { return other->monitor == mon; }); if (it == monitorStates.end()) return monitorStates.emplace_back(makeShared(mon)); @@ -503,7 +503,7 @@ SP CPointerManager::renderHWCursorBuffer(SP pMonitor, timespec* now, CRegion& damage, std::optional overridePos) { +void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* now, CRegion& damage, std::optional overridePos) { if (!hasCursor()) return; @@ -538,7 +538,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* currentCursorImage.surface->resource()->frame(now); } -Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { +Vector2D CPointerManager::getCursorPosForMonitor(PHLMONITOR pMonitor) { return CBox{pointerPos - pMonitor->vecPosition, {0, 0}} .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x / pMonitor->scale, pMonitor->vecTransformedSize.y / pMonitor->scale) @@ -546,7 +546,7 @@ Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { pMonitor->scale; } -Vector2D CPointerManager::transformedHotspot(SP pMonitor) { +Vector2D CPointerManager::transformedHotspot(PHLMONITOR pMonitor) { if (!pMonitor->cursorSwapchain) return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors @@ -556,7 +556,7 @@ Vector2D CPointerManager::transformedHotspot(SP pMonitor) { .pos(); } -CBox CPointerManager::getCursorBoxLogicalForMonitor(SP pMonitor) { +CBox CPointerManager::getCursorBoxLogicalForMonitor(PHLMONITOR pMonitor) { return getCursorBoxGlobal().translate(-pMonitor->vecPosition); } @@ -678,7 +678,7 @@ void CPointerManager::move(const Vector2D& deltaLogical) { void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { - SP currentMonitor = g_pCompositor->m_pLastMonitor.lock(); + PHLMONITOR currentMonitor = g_pCompositor->m_pLastMonitor.lock(); if (!currentMonitor || !dev) return; @@ -1055,7 +1055,7 @@ void CPointerManager::detachTablet(SP tablet) { std::erase_if(tabletListeners, [tablet](const auto& e) { return e->tablet.expired() || e->tablet == tablet; }); } -void CPointerManager::damageCursor(SP pMonitor) { +void CPointerManager::damageCursor(PHLMONITOR pMonitor) { for (auto const& mw : monitorStates) { if (mw->monitor != pMonitor) continue; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index aef2490d..a0cd0fff 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -43,18 +43,18 @@ class CPointerManager { void setCursorSurface(SP buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); - void lockSoftwareForMonitor(SP pMonitor); - void unlockSoftwareForMonitor(SP pMonitor); + void lockSoftwareForMonitor(PHLMONITOR pMonitor); + void unlockSoftwareForMonitor(PHLMONITOR pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); - bool softwareLockedFor(SP pMonitor); + bool softwareLockedFor(PHLMONITOR pMonitor); - void renderSoftwareCursorsFor(SP pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); + void renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); // this is needed e.g. during screensharing where // the software cursors aren't locked during the cursor move, but they // are rendered later. - void damageCursor(SP pMonitor); + void damageCursor(PHLMONITOR pMonitor); // Vector2D position(); @@ -78,13 +78,13 @@ class CPointerManager { Vector2D closestValid(const Vector2D& pos); // returns the thing in device coordinates. Is NOT offset by the hotspot, relies on set_cursor with hotspot. - Vector2D getCursorPosForMonitor(SP pMonitor); + Vector2D getCursorPosForMonitor(PHLMONITOR pMonitor); // returns the thing in logical coordinates of the monitor - CBox getCursorBoxLogicalForMonitor(SP pMonitor); + CBox getCursorBoxLogicalForMonitor(PHLMONITOR pMonitor); // returns the thing in global coords CBox getCursorBoxGlobal(); - Vector2D transformedHotspot(SP pMonitor); + Vector2D transformedHotspot(PHLMONITOR pMonitor); SP getCurrentCursorTexture(); @@ -160,10 +160,10 @@ class CPointerManager { Vector2D storedUnaccel = {0, 0}; struct SMonitorPointerState { - SMonitorPointerState(SP m) : monitor(m) {} + SMonitorPointerState(PHLMONITOR m) : monitor(m) {} ~SMonitorPointerState() {} - WP monitor; + PHLMONITORREF monitor; int softwareLocks = 0; bool hardwareFailed = false; @@ -176,7 +176,7 @@ class CPointerManager { }; std::vector> monitorStates; - SP stateFor(SP mon); + SP stateFor(PHLMONITOR mon); bool attemptHardwareCursor(SP state); SP renderHWCursorBuffer(SP state, SP texture); bool setHWCursorBuffer(SP state, SP buf); diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index f2a54c6f..cddad830 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -81,6 +81,6 @@ void CHyprlandCTMControlProtocol::destroyResource(CHyprlandCTMControlResource* r std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); } -void CHyprlandCTMControlProtocol::setCTM(SP monitor, const Mat3x3& ctm) { +void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) { monitor->setCTM(ctm); } diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp index 08f1b0e8..70bc79bc 100644 --- a/src/protocols/CTMControl.hpp +++ b/src/protocols/CTMControl.hpp @@ -31,7 +31,7 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol { private: void destroyResource(CHyprlandCTMControlResource* resource); - void setCTM(SP monitor, const Mat3x3& ctm); + void setCTM(PHLMONITOR monitor, const Mat3x3& ctm); // std::vector> m_vManagers; diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index d0114ce7..be5a6985 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -129,7 +129,7 @@ SP CDRMLeaseConnectorResource::fromResource(wl_resou return data ? data->self.lock() : nullptr; } -CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { +CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { if (!good()) return; @@ -203,7 +203,7 @@ bool CDRMLeaseDeviceResource::good() { return resource->resource(); } -void CDRMLeaseDeviceResource::sendConnector(SP monitor) { +void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e && !e->dead && e->monitor == monitor; }) != connectorsSent.end()) return; @@ -289,7 +289,7 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { std::erase_if(m_vLeases, [resource](const auto& e) { return e.get() == resource; }); } -void CDRMLeaseProtocol::offer(SP monitor) { +void CDRMLeaseProtocol::offer(PHLMONITOR monitor) { std::erase_if(primaryDevice->offeredOutputs, [](const auto& e) { return e.expired(); }); if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) return; diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index 3671cfce..37de40e3 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -56,7 +56,7 @@ class CDRMLeaseRequestResource { class CDRMLeaseConnectorResource { public: - CDRMLeaseConnectorResource(SP resource_, SP monitor_); + CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_); static SP fromResource(wl_resource*); bool good(); @@ -64,7 +64,7 @@ class CDRMLeaseConnectorResource { WP self; WP parent; - WP monitor; + PHLMONITORREF monitor; bool dead = false; private: @@ -82,7 +82,7 @@ class CDRMLeaseDeviceResource { CDRMLeaseDeviceResource(SP resource_); bool good(); - void sendConnector(SP monitor); + void sendConnector(PHLMONITOR monitor); std::vector> connectorsSent; @@ -102,7 +102,7 @@ class CDRMLeaseDevice { bool success = false; SP backend; - std::vector> offeredOutputs; + std::vector offeredOutputs; }; class CDRMLeaseProtocol : public IWaylandProtocol { @@ -111,7 +111,7 @@ class CDRMLeaseProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void offer(SP monitor); + void offer(PHLMONITOR monitor); private: void destroyResource(CDRMLeaseDeviceResource* resource); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 8e26c74f..e81d7e01 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -21,7 +21,7 @@ static std::optional devIDFromFD(int fd) { return stat.st_rdev; } -CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector, SDMABUFTranche>> tranches_) : +CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector> tranches_) : rendererTranche(_rendererTranche), monitorTranches(tranches_) { std::vector formatsVec; @@ -436,7 +436,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const .formats = g_pHyprOpenGL->getDRMFormats(), }; - std::vector, SDMABUFTranche>> tches; + std::vector> tches; if (g_pCompositor->m_pAqBackend->hasSession()) { // this assumes there's only 1 device used for both scanout and rendering @@ -453,20 +453,18 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { auto pMonitor = std::any_cast(param); - auto mon = pMonitor->self.lock(); auto tranche = SDMABUFTranche{ .device = mainDevice, .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, - .formats = mon->output->getRenderFormats(), + .formats = pMonitor->output->getRenderFormats(), }; - formatTable->monitorTranches.push_back(std::make_pair<>(mon, tranche)); + formatTable->monitorTranches.push_back(std::make_pair<>(pMonitor, tranche)); resetFormatTable(); }); static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { auto pMonitor = std::any_cast(param); - auto mon = pMonitor->self.lock(); - std::erase_if(formatTable->monitorTranches, [mon](std::pair, SDMABUFTranche> pair) { return pair.first == mon; }); + std::erase_if(formatTable->monitorTranches, [pMonitor](std::pair pair) { return pair.first == pMonitor; }); resetFormatTable(); }); } @@ -508,8 +506,8 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { for (auto const& feedback : m_vFeedbacks) { feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); if (feedback->lastFeedbackWasScanout) { - SP mon; - auto HLSurface = CWLSurface::fromResource(feedback->surface); + PHLMONITOR mon; + auto HLSurface = CWLSurface::fromResource(feedback->surface); if (auto w = HLSurface->getWindow(); w) if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m) mon = m->self.lock(); @@ -560,7 +558,7 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) { std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; }); } -void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, SP pMonitor) { +void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, PHLMONITOR pMonitor) { SP feedbackResource; for (auto const& f : m_vFeedbacks) { if (f->surface != surface) @@ -582,7 +580,7 @@ void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface } const auto& monitorTranchePair = std::find_if(formatTable->monitorTranches.begin(), formatTable->monitorTranches.end(), - [pMonitor](std::pair, SDMABUFTranche> pair) { return pair.first == pMonitor; }); + [pMonitor](std::pair pair) { return pair.first == pMonitor; }); if (monitorTranchePair == formatTable->monitorTranches.end()) { LOGM(LOG, "updateScanoutTranche: monitor has no tranche"); diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 0e25cdc6..e4941a6d 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -48,13 +48,13 @@ struct SDMABUFTranche { class CDMABUFFormatTable { public: - CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector, SDMABUFTranche>> tranches); + CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector> tranches); ~CDMABUFFormatTable(); - int tableFD = -1; - size_t tableSize = 0; - SDMABUFTranche rendererTranche; - std::vector, SDMABUFTranche>> monitorTranches; + int tableFD = -1; + size_t tableSize = 0; + SDMABUFTranche rendererTranche; + std::vector> monitorTranches; }; class CLinuxDMABBUFParamsResource { @@ -111,7 +111,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { ~CLinuxDMABufV1Protocol(); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void updateScanoutTranche(SP surface, SP pMonitor); + void updateScanoutTranche(SP surface, PHLMONITOR pMonitor); private: void destroyResource(CLinuxDMABUFResource* resource); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 77cedd41..0c6a3348 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -633,7 +633,7 @@ SP COutputManagementProtocol::modeFromResource(wl_resource* r) { return nullptr; } -SP COutputManagementProtocol::getOutputStateFor(SP pMonitor) { +SP COutputManagementProtocol::getOutputStateFor(PHLMONITOR pMonitor) { for (auto const& m : m_vManagers) { if (!m->monitorStates.contains(pMonitor->szName)) continue; diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index 6deab017..b9e7ce98 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -153,7 +153,7 @@ class COutputManagementProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); // doesn't have to return one - SP getOutputStateFor(SP pMonitor); + SP getOutputStateFor(PHLMONITOR pMonitor); private: void destroyResource(COutputManager* resource); diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index b66694bf..411036c3 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -14,7 +14,7 @@ void CQueuedPresentationData::setPresentationType(bool zeroCopy_) { zeroCopy = zeroCopy_; } -void CQueuedPresentationData::attachMonitor(SP pMonitor_) { +void CQueuedPresentationData::attachMonitor(PHLMONITOR pMonitor_) { pMonitor = pMonitor_; } @@ -73,7 +73,7 @@ void CPresentationFeedback::sendQueued(SP data, timespe CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - const auto PMONITOR = std::any_cast(param); + const auto PMONITOR = PHLMONITORREF{std::any_cast(param)}; std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); }); } @@ -107,7 +107,7 @@ void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* su } } -void CPresentationProtocol::onPresented(SP pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { +void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { timespec now; timespec* presentedAt = when; if (!presentedAt) { diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 421bb838..d9b45448 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -14,7 +14,7 @@ class CQueuedPresentationData { CQueuedPresentationData(SP surf); void setPresentationType(bool zeroCopy); - void attachMonitor(SP pMonitor); + void attachMonitor(PHLMONITOR pMonitor); void presented(); void discarded(); @@ -24,7 +24,7 @@ class CQueuedPresentationData { private: bool wasPresented = false; bool zeroCopy = false; - WP pMonitor; + PHLMONITORREF pMonitor; WP surface; friend class CPresentationFeedback; @@ -53,7 +53,7 @@ class CPresentationProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void onPresented(SP pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); + void onPresented(PHLMONITOR pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); void queueData(SP data); private: diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index eb92a640..4c5aa13a 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -1,7 +1,7 @@ #include "VirtualPointer.hpp" #include "core/Output.hpp" -CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, WP boundOutput_) : boundOutput(boundOutput_), resource(resource_) { +CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, PHLMONITORREF boundOutput_) : boundOutput(boundOutput_), resource(resource_) { if (!good()) return; @@ -134,7 +134,7 @@ void CVirtualPointerProtocol::destroyResource(CVirtualPointerV1Resource* pointer std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == pointer; }); } -void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, WP output) { +void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, PHLMONITORREF output) { const auto RESOURCE = m_vPointers.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id), output)); diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 7ee450dc..68fe124e 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -12,7 +12,7 @@ class CVirtualPointerV1Resource { public: - CVirtualPointerV1Resource(SP resource_, WP boundOutput_); + CVirtualPointerV1Resource(SP resource_, PHLMONITORREF boundOutput_); ~CVirtualPointerV1Resource(); struct { @@ -35,12 +35,12 @@ class CVirtualPointerV1Resource { CSignal holdEnd; } events; - bool good(); - wl_client* client(); + bool good(); + wl_client* client(); - std::string name; + std::string name; - WP boundOutput; + PHLMONITORREF boundOutput; private: SP resource; @@ -63,7 +63,7 @@ class CVirtualPointerProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); void destroyResource(CVirtualPointerV1Resource* pointer); - void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, WP output); + void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, PHLMONITORREF output); // std::vector> m_vManagers; diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 0598e713..deb87829 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -95,7 +95,7 @@ void CXDGOutputProtocol::updateAllOutputs() { // -CXDGOutput::CXDGOutput(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { +CXDGOutput::CXDGOutput(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { if (!resource->resource()) return; diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 520f3aaa..6a5be284 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -10,12 +10,12 @@ class CWLOutputProtocol; class CXDGOutput { public: - CXDGOutput(SP resource, SP monitor_); + CXDGOutput(SP resource, PHLMONITOR monitor_); void sendDetails(); private: - WP monitor; + PHLMONITORREF monitor; SP resource; WP outputProto; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 3d4b63c1..9a2e00a9 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -182,7 +182,7 @@ wl_client* CWLSurfaceResource::client() { return pClient; } -void CWLSurfaceResource::enter(SP monitor) { +void CWLSurfaceResource::enter(PHLMONITOR monitor) { if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) != enteredOutputs.end()) return; @@ -209,7 +209,7 @@ void CWLSurfaceResource::enter(SP monitor) { resource->sendEnter(output->getResource().get()); } -void CWLSurfaceResource::leave(SP monitor) { +void CWLSurfaceResource::leave(PHLMONITOR monitor) { if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) == enteredOutputs.end()) return; @@ -509,7 +509,7 @@ void CWLSurfaceResource::updateCursorShm() { memcpy(shmData.data(), pixelData, bufLen); } -void CWLSurfaceResource::presentFeedback(timespec* when, SP pMonitor) { +void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) { frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index b3c067c9..fbffd966 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -60,8 +60,8 @@ class CWLSurfaceResource { bool good(); wl_client* client(); - void enter(SP monitor); - void leave(SP monitor); + void enter(PHLMONITOR monitor); + void leave(PHLMONITOR monitor); void sendPreferredTransform(wl_output_transform t); void sendPreferredScale(int32_t scale); void frame(timespec* now); @@ -115,7 +115,7 @@ class CWLSurfaceResource { std::vector> callbacks; WP self; WP hlSurface; - std::vector> enteredOutputs; + std::vector enteredOutputs; bool mapped = false; std::vector> subsurfaces; SP role; @@ -124,7 +124,7 @@ class CWLSurfaceResource { void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); - void presentFeedback(timespec* when, SP pMonitor); + void presentFeedback(timespec* when, PHLMONITOR pMonitor); void lockPendingState(); void unlockPendingState(); diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index e9f35abc..edeeb584 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -3,7 +3,7 @@ #include "../../Compositor.hpp" #include "../../helpers/Monitor.hpp" -CWLOutputResource::CWLOutputResource(SP resource_, SP pMonitor) : monitor(pMonitor), resource(resource_) { +CWLOutputResource::CWLOutputResource(SP resource_, PHLMONITOR pMonitor) : monitor(pMonitor), resource(resource_) { if (!good()) return; @@ -83,7 +83,7 @@ void CWLOutputResource::updateState() { resource->sendDone(); } -CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP pMonitor) : +CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, PHLMONITOR pMonitor) : IWaylandProtocol(iface, ver, name), monitor(pMonitor), szName(pMonitor->szName) { listeners.modeChanged = monitor->events.modeChanged.registerListener([this](std::any d) { diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index 49c32ec1..a4c81d72 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -12,7 +12,7 @@ class CWLOutputProtocol; class CWLOutputResource { public: - CWLOutputResource(SP resource_, SP pMonitor); + CWLOutputResource(SP resource_, PHLMONITOR pMonitor); static SP fromResource(wl_resource*); bool good(); @@ -20,7 +20,7 @@ class CWLOutputResource { SP getResource(); void updateState(); - WP monitor; + PHLMONITORREF monitor; WP owner; WP self; @@ -33,14 +33,14 @@ class CWLOutputResource { class CWLOutputProtocol : public IWaylandProtocol { public: - CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP pMonitor); + CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, PHLMONITOR pMonitor); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); SP outputResourceFrom(wl_client* client); void sendDone(); - WP monitor; + PHLMONITORREF monitor; WP self; // will mark the protocol for removal, will be removed when no. of bound outputs is 0 (or when overwritten by a new global) diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 04f69d49..115dcac7 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -206,30 +206,30 @@ class CHyprOpenGLImpl { void setDamage(const CRegion& damage, std::optional finalDamage = {}); uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window - PHLLS m_pCurrentLayer; // hack to get the current rendered layer + PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window + PHLLS m_pCurrentLayer; // hack to get the current rendered layer - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; - std::unordered_map m_mMonitorRenderResources; - std::unordered_map m_mMonitorBGFBs; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; + std::map m_mMonitorRenderResources; + std::map m_mMonitorBGFBs; struct { PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 5df0c070..c69167c8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1085,7 +1085,7 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } -void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, SP pMonitor, bool main, const Vector2D& projSize, +void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize, const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { Vector2D uvTL; @@ -1603,7 +1603,7 @@ void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE } } -void CHyprRenderer::setSurfaceScanoutMode(SP surface, SP monitor) { +void CHyprRenderer::setSurfaceScanoutMode(SP surface, PHLMONITOR monitor) { if (!PROTO::linuxDma) return; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 41f40b5a..4524008b 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -64,7 +64,7 @@ class CHyprRenderer { void ensureCursorRenderingMode(); bool shouldRenderCursor(); void setCursorHidden(bool hide); - void calculateUVForSurface(PHLWINDOW, SP, SP pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, + void calculateUVForSurface(PHLWINDOW, SP, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(PHLMONITOR pMonitor); // avg max min void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry); @@ -95,7 +95,7 @@ class CHyprRenderer { DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); - void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets + void setSurfaceScanoutMode(SP surface, PHLMONITOR monitor); // nullptr monitor resets void initiateManualCrash(); bool m_bCrashingInProgress = false; From 3dd8db83f166733d1dd6a753bd6eb07727320768 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 26 Oct 2024 02:12:43 +0100 Subject: [PATCH 0180/1803] pointer: add default auto for no_hw_cursors auto defaults to off on nvidia, on for everyone else. Gotta wait until we do fucking drm_dumb and it fucking works --- src/config/ConfigDescriptions.hpp | 4 ++-- src/config/ConfigManager.cpp | 14 +++++++++++++- src/config/ConfigManager.hpp | 2 ++ src/managers/PointerManager.cpp | 12 ++++-------- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 7910e865..0177f92b 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1244,8 +1244,8 @@ inline static const std::vector CONFIG_OPTIONS = { SConfigOptionDescription{ .value = "cursor:no_hardware_cursors", .description = "disables hardware cursors", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Auto"}, }, SConfigOptionDescription{ .value = "cursor:no_break_fs_vrr", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e2dc4b0f..909dfc63 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -552,7 +552,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2}); - m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); @@ -2778,6 +2778,18 @@ const std::vector& CConfigManager::getAllDescriptions( return CONFIG_OPTIONS; } +bool CConfigManager::shouldUseSoftwareCursors() { + static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); + + switch (*PNOHW) { + case 0: return false; + case 1: return true; + default: return g_pHyprRenderer->isNvidia(); + } + + return true; +} + std::string SConfigOptionDescription::jsonify() const { auto parseData = [this]() -> std::string { return std::visit( diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index cf053daa..88b74b6e 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -200,6 +200,8 @@ class CConfigManager { void ensureMonitorStatus(); void ensureVRR(PHLMONITOR pMonitor = nullptr); + bool shouldUseSoftwareCursors(); + std::string parseKeyword(const std::string&, const std::string&); void addParseError(const std::string&); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 0d6e0206..d2114e79 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -247,9 +247,7 @@ void CPointerManager::resetCursorImage(bool apply) { } void CPointerManager::updateCursorBackend() { - static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); - - const auto CURSORBOX = getCursorBoxGlobal(); + const auto CURSORBOX = getCursorBoxGlobal(); for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); @@ -268,7 +266,7 @@ void CPointerManager::updateCursorBackend() { continue; } - if (state->softwareLocks > 0 || *PNOHW || !attemptHardwareCursor(state)) { + if (state->softwareLocks > 0 || g_pConfigManager->shouldUseSoftwareCursors() || !attemptHardwareCursor(state)) { Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); state->hardwareFailed = true; @@ -641,15 +639,13 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { } void CPointerManager::damageIfSoftware() { - auto b = getCursorBoxGlobal().expand(4); - - static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); + auto b = getCursorBoxGlobal().expand(4); for (auto const& mw : monitorStates) { if (mw->monitor.expired() || !mw->monitor->output) continue; - if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { + if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors()) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { g_pHyprRenderer->damageBox(&b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent()); break; } From 0b29caf9ab86518ff474eed5e7d19c12f96ebbd0 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sat, 26 Oct 2024 01:22:37 +0000 Subject: [PATCH 0181/1803] core: fix group members disappearing when you move the group to another monitor (#8237) * fix group members disappearance when you move the group to another monitor * remove repeated action --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 743895aa..d4e2db17 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2795,11 +2795,11 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor pWindow->updateToplevel(); pWindow->updateDynamicRules(); pWindow->uncacheWindowDecos(); + pWindow->updateGroupOutputs(); if (!pWindow->m_sGroupData.pNextWindow.expired()) { PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock(); while (next != pWindow) { - next->moveToWorkspace(pWorkspace); next->updateToplevel(); next = next->m_sGroupData.pNextWindow.lock(); } From c356e425008cba8bd0c87487a2c79b9be4eda2aa Mon Sep 17 00:00:00 2001 From: Damianu Date: Sat, 26 Oct 2024 17:50:31 +0200 Subject: [PATCH 0182/1803] misc: Fix bad links to wiki (#8240) Same as in https://github.com/hyprwm/hyprland-wiki/pull/828 --- README.md | 2 +- docs/ISSUE_GUIDELINES.md | 2 +- example/hyprland.conf | 2 +- src/config/defaultConfig.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f271c29c..0970819c 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ easy IPC, much more QoL stuff than other compositors and more... -[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ +[Configure]: https://wiki.hyprland.org/Configuring/ [Stars]: https://starchart.cc/hyprwm/Hyprland [Hypr]: https://github.com/hyprwm/Hypr diff --git a/docs/ISSUE_GUIDELINES.md b/docs/ISSUE_GUIDELINES.md index 2f6cbbf8..9328642d 100644 --- a/docs/ISSUE_GUIDELINES.md +++ b/docs/ISSUE_GUIDELINES.md @@ -3,7 +3,7 @@ First of all, please remember to: - Check that your issue is not a duplicate - Read the [FAQ](https://wiki.hyprland.org/FAQ/) -- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland) +- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/)
diff --git a/example/hyprland.conf b/example/hyprland.conf index f94cb1d1..f1139c3b 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -1,6 +1,6 @@ # This is an example Hyprland config file. # Refer to the wiki for more information. -# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ +# https://wiki.hyprland.org/Configuring/ # Please note not all available settings / options are set here. # For a full list, see the wiki diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 4a33ec91..facb16e2 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -13,7 +13,7 @@ autogenerated = 1 # remove this line to remove the warning # This is an example Hyprland config file. # Refer to the wiki for more information. -# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ +# https://wiki.hyprland.org/Configuring/ # Please note not all available settings / options are set here. # For a full list, see the wiki From f3f7d3629a632682b1b3acf800f0b5fb10cd48f4 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:49:00 +0500 Subject: [PATCH 0183/1803] Build with hyprland-session.service (#8251) Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 10 ++++++++++ meson.build | 3 +++ .../hyprland-session.service.in | 6 +++--- {example => systemd}/hyprland-systemd.desktop | 0 systemd/meson.build | 15 +++++++++++++++ 5 files changed, 31 insertions(+), 3 deletions(-) rename example/hyprland-session.service => systemd/hyprland-session.service.in (61%) rename {example => systemd}/hyprland-systemd.desktop (100%) create mode 100644 systemd/meson.build diff --git a/CMakeLists.txt b/CMakeLists.txt index df919d76..ec8c331e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,9 @@ include(GNUInstallDirs) set(HYPRLAND_VERSION ${VER}) set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(BINDIR ${CMAKE_INSTALL_BINDIR}) configure_file(hyprland.pc.in hyprland.pc @ONLY) +configure_file(systemd/hyprland-session.service.in systemd/hyprland-session.service @ONLY) set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") @@ -357,6 +359,11 @@ install( install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + +# session file -systemd +install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + # allow Hyprland to find assets add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") @@ -397,3 +404,6 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland FILES_MATCHING PATTERN "*.h*") + +#install systemd service +install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) diff --git a/meson.build b/meson.build index 33e8fdbe..d0ba9a5c 100644 --- a/meson.build +++ b/meson.build @@ -80,6 +80,8 @@ if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized' warning('Profiling builds should set -- buildtype = debugoptimized') endif + + subdir('protocols') subdir('src') subdir('hyprctl') @@ -87,6 +89,7 @@ subdir('hyprpm/src') subdir('assets') subdir('example') subdir('docs') +subdir('systemd') # Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') diff --git a/example/hyprland-session.service b/systemd/hyprland-session.service.in similarity index 61% rename from example/hyprland-session.service rename to systemd/hyprland-session.service.in index 3089a961..dafdc141 100644 --- a/example/hyprland-session.service +++ b/systemd/hyprland-session.service.in @@ -9,8 +9,8 @@ After=graphical-session-pre.target [Service] Type=notify -ExecStart=/usr/bin/Hyprland -ExecStop=/usr/bin/hyprctl dispatch exit -ExecStopPost=/usr/bin/systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP +ExecStart=@PREFIX@/@BINDIR@/Hyprland +ExecStop=@PREFIX@/@BINDIR@/hyprctl dispatch exit +ExecStopPost=systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP Restart=on-failure Slice=session.slice diff --git a/example/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop similarity index 100% rename from example/hyprland-systemd.desktop rename to systemd/hyprland-systemd.desktop diff --git a/systemd/meson.build b/systemd/meson.build new file mode 100644 index 00000000..497e64f4 --- /dev/null +++ b/systemd/meson.build @@ -0,0 +1,15 @@ +install_data( + 'hyprland-systemd.desktop', + install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), + install_tag: 'runtime', +) + +conf_data = configuration_data() +conf_data.set('PREFIX', get_option('prefix')) +conf_data.set('BINDIR', get_option('bindir')) + +configure_file( + configuration: conf_data, + input: 'hyprland-session.service.in', + output: '@BASENAME@', + install_dir: join_paths(get_option('libdir'), 'systemd/user') ) From a3d3b4fd64a51a8c1663b450bd2a408f1f0fa9b3 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 27 Oct 2024 00:44:55 +0000 Subject: [PATCH 0184/1803] groups: fix swallowing (#8223) * fix swallowing for groups * remove unnecessary check * clang-format * clarify comment * make variables consistent * make aditional variables consistent --- src/desktop/Window.hpp | 1 + src/events/Windows.cpp | 32 +++++++++---------- src/layout/IHyprLayout.cpp | 29 +++++++---------- .../decorations/CHyprGroupBarDecoration.cpp | 7 ++-- 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index b2a8e763..9867a8c9 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -357,6 +357,7 @@ class CWindow { // swallowing PHLWINDOWREF m_pSwallowed; + bool m_bGroupSwallowed = false; // focus stuff bool m_bStayFocused = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 57a28948..e8abe30d 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -44,8 +44,6 @@ void Events::listener_mapWindow(void* owner, void* data) { 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 PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); @@ -322,6 +320,10 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->updateWindowData(); + // Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped. + const auto SWALLOWER = PWINDOW->getSwallower(); + PWINDOW->m_pSwallowed = SWALLOWER; + if (PWINDOW->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; @@ -567,20 +569,12 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->focusWindow(nullptr); } - // verify swallowing - if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) { - const auto SWALLOWER = PWINDOW->getSwallower(); - - if (SWALLOWER) { - // swallow - PWINDOW->m_pSwallowed = SWALLOWER; - - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); - - SWALLOWER->setHidden(true); - - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); - } + // swallow + if (SWALLOWER) { + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); + g_pHyprRenderer->damageWindow(SWALLOWER); + SWALLOWER->setHidden(true); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); } PWINDOW->m_bFirstMap = false; @@ -662,7 +656,13 @@ void Events::listener_unmapWindow(void* owner, void* data) { // swallowing if (valid(PWINDOW->m_pSwallowed)) { PWINDOW->m_pSwallowed->setHidden(false); + + if (PWINDOW->m_sGroupData.pNextWindow.lock()) + PWINDOW->m_pSwallowed->m_bGroupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false. + g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed.lock()); + + PWINDOW->m_pSwallowed->m_bGroupSwallowed = false; PWINDOW->m_pSwallowed.reset(); } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 655f2341..454a6132 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -184,22 +184,20 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { - static auto PAUTOGROUP = CConfigValue("group:auto_group"); - PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? - g_pCompositor->m_pLastWindow.lock() : - g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + static auto PAUTOGROUP = CConfigValue("group:auto_group"); + const PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? + g_pCompositor->m_pLastWindow.lock() : + g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + const bool FLOATEDINTOTILED = pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating; + const bool SWALLOWING = pWindow->m_pSwallowed || pWindow->m_bGroupSwallowed; - bool denied = false; - if (pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating) - denied = true; - - if (*PAUTOGROUP // check if auto_group is enabled. + if ((*PAUTOGROUP || SWALLOWING) // continue if auto_group is enabled or if dealing with window swallowing. && OPENINGON // this shouldn't be 0, but honestly, better safe than sorry. && OPENINGON != pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. - && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. - && !denied) { // don't group a new floated window into a tiled group (for convenience). + && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !FLOATEDINTOTILED. + && !FLOATEDINTOTILED) { // don't group a new floated window into a tiled group (for convenience). pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state. Needed to autogroup a new tiled window into a floated group. @@ -341,12 +339,9 @@ void IHyprLayout::onEndDragWindow() { if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW)) return; - bool denied = false; - if (!pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled) - denied = true; - - static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); - if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !denied) { + const bool FLOATEDINTOTILED = !pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled; + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !FLOATEDINTOTILED) { if (DRAGGINGWINDOW->m_bDraggingTiled) { changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4219a5a8..1868bb5c 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -405,12 +405,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND static auto PSTACKED = CConfigValue("group:groupbar:stacked"); static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); + const bool FLOATEDINTOTILED = !m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled; - bool denied = false; - if (!m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) - denied = true; - - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || denied) + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR)) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; From f9b52203f58bcb716144d89ee9f85fe12ebfe94d Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 27 Oct 2024 18:51:26 +0100 Subject: [PATCH 0185/1803] internal: optimize cursor move a bit (#8264) * window: inline and const getWindowMainSurfaceBox getWindowMainSurfaceBox gets called a lot of times from deep down from mousemoveunified, profiling mousemoveunified it spends quite a lot of cpu time in here, let the compiler optimize the call to getWindowMainSurfaceBox by inlining and making it const. reducing the overhead. * inputmgr: return early and use std::any_of return early in mousemoveunified to reduce the amount of unnecessery calls to various pointers when not needed, also make isconstrained use std::any_of instead of for loop to use the STL optimized paths with hopes and dreams marginally faster. * decoration: return early, reduce temporar copy return earlier and reduce the temp copies by using one .lock instead of two --- src/desktop/Window.cpp | 4 --- src/desktop/Window.hpp | 10 +++--- src/managers/input/InputManager.cpp | 35 +++++++------------ .../decorations/DecorationPositioner.cpp | 14 ++++---- 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 1297bb83..0772b676 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -240,10 +240,6 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { return box; } -CBox CWindow::getWindowMainSurfaceBox() { - return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; -} - SBoxExtents CWindow::getFullWindowReservedArea() { return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock()); } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 9867a8c9..64f39558 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -396,10 +396,12 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SBoxExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - CBox getWindowMainSurfaceBox(); + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); + inline CBox getWindowMainSurfaceBox() const { + return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; + } CBox getWindowIdealBoundingBoxIgnoreReserved(); void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 6f7d8017..028286bf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -139,6 +139,15 @@ void CInputManager::sendMotionEventsToFocused() { } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { + if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) + return; + + Vector2D const mouseCoords = getMouseCoordsInternal(); + auto const MOUSECOORDSFLOORED = mouseCoords.floor(); + + if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) + return; + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); static auto PFOLLOWONDND = CConfigValue("misc:always_follow_on_dnd"); @@ -159,15 +168,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { PHLWINDOW pFoundWindow; PHLLS pFoundLayerSurface; - if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) - return; - - Vector2D mouseCoords = getMouseCoordsInternal(); - const auto MOUSECOORDSFLOORED = mouseCoords.floor(); - - if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) - return; - EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED); m_vLastCursorPosFloored = MOUSECOORDSFLOORED; @@ -1418,19 +1418,10 @@ void CInputManager::unconstrainMouse() { } bool CInputManager::isConstrained() { - for (auto const& c : m_vConstraints) { - const auto C = c.lock(); - - if (!C) - continue; - - if (!C->isActive() || C->owner()->resource() != g_pCompositor->m_pLastFocus) - continue; - - return true; - } - - return false; + return std::any_of(m_vConstraints.begin(), m_vConstraints.end(), [](auto const& c) { + const auto constraint = c.lock(); + return constraint && constraint->isActive() && constraint->owner()->resource() == g_pCompositor->m_pLastFocus; + }); } bool CInputManager::isLocked() { diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 4666a59e..3eb45546 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -297,15 +297,16 @@ SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, CBox accum = pWindow->getWindowMainSurfaceBox(); for (auto const& data : m_vWindowPositioningDatas) { - if (data->pWindow.lock() != pWindow) - continue; - - if (!data->pWindow.lock() || !data->pDecoration) + if (!data->pDecoration) continue; if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly) continue; + auto const window = data->pWindow.lock(); + if (!window || window != pWindow) + continue; + CBox decoBox; if (data->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { @@ -373,9 +374,10 @@ CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { } CBox CDecorationPositioner::getWindowDecorationBox(IHyprWindowDecoration* deco) { - const auto DATA = getDataFor(deco, deco->m_pWindow.lock()); + auto const window = deco->m_pWindow.lock(); + const auto DATA = getDataFor(deco, window); CBox box = DATA->lastReply.assignedGeometry; - box.translate(getEdgeDefinedPoint(DATA->positioningInfo.edges, deco->m_pWindow.lock())); + box.translate(getEdgeDefinedPoint(DATA->positioningInfo.edges, window)); return box; } From b6e226c3200276978e487a68a16fd696fcb7e7c8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 27 Oct 2024 14:26:42 -0400 Subject: [PATCH 0186/1803] groupbar: set locked color when groups are globally locked (#8257) --- src/render/decorations/CHyprGroupBarDecoration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 1868bb5c..e342e244 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -143,7 +143,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float a) { auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData(); auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData(); - const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; + const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked || g_pKeybindManager->m_bGroupsLocked; const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; From 5d4b54b01286c10d4b6bf402a772b5938b054ce6 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:45:38 +0000 Subject: [PATCH 0187/1803] core: move internal structures to monitor pointers (#8266) --- src/Compositor.cpp | 63 ++++++++++++++-------------- src/debug/HyprCtl.cpp | 6 +-- src/desktop/LayerSurface.cpp | 24 ++++++----- src/desktop/LayerSurface.hpp | 5 ++- src/desktop/Window.cpp | 54 +++++++++++++----------- src/desktop/Window.hpp | 5 ++- src/desktop/Workspace.cpp | 30 +++++++------ src/desktop/Workspace.hpp | 11 ++--- src/events/Windows.cpp | 34 +++++++-------- src/helpers/MiscFunctions.cpp | 6 +-- src/helpers/Monitor.cpp | 20 ++++----- src/layout/DwindleLayout.cpp | 18 ++++---- src/layout/IHyprLayout.cpp | 18 ++++---- src/layout/MasterLayout.cpp | 40 +++++++++--------- src/managers/AnimationManager.cpp | 6 +-- src/managers/KeybindManager.cpp | 34 +++++++-------- src/managers/XWaylandManager.cpp | 2 +- src/managers/input/Swipe.cpp | 3 +- src/managers/input/Touch.cpp | 4 +- src/protocols/ForeignToplevelWlr.cpp | 4 +- src/protocols/LinuxDMABUF.cpp | 2 +- src/protocols/ToplevelExport.cpp | 8 ++-- src/render/OpenGL.cpp | 12 +++--- src/render/Renderer.cpp | 32 +++++++------- 24 files changed, 226 insertions(+), 215 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d4e2db17..a2fe9935 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -834,7 +834,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; const auto BB = w->getWindowBoxUnified(properties); - const auto PWINDOWMONITOR = getMonitorFromID(w->m_iMonitorID); + const auto PWINDOWMONITOR = w->m_pMonitor.lock(); // to avoid focusing windows behind special workspaces from other monitors if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace && @@ -1063,7 +1063,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface if (pWindow->m_bPinned) pWindow->m_pWorkspace = m_pLastMonitor->activeWorkspace; - const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!isWorkspaceVisible(pWindow->m_pWorkspace)) { const auto PWORKSPACE = pWindow->m_pWorkspace; @@ -1259,7 +1259,7 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { if (!valid(w)) return false; - const auto PMONITOR = getMonitorFromID(w->m_iMonitorID); + const auto PMONITOR = w->m_pMonitor.lock(); if (PMONITOR->activeSpecialWorkspace) return PMONITOR->activeSpecialWorkspace->m_iID == w->m_iID; @@ -1354,7 +1354,7 @@ PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { if (!PWORKSPACE) return nullptr; - const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID); + const auto PMONITOR = PWORKSPACE->m_pMonitor.lock(); for (auto const& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden()) @@ -1405,7 +1405,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { } if (pw->m_bIsMapped) - g_pHyprRenderer->damageMonitor(getMonitorFromID(pw->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(pw->m_pMonitor.lock()); }; if (top) @@ -1444,7 +1444,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { auto w = ww.lock(); - if (w->m_iMonitorID != monid) + if (w->monitorID() != monid && w->m_pMonitor) continue; if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { @@ -1474,7 +1474,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { continue; } - if (ls->monitorID != monid) + if (ls->monitorID() != monid && ls->monitor) continue; // mark blur for recalc @@ -1537,7 +1537,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { static auto PMETHOD = CConfigValue("binds:focus_preferred_method"); static auto PMONITORFALLBACK = CConfigValue("binds:window_direction_monitor_fallback"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR) return nullptr; // ?? @@ -1558,13 +1558,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; - if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace) + if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) continue; if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) continue; - if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID) + if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor) continue; const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); @@ -1650,13 +1650,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; - if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace) + if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) continue; if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) continue; - if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID) + if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor) continue; const auto DIST = w->middle().distance(pWindow->middle()); @@ -1996,7 +1996,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor const auto PWORKSPACEA = pMonitorA->activeWorkspace; const auto PWORKSPACEB = pMonitorB->activeWorkspace; - PWORKSPACEA->m_iMonitorID = pMonitorB->ID; + PWORKSPACEA->m_pMonitor = pMonitorB; PWORKSPACEA->moveToMonitor(pMonitorB->ID); for (auto const& w : m_vWindows) { @@ -2006,7 +2006,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor continue; } - w->m_iMonitorID = pMonitorB->ID; + w->m_pMonitor = pMonitorB; // additionally, move floating and fs windows manually if (w->m_bIsFloating) @@ -2021,7 +2021,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor } } - PWORKSPACEB->m_iMonitorID = pMonitorA->ID; + PWORKSPACEB->m_pMonitor = pMonitorA; PWORKSPACEB->moveToMonitor(pMonitorA->ID); for (auto const& w : m_vWindows) { @@ -2031,7 +2031,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor continue; } - w->m_iMonitorID = pMonitorA->ID; + w->m_pMonitor = pMonitorA; // additionally, move floating and fs windows manually if (w->m_bIsFloating) @@ -2156,12 +2156,12 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo // We trust the monitor to be correct. - if (pWorkspace->m_iMonitorID == pMonitor->ID) + if (pWorkspace->m_pMonitor == pMonitor) return; Debug::log(LOG, "moveWorkspaceToMonitor: Moving {} to monitor {}", pWorkspace->m_iID, pMonitor->ID); - const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID); + const auto POLDMON = pWorkspace->m_pMonitor.lock(); const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false; @@ -2171,7 +2171,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo nextWorkspaceOnMonitorID = pWorkspace->m_iID; else { for (auto const& w : m_vWorkspaces) { - if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) { + if (w->m_pMonitor == POLDMON && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) { nextWorkspaceOnMonitorID = w->m_iID; break; } @@ -2196,7 +2196,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo } // move the workspace - pWorkspace->m_iMonitorID = pMonitor->ID; + pWorkspace->m_pMonitor = pMonitor; pWorkspace->moveToMonitor(pMonitor->ID); for (auto const& w : m_vWindows) { @@ -2206,7 +2206,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo continue; } - w->m_iMonitorID = pMonitor->ID; + w->m_pMonitor = pMonitor; // additionally, move floating and fs windows manually if (w->m_bIsMapped && !w->isHidden()) { @@ -2299,7 +2299,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { } } - const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { @@ -2342,7 +2342,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS state.internal = std::clamp(state.internal, (eFullscreenMode)0, FSMODE_MAX); state.client = std::clamp(state.client, (eFullscreenMode)0, FSMODE_MAX); - const auto PMONITOR = getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const auto PWORKSPACE = PWINDOW->m_pWorkspace; const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal); @@ -2360,7 +2360,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS if (!CHANGEINTERNAL) { PWINDOW->updateDynamicRules(); updateWindowAnimatedDecorationValues(PWINDOW); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); return; } @@ -2375,7 +2375,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS PWINDOW->updateDynamicRules(); updateWindowAnimatedDecorationValues(PWINDOW); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); // make all windows on the same workspace under the fullscreen window for (auto const& w : m_vWindows) { @@ -2663,13 +2663,12 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO auto monID = monid; // check if bound - if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) { + if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) monID = PMONITOR->ID; - } const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2; - const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL, isEmpty)); + const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty)); PWORKSPACE->m_fAlpha.setValueAndWarp(0); @@ -2751,15 +2750,15 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true); - const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; - const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); if (!pWindow->m_bIsFloating) g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); pWindow->moveToWorkspace(pWorkspace); - pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; + pWindow->m_pMonitor = pWorkspace->m_pMonitor; static auto PGROUPONMOVETOWORKSPACE = CConfigValue("group:group_on_movetoworkspace"); if (*PGROUPONMOVETOWORKSPACE && visibleWindowsOnWorkspace == 1 && pFirstWindowOnWorkspace && pFirstWindowOnWorkspace != pWindow && @@ -3077,7 +3076,7 @@ void CCompositor::onNewMonitor(SP output) { checkDefaultCursorWarp(PNEWMONITOR); for (auto const& w : g_pCompositor->m_vWindows) { - if (w->m_iMonitorID == PNEWMONITOR->ID) { + if (w->m_pMonitor == PNEWMONITOR) { w->m_iLastSurfaceMonitorID = MONITOR_INVALID; w->updateSurfaceScaleTransformDetails(); } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 82290f94..bf3ecfc8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -242,7 +242,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { (uintptr_t)w.get(), (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_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), - (int64_t)w->m_iMonitorID, escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), + (int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); @@ -254,7 +254,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", (uintptr_t)w.get(), 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_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), - (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), + (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } @@ -288,7 +288,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format) { const auto PLASTW = w->getLastFocusedWindow(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID); + const auto PMONITOR = w->m_pMonitor.lock(); if (format == eHyprCtlOutputFormat::FORMAT_JSON) { return std::format(R"#({{ "id": {}, diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 6c024ee0..f073da82 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -26,7 +26,7 @@ PHLLS CLayerSurface::create(SP resource) { pLS->layer = resource->current.layer; pLS->popupHead = std::make_unique(pLS); - pLS->monitorID = pMonitor->ID; + pLS->monitor = pMonitor; pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS); pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); @@ -50,7 +50,7 @@ PHLLS CLayerSurface::create(SP resource) { void CLayerSurface::registerCallbacks() { alpha.setUpdateCallback([this](void*) { if (dimAround) - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(monitorID)); + g_pHyprRenderer->damageMonitor(monitor.lock()); }); } @@ -82,9 +82,9 @@ CLayerSurface::~CLayerSurface() { void CLayerSurface::onDestroy() { Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface.get()); - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); - if (!g_pCompositor->getMonitorFromID(monitorID)) + if (!PMONITOR) Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)"); if (!fadingOut) { @@ -137,7 +137,7 @@ void CLayerSurface::onMap() { g_pCompositor->removeFromFadingOutSafe(self.lock()); // fix if it changed its mon - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); if (!PMONITOR) return; @@ -197,7 +197,7 @@ void CLayerSurface::onUnmap() { std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); - if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) { + if (!monitor || g_pCompositor->m_bUnsafeState) { Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring."); g_pCompositor->addToFadingOutSafe(self.lock()); @@ -221,7 +221,7 @@ void CLayerSurface::onUnmap() { g_pCompositor->addToFadingOutSafe(self.lock()); - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); @@ -256,13 +256,13 @@ void CLayerSurface::onCommit() { if (layerSurface->surface && !layerSurface->surface->current.texture) { fadingOut = false; geometry = {}; - g_pHyprRenderer->arrangeLayersForMonitor(monitorID); + g_pHyprRenderer->arrangeLayersForMonitor(monitorID()); } return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); if (!PMONITOR) return; @@ -336,7 +336,7 @@ void CLayerSurface::onCommit() { // moveMouseUnified won't focus non interactive layers but it won't unfocus them either, // so unfocus the surface here. g_pCompositor->focusSurface(nullptr); - g_pInputManager->refocusLastWindow(g_pCompositor->getMonitorFromID(monitorID)); + g_pInputManager->refocusLastWindow(monitor.lock()); } else if (!WASEXCLUSIVE && ISEXCLUSIVE) { // if now exclusive and not previously g_pSeatManager->setGrab(nullptr); @@ -545,3 +545,7 @@ int CLayerSurface::popupsCount() { popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no); return no; } + +MONITORID CLayerSurface::monitorID() { + return monitor ? monitor->ID : MONITOR_INVALID; +} diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index e0f17039..6aa8eb81 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -42,7 +42,7 @@ class CLayerSurface { bool mapped = false; uint32_t layer = 0; - MONITORID monitorID = -1; + PHLMONITORREF monitor; bool fadingOut = false; bool readyToDelete = false; @@ -70,6 +70,7 @@ class CLayerSurface { void onMap(); void onUnmap(); void onCommit(); + MONITORID monitorID(); private: struct { @@ -83,6 +84,6 @@ class CLayerSurface { // For the list lookup bool operator==(const CLayerSurface& rhs) const { - return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID; + return layerSurface == rhs.layerSurface && monitor == rhs.monitor; } }; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 0772b676..e4f987eb 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -113,7 +113,7 @@ SBoxExtents CWindow::getFullWindowExtents() { const int BORDERSIZE = getRealBorderSize(); if (m_sWindowData.dimAround.valueOrDefault()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) 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)}}; } @@ -173,7 +173,7 @@ SBoxExtents CWindow::getFullWindowExtents() { CBox CWindow::getFullWindowBoundingBox() { if (m_sWindowData.dimAround.valueOrDefault()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } @@ -186,7 +186,7 @@ CBox CWindow::getFullWindowBoundingBox() { } CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (!PMONITOR) return {m_vPosition, m_vSize}; @@ -221,7 +221,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { CBox CWindow::getWindowBoxUnified(uint64_t properties) { if (m_sWindowData.dimAround.valueOrDefault()) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR) return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } @@ -352,9 +352,9 @@ void CWindow::updateSurfaceScaleTransformDetails(bool force) { const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID); - m_iLastSurfaceMonitorID = m_iMonitorID; + m_iLastSurfaceMonitorID = monitorID(); - const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PNEWMONITOR = m_pMonitor.lock(); if (!PNEWMONITOR) return; @@ -366,10 +366,10 @@ void CWindow::updateSurfaceScaleTransformDetails(bool force) { m_pWLSurface->resource()->breadthfirst([PNEWMONITOR](SP s, const Vector2D& offset, void* d) { s->enter(PNEWMONITOR->self.lock()); }, nullptr); } - m_pWLSurface->resource()->breadthfirst( - [this](SP s, const Vector2D& offset, void* d) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); + m_pWLSurface->resource()->breadthfirst( + [PMONITOR](SP s, const Vector2D& offset, void* d) { const auto PSURFACE = CWLSurface::fromResource(s); if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale) return; @@ -404,7 +404,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { const auto OLDWORKSPACE = m_pWorkspace; - m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->m_iMonitorID : -1; + m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F); m_fMovingToWorkspaceAlpha = 0.F; m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; }); @@ -415,11 +415,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID); g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID()); g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -431,14 +431,14 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { if (const auto SWALLOWED = m_pSwallowed.lock()) { SWALLOWED->moveToWorkspace(pWorkspace); - SWALLOWED->m_iMonitorID = m_iMonitorID; + SWALLOWED->m_pMonitor = m_pMonitor; } // update xwayland coords g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value()); if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE->m_iID) == 0 && *PCLOSEONLASTSPECIAL) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID); PMONITOR) + if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) PMONITOR->setSpecialWorkspace(nullptr); } } @@ -517,19 +517,19 @@ void CWindow::onUnmap() { std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(workspaceID()) == 0 && onSpecialWorkspace()) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace == m_pWorkspace) PMONITOR->setSpecialWorkspace(nullptr); } - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this) PMONITOR->solitaryClient.reset(); g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); m_pWorkspace.reset(); @@ -790,7 +790,7 @@ void CWindow::updateDynamicRules() { EMIT_HOOK_EVENT("windowUpdateRules", m_pSelf.lock()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); } // check if the point is "hidden" under a rounded corner of the window @@ -857,7 +857,7 @@ void CWindow::createGroup() { g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("1,{:x}", (uintptr_t)this)}); @@ -875,7 +875,7 @@ void CWindow::destroyGroup() { updateWindowDecos(); g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("0,{:x}", (uintptr_t)this)}); @@ -911,7 +911,7 @@ void CWindow::destroyGroup() { g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); if (!addresses.empty()) @@ -1087,7 +1087,7 @@ void CWindow::updateGroupOutputs() { const auto WS = m_pWorkspace; while (curr.get() != this) { - curr->m_iMonitorID = m_iMonitorID; + curr->m_pMonitor = m_pMonitor; curr->moveToWorkspace(WS); curr->m_vRealPosition = m_vRealPosition.goal(); @@ -1209,7 +1209,7 @@ void CWindow::onWorkspaceAnimUpdate() { if (!PWORKSPACE) return; - const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + const auto PWSMON = m_pMonitor.lock(); if (!PWSMON) return; @@ -1275,6 +1275,10 @@ WORKSPACEID CWindow::workspaceID() { return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace; } +MONITORID CWindow::monitorID() { + return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID; +} + bool CWindow::onSpecialWorkspace() { return m_pWorkspace ? m_pWorkspace->m_bIsSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_iLastWorkspace); } @@ -1461,7 +1465,7 @@ void CWindow::onX11Configure(CBox box) { m_pXWaylandSurface->configure(box); m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) m_fX11SurfaceScaledBy = PMONITOR->scale; return; } @@ -1487,7 +1491,7 @@ void CWindow::onX11Configure(CBox box) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) { + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale); m_fX11SurfaceScaledBy = PMONITOR->scale; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 64f39558..825e8ca2 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -272,12 +272,12 @@ class CWindow { bool m_bDraggingTiled = false; // for dragging around tiled windows bool m_bWasMaximized = false; sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; - MONITORID m_iMonitorID = -1; std::string m_szTitle = ""; std::string m_szClass = ""; std::string m_szInitialTitle = ""; std::string m_szInitialClass = ""; PHLWORKSPACE m_pWorkspace; + PHLMONITORREF m_pMonitor; bool m_bIsMapped = false; @@ -429,6 +429,7 @@ class CWindow { void setSuspended(bool suspend); bool visibleOnMonitor(PHLMONITOR pMonitor); WORKSPACEID workspaceID(); + MONITORID monitorID(); bool onSpecialWorkspace(); void activate(bool force = false); int surfacesCount(); @@ -559,7 +560,7 @@ struct std::formatter : std::formatter { if (formatWorkspace) std::format_to(out, ", workspace: {}", w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID); if (formatMonitor) - std::format_to(out, ", monitor: {}", w->m_iMonitorID); + std::format_to(out, ", monitor: {}", w->monitorID()); if (formatClass) std::format_to(out, ", class: {}", w->m_szClass); return std::format_to(out, "]"); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 2d92659c..2e1e91f2 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -5,14 +5,14 @@ #include using namespace Hyprutils::String; -PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) { - PHLWORKSPACE workspace = makeShared(id, monitorID, name, special, isEmpty); +PHLWORKSPACE CWorkspace::create(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) { + PHLWORKSPACE workspace = makeShared(id, monitor, name, special, isEmpty); workspace->init(workspace); return workspace; } -CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) { - m_iMonitorID = monitorID; +CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) { + m_pMonitor = monitor; m_iID = id; m_szName = name; m_bIsSpecialWorkspace = special; @@ -103,7 +103,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { }); if (ANIMSTYLE.starts_with("slidefade")) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); float movePerc = 100.f; if (ANIMSTYLE.find("%") != std::string::npos) { @@ -151,7 +151,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 PMONITOR = m_pMonitor.lock(); const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP; m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. @@ -164,7 +164,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } } else { // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP; m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. @@ -224,7 +224,7 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { m_sPrevWorkspace.id = prev->m_iID; m_sPrevWorkspace.name = prev->m_szName; - if (prev->m_iMonitorID == m_iMonitorID) { + if (prev->m_pMonitor == m_pMonitor) { m_sPrevWorkspacePerMonitor.id = prev->m_iID; m_sPrevWorkspacePerMonitor.name = prev->m_szName; } @@ -347,7 +347,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { const auto PMONITOR = g_pCompositor->getMonitorFromString(prop); - if (!(PMONITOR ? PMONITOR->ID == m_iMonitorID : false)) + if (!(PMONITOR ? PMONITOR == m_pMonitor : false)) return false; continue; } @@ -512,12 +512,16 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { } void CWorkspace::markInert() { - m_bInert = true; - m_iID = WORKSPACE_INVALID; - m_iMonitorID = MONITOR_INVALID; - m_bVisible = false; + m_bInert = true; + m_iID = WORKSPACE_INVALID; + m_bVisible = false; + m_pMonitor.reset(); } bool CWorkspace::inert() { return m_bInert; } + +MONITORID CWorkspace::monitorID() { + return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID; +} diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 7a32459c..3ed9f50c 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -17,16 +17,16 @@ class CWindow; class CWorkspace { public: - static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); + static PHLWORKSPACE create(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special = false, bool isEmpty = true); // use create() don't use this - CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); + CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special = false, bool isEmpty = true); ~CWorkspace(); // Workspaces ID-based have IDs > 0 // and workspaces name-based have IDs starting with -1337 - WORKSPACEID m_iID = WORKSPACE_INVALID; - std::string m_szName = ""; - MONITORID m_iMonitorID = MONITOR_INVALID; + WORKSPACEID m_iID = WORKSPACE_INVALID; + std::string m_szName = ""; + PHLMONITORREF m_pMonitor; // Previous workspace ID and name is stored during a workspace change, allowing travel // to the previous workspace. SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; @@ -68,6 +68,7 @@ class CWorkspace { void setActive(bool on); void moveToMonitor(const MONITORID&); + MONITORID monitorID(); PHLWINDOW getLastFocusedWindow(); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e8abe30d..30d982fb 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -53,7 +53,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } auto PWORKSPACE = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; - PWINDOW->m_iMonitorID = PMONITOR->ID; + PWINDOW->m_pMonitor = PMONITOR; PWINDOW->m_pWorkspace = PWORKSPACE; PWINDOW->m_bIsMapped = true; PWINDOW->m_bReadyToDelete = false; @@ -144,18 +144,18 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' '))); if (MONITORSTR == "unset") { - PWINDOW->m_iMonitorID = PMONITOR->ID; + PWINDOW->m_pMonitor = PMONITOR; } else { if (isNumber(MONITORSTR)) { const MONITORID MONITOR = std::stoi(MONITORSTR); - if (!g_pCompositor->getMonitorFromID(MONITOR)) - PWINDOW->m_iMonitorID = 0; + if (const auto PM = g_pCompositor->getMonitorFromID(MONITOR); PM) + PWINDOW->m_pMonitor = PM; else - PWINDOW->m_iMonitorID = MONITOR; + PWINDOW->m_pMonitor = g_pCompositor->m_vMonitors.at(0); } else { const auto PMONITOR = g_pCompositor->getMonitorFromName(MONITORSTR); if (PMONITOR) - PWINDOW->m_iMonitorID = PMONITOR->ID; + PWINDOW->m_pMonitor = PMONITOR; else { Debug::log(ERR, "No monitor in monitor {} rule", MONITORSTR); continue; @@ -163,10 +163,10 @@ void Events::listener_mapWindow(void* owner, void* data) { } } - const auto PMONITORFROMID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITORFROMID = PWINDOW->m_pMonitor.lock(); - if (PWINDOW->m_iMonitorID != PMONITOR->ID) { - g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->m_iMonitorID)); + if (PWINDOW->m_pMonitor != PMONITOR) { + g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->monitorID())); PMONITOR = PMONITORFROMID; } PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; @@ -296,19 +296,19 @@ void Events::listener_mapWindow(void* owner, void* data) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->m_iMonitorID, requestedWorkspaceName); + pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName); PWORKSPACE = pWorkspace; PWINDOW->m_pWorkspace = pWorkspace; - PWINDOW->m_iMonitorID = pWorkspace->m_iMonitorID; + PWINDOW->m_pMonitor = pWorkspace->m_pMonitor; - if (g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeSpecialWorkspace && !pWorkspace->m_bIsSpecialWorkspace) + if (PWINDOW->m_pMonitor.lock()->activeSpecialWorkspace && !pWorkspace->m_bIsSpecialWorkspace) workspaceSilent = true; if (!workspaceSilent) { if (pWorkspace->m_bIsSpecialWorkspace) - g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID)->setSpecialWorkspace(pWorkspace); + pWorkspace->m_pMonitor->setSpecialWorkspace(pWorkspace); else if (PMONITOR->activeWorkspaceID() != REQUESTEDWORKSPACEID) g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspaceName); @@ -574,7 +574,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); g_pHyprRenderer->damageWindow(SWALLOWER); SWALLOWER->setHidden(true); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); } PWINDOW->m_bFirstMap = false; @@ -635,7 +635,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (PMONITOR) { PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition; PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value(); @@ -773,7 +773,7 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_pWorkspace->m_bVisible) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (PMONITOR) PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); @@ -911,7 +911,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size()); if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { + if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) { PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale); } } diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 20c79a2b..29861af7 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -302,7 +302,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Collect all the workspaces we can't jump to. for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) { + if (ws->m_bIsSpecialWorkspace || (ws->m_pMonitor != g_pCompositor->m_pLastMonitor)) { // Can't jump to this workspace invalidWSes.insert(ws->m_iID); } @@ -320,7 +320,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Prepare all named workspaces in case when we need them std::vector namedWSes; for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0) + if (ws->m_bIsSpecialWorkspace || (ws->m_pMonitor != g_pCompositor->m_pLastMonitor) || ws->m_iID >= 0) continue; namedWSes.push_back(ws->m_iID); @@ -464,7 +464,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::vector validWSes; for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors)) + if (ws->m_bIsSpecialWorkspace || (ws->m_pMonitor != g_pCompositor->m_pLastMonitor && !onAllMonitors)) continue; validWSes.push_back(ws->m_iID); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 41290b7d..9e71bf5f 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -314,9 +314,8 @@ void CMonitor::onDisconnect(bool destroy) { // move workspaces std::deque wspToMove; for (auto const& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) { + if (w->m_pMonitor == self || !w->m_pMonitor) wspToMove.push_back(w); - } } for (auto const& w : wspToMove) { @@ -464,7 +463,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { if (newDefaultWorkspaceName == "") newDefaultWorkspaceName = std::to_string(wsID); - PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(wsID, ID, newDefaultWorkspaceName)); + PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(wsID, self.lock(), newDefaultWorkspaceName)); } activeWorkspace = PNEWWORKSPACE; @@ -541,9 +540,8 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // move all the WS std::deque wspToMove; for (auto const& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == ID) { + if (w->m_pMonitor == self || !w->m_pMonitor) wspToMove.push_back(w); - } } for (auto const& w : wspToMove) { @@ -626,7 +624,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo } if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace && - !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_iMonitorID == ID)) { + !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); auto pWindow = pWorkspace->getLastFocusedWindow(); @@ -687,7 +685,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); - if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_iMonitorID == ID)) { + if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { if (const auto PLAST = activeWorkspace->getLastFocusedWindow(); PLAST) g_pCompositor->focusWindow(PLAST); else @@ -710,7 +708,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { bool animate = true; //close if open elsewhere - const auto PMONITORWORKSPACEOWNER = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITORWORKSPACEOWNER = pWorkspace->m_pMonitor.lock(); if (PMONITORWORKSPACEOWNER->activeSpecialWorkspace == pWorkspace) { PMONITORWORKSPACEOWNER->activeSpecialWorkspace.reset(); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITORWORKSPACEOWNER->ID); @@ -723,7 +721,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { } // open special - pWorkspace->m_iMonitorID = ID; + pWorkspace->m_pMonitor = self; activeSpecialWorkspace = pWorkspace; activeSpecialWorkspace->m_bVisible = true; if (animate) @@ -731,7 +729,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == pWorkspace) { - w->m_iMonitorID = ID; + w->m_pMonitor = self; w->updateSurfaceScaleTransformDetails(); w->setAnimationsToMove(); @@ -755,7 +753,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); - if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_iMonitorID == ID)) { + if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { if (const auto PLAST = pWorkspace->getLastFocusedWindow(); PLAST) g_pCompositor->focusWindow(PLAST); else diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 0fa57143..059dda99 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -111,7 +111,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for } } } else - PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); + PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); @@ -234,7 +234,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir m_lDwindleNodesData.push_back(SDwindleNodeData()); const auto PNODE = &m_lDwindleNodesData.back(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); static auto PUSEACTIVE = CConfigValue("dwindle:use_active_for_splits"); static auto PDEFAULTSPLIT = CConfigValue("dwindle:default_split_ratio"); @@ -446,7 +446,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride); - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { @@ -512,7 +512,7 @@ void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) { } void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (!PMONITOR) return; @@ -577,7 +577,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn static auto PSMARTRESIZING = CConfigValue("dwindle:smart_resizing"); // get some data about our window - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); 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); @@ -750,7 +750,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn } void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PWORKSPACE = pWindow->m_pWorkspace; // save position and size if floating @@ -860,9 +860,9 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, const auto PMONITORFOCAL = g_pCompositor->getMonitorFromVector(focalPoint); - if (PMONITORFOCAL->ID != pWindow->m_iMonitorID) { + if (PMONITORFOCAL != pWindow->m_pMonitor) { pWindow->moveToWorkspace(PMONITORFOCAL->activeWorkspace); - pWindow->m_iMonitorID = PMONITORFOCAL->ID; + pWindow->m_pMonitor = PMONITORFOCAL; } onWindowCreatedTiling(pWindow); @@ -900,7 +900,7 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { PNODE->pWindow = pWindow2; if (PNODE->workspaceID != PNODE2->workspaceID) { - std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID); + std::swap(pWindow2->m_pMonitor, pWindow->m_pMonitor); std::swap(pWindow2->m_pWorkspace, pWindow->m_pWorkspace); } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 454a6132..a3c14e41 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -13,7 +13,7 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; } else pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); @@ -88,7 +88,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (pWindow->m_bIsX11) { Vector2D xy = {desiredGeometry.x, desiredGeometry.y}; @@ -485,7 +485,7 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, } if (*SNAPMONITORGAP) { - const auto MON = g_pCompositor->getMonitorFromID(DRAGGINGWINDOW->m_iMonitorID); + const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); const CBox mon = {MON->vecPosition.x, MON->vecPosition.y, MON->vecPosition.x + MON->vecSize.x, MON->vecPosition.y + MON->vecSize.y}; const double gap = *SNAPMONITORGAP; @@ -677,7 +677,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle); if (PMONITOR && !SPECIAL) { - DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID; + DRAGGINGWINDOW->m_pMonitor = PMONITOR; DRAGGINGWINDOW->moveToWorkspace(PMONITOR->activeWorkspace); DRAGGINGWINDOW->updateGroupOutputs(); @@ -705,8 +705,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { EMIT_HOOK_EVENT("changeFloatingMode", pWindow); if (!TILED) { - const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); - pWindow->m_iMonitorID = PNEWMON->ID; + const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); + pWindow->m_pMonitor = PNEWMON; pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace); pWindow->updateGroupOutputs(); @@ -734,7 +734,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vRealSize.setValue(PSAVEDSIZE); // fix pseudo leaving artifacts - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); if (pWindow == g_pCompositor->m_pLastWindow) m_pLastTiledWindow = pWindow; @@ -757,7 +757,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vSize = wb.pos(); pWindow->m_vPosition = wb.size(); - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->updateWindowData(); @@ -847,7 +847,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || - pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) + pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_pMonitor != g_pCompositor->m_pLastMonitor) return nullptr; return pWindowCandidate; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 95b5afdf..a2321a41 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -80,7 +80,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire static auto PNEWONTOP = CConfigValue("master:new_on_top"); static auto PNEWSTATUS = CConfigValue("master:new_status"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); const bool BNEWBEFOREACTIVE = *PNEWONACTIVE == "before"; const bool BNEWISMASTER = *PNEWSTATUS == "master"; @@ -229,7 +229,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire } // recalc - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { @@ -279,7 +279,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { } } } - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) { @@ -297,7 +297,7 @@ void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) { } void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (!PMONITOR) return; @@ -604,7 +604,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { } } } else - PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); + PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); @@ -711,7 +711,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); static auto ALWAYSCENTER = CConfigValue("master:always_center_master"); static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); @@ -840,7 +840,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne } void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PWORKSPACE = pWindow->m_pWorkspace; // save position and size if floating @@ -896,7 +896,7 @@ void CHyprMasterLayout::recalculateWindow(PHLWINDOW pWindow) { if (!PNODE) return; - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(PHLWINDOW pWindow) { @@ -922,9 +922,9 @@ void CHyprMasterLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, // if different monitors, send to monitor onWindowRemovedTiling(pWindow); pWindow->moveToWorkspace(PWINDOW2->m_pWorkspace); - pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID; + pWindow->m_pMonitor = PWINDOW2->m_pMonitor; if (!silent) { - const auto pMonitor = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto pMonitor = pWindow->m_pMonitor.lock(); g_pCompositor->setActiveMonitor(pMonitor); } onWindowCreatedTiling(pWindow); @@ -946,7 +946,7 @@ void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { return; if (PNODE->workspaceID != PNODE2->workspaceID) { - std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID); + std::swap(pWindow2->m_pMonitor, pWindow->m_pMonitor); std::swap(pWindow2->m_pWorkspace, pWindow->m_pWorkspace); } @@ -957,9 +957,9 @@ void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { pWindow->setAnimationsToMove(); pWindow2->setAnimationsToMove(); - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); if (PNODE2->workspaceID != PNODE->workspaceID) - recalculateMonitor(pWindow2->m_iMonitorID); + recalculateMonitor(pWindow2->monitorID()); g_pHyprRenderer->damageWindow(pWindow); g_pHyprRenderer->damageWindow(pWindow2); @@ -978,7 +978,7 @@ void CHyprMasterLayout::alterSplitRatio(PHLWINDOW pWindow, float ratio, bool exa float newRatio = exact ? ratio : PMASTER->percMaster + ratio; PMASTER->percMaster = std::clamp(newRatio, 0.05f, 0.95f); - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next) { @@ -1185,7 +1185,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri PNODE->isMaster = true; } - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } else if (command == "removemaster") { @@ -1217,7 +1217,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri PNODE->isMaster = false; } - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } else if (command == "orientationleft" || command == "orientationright" || command == "orientationtop" || command == "orientationbottom" || command == "orientationcenter") { const auto PWINDOW = header.pWindow; @@ -1239,7 +1239,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri else if (command == "orientationcenter") PWORKSPACEDATA->orientation = ORIENTATION_CENTER; - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } else if (command == "orientationnext") { runOrientationCycle(header, nullptr, 1); @@ -1274,7 +1274,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri } } - recalculateMonitor(PWINDOW->m_iMonitorID); + recalculateMonitor(PWINDOW->monitorID()); } else if (command == "rollprev") { const auto PWINDOW = header.pWindow; const auto PNODE = getNodeFromWindow(PWINDOW); @@ -1300,7 +1300,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri } } - recalculateMonitor(PWINDOW->m_iMonitorID); + recalculateMonitor(PWINDOW->monitorID()); } return 0; @@ -1338,7 +1338,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi nextOrPrev = cycle.size() + (nextOrPrev % (int)cycle.size()); PWORKSPACEDATA->orientation = cycle.at(nextOrPrev); - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } void CHyprMasterLayout::buildOrientationCycleVectorFromEOperation(std::vector& cycle) { diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 9ff7497d..0bdf5a7a 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -99,12 +99,12 @@ void CAnimationManager::tick() { PDECO->damageEntire(); } - PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + PMONITOR = PWINDOW->m_pMonitor.lock(); if (!PMONITOR) continue; animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled); } else if (PWORKSPACE) { - PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + PMONITOR = PWORKSPACE->m_pMonitor.lock(); if (!PMONITOR) continue; @@ -325,7 +325,7 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo const auto GOALPOS = pWindow->m_vRealPosition.goal(); const auto GOALSIZE = pWindow->m_vRealSize.goal(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR) return; // unsafe state most likely diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9c22fb93..b54b71ed 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -349,9 +349,9 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { g_pInputManager->m_pForcedFocus.reset(); } - if (PLASTWINDOW && PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) { + if (PLASTWINDOW && PLASTWINDOW->m_pMonitor != PWINDOWTOCHANGETO->m_pMonitor) { // event - const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID); + const auto PNEWMON = PWINDOWTOCHANGETO->m_pMonitor.lock(); g_pCompositor->setActiveMonitor(PNEWMON); } @@ -1011,7 +1011,7 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional< } g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); return {}; @@ -1035,7 +1035,7 @@ SDispatchResult CKeybindManager::centerWindow(std::string args) { if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) return {.success = false, .error = "No floating window found"}; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); auto RESERVEDOFFSET = Vector2D(); if (args == "1") @@ -1081,7 +1081,7 @@ SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCU const auto ID = PCURRENTWORKSPACE->m_iID; if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) { - if (PER_MON && PCURRENTWORKSPACE->m_iMonitorID != PWORKSPACETOCHANGETO->m_iMonitorID) + if (PER_MON && PCURRENTWORKSPACE->m_pMonitor != PWORKSPACETOCHANGETO->m_pMonitor) return {WORKSPACE_NOT_CHANGED, ""}; return {ID, PWORKSPACETOCHANGETO->m_szName}; } @@ -1135,7 +1135,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { g_pInputManager->releaseAllMouseButtons(); - const auto PMONITORWORKSPACEOWNER = PMONITOR->ID == pWorkspaceToChangeTo->m_iMonitorID ? PMONITOR : g_pCompositor->getMonitorFromID(pWorkspaceToChangeTo->m_iMonitorID); + const auto PMONITORWORKSPACEOWNER = PMONITOR == pWorkspaceToChangeTo->m_pMonitor ? PMONITOR : pWorkspaceToChangeTo->m_pMonitor.lock(); if (!PMONITORWORKSPACEOWNER) return {.success = false, .error = "Workspace to switch to has no monitor"}; @@ -1270,11 +1270,11 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { if (pWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); - pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + pMonitor = pWorkspace->m_pMonitor.lock(); g_pCompositor->setActiveMonitor(pMonitor); } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName, false); - pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); + pMonitor = pWorkspace->m_pMonitor.lock(); g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } @@ -1283,7 +1283,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { if (pWorkspace->m_bIsSpecialWorkspace) pMonitor->setSpecialWorkspace(pWorkspace); else if (POLDWS->m_bIsSpecialWorkspace) - g_pCompositor->getMonitorFromID(POLDWS->m_iMonitorID)->setSpecialWorkspace(nullptr); + POLDWS->m_pMonitor.lock()->setSpecialWorkspace(nullptr); if (*PALLOWWORKSPACECYCLES) pWorkspace->rememberPrevWorkspace(POLDWS); @@ -1328,7 +1328,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { if (pWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName, false); + pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } @@ -1475,7 +1475,7 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) { if (PLASTWINDOW->m_bIsFloating) { std::optional vPosx, vPosy; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PLASTWINDOW->m_iMonitorID); + const auto PMONITOR = PLASTWINDOW->m_pMonitor.lock(); const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); switch (arg) { @@ -1882,8 +1882,8 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args workspaceID = pWorkspace->m_iID; } - if (pWorkspace->m_iMonitorID != PCURRMONITOR->ID) { - const auto POLDMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + if (pWorkspace->m_pMonitor != PCURRMONITOR) { + const auto POLDMONITOR = pWorkspace->m_pMonitor.lock(); if (!POLDMONITOR) { // wat Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"); return {.success = false, .error = "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"}; @@ -2509,7 +2509,7 @@ SDispatchResult CKeybindManager::pinActive(std::string args) { PWINDOW->m_bPinned = !PWINDOW->m_bPinned; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "pin: monitor not found"); @@ -2658,9 +2658,9 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property! - if (pWindow->m_iMonitorID != pWindowInDirection->m_iMonitorID) { + if (pWindow->m_pMonitor != pWindowInDirection->m_pMonitor) { pWindow->moveToWorkspace(pWindowInDirection->m_pWorkspace); - pWindow->m_iMonitorID = pWindowInDirection->m_iMonitorID; + pWindow->m_pMonitor = pWindowInDirection->m_pMonitor; } static auto USECURRPOS = CConfigValue("group:insert_after_current"); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 7b3081a2..d0dda8e6 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -117,7 +117,7 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 8f95c6c6..ba0783fa 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -15,9 +15,8 @@ void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) { int onMonitor = 0; for (auto const& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID && !g_pCompositor->isWorkspaceSpecial(w->m_iID)) { + if (w->m_pMonitor == g_pCompositor->m_pLastMonitor && !g_pCompositor->isWorkspaceSpecial(w->m_iID)) onMonitor++; - } } if (onMonitor < 2 && !*PSWIPENEW) diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 454391af..4e3980aa 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -123,7 +123,7 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { return; } if (validMapped(m_sTouchData.touchFocusWindow)) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID); + const auto PMONITOR = m_sTouchData.touchFocusWindow->m_pMonitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); @@ -133,7 +133,7 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { g_pSeatManager->sendTouchMotion(e.timeMs, e.touchID, local); } else if (!m_sTouchData.touchFocusLS.expired()) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID); + const auto PMONITOR = m_sTouchData.touchFocusLS->monitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index ffc335c9..06814c88 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -207,7 +207,7 @@ void CForeignToplevelWlrManager::onMap(PHLWINDOW pWindow) { resource->sendToplevel(NEWHANDLE->resource.get()); NEWHANDLE->resource->sendAppId(pWindow->m_szClass.c_str()); NEWHANDLE->resource->sendTitle(pWindow->m_szTitle.c_str()); - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR) + if (const auto PMONITOR = pWindow->m_pMonitor.lock(); PMONITOR) NEWHANDLE->sendMonitor(PMONITOR); NEWHANDLE->sendState(); NEWHANDLE->resource->sendDone(); @@ -266,7 +266,7 @@ void CForeignToplevelWlrManager::onMoveMonitor(PHLWINDOW pWindow) { if (!H || H->closed) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR) return; diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index e81d7e01..7b2bcbf4 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -509,7 +509,7 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { PHLMONITOR mon; auto HLSurface = CWLSurface::fromResource(feedback->surface); if (auto w = HLSurface->getWindow(); w) - if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m) + if (auto m = w->m_pMonitor.lock(); m) mon = m->self.lock(); if (!mon) { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 8b6208be..f2af89db 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -97,7 +97,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re resource->setDestroy([this](CHyprlandToplevelExportFrameV1* pFrame) { PROTO::toplevelExport->destroyResource(this); }); resource->setCopy([this](CHyprlandToplevelExportFrameV1* pFrame, wl_resource* res, int32_t ignoreDamage) { this->copy(pFrame, res, ignoreDamage); }); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); g_pHyprRenderer->makeEGLCurrent(); @@ -239,7 +239,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm // render the client - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; g_pHyprRenderer->makeEGLCurrent(); @@ -296,7 +296,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { } bool CToplevelExportFrame::copyDmabuf(timespec* now) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; @@ -383,7 +383,7 @@ void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { const auto PWINDOW = f->pWindow; - if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) + if (pMonitor != PWINDOW->m_pMonitor.lock()) continue; CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index fc2d1012..9e524fa4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -693,7 +693,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) { if (*PBLURSPECIAL) { for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (!ws->m_bIsSpecialWorkspace || ws->m_iMonitorID != pMonitor->ID) + if (!ws->m_bIsSpecialWorkspace || ws->m_pMonitor != pMonitor) continue; if (ws->m_fAlpha.value() == 0) @@ -2219,7 +2219,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFramebuffer) { // we trust the window is valid. - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; @@ -2267,7 +2267,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { // we trust the window is valid. - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; @@ -2319,7 +2319,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { // we trust the window is valid. - const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID); + const auto PMONITOR = pLayer->monitor.lock(); if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; @@ -2372,7 +2372,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { if (!FBDATA->m_cTex->m_iTexID) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); CBox windowBox; // some mafs to figure out the correct box @@ -2411,7 +2411,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { if (!FBDATA->m_cTex->m_iTexID) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID); + const auto PMONITOR = pLayer->monitor.lock(); CBox layerBox; // some mafs to figure out the correct box diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c69167c8..1c38eb4e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -314,7 +314,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; - if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_iMonitorID == pMonitor->ID) { + if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_pMonitor == pMonitor) { if (PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) return true; @@ -327,10 +327,10 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return false; } - if (pWindow->m_iMonitorID == pMonitor->ID) + if (pWindow->m_pMonitor == pMonitor) return true; - if (!g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_iMonitorID != pMonitor->ID) + if (!g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_pMonitor != pMonitor) return false; // if not, check if it maybe is active on a different monitor. @@ -341,7 +341,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; // if window is tiled and it's flying in, don't render on other mons (for slide) - if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_iMonitorID != pMonitor->ID) + if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_pMonitor != pMonitor) return false; if (pWindow->m_vRealPosition.isBeingAnimated()) { @@ -379,7 +379,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { return true; for (auto const& m : g_pCompositor->m_vMonitors) { - if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) + if (PWORKSPACE && PWORKSPACE->m_pMonitor == m && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) return true; if (m->activeSpecialWorkspace && pWindow->onSpecialWorkspace()) @@ -422,10 +422,10 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (w->isFullscreen() || !w->m_bIsFloating) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) continue; // special on another are rendered as a part of the base pass renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL); @@ -439,14 +439,14 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering))) continue; - if (w->m_iMonitorID != pMonitor->ID) + if (w->m_pMonitor != pMonitor) continue; } if (!w->isFullscreen()) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; if (shouldRenderWindow(w, pMonitor)) @@ -469,10 +469,10 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) continue; // special on another are rendered as a part of the base pass renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL); @@ -543,7 +543,7 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) continue; // special on another are rendered as a part of the base pass // render the bad boy @@ -556,7 +556,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe return; if (pWindow->m_bFadingOut) { - if (pMonitor->ID == pWindow->m_iMonitorID) // TODO: fix this + if (pMonitor == pWindow->m_pMonitor) // TODO: fix this g_pHyprOpenGL->renderSnapshot(pWindow); return; } @@ -965,7 +965,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA // and then special for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { + if (ws->m_pMonitor == pMonitor && 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->activeSpecialWorkspace; @@ -2533,7 +2533,7 @@ void CHyprRenderer::initiateManualCrash() { void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace) { CRegion rg; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (!PMONITOR->activeSpecialWorkspace) return; @@ -2562,7 +2562,7 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pW void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace) { CRegion rg; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); static auto PBLUR = CConfigValue("decoration:blur:enabled"); static auto PBLURSIZE = CConfigValue("decoration:blur:size"); From b1120ec4334abdb57677354dfcdcf48b6c34f397 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 27 Oct 2024 23:39:52 +0000 Subject: [PATCH 0188/1803] layout: window snapping cleanup + fixes way better now heh fixes #8259 fixes #8267 --- src/layout/IHyprLayout.cpp | 94 ++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index a3c14e41..30b5632c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -415,7 +415,7 @@ static void snapResizeRight(double& pos, double& len, const double p) { typedef std::function SnapFn; -static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { +static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); @@ -425,59 +425,59 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const SnapFn snapUp = snapLeft; int snaps = 0; + const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW->getRealBorderSize(); + CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE); + if (*SNAPWINDOWGAP) { const auto PID = DRAGGINGWINDOW->getPID(); const auto WSID = DRAGGINGWINDOW->workspaceID(); - const int BORD = DRAGGINGWINDOW->getRealBorderSize(); for (auto& other : g_pCompositor->m_vWindows) { if (other->workspaceID() != WSID || other->getPID() == PID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) continue; - const int bord = std::max(BORD, other->getRealBorderSize()); - const double gap = *SNAPWINDOWGAP + bord; + const int BORDERSIZE = other->getRealBorderSize(); + const double GAPSIZE = *SNAPWINDOWGAP + BORDERSIZE; - const CBox box = other->getWindowMainSurfaceBox(); - const CBox ob = {box.x, box.y, box.x + box.w, box.y + box.h}; - const CBox bb = {ob.x - bord, ob.y - bord, ob.w + bord, ob.h + bord}; - const Vector2D end = {pos.x + size.x, pos.y + size.y}; + const CBox SURFBB = other->getWindowMainSurfaceBox().expand(BORDERSIZE); + const Vector2D end = sourceBox.pos() + sourceBox.size(); // only snap windows if their ranges intersect in the opposite axis - if (pos.y <= bb.h && bb.y <= end.y) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, bb.w, gap)) { - snapLeft(pos.x, size.x, bb.w); + if (sourceBox.y <= SURFBB.y + SURFBB.h && SURFBB.y <= end.y) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x + SURFBB.w, GAPSIZE)) { + snapLeft(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, bb.x, gap)) { - snapRight(pos.x, size.x, bb.x); + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x, GAPSIZE)) { + snapRight(sourceBox.x, sourceBox.w, SURFBB.x); snaps |= SNAP_RIGHT; } } - if (pos.x <= bb.w && bb.x <= end.x) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, bb.h, gap)) { - snapUp(pos.y, size.y, bb.h); + if (sourceBox.x <= SURFBB.x + SURFBB.w && SURFBB.x <= end.x) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y + SURFBB.h, GAPSIZE)) { + snapUp(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, bb.y, gap)) { - snapDown(pos.y, size.y, bb.y); + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y, GAPSIZE)) { + snapDown(sourceBox.y, sourceBox.h, SURFBB.y); snaps |= SNAP_DOWN; } } // corner snapping - if (pos.x == bb.w || bb.x == pos.x + size.x) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, ob.y, gap)) { - snapUp(pos.y, size.y, ob.y); + if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) { + snapUp(sourceBox.y, sourceBox.w, SURFBB.y); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, ob.h, gap)) { - snapDown(pos.y, size.y, ob.h); + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) { + snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); snaps |= SNAP_DOWN; } } - if (pos.y == bb.h || bb.y == pos.y + size.y) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, ob.x, gap)) { - snapLeft(pos.x, size.x, ob.x); + if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.w) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) { + snapLeft(sourceBox.x, sourceBox.w, SURFBB.x); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, ob.w, gap)) { - snapRight(pos.x, size.x, ob.w); + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x + SURFBB.w, GAPSIZE)) { + snapRight(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); snaps |= SNAP_RIGHT; } } @@ -485,24 +485,26 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, } if (*SNAPMONITORGAP) { - const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - const CBox mon = {MON->vecPosition.x, MON->vecPosition.y, MON->vecPosition.x + MON->vecSize.x, MON->vecPosition.y + MON->vecSize.y}; + const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); + const CBox mon = + CBox{MON->vecPosition.x + MON->vecReservedTopLeft.x, MON->vecPosition.y + MON->vecReservedTopLeft.y, + MON->vecSize.x - MON->vecReservedTopLeft.x - MON->vecReservedBottomRight.x, MON->vecSize.y - MON->vecReservedBottomRight.y - MON->vecReservedTopLeft.y}; const double gap = *SNAPMONITORGAP; - if (canSnap(pos.x, mon.x, gap)) { - snapLeft(pos.x, size.x, mon.x); + if (canSnap(sourceBox.x, mon.x, gap)) { + snapLeft(sourceBox.x, sourceBox.w, mon.x); snaps |= SNAP_LEFT; } - if (canSnap(pos.x + size.x, mon.w, gap)) { - snapRight(pos.x, size.x, mon.w); + if (canSnap(sourceBox.x + sourceBox.w, mon.x + mon.w, gap)) { + snapRight(sourceBox.x, sourceBox.w, mon.w + mon.x); snaps |= SNAP_RIGHT; } - if (canSnap(pos.y, mon.y, gap)) { - snapUp(pos.y, size.y, mon.y); + if (canSnap(sourceBox.y, mon.y, gap)) { + snapUp(sourceBox.y, sourceBox.h, mon.y); snaps |= SNAP_UP; } - if (canSnap(pos.y + size.y, mon.h, gap)) { - snapDown(pos.y, size.y, mon.h); + if (canSnap(sourceBox.y + sourceBox.h, mon.y + mon.h, gap)) { + snapDown(sourceBox.y, sourceBox.h, mon.h + mon.y); snaps |= SNAP_DOWN; } } @@ -511,17 +513,21 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const double RATIO = beginSize.y / beginSize.x; if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { - const double sizeY = size.x * RATIO; + const double sizeY = sourceBox.h * RATIO; if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) - pos.y += size.y - sizeY; - size.y = sizeY; + sourceBox.y += sourceBox.h - sizeY; + sourceBox.h = sizeY; } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { - const double sizeX = size.y / RATIO; + const double sizeX = sourceBox.h / RATIO; if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) - pos.x += size.x - sizeX; - size.x = sizeX; + sourceBox.x += sourceBox.w - sizeX; + sourceBox.w = sizeX; } } + + sourceBox.expand(-DRAGGINGBORDERSIZE).round(); + sourcePos = sourceBox.pos(); + sourceSize = sourceBox.size(); } void IHyprLayout::onMouseMove(const Vector2D& mousePos) { From 6cf193e1662f6f750e964a3e174ae017246b4d48 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 27 Oct 2024 23:41:22 +0000 Subject: [PATCH 0189/1803] layout: don't snap to self and allow same-pid snaps fixes #8255 --- src/layout/IHyprLayout.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 30b5632c..bd81500d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -429,11 +429,10 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE); if (*SNAPWINDOWGAP) { - const auto PID = DRAGGINGWINDOW->getPID(); const auto WSID = DRAGGINGWINDOW->workspaceID(); for (auto& other : g_pCompositor->m_vWindows) { - if (other->workspaceID() != WSID || other->getPID() == PID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) + if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) continue; const int BORDERSIZE = other->getRealBorderSize(); From 2c481202effe707451608e272b5a801f8c970052 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Mon, 28 Oct 2024 09:39:05 -0400 Subject: [PATCH 0190/1803] layout: slight adjustments to snapping logic (#8273) fixes some bugs with resizing and corner snapping --- src/layout/IHyprLayout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index bd81500d..e3606532 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -464,14 +464,14 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA // corner snapping if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) { if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) { - snapUp(sourceBox.y, sourceBox.w, SURFBB.y); + snapUp(sourceBox.y, sourceBox.h, SURFBB.y); snaps |= SNAP_UP; } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) { snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); snaps |= SNAP_DOWN; } } - if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.w) { + if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.h) { if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) { snapLeft(sourceBox.x, sourceBox.w, SURFBB.x); snaps |= SNAP_LEFT; @@ -512,7 +512,7 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA const double RATIO = beginSize.y / beginSize.x; if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { - const double sizeY = sourceBox.h * RATIO; + const double sizeY = sourceBox.w * RATIO; if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) sourceBox.y += sourceBox.h - sizeY; sourceBox.h = sizeY; From d49a1334a8af7c704626cdf1746cb72415ad6d0d Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 28 Oct 2024 16:52:14 +0000 Subject: [PATCH 0191/1803] swallow: check if swallow_regex doesn't exist (#8265) Avoid to run CWindow::getSwallower() when `swallow_regex` doesn't exist in the user's config file. --- src/desktop/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e4f987eb..60f3b79d 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1535,7 +1535,7 @@ PHLWINDOW CWindow::getSwallower() { static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); static auto PSWALLOW = CConfigValue("misc:enable_swallow"); - if (!*PSWALLOW || (*PSWALLOWREGEX).empty()) + if (!*PSWALLOW || std::string{*PSWALLOWREGEX} == STRVAL_EMPTY || (*PSWALLOWREGEX).empty()) return nullptr; // check parent From c7315617eb6186912d03232e1968f32b88f153f2 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 28 Oct 2024 19:02:52 +0100 Subject: [PATCH 0192/1803] internal: few more marginal optimisations from profiling (#8271) * deco: reduce local temporars and function calls profiling shows this is a high used function, reduce the amount of function calls and local temporar copies and also check if we even need to add extents at all in the loop. * popup: optimize bfhelper in popups pass nodes as const reference and reserve the size of the children node vector help reduce the reallocations. * procotol: make compositor bfhelper use const ref use const ref for nodes and reserve second nodes vector size to reduce amount of reallocation needed. --- src/desktop/Popup.cpp | 3 +- src/desktop/Popup.hpp | 2 +- src/protocols/core/Compositor.cpp | 3 +- src/protocols/core/Compositor.hpp | 2 +- .../decorations/DecorationPositioner.cpp | 39 +++++++++++-------- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 9e254fa6..58995f00 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -288,12 +288,13 @@ bool CPopup::visible() { return false; } -void CPopup::bfHelper(std::vector nodes, std::function fn, void* data) { +void CPopup::bfHelper(std::vector const& nodes, std::function fn, void* data) { for (auto const& n : nodes) { fn(n, data); } std::vector nodes2; + nodes2.reserve(nodes.size() * 2); for (auto const& n : nodes) { for (auto const& c : n->m_vChildren) { diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 04996612..f34b8a2c 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -81,5 +81,5 @@ class CPopup { Vector2D localToGlobal(const Vector2D& rel); Vector2D t1ParentCoords(); - static void bfHelper(std::vector nodes, std::function fn, void* data); + static void bfHelper(std::vector const& nodes, std::function fn, void* data); }; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 9a2e00a9..d78d3d8b 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -252,9 +252,10 @@ void CWLSurfaceResource::resetRole() { role = makeShared(); } -void CWLSurfaceResource::bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data) { +void CWLSurfaceResource::bfHelper(std::vector> const& nodes, std::function, const Vector2D&, void*)> fn, void* data) { std::vector> nodes2; + nodes2.reserve(nodes.size() * 2); // first, gather all nodes below for (auto const& n : nodes) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index fbffd966..e5bdf082 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -147,7 +147,7 @@ class CWLSurfaceResource { void dropPendingBuffer(); void dropCurrentBuffer(); void commitPendingState(); - void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); + void bfHelper(std::vector> const& nodes, std::function, const Vector2D&, void*)> fn, void* data); void updateCursorShm(); friend class CWLPointerResource; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 3eb45546..995283c6 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -294,13 +294,11 @@ SBoxExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow } SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { - CBox accum = pWindow->getWindowMainSurfaceBox(); + CBox const mainSurfaceBox = pWindow->getWindowMainSurfaceBox(); + CBox accum = mainSurfaceBox; for (auto const& data : m_vWindowPositioningDatas) { - if (!data->pDecoration) - continue; - - if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly) + if (!data->pDecoration || (inputOnly && !(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))) continue; auto const window = data->pWindow.lock(); @@ -308,31 +306,40 @@ SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, continue; CBox decoBox; - if (data->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { - decoBox = data->pWindow->getWindowMainSurfaceBox(); + decoBox = mainSurfaceBox; decoBox.addExtents(data->positioningInfo.desiredExtents); } else { - decoBox = data->lastReply.assignedGeometry; - const auto EDGEPOINT = getEdgeDefinedPoint(data->positioningInfo.edges, pWindow); - decoBox.translate(EDGEPOINT); + decoBox = data->lastReply.assignedGeometry; + decoBox.translate(getEdgeDefinedPoint(data->positioningInfo.edges, pWindow)); } + // Check bounds only if decoBox extends beyond accum SBoxExtents extentsToAdd; + bool needUpdate = false; - if (decoBox.x < accum.x) + if (decoBox.x < accum.x) { extentsToAdd.topLeft.x = accum.x - decoBox.x; - if (decoBox.y < accum.y) + needUpdate = true; + } + if (decoBox.y < accum.y) { extentsToAdd.topLeft.y = accum.y - decoBox.y; - if (decoBox.x + decoBox.w > accum.x + accum.w) + needUpdate = true; + } + if (decoBox.x + decoBox.w > accum.x + accum.w) { extentsToAdd.bottomRight.x = (decoBox.x + decoBox.w) - (accum.x + accum.w); - if (decoBox.y + decoBox.h > accum.y + accum.h) + needUpdate = true; + } + if (decoBox.y + decoBox.h > accum.y + accum.h) { extentsToAdd.bottomRight.y = (decoBox.y + decoBox.h) - (accum.y + accum.h); + needUpdate = true; + } - accum.addExtents(extentsToAdd); + if (needUpdate) + accum.addExtents(extentsToAdd); } - return accum.extentsFrom(pWindow->getWindowMainSurfaceBox()); + return accum.extentsFrom(mainSurfaceBox); } CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { From 7188ee4f992966c5793efebd6dc70ab377820066 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:18:58 +0000 Subject: [PATCH 0193/1803] hyprctl: move setprop into dispatchers (#8275) * move setprop into dispatchers modified: src/debug/HyprCtl.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp * add deprecated modified: src/debug/HyprCtl.cpp --- src/debug/HyprCtl.cpp | 97 +-------------------------------- src/managers/KeybindManager.cpp | 95 ++++++++++++++++++++++++++++++++ src/managers/KeybindManager.hpp | 1 + 3 files changed, 98 insertions(+), 95 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index bf3ecfc8..93e0f620 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1262,101 +1262,8 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { } std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { - CVarList vars(request, 0, ' '); - - if (vars.size() < 4) - return "not enough args"; - - const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); - - if (!PWINDOW) - return "window not found"; - - const auto PROP = vars[2]; - const auto VAL = vars[3]; - - bool noFocus = PWINDOW->m_sWindowData.noFocus.valueOrDefault(); - - try { - if (PROP == "animationstyle") { - PWINDOW->m_sWindowData.animationStyle = CWindowOverridableVar(VAL, PRIORITY_SET_PROP); - } else if (PROP == "maxsize") { - PWINDOW->m_sWindowData.maxSize = CWindowOverridableVar(configStringToVector2D(VAL + " " + vars[4]), PRIORITY_SET_PROP); - PWINDOW->m_vRealSize = Vector2D(std::min((double)PWINDOW->m_sWindowData.maxSize.value().x, PWINDOW->m_vRealSize.goal().x), - std::min((double)PWINDOW->m_sWindowData.maxSize.value().y, PWINDOW->m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - PWINDOW->setHidden(false); - } else if (PROP == "minsize") { - PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL + " " + vars[4]), PRIORITY_SET_PROP); - PWINDOW->m_vRealSize = Vector2D(std::max((double)PWINDOW->m_sWindowData.minSize.value().x, PWINDOW->m_vRealSize.goal().x), - std::max((double)PWINDOW->m_sWindowData.minSize.value().y, PWINDOW->m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - PWINDOW->setHidden(false); - } else if (PROP == "alpha") { - PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); - } else if (PROP == "alphainactive") { - PWINDOW->m_sWindowData.alphaInactive = - CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); - } else if (PROP == "alphafullscreen") { - PWINDOW->m_sWindowData.alphaFullscreen = - CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); - } else if (PROP == "alphaoverride") { - PWINDOW->m_sWindowData.alpha = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); - } else if (PROP == "alphainactiveoverride") { - PWINDOW->m_sWindowData.alphaInactive = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); - } else if (PROP == "alphafullscreenoverride") { - PWINDOW->m_sWindowData.alphaFullscreen = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); - } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { - CGradientValueData colorData = {}; - if (vars.size() > 4) { - for (int i = 3; i < static_cast(vars.size()); ++i) { - const auto TOKEN = vars[i]; - if (TOKEN.ends_with("deg")) - colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else - colorData.m_vColors.push_back(configStringToInt(TOKEN)); - } - } else if (VAL != "-1") - colorData.m_vColors.push_back(configStringToInt(VAL)); - - if (PROP == "activebordercolor") - PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); - else - PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); - } else if (auto search = g_pConfigManager->mbWindowProperties.find(PROP); search != g_pConfigManager->mbWindowProperties.end()) { - auto pWindowDataElement = search->second(PWINDOW); - if (VAL == "toggle") - *pWindowDataElement = CWindowOverridableVar(!pWindowDataElement->valueOrDefault(), PRIORITY_SET_PROP); - else if (VAL == "unset") - pWindowDataElement->unset(PRIORITY_SET_PROP); - else - *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); - } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { - if (VAL == "unset") - search->second(PWINDOW)->unset(PRIORITY_SET_PROP); - else - *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); - } else { - return "prop not found"; - } - } catch (std::exception& e) { return "error in parsing prop value: " + std::string(e.what()); } - - g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - - if (!(PWINDOW->m_sWindowData.noFocus.valueOrDefault() == noFocus)) { - g_pCompositor->focusWindow(nullptr); - g_pCompositor->focusWindow(PWINDOW); - g_pCompositor->focusWindow(PLASTWINDOW); - } - - for (auto const& m : g_pCompositor->m_vMonitors) - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); - - return "ok"; + auto result = g_pKeybindManager->m_mDispatchers["setprop"](request.substr(request.find_first_of(' ') + 1, -1)); + return "DEPRECATED: use hyprctl dispatch setprop instead" + (result.success ? "" : "\n" + result.error); } std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index b54b71ed..c2779c58 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -126,6 +126,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup; m_mDispatchers["event"] = event; m_mDispatchers["global"] = global; + m_mDispatchers["setprop"] = setProp; m_tScrollTimer.reset(); @@ -2891,3 +2892,97 @@ SDispatchResult CKeybindManager::event(std::string args) { g_pEventManager->postEvent(SHyprIPCEvent{"custom", args}); return {}; } + +SDispatchResult CKeybindManager::setProp(std::string args) { + CVarList vars(args, 3, ' '); + + if (vars.size() < 3) + return {.success = false, .error = "Not enough args"}; + + const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); + const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[0]); + + if (!PWINDOW) + return {.success = false, .error = "Window not found"}; + + const auto PROP = vars[1]; + const auto VAL = vars[2]; + + bool noFocus = PWINDOW->m_sWindowData.noFocus.valueOrDefault(); + + try { + if (PROP == "animationstyle") { + PWINDOW->m_sWindowData.animationStyle = CWindowOverridableVar(VAL, PRIORITY_SET_PROP); + } else if (PROP == "maxsize") { + PWINDOW->m_sWindowData.maxSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP); + PWINDOW->clampWindowSize(std::nullopt, PWINDOW->m_sWindowData.maxSize.value()); + PWINDOW->setHidden(false); + } else if (PROP == "minsize") { + PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP); + PWINDOW->clampWindowSize(PWINDOW->m_sWindowData.minSize.value(), std::nullopt); + PWINDOW->setHidden(false); + } else if (PROP == "alpha") { + PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphainactive") { + PWINDOW->m_sWindowData.alphaInactive = + CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphafullscreen") { + PWINDOW->m_sWindowData.alphaFullscreen = + CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphaoverride") { + PWINDOW->m_sWindowData.alpha = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "alphainactiveoverride") { + PWINDOW->m_sWindowData.alphaInactive = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "alphafullscreenoverride") { + PWINDOW->m_sWindowData.alphaFullscreen = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { + CGradientValueData colorData = {}; + if (vars.size() > 4) { + for (int i = 3; i < static_cast(vars.size()); ++i) { + const auto TOKEN = vars[i]; + if (TOKEN.ends_with("deg")) + colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); + else + colorData.m_vColors.push_back(configStringToInt(TOKEN)); + } + } else if (VAL != "-1") + colorData.m_vColors.push_back(configStringToInt(VAL)); + + if (PROP == "activebordercolor") + PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); + else + PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); + } else if (auto search = g_pConfigManager->mbWindowProperties.find(PROP); search != g_pConfigManager->mbWindowProperties.end()) { + auto pWindowDataElement = search->second(PWINDOW); + if (VAL == "toggle") + *pWindowDataElement = CWindowOverridableVar(!pWindowDataElement->valueOrDefault(), PRIORITY_SET_PROP); + else if (VAL == "unset") + pWindowDataElement->unset(PRIORITY_SET_PROP); + else + *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); + } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { + if (VAL == "unset") + search->second(PWINDOW)->unset(PRIORITY_SET_PROP); + else + *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); + } else { + return {.success = false, .error = "Prop not found"}; + } + } catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; } + + g_pCompositor->updateAllWindowsAnimatedDecorationValues(); + + if (!(PWINDOW->m_sWindowData.noFocus.valueOrDefault() == noFocus)) { + g_pCompositor->focusWindow(nullptr); + g_pCompositor->focusWindow(PWINDOW); + g_pCompositor->focusWindow(PLASTWINDOW); + } + + for (auto const& m : g_pCompositor->m_vMonitors) + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); + + return {}; +} diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 8981dcaf..24a09836 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -217,6 +217,7 @@ class CKeybindManager { static SDispatchResult denyWindowFromGroup(std::string); static SDispatchResult global(std::string); static SDispatchResult event(std::string); + static SDispatchResult setProp(std::string); friend class CCompositor; friend class CInputManager; From d679d200299ed4670f0d0f138c793d5f507b7cec Mon Sep 17 00:00:00 2001 From: staticssleever668 Date: Mon, 28 Oct 2024 22:25:27 +0300 Subject: [PATCH 0194/1803] seat: avoid sending pointless 'keymap' and 'repeat_info' events (#8276) #### Describe your PR, what does it fix/add? Fix lag spikes when pressing more than 6 keys at the same time. #### Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.) Debugging process:
This is triggered by typing some applications, like CopyQ or XWayland. Typing in Firefox doesn't lead to lag, however it itself does lag handling these events. Profiling CopyQ shows that paths leading to `QtWaylandClient::QWaylandInputDevice::Keyboard::keyboard` take over 80% of processing time of an otherwise idle program. Looking at output of 'wev' even when it's not focused shows same events received over and over again. ``` [14: wl_keyboard] repeat_info: rate: 25 keys/sec; delay: 300 ms [14: wl_keyboard] keymap: format: 1 (xkb v1), size: 64754 ``` Looking at what passes through CInputManager::onKeyboardKey() -> CSeatManager::setKeyboard() shows Hyprland 'switching' between endpoints of the same keyboard, one of them being named like the other but with '-1' suffix.
Tested changing layouts in Fcitx5 and with following config. ``` input:kb_layout = us,cz input:kb_variant = ,qwerty input:kb_options = grp:alt_shift_toggle ``` Also tested changing 'input:repeat_delay' while running. Curiously, now these events appear in the output of 'wev' only once. Changing layouts still seems to work fine though. #### Is it ready for merging, or does it need work? Ready for merging. --- src/protocols/core/Seat.cpp | 24 ++++++++++++++++++------ src/protocols/core/Seat.hpp | 4 ++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 6ae0ddc4..d95e0e12 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -317,12 +317,13 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) return; - wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; - int fd; - uint32_t size; + std::string_view keymap; + int fd; + uint32_t size; if (keyboard) { - fd = keyboard->xkbKeymapFD; - size = keyboard->xkbKeymapString.length() + 1; + keymap = keyboard->xkbKeymapString; + fd = keyboard->xkbKeymapFD; + size = keyboard->xkbKeymapString.length() + 1; } else { fd = open("/dev/null", O_RDONLY | O_CLOEXEC); if (fd < 0) { @@ -332,6 +333,15 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { size = 0; } + if (keymap == lastKeymap) { + if (!keyboard) + close(fd); + return; + } + lastKeymap = keymap; + + const wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; + resource->sendKeymap(format, fd, size); if (!keyboard) @@ -396,8 +406,10 @@ void CWLKeyboardResource::sendMods(uint32_t depressed, uint32_t latched, uint32_ } void CWLKeyboardResource::repeatInfo(uint32_t rate, uint32_t delayMs) { - if (!owner || resource->version() < 4) + if (!owner || resource->version() < 4 || (rate == lastRate && delayMs == lastDelayMs)) return; + lastRate = rate; + lastDelayMs = delayMs; resource->sendRepeatInfo(rate, delayMs); } diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 755a9c2f..1b43dd04 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -119,6 +119,10 @@ class CWLKeyboardResource { struct { CHyprSignalListener destroySurface; } listeners; + + std::string lastKeymap = ""; + uint32_t lastRate = 0; + uint32_t lastDelayMs = 0; }; class CWLSeatResource { From 5f721dce36651232ae245d872c17dfa3aae5cc6c Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 30 Oct 2024 10:00:58 +0000 Subject: [PATCH 0195/1803] group: fix moveWindowIntoGroup (#8297) --- src/layout/IHyprLayout.cpp | 19 ++++++++----------- src/managers/KeybindManager.cpp | 3 +-- .../decorations/CHyprGroupBarDecoration.cpp | 6 +++--- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index e3606532..f2616668 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -341,7 +341,9 @@ void IHyprLayout::onEndDragWindow() { const bool FLOATEDINTOTILED = !pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled; static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !FLOATEDINTOTILED) { + if (DRAGGINGWINDOW->m_bDraggingTiled) { changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; @@ -349,17 +351,12 @@ void IHyprLayout::onEndDragWindow() { } if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { - std::vector members; - PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); - do { - members.push_back(curr); - curr = curr->m_sGroupData.pNextWindow.lock(); - } while (curr != members[0]); - - for (auto it = members.begin(); it != members.end(); ++it) { - (*it)->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members - if (pWindow->m_bIsFloating) - (*it)->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); + while (next != DRAGGINGWINDOW) { + next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members + next->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + next->m_vRealPosition = pWindow->m_vRealPosition.goal(); // match the position of group members + next = next->m_sGroupData.pNextWindow.lock(); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c2779c58..5be6a1d9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2665,9 +2665,8 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn } static auto USECURRPOS = CConfigValue("group:insert_after_current"); - pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail(); + (*USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail())->insertWindowToGroup(pWindow); - pWindowInDirection->insertWindowToGroup(pWindow); pWindowInDirection->setGroupCurrent(pWindow); pWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index e342e244..c9f812d7 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -439,9 +439,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND // restores the group for (auto it = members.begin(); it != members.end(); ++it) { - (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members - if (pWindowInsertAfter->m_bIsFloating) - (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members + (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members + (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members + (*it)->m_vRealPosition = pWindowInsertAfter->m_vRealPosition.goal(); // match the position of group members if (std::next(it) != members.end()) (*it)->m_sGroupData.pNextWindow = *std::next(it); else From 12c1bb936dd463c4188def1c73c2bb786433a6dc Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:58:36 +0000 Subject: [PATCH 0196/1803] internal: check size limit in layouts (#8298) modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/helpers/MiscFunctions.cpp modified: src/helpers/MiscFunctions.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/IHyprLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/macros.hpp --- src/desktop/Window.cpp | 2 +- src/desktop/Window.hpp | 7 +++++++ src/events/Windows.cpp | 32 +++++++++++--------------------- src/helpers/MiscFunctions.cpp | 7 +++++++ src/helpers/MiscFunctions.hpp | 1 + src/layout/DwindleLayout.cpp | 4 +++- src/layout/IHyprLayout.cpp | 19 +++++++++---------- src/layout/MasterLayout.cpp | 4 +++- src/macros.hpp | 2 ++ 9 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 60f3b79d..20fed565 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1255,7 +1255,7 @@ int CWindow::surfacesCount() { void CWindow::clampWindowSize(const std::optional minSize, const std::optional maxSize) { const Vector2D REALSIZE = m_vRealSize.goal(); - const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{0.f, 0.f}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); + const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); const Vector2D DELTA = REALSIZE - NEWSIZE; m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 825e8ca2..b8dd3cf7 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -144,6 +144,13 @@ class CWindowOverridableVar { unset(priority); } + operator std::optional() { + if (hasValue()) + return value(); + else + return std::nullopt; + } + private: std::map values; T defaultValue; // used for toggling, so required for bool diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 30d982fb..f946ce03 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -334,13 +334,6 @@ void Events::listener_mapWindow(void* owner, void* data) { try { auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) { - auto stringToPercentage = [](const std::string& VALUE, const float REL) { - if (VALUE.ends_with('%')) - return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100; - else - return std::stof(VALUE); - }; - if (VALUE.starts_with('<')) return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL)); else if (VALUE.starts_with('>')) @@ -355,11 +348,11 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); - const float SIZEX = - SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); + const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : + stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); - const float SIZEY = - SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); + const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : + stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size, applying to {}", PWINDOW); @@ -472,18 +465,15 @@ void Events::listener_mapWindow(void* owner, void* data) { for (auto const& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("size")) { 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 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 MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); - const auto SIZEX = SIZEXSTR == "max" ? - std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : - (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x); - const auto SIZEY = SIZEYSTR == "max" ? - std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : - (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y); + const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToPercentage(SIZEXSTR, PMONITOR->vecSize.x); + + const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : stringToPercentage(SIZEYSTR, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 29861af7..878f5ca1 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -863,3 +863,10 @@ bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) { *ro_fd_ptr = ro_fd; return true; } + +float stringToPercentage(const std::string& VALUE, const float REL) { + if (VALUE.ends_with('%')) + return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100.f; + else + return std::stof(VALUE); +}; diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index f696fc5d..34b23746 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -40,6 +40,7 @@ void throwError(const std::string& err); bool envEnabled(const std::string& env); int allocateSHMFile(size_t len); bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 059dda99..32f64e4e 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -568,7 +568,9 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - 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->m_vRealSize = + (PWINDOW->m_vRealSize.goal() + pixResize) + .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f2616668..73e7a125 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -881,18 +881,17 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { if (r.szRule.starts_with("size")) { 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 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 MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); - const auto SIZEX = SIZEXSTR == "max" ? - std::clamp(MAXSIZE.x, 20.0, g_pCompositor->m_pLastMonitor->vecSize.x) : - (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * g_pCompositor->m_pLastMonitor->vecSize.x); - const auto SIZEY = SIZEYSTR == "max" ? - std::clamp(MAXSIZE.y, 20.0, g_pCompositor->m_pLastMonitor->vecSize.y) : - (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * g_pCompositor->m_pLastMonitor->vecSize.y); + const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.x) : + stringToPercentage(SIZEXSTR, g_pCompositor->m_pLastMonitor->vecSize.x); + + const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.y) : + stringToPercentage(SIZEYSTR, g_pCompositor->m_pLastMonitor->vecSize.y); sizeOverride = {SIZEX, SIZEY}; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index a2321a41..afe79ecf 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -706,7 +706,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - 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->m_vRealSize = + (PWINDOW->m_vRealSize.goal() + pixResize) + .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; } diff --git a/src/macros.hpp b/src/macros.hpp index 44014085..8915e12d 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -29,6 +29,8 @@ #define MONITOR_INVALID -1L +#define MIN_WINDOW_SIZE 20.0 + #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ inline wl_listener listen_##name = {.notify = listener_##name} From ee91df62f0be6ac65eae0eb3ed74383a3671aef7 Mon Sep 17 00:00:00 2001 From: nickodei <46863421+nickodei@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:12:16 +0100 Subject: [PATCH 0197/1803] input: simulate mouse movement after scroll to refocus window (#8279) --- src/managers/input/InputManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 028286bf..91c12ece 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -831,6 +831,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete); g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); + simulateMouseMovement(); } Vector2D CInputManager::getMouseCoordsInternal() { From a0b2169ed600b71627188dcd208b26911da8d583 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 30 Oct 2024 22:14:43 +0000 Subject: [PATCH 0198/1803] input: revert #8279 --- src/managers/input/InputManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 91c12ece..028286bf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -831,7 +831,6 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete); g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); - simulateMouseMovement(); } Vector2D CInputManager::getMouseCoordsInternal() { From 7c7a84ff60f8c1e00c6a0de3f7656f0bbd933d56 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 31 Oct 2024 00:20:32 +0100 Subject: [PATCH 0199/1803] internal: more profiling less calls and local copies (#8300) * compositor: reduce amount of window box copies mousemoveunified can call this very frequently, the cbox copying actually shows up as an impact in such cases, move it down in the scope and only do it when necessery. * core: constify and reference frequent calls profiling shows these as frequent called functions try to reduce the amount of copies with references and const the variables. * pointermgr: remove not used local copy, const ref remove unneded local copies and const ref cursorsize. * inputmgr: reduce amount of calls to vectortowindow the amount of calls to g_pCompositor->vectorToWindowUnified fast ramps up in cpu usage with enough windows existing and moving the mouse, move the PWINDOWIDEAL up and reuse it if its already the same. * protocol: compositor remove unused local copy remove unused local copy of accumulateCurrentBufferDamage and const previousBuffer. * renderer: reduce scope of variables and refactor move a few variables down in their scopes to reduce the amount of calls and copies when not needed, also add one more for loop in renderWorkspaceWindows and store the windows in a vector with weakpointers that should be rendered, this adds a loop but reduces the amount of repeated calls to shouldRenderWindow and also makes the rest of the loops go over way smaller vector when many windows exist. --- src/Compositor.cpp | 29 ++++++---- src/managers/PointerManager.cpp | 19 +++---- src/managers/eventLoop/EventLoopManager.cpp | 2 +- src/managers/input/InputManager.cpp | 14 +++-- src/protocols/core/Compositor.cpp | 6 +- src/render/Renderer.cpp | 55 ++++++++++--------- .../decorations/CHyprBorderDecoration.cpp | 2 +- .../decorations/CHyprBorderDecoration.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 2 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.hpp | 2 +- .../decorations/IHyprWindowDecoration.hpp | 2 +- 13 files changed, 71 insertions(+), 68 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a2fe9935..65891633 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -811,10 +811,10 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper // pinned windows on top of floating regardless if (properties & ALLOW_FLOATING) { for (auto const& w : m_vWindows | std::views::reverse) { - const auto BB = w->getWindowBoxUnified(properties); - CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { + const auto BB = w->getWindowBoxUnified(properties); + CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (box.containsPoint(g_pPointerManager->position())) return w; @@ -833,22 +833,25 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular continue; - const auto BB = w->getWindowBoxUnified(properties); const auto PWINDOWMONITOR = w->m_pMonitor.lock(); // to avoid focusing windows behind special workspaces from other monitors - if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace && - 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; + if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace) { + const auto BB = w->getWindowBoxUnified(properties); + if (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.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect()) continue; + const auto BB = w->getWindowBoxUnified(properties); + CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (box.containsPoint(g_pPointerManager->position())) { if (w->m_bIsX11 && w->isX11OverrideRedirect() && !w->m_pXWaylandSurface->wantsFocus()) { @@ -906,10 +909,12 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; - CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; - if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) - return w; + if (!w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && + w != pIgnoreWindow) { + CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; + if (box.containsPoint(pos)) + return w; + } } return nullptr; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index d2114e79..b309ba82 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -52,7 +52,7 @@ void CPointerManager::unlockSoftwareAll() { } void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) { - auto state = stateFor(mon); + auto const state = stateFor(mon); state->softwareLocks++; if (state->softwareLocks == 1) @@ -60,7 +60,7 @@ void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) { } void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { - auto state = stateFor(mon); + auto const state = stateFor(mon); state->softwareLocks--; if (state->softwareLocks < 0) state->softwareLocks = 0; @@ -70,7 +70,7 @@ void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { } bool CPointerManager::softwareLockedFor(PHLMONITOR mon) { - auto state = stateFor(mon); + auto const state = stateFor(mon); return state->softwareLocks > 0 || state->hardwareFailed; } @@ -250,14 +250,13 @@ void CPointerManager::updateCursorBackend() { const auto CURSORBOX = getCursorBoxGlobal(); for (auto const& m : g_pCompositor->m_vMonitors) { - auto state = stateFor(m); - if (!m->m_bEnabled || !m->dpmsStatus) { Debug::log(TRACE, "Not updating hw cursors: disabled / dpms off display"); continue; } auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty(); + auto state = stateFor(m); if (!CROSSES) { if (state->cursorFrontBuffer) @@ -373,10 +372,8 @@ bool CPointerManager::setHWCursorBuffer(SP state, SP CPointerManager::renderHWCursorBuffer(SP state, SP texture) { - auto output = state->monitor->output; - - auto maxSize = output->cursorPlaneSize(); - auto cursorSize = currentCursorImage.size; + auto maxSize = state->monitor->output->cursorPlaneSize(); + auto const& cursorSize = currentCursorImage.size; if (maxSize == Vector2D{}) return nullptr; @@ -423,8 +420,6 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor; @@ -483,7 +478,7 @@ SP CPointerManager::renderHWCursorBuffer(SPbind(); - g_pHyprOpenGL->beginSimple(state->monitor.lock(), damage, RBO); + g_pHyprOpenGL->beginSimple(state->monitor.lock(), {0, 0, INT16_MAX, INT16_MAX}, RBO); g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 081268c3..755ecbbc 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -98,7 +98,7 @@ void CEventLoopManager::nudgeTimers() { long nextTimerUs = 10 * 1000 * 1000; // 10s for (auto const& t : m_sTimers.timers) { - if (const auto µs = t->leftUs(); µs < nextTimerUs) + if (auto const& µs = t->leftUs(); µs < nextTimerUs) nextTimerUs = µs; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 028286bf..af725927 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -291,7 +291,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface); // then, we check if the workspace doesnt have a fullscreen window - const auto PWORKSPACE = PMONITOR->activeWorkspace; + const auto PWORKSPACE = PMONITOR->activeWorkspace; + const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN) { pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -301,8 +302,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { return; } - const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); - if (PWINDOWIDEAL && ((PWINDOWIDEAL->m_bIsFloating && PWINDOWIDEAL->m_bCreatedOverFullscreen) /* floating over fullscreen */ || (PMONITOR->activeSpecialWorkspace == PWINDOWIDEAL->m_pWorkspace) /* on an open special workspace */)) @@ -322,7 +321,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FSMODE_MAXIMIZED) { if (!foundSurface) { if (PMONITOR->activeSpecialWorkspace) { - pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); + if (pFoundWindow != PWINDOWIDEAL) + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (pFoundWindow && !pFoundWindow->onSpecialWorkspace()) { pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -335,7 +335,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } if (!foundSurface) { - pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); + if (pFoundWindow != PWINDOWIDEAL) + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen)) pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -344,7 +345,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } } else { - pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); + if (pFoundWindow != PWINDOWIDEAL) + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); } if (pFoundWindow) { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index d78d3d8b..57f61f87 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -423,10 +423,8 @@ void CWLSurfaceResource::unlockPendingState() { } void CWLSurfaceResource::commitPendingState() { - auto previousBuffer = current.buffer; - CRegion previousBufferDamage = accumulateCurrentBufferDamage(); - - current = pending; + auto const previousBuffer = current.buffer; + current = pending; pending.damage.clear(); pending.bufferDamage.clear(); pending.newBuffer = false; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1c38eb4e..1dedcc7d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -158,9 +158,7 @@ static void renderSurface(SP surface, int x, int y, void* da if (!surface->current.texture) return; - const auto& TEXTURE = surface->current.texture; - const auto RDATA = (SRenderData*)data; - const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; + const auto& TEXTURE = surface->current.texture; // this is bad, probably has been logged elsewhere. Means the texture failed // uploading to the GPU. @@ -175,6 +173,8 @@ static void renderSurface(SP surface, int x, int y, void* da } } + const auto RDATA = (SRenderData*)data; + const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y; @@ -484,36 +484,43 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); - // Non-floating main + std::vector windows; + windows.reserve(g_pCompositor->m_vWindows.size()); + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; - if (w->m_bIsFloating) - continue; // floating are in the second pass - if (!shouldRenderWindow(w, pMonitor)) continue; + windows.push_back(w); + } + + // Non-floating main + for (auto& w : windows) { + if (w->m_bIsFloating) + continue; // floating are in the second pass + if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; // render active window after all others of this pass if (w == g_pCompositor->m_pLastWindow) { - lastWindow = w; + lastWindow = w.lock(); continue; } // render the bad boy - renderWindow(w, pMonitor, time, true, RENDER_PASS_MAIN); + renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_MAIN); } if (lastWindow) renderWindow(lastWindow, pMonitor, time, true, RENDER_PASS_MAIN); // Non-floating popup - for (auto const& w : g_pCompositor->m_vWindows) { - if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) + for (auto& w : windows) { + if (!w) continue; if (w->m_bIsFloating) @@ -522,24 +529,19 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (!shouldRenderWindow(w, pMonitor)) - continue; - // render the bad boy - renderWindow(w, pMonitor, time, true, RENDER_PASS_POPUP); + renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_POPUP); + w.reset(); } // floating on top - for (auto const& w : g_pCompositor->m_vWindows) { - if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) + for (auto& w : windows) { + if (!w) continue; if (!w->m_bIsFloating || w->m_bPinned) continue; - if (!shouldRenderWindow(w, pMonitor)) - continue; - if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; @@ -547,7 +549,7 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo continue; // special on another are rendered as a part of the base pass // render the bad boy - renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL); + renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_ALL); } } @@ -1093,8 +1095,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPcurrent.viewport.hasSource) { // we stretch it to dest. if no dest, to 1,1 - Vector2D bufferSize = pSurface->current.bufferSize; - auto bufferSource = pSurface->current.viewport.source; + Vector2D const& bufferSize = pSurface->current.bufferSize; + auto const& bufferSource = pSurface->current.viewport.source; // calculate UV for the basic src_box. Assume dest == size. Scale to dest later uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y); @@ -1904,10 +1906,11 @@ void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) { if (m->isMirror()) continue; // don't damage mirrors traditionally - CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; - damageBox.scale(m->scale); - if (!skipFrameSchedule) + if (!skipFrameSchedule) { + CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; + damageBox.scale(m->scale); m->addDamage(&damageBox); + } } static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 68325a9c..d62e67c4 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -46,7 +46,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() { return box.translate(WORKSPACEOFFSET); } -void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float a) { +void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (doesntWantBorders()) return; diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 5d248a81..bc9d7836 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -11,7 +11,7 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(PHLMONITOR, float a); + virtual void draw(PHLMONITOR, float const& a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index a4388a67..79d5940b 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -86,7 +86,7 @@ void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) { m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); } -void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float a) { +void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { const auto PWINDOW = m_pWindow.lock(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index fce9a7c7..8335cde9 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -11,7 +11,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(PHLMONITOR, float a); + virtual void draw(PHLMONITOR, float const& a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index c9f812d7..ec9f876b 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -94,7 +94,7 @@ void CHyprGroupBarDecoration::damageEntire() { g_pHyprRenderer->damageBox(&box); } -void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float a) { +void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index e388fa38..338a8449 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -31,7 +31,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(PHLMONITOR, float a); + virtual void draw(PHLMONITOR, float const& a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 99698a56..d6d57902 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -39,7 +39,7 @@ class IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply) = 0; - virtual void draw(PHLMONITOR, float a) = 0; + virtual void draw(PHLMONITOR, float const& a) = 0; virtual eDecorationType getDecorationType() = 0; From 93b4478e70af6ffb08a4a66a6d0364c3296db296 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Thu, 31 Oct 2024 07:21:08 -0400 Subject: [PATCH 0200/1803] snap: add option `border_overlap` and other improvements (#8289) * snap: add option `border_overlap` and other improvements I really liked the way borders used to overlap when snapping and how only the window's main surface would snap to the monitor, so I would like to bring that behavior back, but in the form of a config option. Other improvements include: - reduced the number of snap functions from 4 down to 2, and only one ever gets called at any given time. - border size should not be added to gap size. It seemed like the right thing to do at the time, but it makes snapping feel way stronger than it actually should. - all const variables have been given the all-caps naming convention. - to avoid excessive casting, border size is declared as a double. - to avoid excessive x + w, y + h calculations. I'm using a struct called Range and working only with start and end values until the very end of the function. - check for both monitor snapping as well as reserved monitor space snapping in a relatively efficient way. * snap: always border-align for corners and reserved monitor space We probably don't want to treat reserved monitor space as if it were just a smaller monitor. Instead, it should be treated more like a borderless window, which means our window's border should never encroach upon it. --- src/config/ConfigDescriptions.hpp | 6 ++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 161 +++++++++++++++--------------- 3 files changed, 89 insertions(+), 79 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 0177f92b..07034e71 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -122,6 +122,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{10, 0, 100}, }, + SConfigOptionDescription{ + .value = "general:snap:border_overlap", + .description = "if true, windows snap such that only one border's worth of space is between them", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * decoration: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 909dfc63..f1ba8d7f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -344,6 +344,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("general:snap:enabled", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:snap:window_gap", Hyprlang::INT{10}); m_pConfig->addConfigValue("general:snap:monitor_gap", Hyprlang::INT{10}); + m_pConfig->addConfigValue("general:snap:border_overlap", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_hyprland_logo", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_splash_rendering", Hyprlang::INT{0}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 73e7a125..980311d6 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -389,91 +389,93 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->m_bWasDraggingWindow = false; } -static inline bool canSnap(const double sideA, const double sideB, const double gap) { - return std::abs(sideA - sideB) < gap; +static inline bool canSnap(const double SIDEA, const double SIDEB, const double GAP) { + return std::abs(SIDEA - SIDEB) < GAP; } -static void snapMoveLeft(double& pos, double& len, const double p) { - pos = p; +static void snapMove(double& start, double& end, const double P) { + end = P + (end - start); + start = P; } -static void snapMoveRight(double& pos, double& len, const double p) { - pos = p - len; -} - -static void snapResizeLeft(double& pos, double& len, const double p) { - len += pos - p; - pos = p; -} - -static void snapResizeRight(double& pos, double& len, const double p) { - len = p - pos; +static void snapResize(double& start, double& end, const double P) { + start = P; } typedef std::function SnapFn; -static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { - static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); - static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); +static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode MODE, const int CORNER, const Vector2D& BEGINSIZE) { + static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); + static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); + static auto SNAPBORDEROVERLAP = CConfigValue("general:snap:border_overlap"); - const SnapFn snapRight = (mode == MBIND_MOVE) ? snapMoveRight : snapResizeRight; - const SnapFn snapLeft = (mode == MBIND_MOVE) ? snapMoveLeft : snapResizeLeft; - const SnapFn snapDown = snapRight; - const SnapFn snapUp = snapLeft; - int snaps = 0; + const SnapFn SNAP = (MODE == MBIND_MOVE) ? snapMove : snapResize; + int snaps = 0; + const bool OVERLAP = *SNAPBORDEROVERLAP; const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW->getRealBorderSize(); - CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE); + + struct SRange { + double start = 0; + double end = 0; + }; + SRange sourceX = {sourcePos.x, sourcePos.x + sourceSize.x}; + SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y}; if (*SNAPWINDOWGAP) { - const auto WSID = DRAGGINGWINDOW->workspaceID(); + const double GAPSIZE = *SNAPWINDOWGAP; + const auto WSID = DRAGGINGWINDOW->workspaceID(); for (auto& other : g_pCompositor->m_vWindows) { if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) continue; - const int BORDERSIZE = other->getRealBorderSize(); - const double GAPSIZE = *SNAPWINDOWGAP + BORDERSIZE; + const int OTHERBORDERSIZE = other->getRealBorderSize(); + const double BORDERSIZE = OVERLAP ? std::max(DRAGGINGBORDERSIZE, OTHERBORDERSIZE) : (DRAGGINGBORDERSIZE + OTHERBORDERSIZE); - const CBox SURFBB = other->getWindowMainSurfaceBox().expand(BORDERSIZE); - const Vector2D end = sourceBox.pos() + sourceBox.size(); + const CBox SURF = other->getWindowMainSurfaceBox(); + const SRange SURFBX = {SURF.x - BORDERSIZE, SURF.x + SURF.w + BORDERSIZE}; + const SRange SURFBY = {SURF.y - BORDERSIZE, SURF.y + SURF.h + BORDERSIZE}; - // only snap windows if their ranges intersect in the opposite axis - if (sourceBox.y <= SURFBB.y + SURFBB.h && SURFBB.y <= end.y) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x + SURFBB.w, GAPSIZE)) { - snapLeft(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); + // only snap windows if their ranges overlap in the opposite axis + if (sourceY.start <= SURFBY.end && SURFBY.start <= sourceY.end) { + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFBX.end, GAPSIZE)) { + SNAP(sourceX.start, sourceX.end, SURFBX.end); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x, GAPSIZE)) { - snapRight(sourceBox.x, sourceBox.w, SURFBB.x); + } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFBX.start, GAPSIZE)) { + SNAP(sourceX.end, sourceX.start, SURFBX.start); snaps |= SNAP_RIGHT; } } - if (sourceBox.x <= SURFBB.x + SURFBB.w && SURFBB.x <= end.x) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y + SURFBB.h, GAPSIZE)) { - snapUp(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); + if (sourceX.start <= SURFBX.end && SURFBX.start <= sourceX.end) { + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFBY.end, GAPSIZE)) { + SNAP(sourceY.start, sourceY.end, SURFBY.end); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y, GAPSIZE)) { - snapDown(sourceBox.y, sourceBox.h, SURFBB.y); + } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFBY.start, GAPSIZE)) { + SNAP(sourceY.end, sourceY.start, SURFBY.start); snaps |= SNAP_DOWN; } } // corner snapping - if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) { - snapUp(sourceBox.y, sourceBox.h, SURFBB.y); + const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE; + if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) { + const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF}; + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) { + SNAP(sourceY.start, sourceY.end, SURFY.start); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) { - snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); + } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFY.end, GAPSIZE)) { + SNAP(sourceY.end, sourceY.start, SURFY.end); snaps |= SNAP_DOWN; } } - if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.h) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) { - snapLeft(sourceBox.x, sourceBox.w, SURFBB.x); + if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) { + const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF}; + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) { + SNAP(sourceX.start, sourceX.end, SURFX.start); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x + SURFBB.w, GAPSIZE)) { - snapRight(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); + } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFX.end, GAPSIZE)) { + SNAP(sourceX.end, sourceX.start, SURFX.end); snaps |= SNAP_RIGHT; } } @@ -481,49 +483,50 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA } if (*SNAPMONITORGAP) { - const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - const CBox mon = - CBox{MON->vecPosition.x + MON->vecReservedTopLeft.x, MON->vecPosition.y + MON->vecReservedTopLeft.y, - MON->vecSize.x - MON->vecReservedTopLeft.x - MON->vecReservedBottomRight.x, MON->vecSize.y - MON->vecReservedBottomRight.y - MON->vecReservedTopLeft.y}; - const double gap = *SNAPMONITORGAP; + const double GAPSIZE = *SNAPMONITORGAP; + const double BORDERSIZE = OVERLAP ? 0 : DRAGGINGBORDERSIZE; + const double BORDERDIFF = DRAGGINGBORDERSIZE - BORDERSIZE; + const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - if (canSnap(sourceBox.x, mon.x, gap)) { - snapLeft(sourceBox.x, sourceBox.w, mon.x); + SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecSize.x - BORDERSIZE}; + SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecSize.y - BORDERSIZE}; + + if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) { + SNAP(sourceX.start, sourceX.end, monX.start); snaps |= SNAP_LEFT; } - if (canSnap(sourceBox.x + sourceBox.w, mon.x + mon.w, gap)) { - snapRight(sourceBox.x, sourceBox.w, mon.w + mon.x); + if (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE)) { + SNAP(sourceX.end, sourceX.start, monX.end); snaps |= SNAP_RIGHT; } - if (canSnap(sourceBox.y, mon.y, gap)) { - snapUp(sourceBox.y, sourceBox.h, mon.y); + if (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE)) { + SNAP(sourceY.start, sourceY.end, monY.start); snaps |= SNAP_UP; } - if (canSnap(sourceBox.y + sourceBox.h, mon.y + mon.h, gap)) { - snapDown(sourceBox.y, sourceBox.h, mon.h + mon.y); + if (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE)) { + SNAP(sourceY.end, sourceY.start, monY.end); snaps |= SNAP_DOWN; } } - if (mode == MBIND_RESIZE_FORCE_RATIO) { - const double RATIO = beginSize.y / beginSize.x; - - if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { - const double sizeY = sourceBox.w * RATIO; - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) - sourceBox.y += sourceBox.h - sizeY; - sourceBox.h = sizeY; - } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { - const double sizeX = sourceBox.h / RATIO; - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) - sourceBox.x += sourceBox.w - sizeX; - sourceBox.w = sizeX; + if (MODE == MBIND_RESIZE_FORCE_RATIO) { + if ((CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { + const double SIZEY = (sourceX.end - sourceX.start) * (BEGINSIZE.y / BEGINSIZE.x); + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) + sourceY.start = sourceY.end - SIZEY; + else + sourceY.end = sourceY.start + SIZEY; + } else if ((CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { + const double SIZEX = (sourceY.end - sourceY.start) * (BEGINSIZE.x / BEGINSIZE.y); + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) + sourceX.start = sourceX.end - SIZEX; + else + sourceX.end = sourceX.start + SIZEX; } } - sourceBox.expand(-DRAGGINGBORDERSIZE).round(); - sourcePos = sourceBox.pos(); - sourceSize = sourceBox.size(); + sourcePos = {sourceX.start, sourceY.start}; + sourceSize = {sourceX.end - sourceX.start, sourceY.end - sourceY.start}; } void IHyprLayout::onMouseMove(const Vector2D& mousePos) { From c4d214c42d743a69f606ff476b7266b3ace7d70e Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:30:26 -0500 Subject: [PATCH 0201/1803] monitors: fix vrr breaking monitor disconnect (#8314) --- src/config/ConfigManager.cpp | 8 +++++--- src/helpers/Monitor.cpp | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f1ba8d7f..62c71dc7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1608,9 +1608,6 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { m->vrrActive = true; return; } else if (USEVRR == 2) { - /* fullscreen */ - m->vrrActive = true; - const auto PWORKSPACE = m->activeWorkspace; if (!PWORKSPACE) @@ -1619,6 +1616,9 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && (PWORKSPACE->m_efFullscreenMode & FSMODE_FULLSCREEN); if (WORKSPACEFULL) { + /* fullscreen */ + m->vrrActive = true; + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(true); @@ -1631,6 +1631,8 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name); } else if (!WORKSPACEFULL) { + m->vrrActive = false; + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(false); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9e71bf5f..bfab2fd3 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -334,6 +334,7 @@ void CMonitor::onDisconnect(bool destroy) { activeWorkspace.reset(); output->state->resetExplicitFences(); + output->state->setAdaptiveSync(false); output->state->setEnabled(false); if (!state.commit()) From 3852418d2446555509738bf1486940042107afe7 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 1 Nov 2024 13:03:06 +0000 Subject: [PATCH 0202/1803] hyprctl: reload windowrules on reloadAll --- src/debug/HyprCtl.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 93e0f620..f5c63f86 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1041,7 +1041,8 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { } // decorations will probably need a repaint - if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { + if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" || + COMMAND.starts_with("windowrule")) { for (auto const& m : g_pCompositor->m_vMonitors) { g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); @@ -1698,6 +1699,14 @@ std::string CHyprCtl::getReply(std::string request) { rd.blurFBDirty = true; } + for (auto const& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || !g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) + continue; + + w->updateDynamicRules(); + g_pCompositor->updateWindowAnimatedDecorationValues(w); + } + for (auto const& m : g_pCompositor->m_vMonitors) { g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); From d8b865366af9d5ed30d2ee0a437b9a3ed43c10bd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 1 Nov 2024 15:52:03 +0000 Subject: [PATCH 0203/1803] renderer: Add a missing texture asset and a user check When an asset is missing, instead of a black screen, render an obnoxious, yet standard, missing texture. Additionally, warn the user assets failed to load. Shoutout to Arch for having their assets broken for months. Fix your shit. I am tired of it, and it's negatively impacting users. --- src/Compositor.cpp | 6 ++ src/render/Framebuffer.cpp | 15 +++- src/render/OpenGL.cpp | 155 +++++++++++++++++++++++++------------ src/render/OpenGL.hpp | 14 ++-- src/render/Renderer.cpp | 20 ++--- 5 files changed, 139 insertions(+), 71 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 65891633..62612398 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2738,6 +2738,12 @@ void CCompositor::performUserChecks() { CColor{}, 15000, ICON_WARNING); } } + + if (g_pHyprOpenGL->failedAssetsNo > 0) { + g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!", + g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""), + CColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR); + } } void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) { diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index c48ff6f3..7e086778 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -2,7 +2,7 @@ #include "OpenGL.hpp" CFramebuffer::CFramebuffer() { - m_cTex = makeShared(); + ; } bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { @@ -12,6 +12,9 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { uint32_t glFormat = FormatUtils::drmFormatToGL(drmFormat); uint32_t glType = FormatUtils::glFormatToType(glFormat); + if (!m_cTex) + m_cTex = makeShared(); + if (!m_iFbAllocated) { firstAlloc = true; glGenFramebuffers(1, &m_iFb); @@ -54,7 +57,8 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { } glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); + if (g_pHyprOpenGL) + glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); m_vSize = Vector2D(w, h); @@ -85,14 +89,17 @@ void CFramebuffer::bind() { #else glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); #endif - glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); + if (g_pHyprOpenGL) + glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); + else + glViewport(0, 0, m_vSize.x, m_vSize.y); } void CFramebuffer::release() { if (m_iFbAllocated) glDeleteFramebuffers(1, &m_iFb); - m_cTex->destroyTexture(); + m_cTex.reset(); m_iFbAllocated = false; m_vSize = Vector2D(); } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 9e524fa4..20963707 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -13,6 +13,13 @@ #include #include +const std::vector ASSET_PATHS = { +#ifdef DATAROOTDIR + DATAROOTDIR, +#endif + "/usr/share", +}; + inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); if (proc == NULL) { @@ -2595,11 +2602,32 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const cairo_surface_flush(CAIROSURFACE); } -SP CHyprOpenGLImpl::loadAsset(const std::string& file) { - const auto CAIROSURFACE = cairo_image_surface_create_from_png(file.c_str()); +SP CHyprOpenGLImpl::loadAsset(const std::string& filename) { - if (!CAIROSURFACE) - return nullptr; + std::string fullPath; + for (auto& e : ASSET_PATHS) { + std::string p = std::string{e} + "/hypr/" + filename; + std::error_code ec; + if (std::filesystem::exists(p, ec)) { + fullPath = p; + break; + } else + Debug::log(LOG, "loadAsset: looking at {} unsuccessful: ec {}", filename, ec.message()); + } + + if (fullPath.empty()) { + failedAssetsNo++; + Debug::log(ERR, "loadAsset: looking for {} failed (no provider found)", filename); + return m_pMissingAssetTexture; + } + + const auto CAIROSURFACE = cairo_image_surface_create_from_png(fullPath.c_str()); + + if (!CAIROSURFACE) { + failedAssetsNo++; + Debug::log(ERR, "loadAsset: failed to load {} (corrupt / inaccessible / not png)", fullPath); + return m_pMissingAssetTexture; + } const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE); auto tex = makeShared(); @@ -2710,51 +2738,68 @@ SP CHyprOpenGLImpl::renderText(const std::string& text, CColor col, in return tex; } -void CHyprOpenGLImpl::initAssets() { - std::string assetsPath = ""; -#ifndef DATAROOTDIR - assetsPath = "/usr/share/hypr/"; -#else - assetsPath = std::format("{}{}", DATAROOTDIR, "/hypr/"); -#endif +void CHyprOpenGLImpl::initMissingAssetTexture() { + SP tex = makeShared(); + tex->allocate(); - m_pLockDeadTexture = loadAsset(assetsPath + "lockdead.png"); - m_pLockDead2Texture = loadAsset(assetsPath + "lockdead2.png"); + const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 512, 512); + const auto CAIRO = cairo_create(CAIROSURFACE); + + cairo_set_antialias(CAIRO, CAIRO_ANTIALIAS_NONE); + cairo_save(CAIRO); + cairo_set_source_rgba(CAIRO, 0, 0, 0, 1); + cairo_set_operator(CAIRO, CAIRO_OPERATOR_SOURCE); + cairo_paint(CAIRO); + cairo_set_source_rgba(CAIRO, 1, 0, 1, 1); + cairo_rectangle(CAIRO, 256, 0, 256, 256); + cairo_fill(CAIRO); + cairo_rectangle(CAIRO, 0, 256, 256, 256); + cairo_fill(CAIRO); + cairo_restore(CAIRO); + + cairo_surface_flush(CAIROSURFACE); + + tex->m_vSize = {512, 512}; + + // copy the data to an OpenGL texture we have + const GLint glFormat = GL_RGBA; + const GLint glType = GL_UNSIGNED_BYTE; + + const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); + glBindTexture(GL_TEXTURE_2D, tex->m_iTexID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#ifndef GLES2 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); +#endif + glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA); + + cairo_surface_destroy(CAIROSURFACE); + cairo_destroy(CAIRO); + + m_pMissingAssetTexture = tex; +} + +void CHyprOpenGLImpl::initAssets() { + initMissingAssetTexture(); + + static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); + + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); + + m_pLockDeadTexture = loadAsset("lockdead.png"); + m_pLockDead2Texture = loadAsset("lockdead2.png"); m_pLockTtyTextTexture = renderText(std::format("Running on tty {}", g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ? std::to_string(g_pCompositor->m_pAqBackend->session->vt) : "unknown"), CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); -} -void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { - RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); - - Debug::log(LOG, "Creating a texture for BGTex"); - - 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)); - - if (*PRENDERTEX) - return; - - // release the last tex if exists - const auto PFB = &m_mMonitorBGFBs[pMonitor]; - PFB->release(); - - PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); - - if (!m_pBackgroundTexture) { - std::string texPath = ""; -#ifndef DATAROOTDIR - texPath = "/usr/share/hypr/wall"; -#else - texPath = std::format("{}{}", DATAROOTDIR, "/hypr/wall"); -#endif + // create the default background texture + { + std::string texPath = std::format("{}", "wall"); // get the adequate tex if (FORCEWALLPAPER == -1) { @@ -2767,15 +2812,29 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { texPath += ".png"; - // check if wallpapers exist - std::error_code err; - if (!std::filesystem::exists(texPath, err)) { - Debug::log(ERR, "createBGTextureForMonitor: failed, file \"{}\" doesn't exist or access denied, ec: {}", texPath, err.message()); - return; // the texture will be empty, oh well. We'll clear with a solid color anyways. - } - m_pBackgroundTexture = loadAsset(texPath); } +} + +void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { + RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); + + Debug::log(LOG, "Creating a texture for BGTex"); + + static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); + static auto PNOSPLASH = CConfigValue("misc:disable_splash_rendering"); + + if (*PRENDERTEX) + return; + + // release the last tex if exists + const auto PFB = &m_mMonitorBGFBs[pMonitor]; + PFB->release(); + + PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + + if (!m_pBackgroundTexture) // ?!?!?! + return; // create a new one with cairo SP tex = makeShared(); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 115dcac7..c594a7cc 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -215,11 +215,12 @@ class CHyprOpenGLImpl { GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; + uint failedAssetsNo = 0; bool m_bReloadScreenShader = true; // at launch it can be set @@ -277,7 +278,7 @@ class CHyprOpenGLImpl { CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; - SP m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; + SP m_pMissingAssetTexture, m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); @@ -290,6 +291,7 @@ class CHyprOpenGLImpl { SP loadAsset(const std::string& file); SP renderText(const std::string& text, CColor col, int pt, bool italic = false); void initAssets(); + void initMissingAssetTexture(); // std::optional> getModsForFormat(EGLint format); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1dedcc7d..a133899b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1063,22 +1063,16 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { if (ANY_PRESENT) { // render image2, without instructions. Lock still "alive", unless texture dead - if (g_pHyprOpenGL->m_pLockDead2Texture) - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA); - else - g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA); } else { // render image, with instructions. Lock is gone. - if (g_pHyprOpenGL->m_pLockDeadTexture) { - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA); - // also render text for the tty number - if (g_pHyprOpenGL->m_pLockTtyTextTexture) { - CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize}; - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F); - } - } else - g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + // also render text for the tty number + if (g_pHyprOpenGL->m_pLockTtyTextTexture) { + CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize}; + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F); + } } if (ALPHA < 1.f) /* animate */ From 3c0605c68e50416819fea471a8fbef05e4a18684 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Fri, 1 Nov 2024 22:21:36 +0500 Subject: [PATCH 0204/1803] hyprland-systemd.desktop improvements (#8318) --- systemd/hyprland-systemd.desktop | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop index b36a87b2..8c065a81 100644 --- a/systemd/hyprland-systemd.desktop +++ b/systemd/hyprland-systemd.desktop @@ -1,5 +1,7 @@ [Desktop Entry] -Name=Hyprland +Name=Hyprland (systemd session) Comment=An intelligent dynamic tiling Wayland compositor Exec=systemctl --user start --wait hyprland-session Type=Application +DesktopNames=Hyprland (systemd session) +Keywords=tiling;wayland;compositor; From 29e7dc642831801d14480cf7e4bb19f6ffb118e9 Mon Sep 17 00:00:00 2001 From: Pavel Solovev Date: Fri, 1 Nov 2024 13:54:17 +0000 Subject: [PATCH 0205/1803] Systemd fixes Fix installation path, install the service only if the systemd option is enabled --- meson.build | 3 ++- systemd/meson.build | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index d0ba9a5c..76765645 100644 --- a/meson.build +++ b/meson.build @@ -53,7 +53,9 @@ epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs # Handle options if get_option('systemd').enabled() + systemd = dependency('systemd') add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') + subdir('systemd') endif if get_option('legacy_renderer').enabled() @@ -89,7 +91,6 @@ subdir('hyprpm/src') subdir('assets') subdir('example') subdir('docs') -subdir('systemd') # Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') diff --git a/systemd/meson.build b/systemd/meson.build index 497e64f4..2cd5312a 100644 --- a/systemd/meson.build +++ b/systemd/meson.build @@ -7,9 +7,11 @@ install_data( conf_data = configuration_data() conf_data.set('PREFIX', get_option('prefix')) conf_data.set('BINDIR', get_option('bindir')) +user_unit_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir', + pkgconfig_define: ['prefix', get_option('prefix')]) configure_file( configuration: conf_data, input: 'hyprland-session.service.in', output: '@BASENAME@', - install_dir: join_paths(get_option('libdir'), 'systemd/user') ) + install_dir: user_unit_dir ) From 32b18179dd789cde948c97eb3c2ebbdd6af36bf7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 1 Nov 2024 19:31:20 +0200 Subject: [PATCH 0206/1803] CMake: systemd fixes --- CMakeLists.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec8c331e..877ba461 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,6 @@ set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) set(BINDIR ${CMAKE_INSTALL_BINDIR}) configure_file(hyprland.pc.in hyprland.pc @ONLY) -configure_file(systemd/hyprland-session.service.in systemd/hyprland-session.service @ONLY) set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") @@ -223,6 +222,16 @@ if(NO_SYSTEMD) else() message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") add_compile_definitions(USES_SYSTEMD) + configure_file(systemd/hyprland-session.service.in + systemd/hyprland-session.service @ONLY) + + # session file -systemd + install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + + # install systemd service + install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service + DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) @@ -359,11 +368,6 @@ install( install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) - -# session file -systemd -install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) - # allow Hyprland to find assets add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") @@ -404,6 +408,3 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland FILES_MATCHING PATTERN "*.h*") - -#install systemd service -install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) From 40081cb330fa838ad9c0a7b87c20b2300ea7fb38 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 2 Nov 2024 15:26:25 +0000 Subject: [PATCH 0207/1803] renderer: improve api around new framebuffer changes ref #8325 --- src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- src/render/Framebuffer.cpp | 19 ++++- src/render/Framebuffer.hpp | 12 ++- src/render/OpenGL.cpp | 75 ++++++++++--------- .../decorations/CHyprDropShadowDecoration.cpp | 2 +- 6 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 780c081d..1fcaff05 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -253,7 +253,7 @@ bool CScreencopyFrame::copyShm() { g_pHyprOpenGL->setMonitorTransformEnabled(false); #ifndef GLES2 - glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID()); #else glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb); #endif diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index f2af89db..04c089d7 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -279,7 +279,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { outFB.bind(); #ifndef GLES2 - glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.m_iFb); + glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID()); #endif glPixelStorei(GL_PACK_ALIGNMENT, 1); diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 7e086778..814a3339 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -65,9 +65,10 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { return true; } -void CFramebuffer::addStencil() { +void CFramebuffer::addStencil(SP tex) { // TODO: Allow this with gles2 #ifndef GLES2 + m_pStencilTex = tex; glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0); @@ -109,5 +110,17 @@ CFramebuffer::~CFramebuffer() { } bool CFramebuffer::isAllocated() { - return m_iFbAllocated; -} \ No newline at end of file + return m_iFbAllocated && m_cTex; +} + +SP CFramebuffer::getTexture() { + return m_cTex; +} + +GLuint CFramebuffer::getFBID() { + return m_iFbAllocated ? m_iFb : 0; +} + +SP CFramebuffer::getStencilTex() { + return m_pStencilTex; +} diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index ca7f9e8a..84dfeef1 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -9,17 +9,23 @@ class CFramebuffer { ~CFramebuffer(); bool alloc(int w, int h, uint32_t format = GL_RGBA); - void addStencil(); + void addStencil(SP tex); void bind(); void release(); void reset(); bool isAllocated(); + SP getTexture(); + SP getStencilTex(); + GLuint getFBID(); Vector2D m_vSize; + private: SP m_cTex; - GLuint m_iFb; - bool m_iFbAllocated{false}; + GLuint m_iFb = -1; + bool m_iFbAllocated = false; SP m_pStencilTex; + + friend class CRenderbuffer; }; \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 20963707..415bb920 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -830,15 +830,15 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb if (m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) { m_RenderData.pCurrentMonData->stencilTex->allocate(); - m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + + m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + m_RenderData.pCurrentMonData->mirrorSwapFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); } if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty()) @@ -870,10 +870,9 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb // we can render to the rbo / fbo (fake) directly const auto PFBO = fb ? fb : PRBO->getFB(); m_RenderData.currentFB = PFBO; - if (PFBO->m_pStencilTex != m_RenderData.pCurrentMonData->stencilTex) { - PFBO->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - PFBO->addStencil(); - } + if (PFBO->getStencilTex() != m_RenderData.pCurrentMonData->stencilTex) + PFBO->addStencil(m_RenderData.pCurrentMonData->stencilTex); + PFBO->bind(); m_bOffloadedFramebuffer = false; } @@ -924,9 +923,9 @@ void CHyprOpenGLImpl::end() { blend(false); if (m_sFinalScreenShader.program < 1 && !g_pHyprRenderer->m_bCrashingInProgress) - renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox); + renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox); else - renderTexture(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox, 1.f); + renderTexture(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox, 1.f); blend(true); @@ -1269,7 +1268,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round m_bEndFrame = true; // fix transformed const auto SAVEDRENDERMODIF = m_RenderData.renderModif; m_RenderData.renderModif = {}; // fix shit - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, blurA, &damage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, &damage, 0, false, false, false); m_bEndFrame = false; m_RenderData.renderModif = SAVEDRENDERMODIF; @@ -1629,7 +1628,8 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf glBindTexture(tex->m_iTarget, tex->m_iTexID); glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(matte.m_cTex->m_iTarget, matte.m_cTex->m_iTexID); + auto matteTex = matte.getTexture(); + glBindTexture(matteTex->m_iTarget, matteTex->m_iTexID); glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -1696,9 +1696,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(m_RenderData.currentFB->m_cTex->m_iTarget, m_RenderData.currentFB->m_cTex->m_iTexID); + auto currentTex = m_RenderData.currentFB->getTexture(); - glTexParameteri(m_RenderData.currentFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID); + + glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); @@ -1740,9 +1742,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID); + auto currentTex = currentRenderToFB->getTexture(); - glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID); + + glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(pShader->program); @@ -1790,7 +1794,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // draw the things. // first draw is swap -> mirr PMIRRORFB->bind(); - glBindTexture(PMIRRORSWAPFB->m_cTex->m_iTarget, PMIRRORSWAPFB->m_cTex->m_iTexID); + glBindTexture(PMIRRORSWAPFB->getTexture()->m_iTarget, PMIRRORSWAPFB->getTexture()->m_iTexID); // damage region will be scaled, make a temp CRegion tempDamage{damage}; @@ -1818,9 +1822,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID); + auto currentTex = currentRenderToFB->getTexture(); - glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID); + + glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program); @@ -1858,7 +1864,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o } // finish - glBindTexture(PMIRRORFB->m_cTex->m_iTarget, 0); + glBindTexture(PMIRRORFB->getTexture()->m_iTarget, 0); blend(BLENDBEFORE); @@ -1972,7 +1978,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { clear(CColor(0, 0, 0, 0)); m_bEndFrame = true; // fix transformed - renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false); m_bEndFrame = false; m_RenderData.currentFB->bind(); @@ -2003,7 +2009,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); static auto PBLURXRAY = CConfigValue("decoration:blur:xray"); - if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID) + if (!m_RenderData.pCurrentMonData->blurFB.getTexture()) return false; if (pWindow && pWindow->m_sWindowData.xray.hasValue() && !pWindow->m_sWindowData.xray.valueOrDefault()) @@ -2105,7 +2111,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float setMonitorTransformEnabled(true); if (!USENEWOPTIMIZE) setRenderModifEnabled(false); - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false); if (!USENEWOPTIMIZE) setRenderModifEnabled(true); setMonitorTransformEnabled(false); @@ -2238,9 +2244,8 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr g_pHyprRenderer->makeEGLCurrent(); - pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); + pFramebuffer->addStencil(m_RenderData.pCurrentMonData->stencilTex); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); @@ -2376,7 +2381,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { const auto FBDATA = &m_mWindowFramebuffers.at(ref); - if (!FBDATA->m_cTex->m_iTexID) + if (!FBDATA->getTexture()) return; const auto PMONITOR = pWindow->m_pMonitor.lock(); @@ -2402,7 +2407,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { m_bEndFrame = true; - renderTextureInternalWithDamage(FBDATA->m_cTex, &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0); + renderTextureInternalWithDamage(FBDATA->getTexture(), &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0); m_bEndFrame = false; } @@ -2415,7 +2420,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { const auto FBDATA = &m_mLayerFramebuffers.at(pLayer); - if (!FBDATA->m_cTex->m_iTexID) + if (!FBDATA->getTexture()) return; const auto PMONITOR = pLayer->monitor.lock(); @@ -2435,7 +2440,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { m_bEndFrame = true; - renderTextureInternalWithDamage(FBDATA->m_cTex, &layerBox, pLayer->alpha.value(), &fakeDamage, 0); + renderTextureInternalWithDamage(FBDATA->getTexture(), &layerBox, pLayer->alpha.value(), &fakeDamage, 0); m_bEndFrame = false; } @@ -2526,7 +2531,7 @@ void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) { blend(false); - renderTexture(m_RenderData.currentFB->m_cTex, box, 1.f, 0, false, false); + renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, false, false); blend(true); @@ -2548,7 +2553,7 @@ void CHyprOpenGLImpl::renderMirrored() { monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; const auto PFB = &m_mMonitorRenderResources[mirrored].monitorMirrorFB; - if (!PFB->isAllocated() || PFB->m_cTex->m_iTexID <= 0) + if (!PFB->isAllocated() || !PFB->getTexture()) return; // replace monitor projection to undo the mirrored monitor's projection @@ -2561,7 +2566,7 @@ void CHyprOpenGLImpl::renderMirrored() { // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); - renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false); + renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false); // reset matrix for further drawing m_RenderData.monitorProjection = monitor->projMatrix; @@ -2926,7 +2931,7 @@ void CHyprOpenGLImpl::clearWithTex() { if (TEXIT != m_mMonitorBGFBs.end()) { CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; m_bEndFrame = true; - renderTexture(TEXIT->second.m_cTex, &monbox, 1); + renderTexture(TEXIT->second.getTexture(), &monbox, 1); m_bEndFrame = false; } } @@ -2978,7 +2983,7 @@ void CHyprOpenGLImpl::bindOffMain() { void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - renderTexturePrimitive(off->m_cTex, &monbox); + renderTexturePrimitive(off->getTexture(), &monbox); } void CHyprOpenGLImpl::bindBackOnMain() { diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 79d5940b..f146776f 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -199,7 +199,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); + g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), &monbox, alphaFB); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); From 514e0ff509f3bf4c98515f08216ac2eeb8797517 Mon Sep 17 00:00:00 2001 From: diniamo Date: Sun, 3 Nov 2024 09:52:09 +0100 Subject: [PATCH 0208/1803] flake: update nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index beb56b5c..27803dc5 100644 --- a/flake.lock +++ b/flake.lock @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1729413321, - "narHash": "sha256-I4tuhRpZFa6Fu6dcH9Dlo5LlH17peT79vx1y1SpeKt0=", + "lastModified": 1730531603, + "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1997e4aa514312c1af7e2bda7fad1644e778ff26", + "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", "type": "github" }, "original": { From 5833abbbd11dca718379863cb2fb5c2423f5d7e7 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Sun, 3 Nov 2024 08:59:46 -0600 Subject: [PATCH 0209/1803] xwayland: minor fixups for stability (#8323) * xwayland: add inline safe closing of fds and fix LOCK_FILE_MODE permissions * xwayland: auto recreate xwayland instance if it crashes * xwayland: delay auto-restart until later --- src/xwayland/Server.cpp | 25 +++++++++++++------------ src/xwayland/XWM.cpp | 3 +++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 5ad9ff23..f356af18 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -30,7 +30,7 @@ constexpr int SOCKET_DIR_PERMISSIONS = 0755; constexpr int SOCKET_BACKLOG = 1; constexpr int MAX_SOCKET_RETRIES = 32; -constexpr int LOCK_FILE_MODE = 044; +constexpr int LOCK_FILE_MODE = 0444; static bool setCloseOnExec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); @@ -58,6 +58,11 @@ void cleanUpSocket(int fd, const char* path) { unlink(path); } +inline void closeSocketSafely(int& fd) { + if (fd >= 0) + close(fd); +} + static int createSocket(struct sockaddr_un* addr, size_t path_size) { socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; int fd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -252,8 +257,8 @@ CXWaylandServer::~CXWaylandServer() { if (display < 0) return; - close(xFDs[0]); - close(xFDs[1]); + closeSocketSafely(xFDs[0]); + closeSocketSafely(xFDs[1]); std::string lockPath = std::format("/tmp/.X{}-lock", display); safeRemove(lockPath); @@ -283,14 +288,10 @@ void CXWaylandServer::die() { if (pipeFd >= 0) close(pipeFd); - if (waylandFDs[0] >= 0) - close(waylandFDs[0]); - if (waylandFDs[1] >= 0) - close(waylandFDs[1]); - if (xwmFDs[0] >= 0) - close(xwmFDs[0]); - if (xwmFDs[1] >= 0) - close(xwmFDs[1]); + closeSocketSafely(waylandFDs[0]); + closeSocketSafely(waylandFDs[1]); + closeSocketSafely(xwmFDs[0]); + closeSocketSafely(xwmFDs[1]); // possible crash. Better to leak a bit. //if (xwaylandClient) @@ -407,7 +408,7 @@ bool CXWaylandServer::start() { close(notify[1]); close(waylandFDs[1]); - close(xwmFDs[1]); + closeSocketSafely(xwmFDs[1]); waylandFDs[1] = -1; xwmFDs[1] = -1; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 248813bf..87fc34e4 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -13,6 +13,7 @@ #include "../defines.hpp" #include "../Compositor.hpp" #include "../protocols/core/Seat.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/SeatManager.hpp" #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" @@ -691,6 +692,8 @@ int CXWM::onEvent(int fd, uint32_t mask) { Debug::log(CRIT, "XWayland has yeeten the xwm off?!"); g_pXWayland->pWM.reset(); g_pXWayland->pServer.reset(); + // Attempt to create fresh instance + g_pEventLoopManager->doLater([]() { g_pXWayland = std::make_unique(true); }); return 0; } From 180c26ada6233c3c59c331cb14a64aac1eeb2941 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 3 Nov 2024 15:16:08 +0000 Subject: [PATCH 0210/1803] renderer: safeguard against non-sampleable currentFB in blurMainFb fixes #8325 --- src/render/Framebuffer.cpp | 6 ++++++ src/render/OpenGL.cpp | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 814a3339..bf75d414 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -97,12 +97,18 @@ void CFramebuffer::bind() { } void CFramebuffer::release() { + if (!m_iFbAllocated && !m_cTex) + return; + + Debug::log(TRACE, "fb {} released", m_iFb); + if (m_iFbAllocated) glDeleteFramebuffers(1, &m_iFb); m_cTex.reset(); m_iFbAllocated = false; m_vSize = Vector2D(); + m_iFb = 0; } CFramebuffer::~CFramebuffer() { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 415bb920..45837509 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1656,6 +1656,11 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf // Dual (or more) kawase blur CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) { + if (!m_RenderData.currentFB->getTexture()) { + Debug::log(ERR, "BUG THIS: null fb texture while attempting to blur main fb?! (introspection off?!)"); + return &m_RenderData.pCurrentMonData->mirrorFB; // return something to sample from at least + } + TRACY_GPU_ZONE("RenderBlurMainFramebufferWithDamage"); const auto BLENDBEFORE = m_bBlend; From cd0d0491261728260de3d1aff150e1b6c05f9e86 Mon Sep 17 00:00:00 2001 From: Gliczy <129636582+Gliczy@users.noreply.github.com> Date: Sun, 3 Nov 2024 17:08:13 +0100 Subject: [PATCH 0211/1803] flake.lock: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 27803dc5..560014b6 100644 --- a/flake.lock +++ b/flake.lock @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1728166987, - "narHash": "sha256-w6dVTguAn9zJ+7aPOhBQgDz8bn6YZ7b56cY8Kg5HJRI=", + "lastModified": 1730187742, + "narHash": "sha256-M0umGIIvVFqCwA0fQ5edivMTbRYA0r/5tXK8sr+M7EA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "fb9c8d665af0588bb087f97d0f673ddf0d501787", + "rev": "998f646762b94fbac61b0271ce66d3e617262858", "type": "github" }, "original": { From 44899cd5488831b147f385f201959625bd010898 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 4 Nov 2024 19:43:23 +0200 Subject: [PATCH 0212/1803] nix/overlays: fix xdph overlay Partial fix for https://github.com/hyprwm/Hyprland/issues/8343 --- nix/overlays.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/overlays.nix b/nix/overlays.nix index a78f3003..b1eb66ad 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -63,7 +63,7 @@ in { # Packages for extra software recommended for usage with Hyprland, # including forked or patched packages for compatibility. hyprland-extras = lib.composeManyExtensions [ - inputs.xdph.overlays.xdg-desktop-portal-hyprland + inputs.xdph.overlays.default ]; # udis86 from nixpkgs is too old, and also does not provide a .pc file From 0fb9a04526b06adfb3fd16b64e13b7d110ae7855 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 4 Nov 2024 20:01:40 +0200 Subject: [PATCH 0213/1803] flake.lock: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 560014b6..8cee27e3 100644 --- a/flake.lock +++ b/flake.lock @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1730187742, - "narHash": "sha256-M0umGIIvVFqCwA0fQ5edivMTbRYA0r/5tXK8sr+M7EA=", + "lastModified": 1730743262, + "narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "998f646762b94fbac61b0271ce66d3e617262858", + "rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d", "type": "github" }, "original": { From 88e9e0394541a853600bc2c910005c05fa156269 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 4 Nov 2024 19:42:47 +0000 Subject: [PATCH 0214/1803] renderer: add expand_undersized_textures adds an option to disable the texture expansion for textures that are smaller while resizing up --- src/config/ConfigManager.cpp | 1 + src/render/Renderer.cpp | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 62c71dc7..c5d53e6a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -590,6 +590,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("render:explicit_sync", Hyprlang::INT{2}); m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2}); m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0}); + m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1}); // devices m_pConfig->addSpecialCategory("device", {"name"}); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a133899b..6af3a99d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1084,8 +1084,10 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize, const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { - Vector2D uvTL; - Vector2D uvBR = Vector2D(1, 1); + static auto PEXPANDEDGES = CConfigValue("render:expand_undersized_textures"); + + Vector2D uvTL; + Vector2D uvBR = Vector2D(1, 1); if (pSurface->current.viewport.hasSource) { // we stretch it to dest. if no dest, to 1,1 @@ -1115,16 +1117,18 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPscale); - const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; - const auto EXPECTED_SIZE = - ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) - .round(); - if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { - // this will not work with shm AFAIK, idk why. - // NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much - const auto FIX = projSize / EXPECTED_SIZE; - uvBR = uvBR * FIX; + if (*PEXPANDEDGES) { + const auto MONITOR_WL_SCALE = std::ceil(pMonitor->scale); + const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; + const auto EXPECTED_SIZE = + ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) + .round(); + if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { + // this will not work with shm AFAIK, idk why. + // NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much + const auto FIX = projSize / EXPECTED_SIZE; + uvBR = uvBR * FIX; + } } g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; From e3882b23d09aad7f5c3a708536c87b062f3b0d8d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 09:59:03 +0000 Subject: [PATCH 0215/1803] screencopy: fix build with legacyrenderer fixes #8355 --- src/protocols/Screencopy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 1fcaff05..a7e515cb 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -255,7 +255,7 @@ bool CScreencopyFrame::copyShm() { #ifndef GLES2 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID()); #else - glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb); + glBindFramebuffer(GL_FRAMEBUFFER, fb.getFBID()); #endif const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); From d1638a09bacd84b994de3f77746b74f427b9d41e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 15:44:40 +0000 Subject: [PATCH 0216/1803] shadow: add sharp and refactor options options moved to decoration:shadow: --- src/Compositor.cpp | 11 +++--- src/config/ConfigDescriptions.hpp | 24 ++++++++----- src/config/ConfigManager.cpp | 17 +++++----- src/managers/AnimationManager.cpp | 2 +- src/render/OpenGL.cpp | 6 ++-- .../decorations/CHyprDropShadowDecoration.cpp | 34 +++++++++++++------ .../decorations/CHyprDropShadowDecoration.hpp | 2 ++ 7 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 62612398..495a2d85 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1893,8 +1893,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { 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 PSHADOWCOL = CConfigValue("decoration:shadow:color"); + static auto PSHADOWCOLINACTIVE = CConfigValue("decoration:shadow:color_inactive"); static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); static auto PDIMENABLED = CConfigValue("decoration:dim_inactive"); @@ -1965,11 +1965,10 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // shadow if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { - if (pWindow == m_pLastWindow) { + if (pWindow == m_pLastWindow) pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); - } else { - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); - } + else + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); } else { pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow } diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 07034e71..5327c599 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -158,49 +158,55 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SFloatData{1, 0, 1}, }, SConfigOptionDescription{ - .value = "decoration:drop_shadow", + .value = "decoration:shadow:enabled", .description = "enable drop shadows on windows", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "decoration:shadow_range", + .value = "decoration:shadow:range", .description = "Shadow range (size) in layout px", .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{4, 0, 100}, }, SConfigOptionDescription{ - .value = "decoration:shadow_render_power", + .value = "decoration:shadow:render_power", .description = "in what power to render the falloff (more power, the faster the falloff) [1 - 4]", .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{3, 1, 4}, }, SConfigOptionDescription{ - .value = "decoration:shadow_ignore_window", + .value = "decoration:shadow:sharp", + .description = "whether the shadow should be sharp or not. Akin to an infinitely high render power.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "decoration:shadow:ignore_window", .description = "if true, the shadow will not be rendered behind the window itself, only around it.", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "decoration:col.shadow", + .value = "decoration:shadow:color", .description = "shadow's color. Alpha dictates shadow's opacity.", .type = CONFIG_OPTION_COLOR, .data = SConfigOptionDescription::SColorData{0xee1a1a1a}, }, SConfigOptionDescription{ - .value = "decoration:col.shadow_inactive", + .value = "decoration:shadow:color_inactive", .description = "inactive shadow color. (if not set, will fall back to col.shadow)", .type = CONFIG_OPTION_COLOR, - .data = SConfigOptionDescription::SColorData{}, //##TODO UNSET? + .data = SConfigOptionDescription::SColorData{}, //TODO: UNSET? }, SConfigOptionDescription{ - .value = "decoration:shadow_offset", + .value = "decoration:shadow:offset", .description = "shadow's rendering offset.", .type = CONFIG_OPTION_VECTOR, .data = SConfigOptionDescription::SVectorData{{}, {-250, -250}, {250, 250}}, }, SConfigOptionDescription{ - .value = "decoration:shadow_scale", + .value = "decoration:shadow:scale", .description = "shadow's scale. [0.0 - 1.0]", .type = CONFIG_OPTION_FLOAT, .data = SConfigOptionDescription::SFloatData{1, 0, 1}, diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c5d53e6a..eafe4cbb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -431,14 +431,15 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("decoration:inactive_opacity", {1.F}); m_pConfig->addConfigValue("decoration:fullscreen_opacity", {1.F}); 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", Hyprlang::INT{0xee1a1a1a}); - m_pConfig->addConfigValue("decoration:col.shadow_inactive", {(Hyprlang::INT)INT_MAX}); + m_pConfig->addConfigValue("decoration:shadow:enabled", 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:shadow:sharp", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:shadow:color", Hyprlang::INT{0xee1a1a1a}); + m_pConfig->addConfigValue("decoration:shadow:color_inactive", {(Hyprlang::INT)INT64_MAX}); 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}); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 0bdf5a7a..ceb594aa 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -64,7 +64,7 @@ void CAnimationManager::tick() { 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:shadow:enabled"); const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 45837509..52392436 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2465,7 +2465,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const box = &newBox; - static auto PSHADOWPOWER = CConfigValue("decoration:shadow_render_power"); + static auto PSHADOWPOWER = CConfigValue("decoration:shadow:render_power"); const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); @@ -2475,7 +2475,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - glEnable(GL_BLEND); + blend(true); glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program); @@ -2485,7 +2485,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const glMatrix.transpose(); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif - glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); + glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r * col.a * a, col.g * col.a * a, col.b * col.a * a, col.a * a); const auto TOPLEFT = Vector2D(range + round, range + round); const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index f146776f..893ad498 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -36,7 +36,7 @@ std::string CHyprDropShadowDecoration::getDisplayName() { } void CHyprDropShadowDecoration::damageEntire() { - static auto PSHADOWS = CConfigValue("decoration:drop_shadow"); + static auto PSHADOWS = CConfigValue("decoration:shadow:enabled"); if (*PSHADOWS != 1) return; // disabled @@ -52,7 +52,7 @@ void CHyprDropShadowDecoration::damageEntire() { shadowBox.translate(PWORKSPACE->m_vRenderOffset.value()); shadowBox.translate(PWINDOW->m_vFloatingOffset); - static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow_ignore_window"); + static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow:ignore_window"); const auto ROUNDING = PWINDOW->rounding(); const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1; @@ -102,11 +102,11 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (PWINDOW->m_sWindowData.noShadow.valueOrDefault()) return; - 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"); + static auto PSHADOWS = CConfigValue("decoration:shadow:enabled"); + 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) return; // disabled @@ -184,7 +184,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { 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, PWINDOW->m_cRealShadowColor.value().a), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); // render black window box ("clip") g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); @@ -204,9 +204,8 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->m_RenderData.damage = saveDamage; - } else { - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); - } + } else + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); if (m_seExtents != m_seReportedExtents) g_pDecorationPositioner->repositionDeco(this); @@ -215,3 +214,16 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; } + +void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CColor color, float a) { + static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); + + g_pHyprOpenGL->blend(true); + + color.a *= a; + + if (*PSHADOWSHARP) + g_pHyprOpenGL->renderRect(box, color, round); + else + g_pHyprOpenGL->renderRoundedShadow(box, round, range, color, 1.F); +} diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 8335cde9..933ee0ef 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -34,6 +34,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; + void drawShadowInternal(CBox* box, int round, int range, CColor color, float a); + CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; }; From 55ccb1a8cf2c8541a32890e9b76e7c20fc9227cd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:00:39 +0000 Subject: [PATCH 0217/1803] shaders: fixup jagged edges in texture rounded corners --- src/render/shaders/Textures.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 6ac33a0a..e99d0a49 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -5,24 +5,27 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string { return R"#( - // branchless baby! + // shoutout me: I fixed this shader being a bit pixelated while watching hentai + highp vec2 pixCoord = vec2(gl_FragCoord); pixCoord -= topLeft + fullSize * 0.5; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; pixCoord -= fullSize * 0.5 - radius; pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left + const float SMOOTHING_CONSTANT = 0.651724; // smoothing constant for the edge: more = blurrier, but smoother + if (pixCoord.x + pixCoord.y > radius) { float dist = length(pixCoord); - if (dist > radius) + if (dist > radius + SMOOTHING_CONSTANT * 2.0) discard; - if (dist > radius - 1.0) { + if (dist > radius - SMOOTHING_CONSTANT * 2.0) { float dist = length(pixCoord); - float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5); + float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; From 0920572e703201368c9fbcc9108ce1888600ffa2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:11:05 +0000 Subject: [PATCH 0218/1803] shaders: improve corner AA in borders shader --- src/render/shaders/Border.hpp | 10 ++++++++-- src/render/shaders/SharedValues.hpp | 3 +++ src/render/shaders/Textures.hpp | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/render/shaders/SharedValues.hpp diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index a33694a7..1f4a1d97 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include "SharedValues.hpp" // makes a stencil without corners inline const std::string FRAGBORDER1 = R"#( @@ -72,18 +74,22 @@ void main() { pixCoordOuter += vec2(1.0, 1.0) / fullSize; if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) { + // smoothing constant for the edge: more = blurrier, but smoother + const float SMOOTHING_CONSTANT = )#" + + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; + float dist = length(pixCoord); float distOuter = length(pixCoordOuter); float h = (thick / 2.0); if (dist < radius - h) { // lower - float normalized = smoothstep(0.0, 1.0, dist - radius + thick + 0.5); + float normalized = smoothstep(0.0, 1.0, (dist - radius + thick + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); additionalAlpha *= normalized; done = true; } else if (min(pixCoordOuter.x, pixCoordOuter.y) > 0.0) { // higher - float normalized = 1.0 - smoothstep(0.0, 1.0, distOuter - radiusOuter + 0.5); + float normalized = 1.0 - smoothstep(0.0, 1.0, (distOuter - radiusOuter + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); additionalAlpha *= normalized; done = true; } else if (distOuter < radiusOuter - h) { diff --git a/src/render/shaders/SharedValues.hpp b/src/render/shaders/SharedValues.hpp new file mode 100644 index 00000000..9a74c892 --- /dev/null +++ b/src/render/shaders/SharedValues.hpp @@ -0,0 +1,3 @@ +#pragma once + +constexpr float SHADER_ROUNDED_SMOOTHING_FACTOR = M_PI / 5.34665792551; \ No newline at end of file diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index e99d0a49..b203ad04 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include "SharedValues.hpp" inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string { return R"#( @@ -13,7 +15,9 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar pixCoord -= fullSize * 0.5 - radius; pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left - const float SMOOTHING_CONSTANT = 0.651724; // smoothing constant for the edge: more = blurrier, but smoother + // smoothing constant for the edge: more = blurrier, but smoother + const float SMOOTHING_CONSTANT = )#" + + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; if (pixCoord.x + pixCoord.y > radius) { From 64c46db0872a576a993035ac1fa5e40af53ca001 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:20:04 +0000 Subject: [PATCH 0219/1803] hyprctl: add mirrorOf to hyprctl monitors fixes #8026 --- src/debug/HyprCtl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index f5c63f86..3e0c75a6 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -107,6 +107,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer "activelyTearing": {}, "disabled": {}, "currentFormat": "{}", + "mirrorOf": "{}", "availableModes": [{}] }},)#", @@ -117,18 +118,19 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(), (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), - availableModesForOutput(m, format)); + m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tmirrorOf: {}\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->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m, format)); + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), + m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format)); } return result; From 81ad218b8b082ce4c9b04bbb668d3c219fc4ff6f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:28:55 +0000 Subject: [PATCH 0220/1803] shadow: fix double premultiplication shader takes straight alpha aaaa --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 52392436..eb0a029f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2485,7 +2485,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const glMatrix.transpose(); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif - glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r * col.a * a, col.g * col.a * a, col.b * col.a * a, col.a * a); + glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); const auto TOPLEFT = Vector2D(range + round, range + round); const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); From e4ab28b1fb063e5554c953c721779644ef6ada08 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:03:37 +0500 Subject: [PATCH 0221/1803] defaultConfig: update default config values for shadows (#8360) --- example/hyprland.conf | 10 ++++++---- src/config/defaultConfig.hpp | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index f1139c3b..edeeac01 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -86,10 +86,12 @@ decoration { active_opacity = 1.0 inactive_opacity = 1.0 - drop_shadow = true - shadow_range = 4 - shadow_render_power = 3 - col.shadow = rgba(1a1a1aee) + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } # https://wiki.hyprland.org/Configuring/Variables/#blur blur { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index facb16e2..02781770 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -99,10 +99,12 @@ decoration { active_opacity = 1.0 inactive_opacity = 1.0 - drop_shadow = true - shadow_range = 4 - shadow_render_power = 3 - col.shadow = rgba(1a1a1aee) + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } # https://wiki.hyprland.org/Configuring/Variables/#blur blur { From 3bf6f78dad5f78dd8f4f519ceaa5a98671c90b14 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:14:48 +0500 Subject: [PATCH 0222/1803] hyprland-systemd.desktop: change name back to Hyprland (#8351) --- systemd/hyprland-systemd.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop index 8c065a81..64ebbd47 100644 --- a/systemd/hyprland-systemd.desktop +++ b/systemd/hyprland-systemd.desktop @@ -3,5 +3,5 @@ Name=Hyprland (systemd session) Comment=An intelligent dynamic tiling Wayland compositor Exec=systemctl --user start --wait hyprland-session Type=Application -DesktopNames=Hyprland (systemd session) +DesktopNames=Hyprland Keywords=tiling;wayland;compositor; From 97a309b7844aea82b200139febc99998e7f06402 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Nov 2024 14:02:39 +0000 Subject: [PATCH 0223/1803] layershell: check if workspace is valid in onMap ref #8296 --- src/desktop/LayerSurface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index f073da82..eb3cdfd2 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -175,8 +175,7 @@ void CLayerSurface::onMap() { CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); - const auto WORKSPACE = PMONITOR->activeWorkspace; - const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN; + const bool FULLSCREEN = PMONITOR->activeWorkspace && PMONITOR->activeWorkspace->m_bHasFullscreenWindow && PMONITOR->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); readyToDelete = false; From 8f42401aa8ac5a7778e29024be7ef3e0a063de13 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 6 Nov 2024 17:52:10 +0100 Subject: [PATCH 0224/1803] groups: add merge_groups_on_groupbar (#8362) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/layout/DwindleLayout.cpp | 5 ----- src/layout/IHyprLayout.cpp | 10 +++------- src/layout/MasterLayout.cpp | 20 +++++++------------ .../decorations/CHyprGroupBarDecoration.cpp | 8 +++++++- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 5327c599..12e81f2a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -778,6 +778,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:merge_groups_on_groupbar", + .description = "whether one group will be merged with another when dragged into its groupbar", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, SConfigOptionDescription{ .value = "general:col.border_active", .description = "border color for inactive windows", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index eafe4cbb..769a7525 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -381,6 +381,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:merge_groups_on_groupbar", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 32f64e4e..e6e9090f 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -310,11 +310,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir return; } - if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) { - if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) - return; - } - // get the node under our cursor m_lDwindleNodesData.push_back(SDwindleNodeData()); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 980311d6..a312555f 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -344,12 +344,6 @@ void IHyprLayout::onEndDragWindow() { if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !FLOATEDINTOTILED) { - if (DRAGGINGWINDOW->m_bDraggingTiled) { - changeWindowFloatingMode(DRAGGINGWINDOW); - DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; - DRAGGINGWINDOW->m_bDraggingTiled = false; - } - if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); while (next != DRAGGINGWINDOW) { @@ -360,7 +354,9 @@ void IHyprLayout::onEndDragWindow() { } } - DRAGGINGWINDOW->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of the window + DRAGGINGWINDOW->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of the window + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + DRAGGINGWINDOW->m_bDraggingTiled = false; if (pWindow->m_bIsFloating) g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index afe79ecf..b8b3efea 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -101,21 +101,15 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->workspaceID = pWindow->workspaceID(); PNODE->pWindow = pWindow; - const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); - static auto PMFACT = CConfigValue("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.lock()) && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? - getNodeFromWindow(g_pCompositor->m_pLastWindow.lock()) : - getMasterNodeOnWorkspace(pWindow->workspaceID()); - - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - - if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) { - if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) - return; - } + auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow.lock()) && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? + getNodeFromWindow(g_pCompositor->m_pLastWindow.lock()) : + getMasterNodeOnWorkspace(pWindow->workspaceID()); + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); eOrientation orientation = getDynamicOrientation(pWindow->m_pWorkspace); const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index ec9f876b..b5189be5 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -405,10 +405,16 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND static auto PSTACKED = CConfigValue("group:groupbar:stacked"); static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); + static auto PMERGEGROUPSONGROUPBAR = CConfigValue("group:merge_groups_on_groupbar"); const bool FLOATEDINTOTILED = !m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled; - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR)) + g_pInputManager->m_bWasDraggingWindow = false; + + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) || + (!*PMERGEGROUPSONGROUPBAR && pDraggedWindow->m_sGroupData.pNextWindow.lock() && m_pWindow->m_sGroupData.pNextWindow.lock())) { + g_pInputManager->m_bWasDraggingWindow = true; return false; + } const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; const float BARSIZE = *PSTACKED ? m_fBarHeight + BAR_PADDING_OUTER_VERT : m_fBarWidth + BAR_HORIZONTAL_PADDING; From 083a5cf3c1127dd2f638c3e9a665a88dd54a59a4 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 6 Nov 2024 19:50:01 +0200 Subject: [PATCH 0225/1803] CI: update actions --- .github/workflows/ci.yaml | 2 +- .github/workflows/man-update.yaml | 4 ++-- .github/workflows/nix-update-inputs.yml | 4 ++-- .github/workflows/release.yaml | 2 +- .github/workflows/security-checks.yml | 2 +- .github/workflows/stale.yml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7739d2b2..22421d18 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,7 +39,7 @@ jobs: tar -cvf Hyprland.tar.xz hyprland - name: Release - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Build archive path: Hyprland.tar.xz diff --git a/.github/workflows/man-update.yaml b/.github/workflows/man-update.yaml index b47787c0..6c0a72f3 100644 --- a/.github/workflows/man-update.yaml +++ b/.github/workflows/man-update.yaml @@ -17,14 +17,14 @@ jobs: run: sudo apt install pandoc - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.PAT }} - name: Build man pages run: make man - - uses: stefanzweifel/git-auto-commit-action@v4 + - uses: stefanzweifel/git-auto-commit-action@v5 name: Commit with: commit_message: "[gha] build man pages" diff --git a/.github/workflows/nix-update-inputs.yml b/.github/workflows/nix-update-inputs.yml index a8f68f3b..c9a094a2 100644 --- a/.github/workflows/nix-update-inputs.yml +++ b/.github/workflows/nix-update-inputs.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.PAT }} @@ -22,6 +22,6 @@ jobs: run: nix/update-inputs.sh - name: Commit - uses: stefanzweifel/git-auto-commit-action@v4 + uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "[gha] Nix: update inputs" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d5ff1aa0..44baff97 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout Hyprland id: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 4f539132..284500e6 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -13,7 +13,7 @@ jobs: security-events: write steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Scan with Flawfinder uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b8be5f55..9d2eed80 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,7 +19,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.STALEBOT_PAT }} stale-issue-label: "stale" From 0ec128e5ed5e15aaebff6c4b5983326ab524d690 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Nov 2024 22:11:41 +0000 Subject: [PATCH 0226/1803] renderer: don't rely on datarootdir for local share --- src/render/OpenGL.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index eb0a029f..63a7e822 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -18,6 +18,7 @@ const std::vector ASSET_PATHS = { DATAROOTDIR, #endif "/usr/share", + "/usr/local/share", }; inline void loadGLProc(void* pProc, const char* name) { From 2ec2b3bfb39ba22ba945bb23dc95970dfa50eb5a Mon Sep 17 00:00:00 2001 From: dawsers <47487972+dawsers@users.noreply.github.com> Date: Thu, 7 Nov 2024 00:30:17 +0100 Subject: [PATCH 0227/1803] renderer: minor fixup to window rendering logic (#8359) Don't render animating windows out of their monitor when they are not moving workspaces --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6af3a99d..469acda9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -355,7 +355,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { windowBox.translate(pWindow->m_vFloatingOffset); const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize}; - if (!windowBox.intersection(monitorBox).empty()) + if (!windowBox.intersection(monitorBox).empty() && (pWindow->workspaceID() == pMonitor->activeWorkspaceID() || pWindow->m_iMonitorMovedFrom != -1)) return true; } From 2dd0b2af71b2bd37f1febc608897f56d1eabab4c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 7 Nov 2024 10:51:48 +0200 Subject: [PATCH 0228/1803] flake.lock: update --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 8cee27e3..b9055015 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1729527199, - "narHash": "sha256-D5/YksfRga8Akd04ZtIkuYSIOjXVrAzQIQBSeplokzU=", + "lastModified": 1730968822, + "narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "8d732fa8aff8b12ef2b1e2f00fc8153e41312b72", + "rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1728941256, - "narHash": "sha256-WRypmcZ2Bw94lLmcmxYokVOHPJSZ7T06V49QZ4tkZeQ=", + "lastModified": 1730968903, + "narHash": "sha256-zFvzLXcSm0Ia4XI1SE4FQ9KE63hlGrRWhLtwMolWuR8=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "fd4be8b9ca932f7384e454bcd923c5451ef2aa85", + "rev": "3ce0cde8709cdacbfba471f8e828433b58a561e9", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730531603, - "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "lastModified": 1730785428, + "narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", "type": "github" }, "original": { @@ -205,11 +205,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1720386169, - "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "lastModified": 1730741070, + "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1729104314, - "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=", + "lastModified": 1730814269, + "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6", + "rev": "d70155fdc00df4628446352fc58adc640cd705c2", "type": "github" }, "original": { From e58e97b0a38b8ccc87a4304c9e4e2b37c9966875 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 7 Nov 2024 10:52:12 +0200 Subject: [PATCH 0229/1803] Nix: build aquamarine and hyprutils in debug when using hyprland-debug --- nix/default.nix | 4 +--- nix/overlays.nix | 8 +++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index d463e271..29d31485 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -56,6 +56,7 @@ adapters = flatten [ stdenvAdapters.useMoldLinker + (lib.optional debug stdenvAdapters.keepDebugInfo) ]; customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters; @@ -147,9 +148,6 @@ in then "debugoptimized" else "release"; - # we want as much debug info as possible - dontStrip = debug; - mesonFlags = flatten [ (mapAttrsToList mesonEnable { "xwayland" = enableXWayland; diff --git a/nix/overlays.nix b/nix/overlays.nix index b1eb66ad..a7106315 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -40,7 +40,13 @@ in { inherit date; }; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; - hyprland-debug = final.hyprland.override {debug = true;}; + + # Build major libs with debug to get as much info as possible in a stacktrace + hyprland-debug = final.hyprland.override { + aquamarine = final.aquamarine.override {debug = true;}; + hyprutils = final.hyprutils.override {debug = true;}; + debug = true; + }; hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;}; # deprecated packages From 3b66351eeb76e802bac37cc892529549efc49905 Mon Sep 17 00:00:00 2001 From: nickodei <46863421+nickodei@users.noreply.github.com> Date: Fri, 8 Nov 2024 18:25:37 +0100 Subject: [PATCH 0230/1803] input: Refocus window on scrolling if follows mouse (#8361) --- src/managers/input/InputManager.cpp | 36 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index af725927..b12a6e03 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -759,6 +759,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { static auto PINPUTSCROLLFACTOR = CConfigValue("input:scroll_factor"); static auto PTOUCHPADSCROLLFACTOR = CConfigValue("input:touchpad:scroll_factor"); static auto PEMULATEDISCRETE = CConfigValue("input:emulate_discrete_scroll"); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e.source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR); @@ -774,24 +775,33 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); const auto PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); - if (PWINDOW && PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) - return; + if (PWINDOW) { + if (PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) + return; - if (PWINDOW && *POFFWINDOWAXIS != 1) { - const auto BOX = PWINDOW->getWindowMainSurfaceBox(); + if (*POFFWINDOWAXIS != 1) { + const auto BOX = PWINDOW->getWindowMainSurfaceBox(); - if (!BOX.containsPoint(MOUSECOORDS) && !PWINDOW->hasPopupAt(MOUSECOORDS)) { - if (*POFFWINDOWAXIS == 0) - return; + if (!BOX.containsPoint(MOUSECOORDS) && !PWINDOW->hasPopupAt(MOUSECOORDS)) { + if (*POFFWINDOWAXIS == 0) + return; - const auto TEMPCURX = std::clamp(MOUSECOORDS.x, BOX.x, BOX.x + BOX.w - 1); - const auto TEMPCURY = std::clamp(MOUSECOORDS.y, BOX.y, BOX.y + BOX.h - 1); + const auto TEMPCURX = std::clamp(MOUSECOORDS.x, BOX.x, BOX.x + BOX.w - 1); + const auto TEMPCURY = std::clamp(MOUSECOORDS.y, BOX.y, BOX.y + BOX.h - 1); - if (*POFFWINDOWAXIS == 3) - g_pCompositor->warpCursorTo({TEMPCURX, TEMPCURY}, true); + if (*POFFWINDOWAXIS == 3) + g_pCompositor->warpCursorTo({TEMPCURX, TEMPCURY}, true); - g_pSeatManager->sendPointerMotion(e.timeMs, Vector2D{TEMPCURX, TEMPCURY} - BOX.pos()); - g_pSeatManager->sendPointerFrame(); + g_pSeatManager->sendPointerMotion(e.timeMs, Vector2D{TEMPCURX, TEMPCURY} - BOX.pos()); + g_pSeatManager->sendPointerFrame(); + } + } + + if (g_pSeatManager->state.pointerFocus) { + const auto PCURRWINDOW = g_pCompositor->getWindowFromSurface(g_pSeatManager->state.pointerFocus.lock()); + + if (*PFOLLOWMOUSE == 1 && PCURRWINDOW && PWINDOW != PCURRWINDOW) + simulateMouseMovement(); } } } From 4c7a2faf85a2d74508cc8a95df42ebe52b47383b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 01:53:01 +0000 Subject: [PATCH 0231/1803] input: cleanup device naming logic ref #8301 --- src/devices/IHID.hpp | 2 +- src/devices/IKeyboard.hpp | 1 - src/devices/IPointer.hpp | 1 - src/devices/ITouch.hpp | 1 - src/devices/Tablet.hpp | 5 ----- src/managers/input/InputManager.cpp | 27 ++++----------------------- src/managers/input/Tablets.cpp | 6 ++++++ 7 files changed, 11 insertions(+), 32 deletions(-) diff --git a/src/devices/IHID.hpp b/src/devices/IHID.hpp index cac25112..4a0ff8fd 100644 --- a/src/devices/IHID.hpp +++ b/src/devices/IHID.hpp @@ -36,5 +36,5 @@ class IHID { CSignal destroy; } events; - std::string deviceName; + std::string deviceName, hlName; }; \ No newline at end of file diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 76d2c31b..dce2127a 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -94,7 +94,6 @@ class IKeyboard : public IHID { std::array modIndexes = {XKB_MOD_INVALID}; uint32_t leds = 0; - std::string hlName = ""; std::string xkbFilePath = ""; std::string xkbKeymapString = ""; int xkbKeymapFD = -1; diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index f38ef55a..503a690e 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -104,7 +104,6 @@ class IPointer : public IHID { CSignal holdEnd; } pointerEvents; - std::string hlName; bool connected = false; // means connected to the cursor std::string boundOutput = ""; diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index bf969b2f..766c0510 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -44,7 +44,6 @@ class ITouch : public IHID { CSignal frame; } touchEvents; - std::string hlName = ""; std::string boundOutput = ""; WP self; diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 01901721..4894ac8e 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -92,7 +92,6 @@ class CTablet : public IHID { WP self; bool relativeInput = false; - std::string hlName = ""; std::string boundOutput = ""; CBox activeArea; CBox boundBox; // output-local @@ -154,8 +153,6 @@ class CTabletPad : public IHID { WP self; WP parent; - std::string hlName; - private: CTabletPad(SP pad); @@ -210,8 +207,6 @@ class CTabletTool : public IHID { std::vector buttonsDown; Vector2D absolutePos; // last known absolute position. - std::string hlName; - private: CTabletTool(SP tool); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b12a6e03..2787cbf7 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1655,31 +1655,12 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) { auto proposedNewName = deviceNameToInternalString(internalName); int dupeno = 0; - while (std::find_if(m_vKeyboards.begin(), m_vKeyboards.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vKeyboards.end()) + auto makeNewName = [&]() { return (proposedNewName.empty() ? "unknown-device" : proposedNewName) + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }; + + while (std::find_if(m_vHIDs.begin(), m_vHIDs.end(), [&](const auto& other) { return other->hlName == makeNewName(); }) != m_vHIDs.end()) dupeno++; - while (std::find_if(m_vPointers.begin(), m_vPointers.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vPointers.end()) - dupeno++; - - while (std::find_if(m_vTouches.begin(), m_vTouches.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTouches.end()) - dupeno++; - - while (std::find_if(m_vTabletPads.begin(), m_vTabletPads.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTabletPads.end()) - dupeno++; - - while (std::find_if(m_vTablets.begin(), m_vTablets.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTablets.end()) - dupeno++; - - while (std::find_if(m_vTabletTools.begin(), m_vTabletTools.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTabletTools.end()) - dupeno++; - - return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); + return makeNewName(); } void CInputManager::releaseAllMouseButtons() { diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 9f80726e..3884afec 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -228,6 +228,12 @@ SP CInputManager::ensureTabletToolPresent(SPhlName = deviceNameToInternalString(pTool->getName()); + } catch (std::exception& e) { + Debug::log(ERR, "Tablet had no name???"); // logic error + } + PTOOL->events.destroy.registerStaticListener( [this](void* owner, std::any d) { auto TOOL = ((CTabletTool*)owner)->self; From f43d4a86383bc8a8251987552ad5a0e51dd85868 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:25:34 +0000 Subject: [PATCH 0232/1803] layershell: minor cleanups and improvements to focus ref #8293 --- src/desktop/LayerSurface.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index eb3cdfd2..31c2482a 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -222,7 +222,7 @@ void CLayerSurface::onUnmap() { const auto PMONITOR = monitor.lock(); - const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); + const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == surface->resource() || g_pSeatManager->state.pointerFocus == surface->resource(); if (!PMONITOR) return; @@ -231,7 +231,7 @@ void CLayerSurface::onUnmap() { // vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable())) g_pInputManager->refocusLastWindow(PMONITOR); - else if (g_pCompositor->m_pLastFocus) + else if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus != surface->resource()) g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock()); CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; @@ -320,8 +320,15 @@ void CLayerSurface::onCommit() { realSize.setValueAndWarp(geometry.size()); } - if (mapped) { - const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); + if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) { + bool WASLASTFOCUS = false; + layerSurface->surface->breadthfirst( + [&WASLASTFOCUS](SP surf, const Vector2D& offset, void* data) { WASLASTFOCUS = WASLASTFOCUS || g_pSeatManager->state.keyboardFocus == surf; }, + nullptr); + if (!WASLASTFOCUS && popupHead) { + popupHead->breadthfirst([&WASLASTFOCUS](CPopup* popup, void* data) { WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); }, + nullptr); + } const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; @@ -331,11 +338,13 @@ void CLayerSurface::onCommit() { std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); // if the surface was focused and interactive but now isn't, refocus - if (WASLASTFOCUS && !layerSurface->current.interactivity) { + if (WASLASTFOCUS && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) { // moveMouseUnified won't focus non interactive layers but it won't unfocus them either, // so unfocus the surface here. g_pCompositor->focusSurface(nullptr); g_pInputManager->refocusLastWindow(monitor.lock()); + } else if (WASLASTFOCUS && WASEXCLUSIVE && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) { + g_pInputManager->simulateMouseMovement(); } else if (!WASEXCLUSIVE && ISEXCLUSIVE) { // if now exclusive and not previously g_pSeatManager->setGrab(nullptr); From 0ccc0ace88fab3969c2eca95deb1cc9b2ac0d16d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:25:54 +0000 Subject: [PATCH 0233/1803] input: ignore non-kb ls-es in refocusLastWindow ref #8293 --- src/managers/input/InputManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2787cbf7..c190f589 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1388,13 +1388,19 @@ void CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { foundSurface = m_dExclusiveLSes[m_dExclusiveLSes.size() - 1]->surface->resource(); // then any surfaces above windows on the same monitor - if (!foundSurface) + if (!foundSurface) { foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface); + if (pFoundLayerSurface && pFoundLayerSurface->interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) + foundSurface = nullptr; + } - if (!foundSurface) + if (!foundSurface) { foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface); + if (pFoundLayerSurface && pFoundLayerSurface->interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) + foundSurface = nullptr; + } if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisibleNotCovered(g_pCompositor->m_pLastWindow->m_pWorkspace)) { // then the last focused window if we're on the same workspace as it From 726d69782124ffb5b609c0377cd21cfd4d6f6f88 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:26:24 +0000 Subject: [PATCH 0234/1803] popup: minor cleanups don't iterate over unmapped popups in breadthfirst, don't refocus if it wasnt in focus ref #8293 --- src/desktop/Popup.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 58995f00..ea6e877b 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -4,6 +4,8 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" +#include "../managers/SeatManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) { @@ -106,6 +108,8 @@ void CPopup::onUnmap() { return; } + m_bMapped = false; + m_vLastSize = m_pResource->surface->surface->current.size; const auto COORDS = coordsGlobal(); @@ -116,8 +120,6 @@ void CPopup::onUnmap() { m_pSubsurfaceHead.reset(); - g_pInputManager->simulateMouseMovement(); - if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP) g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer)); @@ -131,6 +133,11 @@ void CPopup::onUnmap() { g_pHyprRenderer->damageBox(&box); }, nullptr); + + const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource(); + + if (WASLASTFOCUS) + g_pInputManager->simulateMouseMovement(); } void CPopup::onCommit(bool ignoreSiblings) { @@ -317,7 +324,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) { breadthfirst([](CPopup* popup, void* data) { ((std::vector*)data)->push_back(popup); }, &popups); for (auto const& p : popups | std::views::reverse) { - if (!p->m_pResource) + if (!p->m_pResource || !p->m_bMapped) continue; if (!allowsInput) { From b9c439a55e5ecef563657da211bc10ddc3273a1c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:27:01 +0000 Subject: [PATCH 0235/1803] compositor: make sure we don't ret early on no surface if there is no implicit surface passed, make sure the current focus is not null, otherwise we nope early without focusing the window fixes #8293 --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 495a2d85..da20c5cf 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1062,7 +1062,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface return; } - if (m_pLastWindow.lock() == pWindow && g_pSeatManager->state.keyboardFocus == pSurface) + if (m_pLastWindow.lock() == pWindow && g_pSeatManager->state.keyboardFocus == pSurface && g_pSeatManager->state.keyboardFocus) return; if (pWindow->m_bPinned) From cca227a53e10b9101d2fbcfb99e6360b416d7168 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:34:04 +0000 Subject: [PATCH 0236/1803] tablet: use inputMgr unified naming scheme ref #8301 --- src/desktop/LayerSurface.cpp | 7 +++++-- src/managers/input/Tablets.cpp | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 31c2482a..cd1c4742 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -326,8 +326,11 @@ void CLayerSurface::onCommit() { [&WASLASTFOCUS](SP surf, const Vector2D& offset, void* data) { WASLASTFOCUS = WASLASTFOCUS || g_pSeatManager->state.keyboardFocus == surf; }, nullptr); if (!WASLASTFOCUS && popupHead) { - popupHead->breadthfirst([&WASLASTFOCUS](CPopup* popup, void* data) { WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); }, - nullptr); + popupHead->breadthfirst( + [&WASLASTFOCUS](CPopup* popup, void* data) { + WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); + }, + nullptr); } const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 3884afec..36bd5636 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -201,7 +201,7 @@ void CInputManager::newTablet(SP pDevice) { m_vHIDs.push_back(PNEWTABLET); try { - PNEWTABLET->hlName = deviceNameToInternalString(pDevice->getName()); + PNEWTABLET->hlName = g_pInputManager->getNameForNewDevice(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -229,7 +229,7 @@ SP CInputManager::ensureTabletToolPresent(SPhlName = deviceNameToInternalString(pTool->getName()); + PTOOL->hlName = g_pInputManager->getNameForNewDevice(pTool->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -249,7 +249,7 @@ void CInputManager::newTabletPad(SP pDevice) { m_vHIDs.push_back(PNEWPAD); try { - PNEWPAD->hlName = deviceNameToInternalString(pDevice->getName()); + PNEWPAD->hlName = g_pInputManager->getNameForNewDevice(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Pad had no name???"); // logic error } From a425fbebe4cf4238e48a42f724ef2208959d66cf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 14:27:47 +0000 Subject: [PATCH 0237/1803] version: bump to 0.45.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a8ab6c96..bcce5d06 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.44.0 +0.45.0 From dca75db127fedc58fc85ae0e6e47162e3d5d16f9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 16:56:43 +0000 Subject: [PATCH 0238/1803] defaultConfig: fixup smart gaps rules --- example/hyprland.conf | 9 +++------ src/config/defaultConfig.hpp | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index edeeac01..fe1a831a 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -136,13 +136,10 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" # uncomment all if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0 -# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = w[tv1], gapsout:0, gapsin:0 # workspace = f[1], gapsout:0, gapsin:0 -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1] # windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] # windowrulev2 = rounding 0, floating:0, onworkspace:f[1] diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 02781770..d680e92b 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -149,13 +149,10 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" # uncomment all if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0 -# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = w[tv1], gapsout:0, gapsin:0 # workspace = f[1], gapsout:0, gapsin:0 -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1] # windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] # windowrulev2 = rounding 0, floating:0, onworkspace:f[1] From a8ff3a452c1c445d24bdd9e7e4fcd66c8ef2a147 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 17:11:38 +0000 Subject: [PATCH 0239/1803] core: move to os/Process from hyprutils nix bump too --- CMakeLists.txt | 2 +- flake.lock | 6 +++--- hyprpm/CMakeLists.txt | 2 +- hyprpm/src/core/PluginManager.cpp | 19 ++++++++----------- src/helpers/MiscFunctions.cpp | 20 ++++++++------------ 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 877ba461..1ac2e10f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ else() endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) -pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) +pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2) diff --git a/flake.lock b/flake.lock index b9055015..47254052 100644 --- a/flake.lock +++ b/flake.lock @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1730968903, - "narHash": "sha256-zFvzLXcSm0Ia4XI1SE4FQ9KE63hlGrRWhLtwMolWuR8=", + "lastModified": 1731163338, + "narHash": "sha256-Qflei0JBeqQ0c8jxA8e982xAxJvfMwfx4Aci2eJi84s=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "3ce0cde8709cdacbfba471f8e828433b58a561e9", + "rev": "60d3dece30f98e8ad85131829c8529950630d6bc", "type": "github" }, "original": { diff --git a/hyprpm/CMakeLists.txt b/hyprpm/CMakeLists.txt index 692e8da1..65935638 100644 --- a/hyprpm/CMakeLists.txt +++ b/hyprpm/CMakeLists.txt @@ -9,7 +9,7 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") set(CMAKE_CXX_STANDARD 23) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) add_executable(hyprpm ${SRCFILES}) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 57c67641..159b9cd6 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -23,22 +23,19 @@ #include #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::OS; static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; - std::array buffer; - std::string result; - using PcloseType = int (*)(FILE*); - const std::unique_ptr pipe(popen(cmd.c_str(), "r"), static_cast(pclose)); - if (!pipe) - return ""; - result.reserve(buffer.size()); - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; + CProcess proc("/bin/sh", {cmd}); + + if (!proc.runSync()) + return "error"; + + return proc.stdOut(); } SHyprlandVersion CPluginManager::getHyprlandVersion() { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 878f5ca1..75154796 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -17,7 +17,9 @@ #include #endif #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::OS; #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include @@ -583,18 +585,12 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve // Execute a shell command and get the output std::string execAndGet(const char* cmd) { - std::array buffer; - std::string result; - using PcloseType = int (*)(FILE*); - const std::unique_ptr pipe(popen(cmd, "r"), static_cast(pclose)); - if (!pipe) { - Debug::log(ERR, "execAndGet: failed in pipe"); - return ""; - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; + CProcess proc("/bin/sh", {cmd}); + + if (!proc.runSync()) + return "error"; + + return proc.stdOut(); } void logSystemInfo() { From 99b01c5d124d08648d4c9e6754485ea585c42707 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Nov 2024 15:54:00 +0000 Subject: [PATCH 0240/1803] hyprpm: fix format --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 159b9cd6..ef77f540 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -31,7 +31,7 @@ static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; CProcess proc("/bin/sh", {cmd}); - + if (!proc.runSync()) return "error"; From 9e628067fc54851dc9138c2882abb21f72c5a5a6 Mon Sep 17 00:00:00 2001 From: WavyEbuilder Date: Sun, 10 Nov 2024 15:54:15 +0000 Subject: [PATCH 0241/1803] debug: clean up opening of files in HyprCtl (#8401) `std::ifstream` is more suited than `execAndGet` here. --- src/debug/HyprCtl.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 3e0c75a6..709d8b69 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1,6 +1,7 @@ #include "HyprCtl.hpp" #include +#include #include #include #include @@ -949,11 +950,27 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif result += "GPU information: \n" + GPUINFO; - if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) - result += execAndGet("cat /proc/driver/nvidia/version | grep NVRM"); + if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) { + std::ifstream file("/proc/driver/nvidia/version"); + std::string line; + if (file.is_open()) { + while (std::getline(file, line)) { + if (!line.contains("NVRM")) + continue; + result += line; + result += "\n"; + } + } else + result += "error"; + } result += "\n\n"; - result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; + if (std::ifstream file("/etc/os-release"); file.is_open()) { + std::stringstream buffer; + buffer << file.rdbuf(); + result += "os-release: " + buffer.str() + "\n\n"; + } else + result += "os-release: error\n\n"; result += "plugins:\n"; if (g_pPluginSystem) { From c10739e6e35c30ef5f273bfe5d219d361a31e226 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Nov 2024 22:53:11 +0000 Subject: [PATCH 0242/1803] core: fixup execAndGet fixes #8410 --- hyprpm/src/core/PluginManager.cpp | 2 +- src/helpers/MiscFunctions.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index ef77f540..051ad500 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -30,7 +30,7 @@ using namespace Hyprutils::OS; static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; - CProcess proc("/bin/sh", {cmd}); + CProcess proc("/bin/sh", {"-c", cmd}); if (!proc.runSync()) return "error"; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 75154796..7b4d63a7 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -585,7 +585,7 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve // Execute a shell command and get the output std::string execAndGet(const char* cmd) { - CProcess proc("/bin/sh", {cmd}); + CProcess proc("/bin/sh", {"-c", cmd}); if (!proc.runSync()) return "error"; From 1fa0cd7a7574c8e93c567bf0453c155285dd3960 Mon Sep 17 00:00:00 2001 From: WavyEbuilder Date: Mon, 11 Nov 2024 13:44:41 +0000 Subject: [PATCH 0243/1803] debug: clean up fetching of the contents of /proc/device-tree (#8413) --- src/debug/HyprCtl.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 709d8b69..6429e781 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1,7 +1,9 @@ #include "HyprCtl.hpp" +#include #include #include +#include #include #include #include @@ -945,7 +947,24 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) - const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible"); + std::string GPUINFO; + const std::filesystem::path dev_tree = "/proc/device-tree"; + try { + if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) { + std::for_each(std::filesystem::directory_iterator(dev_tree), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& entry) { + if (std::filesystem::is_directory(entry) && entry.path().filename().string().starts_with("soc")) { + std::for_each(std::filesystem::directory_iterator(entry.path()), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& sub_entry) { + if (std::filesystem::is_directory(sub_entry) && sub_entry.path().filename().string().starts_with("gpu")) { + std::filesystem::path file_path = sub_entry.path() / "compatible"; + std::ifstream file(file_path); + if (file) + GPUINFO.append(std::istreambuf_iterator(file), std::istreambuf_iterator()); + } + }); + } + }); + } + } catch (...) { GPUINFO = "error"; } #else const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif From 07052a515bea46e8b01d3ca5b2c284c272c5ed34 Mon Sep 17 00:00:00 2001 From: JManch <61563764+JManch@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:45:33 +0000 Subject: [PATCH 0244/1803] pointer: map devices across all outputs by default (#8352) --- src/config/ConfigDescriptions.hpp | 10 +++- src/config/ConfigManager.cpp | 2 + src/devices/Tablet.hpp | 3 +- src/devices/VirtualPointer.cpp | 2 +- src/managers/PointerManager.cpp | 76 ++++++++++++++--------------- src/managers/input/InputManager.cpp | 3 ++ 6 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 12e81f2a..fde8173d 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -620,16 +620,22 @@ inline static const std::vector CONFIG_OPTIONS = { }, SConfigOptionDescription{ .value = "input:tablet:output", - .description = "the monitor to bind tablets. Empty means unbound..", + .description = "the monitor to bind tablets. Can be current or a monitor name. Leave empty to map across all monitors.", .type = CONFIG_OPTION_STRING_SHORT, .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? }, SConfigOptionDescription{ .value = "input:tablet:region_position", - .description = "position of the mapped region in monitor layout.", + .description = "position of the mapped region in monitor layout relative to the top left corner of the bound monitor or all monitors.", .type = CONFIG_OPTION_VECTOR, .data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}}, }, + SConfigOptionDescription{ + .value = "input:tablet:absolute_region_position", + .description = "whether to treat the region_position as an absolute position in monitor layout. Only applies when output is empty.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, SConfigOptionDescription{ .value = "input:tablet:region_size", .description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 769a7525..fbbc8dbd 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -516,6 +516,7 @@ CConfigManager::CConfigManager() { 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:absolute_region_position", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:tablet:region_size", Hyprlang::VEC2{0, 0}); m_pConfig->addConfigValue("input:tablet:relative_input", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:tablet:left_handed", Hyprlang::INT{0}); @@ -625,6 +626,7 @@ CConfigManager::CConfigManager() { m_pConfig->addSpecialConfigValue("device", "output", {STRVAL_EMPTY}); 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", "absolute_region_position", Hyprlang::INT{0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "region_size", Hyprlang::VEC2{0, 0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "relative_input", Hyprlang::INT{0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "active_area_position", Hyprlang::VEC2{0, 0}); // only for tablets diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 4894ac8e..8f49c984 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -92,9 +92,10 @@ class CTablet : public IHID { WP self; bool relativeInput = false; + bool absolutePos = false; std::string boundOutput = ""; CBox activeArea; - CBox boundBox; // output-local + CBox boundBox; private: CTablet(SP tablet); diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index 7ad18775..514c8c32 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -38,7 +38,7 @@ CVirtualPointer::CVirtualPointer(SP resource) : point listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); }); listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); }); - boundOutput = resource->boundOutput ? resource->boundOutput->szName : "entire"; + boundOutput = resource->boundOutput ? resource->boundOutput->szName : ""; deviceName = pointer->name; } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index b309ba82..75be235f 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -668,9 +668,7 @@ void CPointerManager::move(const Vector2D& deltaLogical) { } void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { - - PHLMONITOR currentMonitor = g_pCompositor->m_pLastMonitor.lock(); - if (!currentMonitor || !dev) + if (!dev) return; if (!std::isnan(abs.x)) @@ -678,20 +676,44 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { if (!std::isnan(abs.y)) abs.y = std::clamp(abs.y, 0.0, 1.0); - // in logical global - CBox mappedArea = currentMonitor->logicalBox(); + // find x and y size of the entire space + const auto& MONITORS = g_pCompositor->m_vMonitors; + Vector2D topLeft = MONITORS.at(0)->vecPosition, bottomRight = MONITORS.at(0)->vecPosition + MONITORS.at(0)->vecSize; + for (size_t i = 1; i < MONITORS.size(); ++i) { + const auto EXTENT = MONITORS[i]->logicalBox().extent(); + const auto POS = MONITORS[i]->logicalBox().pos(); + if (EXTENT.x > bottomRight.x) + bottomRight.x = EXTENT.x; + if (EXTENT.y > bottomRight.y) + bottomRight.y = EXTENT.y; + if (POS.x < topLeft.x) + topLeft.x = POS.x; + if (POS.y < topLeft.y) + topLeft.y = POS.y; + } + CBox mappedArea = {topLeft, bottomRight - topLeft}; + + auto outputMappedArea = [&mappedArea](const std::string& output) { + if (output == "current") { + if (const auto PLASTMONITOR = g_pCompositor->m_pLastMonitor.lock(); PLASTMONITOR) + return PLASTMONITOR->logicalBox(); + } else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(output); PMONITOR) + return PMONITOR->logicalBox(); + return mappedArea; + }; switch (dev->getType()) { case HID_TYPE_TABLET: { CTablet* TAB = reinterpret_cast(dev.get()); if (!TAB->boundOutput.empty()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromString(TAB->boundOutput); PMONITOR) { - currentMonitor = PMONITOR->self.lock(); - mappedArea = currentMonitor->logicalBox(); - } - } + mappedArea = outputMappedArea(TAB->boundOutput); + mappedArea.translate(TAB->boundBox.pos()); + } else if (TAB->absolutePos) { + mappedArea.x = TAB->boundBox.x; + mappedArea.y = TAB->boundBox.y; + } else + mappedArea.translate(TAB->boundBox.pos()); - mappedArea.translate(TAB->boundBox.pos()); if (!TAB->boundBox.empty()) { mappedArea.w = TAB->boundBox.w; mappedArea.h = TAB->boundBox.h; @@ -700,38 +722,14 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { } case HID_TYPE_TOUCH: { ITouch* TOUCH = reinterpret_cast(dev.get()); - if (!TOUCH->boundOutput.empty()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromString(TOUCH->boundOutput); PMONITOR) { - currentMonitor = PMONITOR->self.lock(); - mappedArea = currentMonitor->logicalBox(); - } - } + if (!TOUCH->boundOutput.empty()) + mappedArea = outputMappedArea(TOUCH->boundOutput); break; } case HID_TYPE_POINTER: { IPointer* POINTER = reinterpret_cast(dev.get()); - if (!POINTER->boundOutput.empty()) { - if (POINTER->boundOutput == "entire") { - // find x and y size of the entire space - Vector2D bottomRight = {-9999999, -9999999}, topLeft = {9999999, 9999999}; - for (auto const& m : g_pCompositor->m_vMonitors) { - const auto EXTENT = m->logicalBox().extent(); - const auto POS = m->logicalBox().pos(); - if (EXTENT.x > bottomRight.x) - bottomRight.x = EXTENT.x; - if (EXTENT.y > bottomRight.y) - bottomRight.y = EXTENT.y; - if (POS.x < topLeft.x) - topLeft.x = POS.x; - if (POS.y < topLeft.y) - topLeft.y = POS.y; - } - mappedArea = {topLeft, bottomRight - topLeft}; - } else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(POINTER->boundOutput); PMONITOR) { - currentMonitor = PMONITOR->self.lock(); - mappedArea = currentMonitor->logicalBox(); - } - } + if (!POINTER->boundOutput.empty()) + mappedArea = outputMappedArea(POINTER->boundOutput); break; } default: break; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index c190f589..9110cd15 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1595,6 +1595,9 @@ void CInputManager::setTabletConfigs() { const auto REGION_SIZE = g_pConfigManager->getDeviceVec(NAME, "region_size", "input:tablet:region_size"); t->boundBox = {REGION_POS, REGION_SIZE}; + const auto ABSOLUTE_REGION_POS = g_pConfigManager->getDeviceInt(NAME, "absolute_region_position", "input:tablet:absolute_region_position"); + t->absolutePos = ABSOLUTE_REGION_POS; + const auto ACTIVE_AREA_SIZE = g_pConfigManager->getDeviceVec(NAME, "active_area_size", "input:tablet:active_area_size"); const auto ACTIVE_AREA_POS = g_pConfigManager->getDeviceVec(NAME, "active_area_position", "input:tablet:active_area_position"); if (ACTIVE_AREA_SIZE.x != 0 || ACTIVE_AREA_SIZE.y != 0) { From a551f85b9129eac76a5f295ecfe4fb39f96f435c Mon Sep 17 00:00:00 2001 From: dawsers <47487972+dawsers@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:48:50 +0100 Subject: [PATCH 0245/1803] renderer: scaled surfaces could have zero area (#8423) --- src/render/Renderer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 469acda9..d98e32a9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -222,6 +222,11 @@ static void renderSurface(SP surface, int x, int y, void* da windowBox.height = RDATA->h - y; } + const auto PROJSIZEUNSCALED = windowBox.size(); + + windowBox.scale(RDATA->pMonitor->scale); + windowBox.round(); + if (windowBox.width <= 1 || windowBox.height <= 1) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { Debug::log(TRACE, "presentFeedback for invisible surface"); @@ -231,11 +236,6 @@ static void renderSurface(SP surface, int x, int y, void* da return; // invisible } - const auto PROJSIZEUNSCALED = windowBox.size(); - - windowBox.scale(RDATA->pMonitor->scale); - windowBox.round(); - const bool MISALIGNEDFSV1 = std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ && windowBox.size() != surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, surface->current.bufferSize.x, 3) && DELTALESSTHAN(windowBox.height, surface->current.bufferSize.y, 3) /* off by one-or-two */ && From 8fa4cfb7dfa0be52a66db5f3b13e0ecde3d78b41 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 11 Nov 2024 13:55:32 +0000 Subject: [PATCH 0246/1803] keybinds: don't animate fullscreen size/pos changes coming in when fullscreen, don't animate the pos/size when switching to another fullscreen window, as they can look weird and distracting. Ideally we would do it differently but it's not really possible to do well without reading minds --- src/managers/KeybindManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 5be6a1d9..f2fdab53 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -338,6 +338,10 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { if (!PWINDOWTOCHANGETO->m_bPinned) g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); + + // warp the position + size animation, otherwise it looks weird. + PWINDOWTOCHANGETO->m_vRealPosition.warp(); + PWINDOWTOCHANGETO->m_vRealSize.warp(); } else { updateRelativeCursorCoords(); g_pCompositor->focusWindow(PWINDOWTOCHANGETO); @@ -2110,6 +2114,10 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned) g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE); + + // warp the position + size animation, otherwise it looks weird. + PWINDOW->m_vRealPosition.warp(); + PWINDOW->m_vRealSize.warp(); } } else g_pCompositor->focusWindow(PWINDOW); From 430b5c302a358faf888a015a7a7009a824e62d99 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:35:01 +0500 Subject: [PATCH 0247/1803] systemd: hyprland-systemd.desktop -> hyprland-uwsm.desktop Remove hyprland-session.service. --- systemd/hyprland-systemd.desktop | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop index 64ebbd47..2ed1031b 100644 --- a/systemd/hyprland-systemd.desktop +++ b/systemd/hyprland-systemd.desktop @@ -1,7 +1,6 @@ [Desktop Entry] -Name=Hyprland (systemd session) +Name=Hyprland (uwsm-managed) Comment=An intelligent dynamic tiling Wayland compositor -Exec=systemctl --user start --wait hyprland-session -Type=Application +Exec=uwsm start -N Hyprland -D Hyprland -C An_intelligent_dynamic_tiling_Wayland_compositor -- Hyprland DesktopNames=Hyprland -Keywords=tiling;wayland;compositor; +Type=Application From ccfae82ad1c1a97d06efe980d6ba0dd72be4116c Mon Sep 17 00:00:00 2001 From: Izmyname Date: Thu, 7 Nov 2024 21:01:12 +0500 Subject: [PATCH 0248/1803] rename hyprland-systemd.desktop and remove hyprland-session.service --- CMakeLists.txt | 10 ++-------- systemd/hyprland-session.service.in | 16 ---------------- ...and-systemd.desktop => hyprland-uwsm.desktop} | 0 systemd/meson.build | 14 +------------- 4 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 systemd/hyprland-session.service.in rename systemd/{hyprland-systemd.desktop => hyprland-uwsm.desktop} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ac2e10f..d337680f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,16 +222,10 @@ if(NO_SYSTEMD) else() message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") add_compile_definitions(USES_SYSTEMD) - configure_file(systemd/hyprland-session.service.in - systemd/hyprland-session.service @ONLY) - # session file -systemd - install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop + # session file -uwsm + install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) - - # install systemd service - install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service - DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) diff --git a/systemd/hyprland-session.service.in b/systemd/hyprland-session.service.in deleted file mode 100644 index dafdc141..00000000 --- a/systemd/hyprland-session.service.in +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Hyprland - Tiling compositor with the looks -Documentation=man:Hyprland(1) -BindsTo=graphical-session.target -Before=graphical-session.target -Wants=xdg-desktop-autostart.target -Wants=graphical-session-pre.target -After=graphical-session-pre.target - -[Service] -Type=notify -ExecStart=@PREFIX@/@BINDIR@/Hyprland -ExecStop=@PREFIX@/@BINDIR@/hyprctl dispatch exit -ExecStopPost=systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP -Restart=on-failure -Slice=session.slice diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-uwsm.desktop similarity index 100% rename from systemd/hyprland-systemd.desktop rename to systemd/hyprland-uwsm.desktop diff --git a/systemd/meson.build b/systemd/meson.build index 2cd5312a..731f04e3 100644 --- a/systemd/meson.build +++ b/systemd/meson.build @@ -1,17 +1,5 @@ install_data( - 'hyprland-systemd.desktop', + 'hyprland-uwsm.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime', ) - -conf_data = configuration_data() -conf_data.set('PREFIX', get_option('prefix')) -conf_data.set('BINDIR', get_option('bindir')) -user_unit_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir', - pkgconfig_define: ['prefix', get_option('prefix')]) - -configure_file( - configuration: conf_data, - input: 'hyprland-session.service.in', - output: '@BASENAME@', - install_dir: user_unit_dir ) From 943c7d18cc7c9300e1a6b4b859558b8c7ac540cd Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 11 Nov 2024 09:36:15 +0200 Subject: [PATCH 0249/1803] meson: autodetect systemd --- meson.build | 8 ++++++-- nix/default.nix | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 76765645..e4abad36 100644 --- a/meson.build +++ b/meson.build @@ -52,8 +52,12 @@ backtrace_dep = cpp_compiler.find_library('execinfo', required: false) epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs # Handle options -if get_option('systemd').enabled() - systemd = dependency('systemd') +systemd_option = get_option('systemd') +systemd = dependency('systemd', required: systemd_option) +systemd_option.enable_auto_if(systemd.found()) + +if (systemd_option.enabled()) + message('Enabling systemd integration') add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') subdir('systemd') endif diff --git a/nix/default.nix b/nix/default.nix index 29d31485..90c92272 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -152,7 +152,6 @@ in (mapAttrsToList mesonEnable { "xwayland" = enableXWayland; "legacy_renderer" = legacyRenderer; - "systemd" = withSystemd; }) (mapAttrsToList mesonBool { "b_pch" = false; From ff411658e8b217cadf69887f7313d6fd2fc417f2 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 11 Nov 2024 10:05:01 +0200 Subject: [PATCH 0250/1803] Lock uwsm desktop file behind feature flag The file in the repo cannot be used in NixOS due to missing full paths, and the fact that `uwsm` does not have access to `PATH` to find the listed binaries. Might be useful in other situations as well. --- CMakeLists.txt | 9 +++++++-- meson_options.txt | 1 + systemd/meson.build | 12 +++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d337680f..117932d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,8 +224,13 @@ else() add_compile_definitions(USES_SYSTEMD) # session file -uwsm - install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + if(NO_UWSM) + message(STATUS "UWSM support is disabled...") + else() + message(STATUS "UWSM support is enabled (NO_UWSM not defined)...") + install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + endif() endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) diff --git a/meson_options.txt b/meson_options.txt index d8c9d5e6..9b64fb32 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,5 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') +option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)') option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer') option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') diff --git a/systemd/meson.build b/systemd/meson.build index 731f04e3..bc62e95a 100644 --- a/systemd/meson.build +++ b/systemd/meson.build @@ -1,5 +1,7 @@ -install_data( - 'hyprland-uwsm.desktop', - install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), - install_tag: 'runtime', -) +if (get_option('uwsm').allowed()) + install_data( + 'hyprland-uwsm.desktop', + install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), + install_tag: 'runtime', + ) +endif From b88e4a1a9a8a240d54a5006b35964c9e02f86f6b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 11 Nov 2024 10:15:58 +0200 Subject: [PATCH 0251/1803] Nix: disable uwsm desktop file installation Will be enabled in the NixOS module. --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 90c92272..69174d4d 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -152,6 +152,7 @@ in (mapAttrsToList mesonEnable { "xwayland" = enableXWayland; "legacy_renderer" = legacyRenderer; + "uwsm" = false; }) (mapAttrsToList mesonBool { "b_pch" = false; From f5fa84554ffe55e29a397014964238be89ffa54d Mon Sep 17 00:00:00 2001 From: nnra <104775644+nnra6864@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:49:35 +0100 Subject: [PATCH 0252/1803] config: Changed the default value of decoration:blur:ignore_opacity to true (#8418) This change is made in order to deliver the blur look majority of people expect by default. --- src/config/ConfigDescriptions.hpp | 2 +- src/config/ConfigManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index fde8173d..27bc3c2d 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -268,7 +268,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "blur:ignore_opacity", .description = "make the blur layer ignore the opacity of the window", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, + .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ .value = "blur:new_optimizations", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fbbc8dbd..b768fda3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -417,7 +417,7 @@ CConfigManager::CConfigManager() { 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:ignore_opacity", Hyprlang::INT{1}); 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}); From a29cfa78431a054a093f3c843228bac6783a6d33 Mon Sep 17 00:00:00 2001 From: SoSeDiK Date: Tue, 12 Nov 2024 02:53:55 +0200 Subject: [PATCH 0253/1803] logging: Add some context to config error logs (#8326) --- src/config/ConfigManager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b768fda3..e3d59874 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1851,7 +1851,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { if (it != flagsmap.end()) mode.flags |= it->second; else - Debug::log(ERR, "invalid flag {} in modeline", key); + Debug::log(ERR, "Invalid flag {} in modeline", key); } snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000); @@ -1874,7 +1874,7 @@ std::optional CConfigManager::handleMonitor(const std::string& comm else if (ARGS[1] == "transform") { const auto TSF = std::stoi(ARGS[2]); if (std::clamp(TSF, 0, 7) != TSF) { - Debug::log(ERR, "invalid transform {} in monitor", TSF); + Debug::log(ERR, "Invalid transform {} in monitor", TSF); return "invalid transform"; } @@ -2027,7 +2027,7 @@ std::optional CConfigManager::handleMonitor(const std::string& comm m_dWorkspaceRules.emplace_back(wsRule); argno++; } else { - Debug::log(ERR, "Config error: invalid monitor syntax"); + Debug::log(ERR, "Config error: invalid monitor syntax at \"{}\"", ARGS[argno]); return "invalid syntax at \"" + ARGS[argno] + "\""; } @@ -2247,12 +2247,12 @@ std::optional CConfigManager::handleBind(const std::string& command const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(HANDLER); if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end()) { - Debug::log(ERR, "Invalid dispatcher!"); + Debug::log(ERR, "Invalid dispatcher: {}", HANDLER); return "Invalid dispatcher, requested \"" + HANDLER + "\" does not exist"; } if (MOD == 0 && MODSTR != "") { - Debug::log(ERR, "Invalid mod!"); + Debug::log(ERR, "Invalid mod: {}", MODSTR); return "Invalid mod, requested mod \"" + MODSTR + "\" is not a valid mod."; } @@ -2696,7 +2696,7 @@ std::optional CConfigManager::handleSubmap(const std::string& comma std::optional CConfigManager::handleSource(const std::string& command, const std::string& rawpath) { if (rawpath.length() < 2) { Debug::log(ERR, "source= path garbage"); - return "source path " + rawpath + " bogus!"; + return "source= path " + rawpath + " bogus!"; } std::unique_ptr glob_buf{new glob_t, [](glob_t* g) { globfree(g); }}; memset(glob_buf.get(), 0, sizeof(glob_t)); @@ -2718,8 +2718,8 @@ std::optional CConfigManager::handleSource(const std::string& comma continue; } - Debug::log(ERR, "source= file doesnt exist"); - return "source file " + value + " doesn't exist!"; + Debug::log(ERR, "source= file doesn't exist: {}", value); + return "source= file " + value + " doesn't exist!"; } configPaths.push_back(value); From bb160cfe377da2d2b2e4431a3399fa60114f3911 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 12 Nov 2024 15:26:25 +0000 Subject: [PATCH 0254/1803] makefile: add stub to discourage direct make --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 7cf21119..6c79b8db 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ PREFIX = /usr/local +stub: + @echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland." + legacyrenderer: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` From 3fb47372b79265ebdabeeefdad10359d5b18377a Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 13 Nov 2024 21:34:52 +0200 Subject: [PATCH 0255/1803] flake.lock: update --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 47254052..c1fcb70d 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1730968822, - "narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=", + "lastModified": 1731496216, + "narHash": "sha256-nlQrNN+tmJ+iP6Ck/czwZI0Hxz3oNvUyGkVruxJwgwA=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14", + "rev": "3b00e96f90cb0040de6d88ad99bf5f4d443f0c59", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1731163338, - "narHash": "sha256-Qflei0JBeqQ0c8jxA8e982xAxJvfMwfx4Aci2eJi84s=", + "lastModified": 1731518387, + "narHash": "sha256-aZZw1ZvTMLkcA6udlvkA3hrCkuipoWLy8s/JNnIclxY=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "60d3dece30f98e8ad85131829c8529950630d6bc", + "rev": "315fba5d21d87ddb756d4bebdb49f99d86b0ffe8", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730785428, - "narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", + "lastModified": 1731139594, + "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", + "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1730814269, - "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", + "lastModified": 1731363552, + "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "d70155fdc00df4628446352fc58adc640cd705c2", + "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", "type": "github" }, "original": { From 20031cea92417a852410827a5cdb4adbcaee4342 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:15:51 +0000 Subject: [PATCH 0256/1803] pointer: add drm dumb buffers for cursors (#8399) --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- meson.build | 2 +- src/config/ConfigManager.cpp | 2 +- src/managers/PointerManager.cpp | 132 ++++++++++++++++++------------ src/protocols/core/Compositor.cpp | 26 ++++-- src/protocols/core/Compositor.hpp | 2 +- src/render/Texture.cpp | 21 ++++- src/render/Texture.hpp | 34 ++++---- 8 files changed, 142 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 117932d0..1cbd8b0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4) -pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2) +pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") diff --git a/meson.build b/meson.build index e4abad36..d825f184 100644 --- a/meson.build +++ b/meson.build @@ -31,7 +31,7 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif -aquamarine = dependency('aquamarine', version: '>=0.4.2') +aquamarine = dependency('aquamarine', version: '>=0.4.5') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') xcb_dep = dependency('xcb', required: get_option('xwayland')) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e3d59874..10299277 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -571,7 +571,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); - m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 75be235f..0580c9be 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -375,6 +375,8 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->output->cursorPlaneSize(); auto const& cursorSize = currentCursorImage.size; + static auto PDUMB = CConfigValue("cursor:use_cpu_buffer"); + if (maxSize == Vector2D{}) return nullptr; @@ -386,10 +388,23 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { + if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size || + *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { - if (!state->monitor->cursorSwapchain) - state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend()); + if (!state->monitor->cursorSwapchain || *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { + + auto allocator = state->monitor->output->getBackend()->preferredAllocator(); + if (*PDUMB) { + for (const auto& a : state->monitor->output->getBackend()->getAllocators()) { + if (a->type() == Aquamarine::AQ_ALLOCATOR_TYPE_DRM_DUMB) { + allocator = a; + break; + } + } + } + + state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(allocator, state->monitor->output->getBackend()); + } auto options = state->monitor->cursorSwapchain->currentOptions(); options.size = maxSize; @@ -397,8 +412,10 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; - // We do not set the format. If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, + // We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, // but if it's set, we don't wanna change it. + if (*PDUMB) + options.format = DRM_FORMAT_ARGB8888; if (!state->monitor->cursorSwapchain->reconfigure(options)) { Debug::log(TRACE, "Failed to reconfigure cursor swapchain"); @@ -420,60 +437,69 @@ SP CPointerManager::renderHWCursorBuffer(SPdataCopy(); + if (texData.empty()) { + if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) { + const auto SURFACE = currentCursorImage.surface->resource(); + auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE); + + bool flipRB = false; + + if (SURFACE->current.texture) { + Debug::log(TRACE, "Cursor CPU surface: format {}, expecting AR24", FormatUtils::drmFormatName(SURFACE->current.texture->m_iDrmFormat)); + if (SURFACE->current.texture->m_iDrmFormat == DRM_FORMAT_ABGR8888) { + Debug::log(TRACE, "Cursor CPU surface format AB24, will flip. WARNING: this will break on big endian!"); + flipRB = true; + } else if (SURFACE->current.texture->m_iDrmFormat != DRM_FORMAT_ARGB8888) { + Debug::log(TRACE, "Cursor CPU surface format rejected, falling back to sw"); + return nullptr; + } + } + + if (shmBuffer.data()) + texData = shmBuffer; + else { + texData.resize(texture->m_vSize.x * 4 * texture->m_vSize.y); + memset(texData.data(), 0x00, texData.size()); + } + + if (flipRB) { + for (size_t i = 0; i < shmBuffer.size(); i += 4) { + std::swap(shmBuffer.at(i), shmBuffer.at(i + 2)); // little-endian!!!!!! + } + } + } else { + Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers"); + return nullptr; + } + } + + // then, we just yeet it into the dumb buffer + + auto [data, fmt, size] = buf->beginDataPtr(0); + + memset(data, 0, size); + if (buf->dmabuf().size.x > texture->m_vSize.x) { + size_t STRIDE = 4 * texture->m_vSize.x; + for (int i = 0; i < texture->m_vSize.y; i++) + memcpy(data + i * buf->dmabuf().strides[0], texData.data() + i * STRIDE, STRIDE); + } else + memcpy(data, texData.data(), std::min(size, texData.size())); + + buf->endDataPtr(); + + return buf; + } + g_pHyprRenderer->makeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor; auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); if (!RBO) { Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); - static auto PDUMB = CConfigValue("cursor:allow_dumb_copy"); - if (!*PDUMB) - return nullptr; - - auto bufData = buf->beginDataPtr(0); - auto bufPtr = std::get<0>(bufData); - - // clear buffer - memset(bufPtr, 0, std::get<2>(bufData)); - - if (currentCursorImage.pBuffer) { - auto texAttrs = currentCursorImage.pBuffer->shm(); - - if (!texAttrs.success) { - Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers"); - return nullptr; - } - - auto texData = currentCursorImage.pBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); - auto texPtr = std::get<0>(texData); - Debug::log(TRACE, "cursor texture {}x{} {} {} {}", texAttrs.size.x, texAttrs.size.y, (void*)texPtr, texAttrs.format, texAttrs.stride); - // copy cursor texture - for (int i = 0; i < texAttrs.size.y; i++) - memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * texAttrs.stride, texAttrs.stride); - } else if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) { - const auto SURFACE = currentCursorImage.surface->resource(); - auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE); - Debug::log(TRACE, "cursor texture pixel data length: {}B", shmBuffer.size()); - - if (shmBuffer.data()) { - // copy cursor texture - // assume format is 32bpp - size_t STRIDE = 4 * SURFACE->current.bufferSize.x; - for (int i = 0; i < SURFACE->current.bufferSize.y; i++) - memcpy(bufPtr + i * buf->dmabuf().strides[0], shmBuffer.data() + i * STRIDE, STRIDE); - } else { - // if there is no data, hide the cursor - memset(bufPtr, '\0', buf->size.x * buf->size.y * 4 /* assume 32bpp */); - } - - } else { - Debug::log(TRACE, "Unsupported cursor buffer/surface, falling back to sw (can't dumb copy)"); - return nullptr; - } - - buf->endDataPtr(); - - return buf; + return nullptr; } RBO->bind(); @@ -773,7 +799,7 @@ SP CPointerManager::getCurrentCursorTexture() { if (currentCursorImage.pBuffer) { if (!currentCursorImage.bufferTex) - currentCursorImage.bufferTex = makeShared(currentCursorImage.pBuffer); + currentCursorImage.bufferTex = makeShared(currentCursorImage.pBuffer, true); return currentCursorImage.bufferTex; } diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 57f61f87..89f2a4cb 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -438,12 +438,13 @@ void CWLSurfaceResource::commitPendingState() { current.texture->m_eTransform = wlTransformToHyprutils(current.transform); if (current.buffer && current.buffer->buffer) { - current.buffer->buffer->update(accumulateCurrentBufferDamage()); + const auto DAMAGE = accumulateCurrentBufferDamage(); + current.buffer->buffer->update(DAMAGE); // if the surface is a cursor, update the shm buffer // TODO: don't update the entire texture - if (role->role() == SURFACE_ROLE_CURSOR) - updateCursorShm(); + if (role->role() == SURFACE_ROLE_CURSOR && !DAMAGE.empty()) + updateCursorShm(DAMAGE); // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. @@ -486,13 +487,12 @@ void CWLSurfaceResource::commitPendingState() { lastBuffer = current.buffer ? current.buffer->buffer : WP{}; } -void CWLSurfaceResource::updateCursorShm() { +void CWLSurfaceResource::updateCursorShm(CRegion damage) { auto buf = current.buffer ? current.buffer->buffer : lastBuffer; if (!buf) return; - // TODO: actually use damage auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock()); auto shmAttrs = buf->shm(); @@ -501,11 +501,25 @@ void CWLSurfaceResource::updateCursorShm() { return; } + damage.intersect(CBox{0, 0, buf->size.x, buf->size.y}); + // no need to end, shm. auto [pixelData, fmt, bufLen] = buf->beginDataPtr(0); shmData.resize(bufLen); - memcpy(shmData.data(), pixelData, bufLen); + + if (const auto RECTS = damage.getRects(); RECTS.size() == 1 && RECTS.at(0).x2 == buf->size.x && RECTS.at(0).y2 == buf->size.y) + memcpy(shmData.data(), pixelData, bufLen); + else { + for (auto& box : damage.getRects()) { + for (auto y = box.y1; y < box.y2; ++y) { + // bpp is 32 INSALLAH + auto begin = 4 * box.y1 * (box.x2 - box.x1) + box.x1; + auto len = 4 * (box.x2 - box.x1); + memcpy((uint8_t*)shmData.data() + begin, (uint8_t*)pixelData + begin, len); + } + } + } } void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index e5bdf082..c036041a 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -148,7 +148,7 @@ class CWLSurfaceResource { void dropCurrentBuffer(); void commitPendingState(); void bfHelper(std::vector> const& nodes, std::function, const Vector2D&, void*)> fn, void* data); - void updateCursorShm(); + void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX}); friend class CWLPointerResource; }; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 91e70afa..633f0212 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../protocols/types/Buffer.hpp" #include "../helpers/Format.hpp" +#include CTexture::CTexture() { // naffin' @@ -16,7 +17,7 @@ CTexture::~CTexture() { destroyTexture(); } -CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { +CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_, bool keepDataCopy) : m_iDrmFormat(drmFormat), m_bKeepDataCopy(keepDataCopy) { createFromShm(drmFormat, pixels, stride, size_); } @@ -24,7 +25,7 @@ CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) { createFromDma(attrs, image); } -CTexture::CTexture(const SP buffer) { +CTexture::CTexture(const SP buffer, bool keepDataCopy) : m_bKeepDataCopy(keepDataCopy) { if (!buffer) return; @@ -43,6 +44,8 @@ CTexture::CTexture(const SP buffer) { auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); + m_iDrmFormat = fmt; + createFromShm(fmt, pixelData, bufLen, shm.size); return; } @@ -80,6 +83,11 @@ void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t strid GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels)); GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0)); GLCALL(glBindTexture(GL_TEXTURE_2D, 0)); + + if (m_bKeepDataCopy) { + m_vDataCopy.resize(stride * size_.y); + memcpy(m_vDataCopy.data(), pixels, stride * size_.y); + } } void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) { @@ -135,6 +143,11 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); glBindTexture(GL_TEXTURE_2D, 0); + + if (m_bKeepDataCopy) { + m_vDataCopy.resize(stride * m_vSize.y); + memcpy(m_vDataCopy.data(), pixels, stride * m_vSize.y); + } } void CTexture::destroyTexture() { @@ -152,3 +165,7 @@ void CTexture::allocate() { if (!m_iTexID) GLCALL(glGenTextures(1, &m_iTexID)); } + +const std::vector& CTexture::dataCopy() { + return m_vDataCopy; +} diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index e0ef5503..ae949d5f 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -24,26 +24,32 @@ class CTexture { CTexture(const CTexture&&) = delete; CTexture(const CTexture&) = delete; - CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); + CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false); - CTexture(const SP buffer); + CTexture(const SP buffer, bool keepDataCopy = false); // this ctor takes ownership of the eglImage. CTexture(const Aquamarine::SDMABUFAttrs&, void* image); ~CTexture(); - void destroyTexture(); - void allocate(); - void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage); + void destroyTexture(); + void allocate(); + void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage); + const std::vector& dataCopy(); - TEXTURETYPE m_iType = TEXTURE_RGBA; - GLenum m_iTarget = GL_TEXTURE_2D; - GLuint m_iTexID = 0; - Vector2D m_vSize = {}; - void* m_pEglImage = nullptr; - eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL; - bool m_bOpaque = false; + TEXTURETYPE m_iType = TEXTURE_RGBA; + GLenum m_iTarget = GL_TEXTURE_2D; + GLuint m_iTexID = 0; + Vector2D m_vSize = {}; + void* m_pEglImage = nullptr; + eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL; + bool m_bOpaque = false; + uint32_t m_iDrmFormat = 0; // for shm private: - void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); - void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image); + void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); + void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image); + + bool m_bKeepDataCopy = false; + + std::vector m_vDataCopy; }; \ No newline at end of file From 6f7280a6901aeba0fd1768ccf78fea152fe41f4f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 14 Nov 2024 20:20:51 +0000 Subject: [PATCH 0257/1803] descriptions: add use_cpu_buffer --- src/config/ConfigDescriptions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 27bc3c2d..969ec66f 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1350,8 +1350,8 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "cursor:allow_dumb_copy", - .description = "Makes HW cursors work on Nvidia, at the cost of a possible hitch whenever the image changes", + .value = "cursor:use_cpu_buffer", + .description = "Makes HW cursors use a CPU buffer. Required on Nvidia to have HW cursors. Experimental", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, From 940ed3d525d838bc255070bd8cfc2f75df04229a Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 14 Nov 2024 21:38:16 +0100 Subject: [PATCH 0258/1803] xcursors: store themes in a std:set to order it (#8474) using a unordered_set means its store based on a hash_value meaning currently it can end up loading inherited themes before the actual theme itself depending on the hash of the theme name used, reason for using set at all over vector is to keep unique members and not foreverever looping broken inherit themeing. --- src/managers/XCursorManager.cpp | 8 ++++---- src/managers/XCursorManager.hpp | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 93ee7965..5c3053c7 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -197,7 +197,7 @@ SP CXCursorManager::createCursor(std::string const& shape, XcursorIma return xcursor; } -std::unordered_set CXCursorManager::themePaths(std::string const& theme) { +std::set CXCursorManager::themePaths(std::string const& theme) { auto const* path = XcursorLibraryPath(); auto expandTilde = [](std::string const& path) { @@ -276,10 +276,10 @@ std::unordered_set CXCursorManager::themePaths(std::string const& t return themes; }; - std::unordered_set paths; - std::unordered_set inherits; + std::set paths; + std::set inherits; - auto scanTheme = [&path, &paths, &expandTilde, &inherits, &getInheritThemes](auto const& t) { + auto scanTheme = [&path, &paths, &expandTilde, &inherits, &getInheritThemes](auto const& t) { std::stringstream ss(path); std::string line; diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 1f3c24db..2517e85e 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include #include @@ -34,16 +34,16 @@ class CXCursorManager { void syncGsettings(); private: - SP createCursor(std::string const& shape, XcursorImages* xImages); - std::unordered_set themePaths(std::string const& theme); - std::string getLegacyShapeName(std::string const& shape); - std::vector> loadStandardCursors(std::string const& name, int size); - std::vector> loadAllFromDir(std::string const& path, int size); + SP createCursor(std::string const& shape, XcursorImages* xImages); + std::set themePaths(std::string const& theme); + std::string getLegacyShapeName(std::string const& shape); + std::vector> loadStandardCursors(std::string const& name, int size); + std::vector> loadAllFromDir(std::string const& path, int size); - int lastLoadSize = 0; - float lastLoadScale = 0; - std::string themeName = ""; - SP defaultCursor; - SP hyprCursor; - std::vector> cursors; + int lastLoadSize = 0; + float lastLoadScale = 0; + std::string themeName = ""; + SP defaultCursor; + SP hyprCursor; + std::vector> cursors; }; From 967fe76a60ec6b2928b495ed202f772beca05275 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 15 Nov 2024 03:45:13 +0300 Subject: [PATCH 0259/1803] drm: enable explit out fence in AQ (#8431) --- src/render/Renderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d98e32a9..37e6f81e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1507,6 +1507,9 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { pMonitor->output->state->resetExplicitFences(); if (inFD >= 0) pMonitor->output->state->setExplicitInFence(inFD); + auto explicitOptions = getExplicitSyncSettings(); + if (explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) + pMonitor->output->state->enableExplicitOutFenceForNextCommit(); if (pMonitor->ctmUpdated) { pMonitor->ctmUpdated = false; @@ -1530,8 +1533,6 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { } } - auto explicitOptions = getExplicitSyncSettings(); - if (!explicitOptions.explicitEnabled) return ok; From 098e491a43e8b26f4382b48651a4131464bf6a2f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Nov 2024 00:47:34 +0000 Subject: [PATCH 0260/1803] protocols: mark primarySelection as not privileged fixes #8479 --- src/managers/ProtocolManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 601e564d..cf517b22 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -281,6 +281,7 @@ bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { PROTO::xdgShell->getGlobal(), PROTO::xdgDialog->getGlobal(), PROTO::singlePixel->getGlobal(), + PROTO::primarySelection->getGlobal(), PROTO::sync ? PROTO::sync->getGlobal() : nullptr, PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, From 7affc34ab43c5d5cbf670759b839a9e990d8bbea Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sat, 16 Nov 2024 07:21:59 +0800 Subject: [PATCH 0261/1803] bind: new long press option (#8302) --------- Co-authored-by: Vaxry --- src/config/ConfigManager.cpp | 13 ++++++----- src/debug/HyprCtl.cpp | 7 +++--- src/managers/KeybindManager.cpp | 40 ++++++++++++++++++++++++++++++--- src/managers/KeybindManager.hpp | 5 ++++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 10299277..58db00e9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2171,6 +2171,7 @@ std::optional CConfigManager::handleBind(const std::string& command bool transparent = false; bool ignoreMods = false; bool multiKey = false; + bool longPress = false; bool hasDescription = false; bool dontInhibit = false; const auto BINDARGS = command.substr(4); @@ -2192,6 +2193,8 @@ std::optional CConfigManager::handleBind(const std::string& command ignoreMods = true; } else if (arg == 's') { multiKey = true; + } else if (arg == 'o') { + longPress = true; } else if (arg == 'd') { hasDescription = true; } else if (arg == 'p') { @@ -2201,8 +2204,8 @@ std::optional CConfigManager::handleBind(const std::string& command } } - if (release && repeat) - return "flags r and e are mutually exclusive"; + if ((longPress || release) && repeat) + return "flags e is mutually exclusive with r and o"; if (mouse && (repeat || release || locked)) return "flag m is exclusive"; @@ -2264,9 +2267,9 @@ std::optional CConfigManager::handleBind(const std::string& command return "Invalid catchall, catchall keybinds are only allowed in submaps."; } - g_pKeybindManager->addKeybind(SKeybind{ - parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release, - repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit}); + g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, + COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release, repeat, longPress, + mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit}); } return {}; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 6429e781..c5eba0a7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -843,6 +843,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "mouse": {}, "release": {}, "repeat": {}, + "longPress": {}, "non_consuming": {}, "has_description": {}, "modmask": {}, @@ -854,9 +855,9 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "dispatcher": "{}", "arg": "{}" }},)#", - kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false", - kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false", - escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); + kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.longPress ? "true" : "false", + kb.nonConsuming ? "true" : "false", kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, + kb.catchAll ? "true" : "false", escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); } trimTrailingComma(ret); ret += "]"; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index f2fdab53..b14637f7 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -13,6 +13,7 @@ #include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" +#include "eventLoop/EventLoopManager.hpp" #include #include @@ -130,9 +131,25 @@ CKeybindManager::CKeybindManager() { m_tScrollTimer.reset(); + m_pLongPressTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + if (!m_pLastLongPressKeybind || g_pSeatManager->keyboard.expired()) + return; + + const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(m_pLastLongPressKeybind->handler); + + Debug::log(LOG, "Long press timeout passed, calling dispatcher."); + DISPATCHER->second(m_pLastLongPressKeybind->arg); + }, + nullptr); + + g_pEventLoopManager->addTimer(m_pLongPressTimer); + static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd - m_pActiveKeybind = nullptr; + m_pActiveKeybind = nullptr; + m_pLastLongPressKeybind = nullptr; m_vPressedSpecialBinds.clear(); }); } @@ -140,12 +157,17 @@ CKeybindManager::CKeybindManager() { CKeybindManager::~CKeybindManager() { if (m_pXKBTranslationState) xkb_state_unref(m_pXKBTranslationState); + if (m_pLongPressTimer && g_pEventLoopManager) { + g_pEventLoopManager->removeTimer(m_pLongPressTimer); + m_pLongPressTimer.reset(); + } } void CKeybindManager::addKeybind(SKeybind kb) { m_lKeybinds.push_back(kb); - m_pActiveKeybind = nullptr; + m_pActiveKeybind = nullptr; + m_pLastLongPressKeybind = nullptr; } void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { @@ -158,7 +180,8 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { } } - m_pActiveKeybind = nullptr; + m_pActiveKeybind = nullptr; + m_pLastLongPressKeybind = nullptr; } uint32_t CKeybindManager::stringToModMask(std::string mods) { @@ -409,6 +432,8 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { m_pActiveKeybind = nullptr; } + m_pLastLongPressKeybind = nullptr; + bool suppressEvent = false; if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) { @@ -705,6 +730,15 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } } + if (k.longPress) { + const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); + + m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); + m_pLastLongPressKeybind = &k; + + continue; + } + const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler); if (SPECIALTRIGGERED && !pressed) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 24a09836..4a0af6e9 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -8,6 +8,7 @@ #include #include #include "../devices/IPointer.hpp" +#include "eventLoop/EventLoopTimer.hpp" class CInputManager; class CConfigManager; @@ -28,6 +29,7 @@ struct SKeybind { std::string description = ""; bool release = false; bool repeat = false; + bool longPress = false; bool mouse = false; bool nonConsuming = false; bool transparent = false; @@ -119,7 +121,8 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - SKeybind* m_pActiveKeybind = nullptr; + SKeybind * m_pActiveKeybind = nullptr, *m_pLastLongPressKeybind = nullptr; + SP m_pLongPressTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0; From 83be2480c45bdead9110fdf137a1cd2f5a203378 Mon Sep 17 00:00:00 2001 From: sslater11 <43177940+sslater11@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:39:58 +0000 Subject: [PATCH 0262/1803] workspace: fix missing name via focusworkspaceoncurrentmonitor (#8484) --- src/managers/KeybindManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index b14637f7..4d2f4dcc 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1887,7 +1887,7 @@ SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) { } SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { - auto workspaceID = getWorkspaceIDNameFromString(args).id; + auto [workspaceID, workspaceName] = getWorkspaceIDNameFromString(args); if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; @@ -1903,7 +1903,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID); if (!pWorkspace) { - pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID); + pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID, workspaceName); // we can skip the moving, since it's already on the current monitor changeworkspace(pWorkspace->getConfigName()); return {}; From ec1e6be00377c26dd25497b1544091b3f643c4bc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 16 Nov 2024 23:04:57 +0000 Subject: [PATCH 0263/1803] core: guard pmonitor in focuswindow may be null fixes #8483 --- src/Compositor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index da20c5cf..fbbfd7e7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1077,7 +1077,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface PWORKSPACE->rememberPrevWorkspace(m_pLastMonitor->activeWorkspace); if (PWORKSPACE->m_bIsSpecialWorkspace) m_pLastMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor - else + else if (PMONITOR) PMONITOR->changeWorkspace(PWORKSPACE, false, true); // changeworkspace already calls focusWindow return; @@ -1088,7 +1088,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP 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->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH) + if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !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 From cf18eca86d21c28b127d58938b3a1004800b85c9 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 16 Nov 2024 23:06:35 +0000 Subject: [PATCH 0264/1803] [gha] Nix: update inputs --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index c1fcb70d..969bc157 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1731496216, - "narHash": "sha256-nlQrNN+tmJ+iP6Ck/czwZI0Hxz3oNvUyGkVruxJwgwA=", + "lastModified": 1731774881, + "narHash": "sha256-1Dxryiw8u2ejntxrrv3sMtIE8WHKxmlN4KeH+uMGbmc=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "3b00e96f90cb0040de6d88ad99bf5f4d443f0c59", + "rev": "b31a6a4da8199ae3489057db7d36069a70749a56", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1731518387, - "narHash": "sha256-aZZw1ZvTMLkcA6udlvkA3hrCkuipoWLy8s/JNnIclxY=", + "lastModified": 1731702627, + "narHash": "sha256-+JeO9gevnXannQxMfR5xzZtF4sYmSlWkX/BPmPx0mWk=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "315fba5d21d87ddb756d4bebdb49f99d86b0ffe8", + "rev": "e911361a687753bbbdfe3b6a9eab755ecaf1d9e1", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1731139594, - "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", + "lastModified": 1731676054, + "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", + "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", "type": "github" }, "original": { @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1730743262, - "narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=", + "lastModified": 1731703417, + "narHash": "sha256-rheDc/7C+yI+QspYr9J2z9kQ5P9F4ATapI7qyFAe1XA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d", + "rev": "8070f36deec723de71e7557441acb17e478204d3", "type": "github" }, "original": { From 9d37b1b07339b1b222ceab5952cd9b927fbf6d73 Mon Sep 17 00:00:00 2001 From: staz Date: Sun, 17 Nov 2024 04:07:33 +0500 Subject: [PATCH 0265/1803] workspacerules: Do not check 'on-created-empty' if using a workspace windowrule (#8486) --- src/events/Windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f946ce03..77df7373 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -296,7 +296,7 @@ void Events::listener_mapWindow(void* owner, void* data) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName); + pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName, false); PWORKSPACE = pWorkspace; From af83c825138386d269d69b3ef755b844a2eacb22 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Sun, 17 Nov 2024 02:18:30 +0300 Subject: [PATCH 0266/1803] hyprctl: add json output on hyprctl -j plugins list (#8480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Co-authored-by: Руслан Новокшонов --- src/debug/HyprCtl.cpp | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c5eba0a7..964a193b 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1472,17 +1472,40 @@ std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) { g_pPluginSystem->unloadPlugin(PLUGIN); } else if (OPERATION == "list") { - const auto PLUGINS = g_pPluginSystem->getAllPlugins(); + const auto PLUGINS = g_pPluginSystem->getAllPlugins(); + std::string result = ""; - if (PLUGINS.size() == 0) - return "no plugins loaded"; + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + result += "["; - std::string list = ""; - for (auto const& p : PLUGINS) { - list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description); + if (PLUGINS.size() == 0) + return "[]"; + + for (auto const& p : PLUGINS) { + result += std::format( + R"#( +{{ + "name": "{}", + "author": "{}", + "handle": "{:x}", + "version": "{}", + "description": "{}" +}},)#", + escapeJSONStrings(p->name), escapeJSONStrings(p->author), (uintptr_t)p->m_pHandle, escapeJSONStrings(p->version), escapeJSONStrings(p->description)); + } + trimTrailingComma(result); + result += "]"; + } else { + if (PLUGINS.size() == 0) + return "no plugins loaded"; + + for (auto const& p : PLUGINS) { + result += + std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description); + } } - return list; + return result; } else { return "unknown opt"; } From 0ddbd1c3a40f921816a2c512f871f1e51aca8fe2 Mon Sep 17 00:00:00 2001 From: Alexandre Acebedo Date: Sun, 17 Nov 2024 15:58:18 +0000 Subject: [PATCH 0267/1803] renderer: add lockdead_screen_delay (#8467) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/managers/SessionLockManager.cpp | 10 ++++++++++ src/managers/SessionLockManager.hpp | 3 +++ src/render/Renderer.cpp | 9 +++++---- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 969ec66f..2e3a6720 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1121,6 +1121,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "misc:lockdead_screen_delay", + .description = "the delay in ms after the lockdead screen appears if the lock screen did not appear after a lock event occurred.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1000, 0, 5000}, + }, /* * binds: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 58db00e9..1c025179 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -377,6 +377,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15}); m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:lockdead_screen_delay", Hyprlang::INT{1000}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 1b28cc27..c7a5934a 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -57,6 +57,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { m_pSessionLock = std::make_unique(); m_pSessionLock->lock = pLock; + m_pSessionLock->mLockTimer.reset(); m_pSessionLock->listeners.newSurface = pLock->events.newLockSurface.registerListener([this](std::any data) { auto SURFACE = std::any_cast>(data); @@ -176,3 +177,12 @@ bool CSessionLockManager::isSessionLockPresent() { bool CSessionLockManager::anySessionLockSurfacesPresent() { return m_pSessionLock && std::ranges::any_of(m_pSessionLock->vSessionLockSurfaces, [](const auto& surf) { return surf->mapped; }); } + +bool CSessionLockManager::shallConsiderLockMissing() { + if (!m_pSessionLock) + return false; + + static auto LOCKDEAD_SCREEN_DELAY = CConfigValue("misc:lockdead_screen_delay"); + + return m_pSessionLock->mLockTimer.getMillis() > *LOCKDEAD_SCREEN_DELAY; +} \ No newline at end of file diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index 9b3b882c..59090605 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -29,6 +29,7 @@ struct SSessionLockSurface { struct SSessionLock { WP lock; + CTimer mLockTimer; std::vector> vSessionLockSurfaces; std::unordered_map mMonitorsWithoutMappedSurfaceTimers; @@ -61,6 +62,8 @@ class CSessionLockManager { void onLockscreenRenderedOnMonitor(uint64_t id); + bool shallConsiderLockMissing(); + private: UP m_pSessionLock; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 37e6f81e..3eba8458 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1045,9 +1045,10 @@ void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, timespec* now, const C Vector2D translate = {geometry.x, geometry.y}; const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID); - if (!PSLS) - renderSessionLockMissing(pMonitor); - else { + if (!PSLS) { + if (g_pSessionLockManager->shallConsiderLockMissing()) + renderSessionLockMissing(pMonitor); + } else { renderSessionLockSurface(PSLS, pMonitor, now); g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } @@ -2726,7 +2727,7 @@ bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMod return true; } - /* This is a constant expression, as we always use double-buffering in our swapchain + /* This is a constant expression, as we always use double-buffering in our swapchain TODO: Rewrite the CDamageRing to take advantage of that maybe? It's made to support longer swapchains atm because we used to do wlroots */ static constexpr const int HL_BUFFER_AGE = 2; From fb91c2550f5184785680f6af7b069cb857568104 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 16:16:49 +0000 Subject: [PATCH 0268/1803] renderer: don't render unmapped popups fixes #8485 --- src/desktop/Popup.hpp | 4 ++-- src/render/Renderer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index f34b8a2c..e9b3e0f0 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -41,6 +41,7 @@ class CPopup { // SP m_pWLSurface; + bool m_bMapped = false; private: // T1 owners, each popup has to have one of these @@ -57,8 +58,7 @@ class CPopup { bool m_bRequestedReposition = false; - bool m_bInert = false; - bool m_bMapped = false; + bool m_bInert = false; // std::vector> m_vChildren; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 3eba8458..6067a7f2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -732,7 +732,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe pWindow->m_pPopupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; auto pos = popup->coordsRelativeToParent(); auto rd = (SRenderData*)data; @@ -822,7 +822,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim if (popups) { pLayer->popupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; Vector2D pos = popup->coordsRelativeToParent(); From 4f591e807abe1865d8f8135a1a64932cc418d0f0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 16:42:30 +0000 Subject: [PATCH 0269/1803] renderer: simplify blur enabling logic --- src/render/OpenGL.cpp | 4 +--- src/render/Renderer.cpp | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 63a7e822..9c00daee 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2036,7 +2036,6 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float a, SP pSurface, int round, bool blockBlurOptimization, float blurA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); - static auto PBLURENABLED = CConfigValue("decoration:blur:enabled"); static auto PNOBLUROVERSIZED = CConfigValue("decoration:no_blur_on_oversized"); TRACY_GPU_ZONE("RenderTextureWithBlur"); @@ -2050,8 +2049,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float m_RenderData.renderModif.applyToRegion(texDamage); - if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || - (m_pCurrentWindow.lock() && (m_pCurrentWindow->m_sWindowData.noBlur.valueOrDefault() || m_pCurrentWindow->m_sWindowData.RGBX.valueOrDefault()))) { + if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { renderTexture(tex, pBox, a, round, false, true); return; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6067a7f2..fc17ef9f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -174,6 +174,7 @@ static void renderSurface(SP surface, int x, int y, void* da } const auto RDATA = (SRenderData*)data; + const bool BLUR = RDATA->blur && !TEXTURE->m_bOpaque; const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); @@ -270,12 +271,12 @@ static void renderSurface(SP surface, int x, int y, void* da // is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) if (RDATA->surfaceCounter == 0 && !RDATA->popup) { - if (RDATA->blur) + if (BLUR) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); } else { - if (RDATA->blur && RDATA->popup) + if (BLUR && RDATA->popup) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, true, RDATA->fadeAlpha); else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); @@ -591,6 +592,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace); + const bool DONT_BLUR = pWindow->m_sWindowData.noBlur.valueOrDefault() || pWindow->m_sWindowData.RGBX.valueOrDefault() || pWindow->opaque(); renderdata.surface = pWindow->m_pWLSurface->resource(); renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); @@ -599,7 +601,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; - renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later + renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; renderdata.pWindow = pWindow; if (ignoreAllGeometry) { @@ -715,7 +717,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe static CConfigValue PBLURPOPUPS = CConfigValue("decoration:blur:popups"); static CConfigValue PBLURIGNOREA = CConfigValue("decoration:blur:popups_ignorealpha"); - renderdata.blur = *PBLURPOPUPS; + renderdata.blur = *PBLURPOPUPS && *PBLUR; const auto DM = g_pHyprOpenGL->m_RenderData.discardMode; const auto DA = g_pHyprOpenGL->m_RenderData.discardOpacity; @@ -734,13 +736,15 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe [](CPopup* popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; - auto pos = popup->coordsRelativeToParent(); - auto rd = (SRenderData*)data; - Vector2D oldPos = {rd->x, rd->y}; + const auto pos = popup->coordsRelativeToParent(); + auto rd = (SRenderData*)data; + const Vector2D oldPos = {rd->x, rd->y}; rd->x += pos.x; rd->y += pos.y; + popup->m_pWLSurface->resource()->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, data); + rd->x = oldPos.x; rd->y = oldPos.y; }, @@ -785,6 +789,8 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim return; } + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + TRACY_GPU_ZONE("RenderLayer"); const auto REALPOS = pLayer->realPosition.value(); @@ -792,7 +798,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; renderdata.fadeAlpha = pLayer->alpha.value(); - renderdata.blur = pLayer->forceBlur; + renderdata.blur = pLayer->forceBlur && *PBLUR; renderdata.surface = pLayer->surface->resource(); renderdata.decorate = false; renderdata.w = REALSIZ.x; From 8d5cdedbd350b4730a1aa57dc5491c88dff3415e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 16:46:49 +0000 Subject: [PATCH 0270/1803] hyprpm: fix format crash ref #8487 --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 051ad500..db315193 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -272,7 +272,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& } if (m_bVerbose) - std::println("{}", verboseString("shell returned: " + out)); + std::println("{}", verboseString("shell returned: {}", out)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { progress.printMessageAbove(failureString("Plugin {} failed to build.\n" From b735295d2b0025b26f88852c06f65514a963c711 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 19:31:54 +0000 Subject: [PATCH 0271/1803] windows/xdg: minor cleanup of min/max size calculations fixes #8495 --- src/desktop/Window.cpp | 26 ++++++++++++++++++++++++++ src/desktop/Window.hpp | 19 +++++++++---------- src/events/Windows.cpp | 8 ++++---- src/layout/DwindleLayout.cpp | 2 +- src/layout/IHyprLayout.cpp | 8 ++++---- src/layout/MasterLayout.cpp | 4 ++-- src/managers/XWaylandManager.cpp | 30 ------------------------------ src/managers/XWaylandManager.hpp | 2 -- src/protocols/XDGShell.cpp | 8 ++++++++ src/protocols/XDGShell.hpp | 3 +++ 10 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 20fed565..e74e13a2 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1601,3 +1601,29 @@ bool CWindow::isX11OverrideRedirect() { bool CWindow::isModal() { return (m_pXWaylandSurface && m_pXWaylandSurface->modal); } + +Vector2D CWindow::requestedMinSize() { + if ((m_bIsX11 && !m_pXWaylandSurface->sizeHints) || (!m_bIsX11 && !m_pXDGSurface->toplevel)) + return Vector2D(1, 1); + + Vector2D minSize = m_bIsX11 ? Vector2D(m_pXWaylandSurface->sizeHints->min_width, m_pXWaylandSurface->sizeHints->min_height) : m_pXDGSurface->toplevel->layoutMinSize(); + + minSize = minSize.clamp({1, 1}); + + return minSize; +} + +Vector2D CWindow::requestedMaxSize() { + constexpr int NO_MAX_SIZE_LIMIT = 99999; + if (((m_bIsX11 && !m_pXWaylandSurface->sizeHints) || (!m_bIsX11 && !m_pXDGSurface->toplevel) || m_sWindowData.noMaxSize.valueOrDefault())) + return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); + + Vector2D maxSize = m_bIsX11 ? Vector2D(m_pXWaylandSurface->sizeHints->max_width, m_pXWaylandSurface->sizeHints->max_height) : m_pXDGSurface->toplevel->layoutMaxSize(); + + if (maxSize.x < 5) + maxSize.x = NO_MAX_SIZE_LIMIT; + if (maxSize.y < 5) + maxSize.y = NO_MAX_SIZE_LIMIT; + + return maxSize; +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index b8dd3cf7..ac81e5ef 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -403,12 +403,9 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SBoxExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - inline CBox getWindowMainSurfaceBox() const { - return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; - } + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); CBox getWindowIdealBoundingBoxIgnoreReserved(); void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); @@ -441,19 +438,15 @@ class CWindow { void activate(bool force = false); int surfacesCount(); void clampWindowSize(const std::optional minSize, const std::optional maxSize); - bool isFullscreen(); bool isEffectiveInternalFSMode(const eFullscreenMode); - int getRealBorderSize(); void updateWindowData(); void updateWindowData(const struct SWorkspaceRule&); - void onBorderAngleAnimEnd(void* ptr); bool isInCurvedCorner(double x, double y); bool hasPopupAt(const Vector2D& pos); int popupsCount(); - void applyGroupRules(); void createGroup(); void destroyGroup(); @@ -481,6 +474,12 @@ class CWindow { void unsetWindowData(eOverridePriority priority); bool isX11OverrideRedirect(); bool isModal(); + Vector2D requestedMinSize(); + Vector2D requestedMaxSize(); + + inline CBox getWindowMainSurfaceBox() const { + return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; + } // listeners void onAck(uint32_t serial); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 77df7373..73ab45c1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -346,7 +346,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + const auto MAXSIZE = PWINDOW->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); @@ -469,7 +469,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + const auto MAXSIZE = PWINDOW->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToPercentage(SIZEXSTR, PMONITOR->vecSize.x); @@ -753,8 +753,8 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. if (!PWINDOW->m_bIsX11 && !PWINDOW->isFullscreen() && PWINDOW->m_bIsFloating) { - const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize; - const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize; + const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->layoutMinSize(); + const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->layoutMaxSize(); PWINDOW->clampWindowSize(MINSIZE, MAXSIZE > Vector2D{1, 1} ? std::optional{MAXSIZE} : std::nullopt); g_pHyprRenderer->damageWindow(PWINDOW); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index e6e9090f..c3e394f3 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -283,7 +283,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir // first, check if OPENINGON isn't too big. const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->vecSize; - if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { + if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; m_lDwindleNodesData.remove(*PNODE); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index a312555f..af8b907c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -597,12 +597,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { } 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 = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20))); + Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20))); Vector2D MAXSIZE; if (DRAGGINGWINDOW->m_sWindowData.maxSize.hasValue()) - MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value()); + MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value()); else - MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, Vector2D(std::numeric_limits::max(), std::numeric_limits::max())); + MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, Vector2D(std::numeric_limits::max(), std::numeric_limits::max())); Vector2D newSize = m_vBeginDragSizeXY; Vector2D newPos = m_vBeginDragPositionXY; @@ -884,7 +884,7 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + const auto MAXSIZE = pWindow->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.x) : stringToPercentage(SIZEXSTR, g_pCompositor->m_pLastMonitor->vecSize.x); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index b8b3efea..695dcc99 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -200,7 +200,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->percMaster = lastSplitPercent; // first, check if it isn't too big. - if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) { + if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; m_lMasterNodesData.remove(*PNODE); @@ -212,7 +212,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->percMaster = lastSplitPercent; // first, check if it isn't too big. - if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index d0dda8e6..832173eb 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -213,36 +213,6 @@ void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscree pWindow->m_pXDGSurface->toplevel->setFullscreen(fullscreen); } -Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) { - constexpr int NO_MAX_SIZE_LIMIT = 99999; - if (!validMapped(pWindow) || - ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || - pWindow->m_sWindowData.noMaxSize.valueOrDefault())) - return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); - - Vector2D maxSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : - pWindow->m_pXDGSurface->toplevel->current.maxSize; - - if (maxSize.x < 5) - maxSize.x = NO_MAX_SIZE_LIMIT; - if (maxSize.y < 5) - maxSize.y = NO_MAX_SIZE_LIMIT; - - return maxSize; -} - -Vector2D CHyprXWaylandManager::getMinSizeForWindow(PHLWINDOW pWindow) { - if (!validMapped(pWindow) || ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel))) - return Vector2D(0, 0); - - Vector2D minSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->min_width, pWindow->m_pXWaylandSurface->sizeHints->min_height) : - pWindow->m_pXDGSurface->toplevel->current.minSize; - - minSize = minSize.clamp({1, 1}); - - return minSize; -} - Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index a9f95974..508a20d6 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -21,8 +21,6 @@ class CHyprXWaylandManager { void setWindowFullscreen(PHLWINDOW, bool); bool shouldBeFloated(PHLWINDOW, bool pending = false); void checkBorders(PHLWINDOW); - Vector2D getMaxSizeForWindow(PHLWINDOW); - Vector2D getMinSizeForWindow(PHLWINDOW); Vector2D xwaylandToWaylandCoords(const Vector2D&); }; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 25d8b1ba..932882e9 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -323,6 +323,14 @@ void CXDGToplevelResource::close() { resource->sendClose(); } +Vector2D CXDGToplevelResource::layoutMinSize() { + return owner ? current.minSize + owner->current.geometry.pos() : current.minSize; +} + +Vector2D CXDGToplevelResource::layoutMaxSize() { + return owner ? current.maxSize + owner->current.geometry.pos() : current.maxSize; +} + CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, SP surface_) : owner(owner_), surface(surface_), resource(resource_) { if (!good()) diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 9c766c20..ef847f3b 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -99,6 +99,9 @@ class CXDGToplevelResource { bool good(); + Vector2D layoutMinSize(); + Vector2D layoutMaxSize(); + // schedule a configure event uint32_t setSize(const Vector2D& size); uint32_t setMaximized(bool maximized); From 9b03307653c179a86a8dfdb4e5d16446d0cf6e23 Mon Sep 17 00:00:00 2001 From: Alessio Molinari Date: Sun, 17 Nov 2024 20:34:03 +0100 Subject: [PATCH 0272/1803] hooks: add pre connected/disconnected monitor events (#8503) --- src/helpers/Monitor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index bfab2fd3..9ac48220 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -39,6 +39,7 @@ CMonitor::~CMonitor() { } void CMonitor::onConnect(bool noRule) { + EMIT_HOOK_EVENT("preMonitorAdded", self.lock()); CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; if (output->supportsExplicit) { @@ -238,6 +239,7 @@ void CMonitor::onConnect(bool noRule) { } void CMonitor::onDisconnect(bool destroy) { + EMIT_HOOK_EVENT("preMonitorRemoved", self.lock()); CScopeGuard x = {[this]() { if (g_pCompositor->m_bIsShuttingDown) return; From e8717a4fce1eafa44d5b106b8159d56e8d368840 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 21:57:00 +0000 Subject: [PATCH 0273/1803] shell: don't use fgrep, prefer grep -F --- src/debug/CrashReporter.cpp | 2 +- src/debug/HyprCtl.cpp | 2 +- src/helpers/MiscFunctions.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index 000d8c5d..319c1414 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -159,7 +159,7 @@ void CrashReporter::createAndSaveCrash(int sig) { finalCrashReport += "GPU:\n\t"; #if defined(__DragonFly__) || defined(__FreeBSD__) - finalCrashReport.writeCmdOutput("pciconf -lv | fgrep -A4 vga"); + finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga"); #else finalCrashReport.writeCmdOutput("lspci -vnn | grep VGA"); #endif diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 964a193b..6c9c2b75 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -946,7 +946,7 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) result += "\n\n"; #if defined(__DragonFly__) || defined(__FreeBSD__) - const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); + const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) std::string GPUINFO; const std::filesystem::path dev_tree = "/proc/device-tree"; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 7b4d63a7..cfaae542 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -606,7 +606,7 @@ void logSystemInfo() { Debug::log(NONE, "\n"); #if defined(__DragonFly__) || defined(__FreeBSD__) - const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); + const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible"); #else From 1ba050d603dca644aca48872f62388d794c030b9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 21:58:00 +0000 Subject: [PATCH 0274/1803] shell: propagate new machanism from hyprctl to miscfunctions --- src/helpers/MiscFunctions.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index cfaae542..6ad1b37a 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -608,7 +608,24 @@ void logSystemInfo() { #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) - const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible"); + const std::string GPUINFO; + const std::filesystem::path dev_tree = "/proc/device-tree"; + try { + if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) { + std::for_each(std::filesystem::directory_iterator(dev_tree), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& entry) { + if (std::filesystem::is_directory(entry) && entry.path().filename().string().starts_with("soc")) { + std::for_each(std::filesystem::directory_iterator(entry.path()), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& sub_entry) { + if (std::filesystem::is_directory(sub_entry) && sub_entry.path().filename().string().starts_with("gpu")) { + std::filesystem::path file_path = sub_entry.path() / "compatible"; + std::ifstream file(file_path); + if (file) + GPUINFO.append(std::istreambuf_iterator(file), std::istreambuf_iterator()); + } + }); + } + }); + } + } catch (...) { GPUINFO = "error"; } #else const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif From 2259a885513e8ec793210ceb9d40ca096161849d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 13:59:57 +0000 Subject: [PATCH 0275/1803] miscfunctions: add missing include --- src/helpers/MiscFunctions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 6ad1b37a..c7cd9ed4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include From 6744bb57c639d5359a414eea2566328bb05c7065 Mon Sep 17 00:00:00 2001 From: johannes hanika Date: Mon, 18 Nov 2024 15:02:34 +0100 Subject: [PATCH 0276/1803] constraints: don't warp pointer position on release (#8491) this was annoying for nuklear properties/ui slider elements that grab the pointer via GLFW_CURSOR_DISABLE to allow more range and finer control. upon mouse release, the pointer is reset to the middle of the window without this patch, making long mouse movements necessary to go back to the original position for readjustments. fwiw the new behaviour is consistent with x11 and weston. --- src/protocols/PointerConstraints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 0f2dd991..7f08a7df 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -188,7 +188,7 @@ Vector2D CPointerConstraint::logicPositionHint() { const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{}; - return hintSet ? CONSTRAINTPOS + positionHint : (locked ? CONSTRAINTPOS + SURFBOX->size() / 2.f : cursorPosOnActivate); + return hintSet ? CONSTRAINTPOS + positionHint : cursorPosOnActivate; } CPointerConstraintsProtocol::CPointerConstraintsProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { From 505c1f8f4a5a4a97534f1906a47c11de638d970d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 14:35:09 +0000 Subject: [PATCH 0277/1803] miscfunctions: fix cross build --- src/helpers/MiscFunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index c7cd9ed4..c8b3bef4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -609,7 +609,7 @@ void logSystemInfo() { #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) - const std::string GPUINFO; + std::string GPUINFO; const std::filesystem::path dev_tree = "/proc/device-tree"; try { if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) { From 97493511f96af288e1f7b2bd3a119e47d75541fc Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 18 Nov 2024 15:44:15 +0100 Subject: [PATCH 0278/1803] internal: fix changeWindowZOrder reordering incorrectly (#8494) --- src/Compositor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fbbfd7e7..0e0c75a1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1389,6 +1389,9 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { if (!validMapped(pWindow)) return; + if (top) + pWindow->m_bCreatedOverFullscreen = true; + if (pWindow == (top ? m_vWindows.back() : m_vWindows.front())) return; @@ -1413,9 +1416,6 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { g_pHyprRenderer->damageMonitor(pw->m_pMonitor.lock()); }; - if (top) - pWindow->m_bCreatedOverFullscreen = true; - if (!pWindow->m_bIsX11) moveToZ(pWindow, top); else { From df9ff4489973afa9e29bb94ac47c946db745b460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 18 Nov 2024 16:54:18 +0100 Subject: [PATCH 0279/1803] Fix example config name in auto-generated cfg header (#8509) Previously, it was suggesting to find `hypr.conf` in the `examples/` folder which doesn't exist. This patch fixed that to point to the existing file. Additionally, the change updates `HYPR` to `HYPRLAND` in the same header. --- src/config/defaultConfig.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index d680e92b..c4eb3385 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -4,8 +4,8 @@ inline const std::string AUTOCONFIG = R"#( # ####################################################################################### -# AUTOGENERATED HYPR CONFIG. -# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT, +# AUTOGENERATED HYPRLAND CONFIG. +# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hyprland.conf AND EDIT IT, # OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS. # ####################################################################################### From cc923ad031579a5d1ebe07269d5ecb291331ee51 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:45:22 +0100 Subject: [PATCH 0280/1803] config: update the configStringToInt implementation (#8476) Copied from hyprlang and removed std::expected. --- src/helpers/MiscFunctions.cpp | 74 ++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index c8b3bef4..80681826 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -692,43 +692,79 @@ int64_t getPPIDof(int64_t pid) { } int64_t configStringToInt(const std::string& VALUE) { + auto parseHex = [](const std::string& value) -> int64_t { + try { + size_t position; + auto result = stoll(value, &position, 16); + if (position == value.size()) + return result; + } catch (const std::exception&) {} + throw std::invalid_argument("invalid hex " + value); + }; if (VALUE.starts_with("0x")) { // Values with 0x are hex - const auto VALUEWITHOUTHEX = VALUE.substr(2); - return stol(VALUEWITHOUTHEX, nullptr, 16); + return parseHex(VALUE); } else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) { - const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6); + const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6)); - if (trim(VALUEWITHOUTFUNC).length() != 8) { - Debug::log(WARN, "invalid length {} for rgba", VALUEWITHOUTFUNC.length()); - throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes)"); + // try doing it the comma way first + if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 3) { + // cool + std::string rolling = VALUEWITHOUTFUNC; + auto r = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto g = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + uint8_t a = 0; + try { + a = std::round(std::stof(trim(rolling.substr(0, rolling.find(',')))) * 255.f); + } catch (std::exception& e) { throw std::invalid_argument("failed parsing " + VALUEWITHOUTFUNC); } + + return a * (Hyprlang::INT)0x1000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + } else if (VALUEWITHOUTFUNC.length() == 8) { + const auto RGBA = parseHex(VALUEWITHOUTFUNC); + // now we need to RGBA -> ARGB. The config holds ARGB only. + return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); } - const auto RGBA = std::stol(VALUEWITHOUTFUNC, nullptr, 16); + throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); - // now we need to RGBA -> ARGB. The config holds ARGB only. - return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); } else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) { - const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5); + const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5)); - if (trim(VALUEWITHOUTFUNC).length() != 6) { - Debug::log(WARN, "invalid length {} for rgb", VALUEWITHOUTFUNC.length()); - throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes)"); + // try doing it the comma way first + if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 2) { + // cool + std::string rolling = VALUEWITHOUTFUNC; + auto r = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto g = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + + return (Hyprlang::INT)0xFF000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + } else if (VALUEWITHOUTFUNC.length() == 6) { + return parseHex(VALUEWITHOUTFUNC) + 0xFF000000; } - const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16); - - return RGB + 0xFF000000; // 0xFF for opaque + throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); } else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) { return 1; } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { return 0; } - if (VALUE.empty() || !isNumber(VALUE)) - return 0; + if (VALUE.empty() || !isNumber(VALUE, false)) + throw std::invalid_argument("cannot parse \"" + VALUE + "\" as an int."); - return std::stoll(VALUE); + try { + const auto RES = std::stoll(VALUE); + return RES; + } catch (std::exception& e) { throw std::invalid_argument(std::string{"stoll threw: "} + e.what()); } + + return 0; } Vector2D configStringToVector2D(const std::string& VALUE) { From 6113f4da7fa9839645525e57ff841db5bb00e475 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:48:13 +0000 Subject: [PATCH 0281/1803] keybinds: allow repeating multiple binds (#8290) --- src/managers/KeybindManager.cpp | 69 +++++++++++++++------------------ src/managers/KeybindManager.hpp | 7 ++-- 2 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4d2f4dcc..a0cd01a9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -144,11 +144,30 @@ CKeybindManager::CKeybindManager() { }, nullptr); + m_pRepeatKeyTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired()) + return; + + for (SKeybind* k : m_vActiveKeybinds) { + const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler); + + Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); + DISPATCHER->second(k->arg); + } + + const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); + self->updateTimeout(std::chrono::milliseconds(1000 / PACTIVEKEEB->repeatRate)); + }, + nullptr); + g_pEventLoopManager->addTimer(m_pLongPressTimer); + g_pEventLoopManager->addTimer(m_pRepeatKeyTimer); static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; m_vPressedSpecialBinds.clear(); }); @@ -161,12 +180,16 @@ CKeybindManager::~CKeybindManager() { g_pEventLoopManager->removeTimer(m_pLongPressTimer); m_pLongPressTimer.reset(); } + if (m_pRepeatKeyTimer && g_pEventLoopManager) { + g_pEventLoopManager->removeTimer(m_pRepeatKeyTimer); + m_pRepeatKeyTimer.reset(); + } } void CKeybindManager::addKeybind(SKeybind kb) { m_lKeybinds.push_back(kb); - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; } @@ -180,7 +203,7 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { } } - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; } @@ -426,11 +449,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { .submapAtPress = m_szCurrentSelectedSubmap, }; - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; @@ -482,11 +501,7 @@ bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) { m_tScrollTimer.reset(); - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); bool found = false; if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { @@ -525,11 +540,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { .modmaskAtPressTime = MODS, }; - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) { m_dPressedKeys.push_back(KEY); @@ -580,22 +591,6 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true); } -int repeatKeyHandler(void* data) { - SKeybind** ppActiveKeybind = (SKeybind**)data; - - if (!*ppActiveKeybind || g_pSeatManager->keyboard.expired()) - return 0; - - const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler); - - Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); - DISPATCHER->second((*ppActiveKeybind)->arg); - - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate); - - return 0; -} - eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set keybindKeysyms, const std::set pressedKeysyms) { // Returns whether two sets of keysyms are equal, partially equal, or not // matching. (Partially matching means that pressed is a subset of bound) @@ -770,12 +765,10 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } if (k.repeat) { - m_pActiveKeybind = &k; - m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind); - const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); - wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay); + m_vActiveKeybinds.push_back(&k); + m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); } if (!k.nonConsuming) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 4a0af6e9..d375db0f 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -102,8 +102,6 @@ class CKeybindManager { std::unordered_map> m_mDispatchers; - wl_event_source* m_pActiveKeybindEventSource = nullptr; - bool m_bGroupsLocked = false; std::list m_lKeybinds; @@ -121,8 +119,9 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - SKeybind * m_pActiveKeybind = nullptr, *m_pLastLongPressKeybind = nullptr; - SP m_pLongPressTimer; + std::vector m_vActiveKeybinds; + SKeybind* m_pLastLongPressKeybind = nullptr; + SP m_pLongPressTimer, m_pRepeatKeyTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0; From 936dfedbadbae761cd307ba7509467b55ac5e1ae Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 19:56:26 +0000 Subject: [PATCH 0282/1803] keybinds: move to managed pointers --- src/debug/HyprCtl.cpp | 26 ++++---- src/managers/KeybindManager.cpp | 107 +++++++++++++++----------------- src/managers/KeybindManager.hpp | 10 +-- 3 files changed, 68 insertions(+), 75 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 6c9c2b75..1b94296f 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -814,28 +814,28 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { std::string ret = ""; if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - for (auto const& kb : g_pKeybindManager->m_lKeybinds) { + for (auto const& kb : g_pKeybindManager->m_vKeybinds) { ret += "bind"; - if (kb.locked) + if (kb->locked) ret += "l"; - if (kb.mouse) + if (kb->mouse) ret += "m"; - if (kb.release) + if (kb->release) ret += "r"; - if (kb.repeat) + if (kb->repeat) ret += "e"; - if (kb.nonConsuming) + if (kb->nonConsuming) ret += "n"; - if (kb.hasDescription) + if (kb->hasDescription) ret += "d"; - ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, - kb.key, kb.keycode, kb.catchAll, kb.description, kb.handler, kb.arg); + ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb->modmask, + kb->submap, kb->key, kb->keycode, kb->catchAll, kb->description, kb->handler, kb->arg); } } else { // json ret += "["; - for (auto const& kb : g_pKeybindManager->m_lKeybinds) { + for (auto const& kb : g_pKeybindManager->m_vKeybinds) { ret += std::format( R"#( {{ @@ -855,9 +855,9 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "dispatcher": "{}", "arg": "{}" }},)#", - kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.longPress ? "true" : "false", - kb.nonConsuming ? "true" : "false", kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, - kb.catchAll ? "true" : "false", escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); + kb->locked ? "true" : "false", kb->mouse ? "true" : "false", kb->release ? "true" : "false", kb->repeat ? "true" : "false", kb->longPress ? "true" : "false", + kb->nonConsuming ? "true" : "false", kb->hasDescription ? "true" : "false", kb->modmask, escapeJSONStrings(kb->submap), escapeJSONStrings(kb->key), kb->keycode, + kb->catchAll ? "true" : "false", escapeJSONStrings(kb->description), escapeJSONStrings(kb->handler), escapeJSONStrings(kb->arg)); } trimTrailingComma(ret); ret += "]"; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a0cd01a9..995fee17 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -150,7 +150,7 @@ CKeybindManager::CKeybindManager() { if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired()) return; - for (SKeybind* k : m_vActiveKeybinds) { + for (const auto& k : m_vActiveKeybinds) { const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler); Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); @@ -168,7 +168,7 @@ CKeybindManager::CKeybindManager() { static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); m_vPressedSpecialBinds.clear(); }); } @@ -187,24 +187,17 @@ CKeybindManager::~CKeybindManager() { } void CKeybindManager::addKeybind(SKeybind kb) { - m_lKeybinds.push_back(kb); + m_vKeybinds.emplace_back(makeShared(kb)); m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); } void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { - for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) { - 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()) - break; - } - } + std::erase_if(m_vKeybinds, [&mod, &key](const auto& el) { return el->modmask == mod && el->key == key.key && el->keycode == key.keycode && el->catchAll == key.catchAll; }); m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); } uint32_t CKeybindManager::stringToModMask(std::string mods) { @@ -451,7 +444,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); bool suppressEvent = false; if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) { @@ -612,11 +605,11 @@ eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set k return MK_NO_MATCH; } -eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) { - if (mkKeysymSetMatches(keybind.sMkMods, m_sMkMods) != MK_FULL_MATCH) +eMultiKeyCase CKeybindManager::mkBindMatches(const SP keybind) { + if (mkKeysymSetMatches(keybind->sMkMods, m_sMkMods) != MK_FULL_MATCH) return MK_NO_MATCH; - return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys); + return mkKeysymSetMatches(keybind->sMkKeys, m_sMkKeys); } std::string CKeybindManager::getCurrentSubmap() { @@ -640,35 +633,35 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP m_sMkKeys.erase(key.keysym); } - for (auto& k : m_lKeybinds) { - const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "sendshortcut" || k.handler == "mouse"; + for (auto& k : m_vKeybinds) { + const bool SPECIALDISPATCHER = k->handler == "global" || k->handler == "pass" || k->handler == "sendshortcut" || k->handler == "mouse"; const bool SPECIALTRIGGERED = - std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == &k; }) != m_vPressedSpecialBinds.end(); + std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == k; }) != m_vPressedSpecialBinds.end(); const bool IGNORECONDITIONS = SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. - if (!k.dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) + if (!k->dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) continue; - if (!k.locked && g_pSessionLockManager->isSessionLocked()) + if (!k->locked && g_pSessionLockManager->isSessionLocked()) continue; - if (!IGNORECONDITIONS && ((modmask != k.modmask && !k.ignoreMods) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) + if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || k->submap != m_szCurrentSelectedSubmap || k->shadowed)) continue; - if (k.multiKey) { + if (k->multiKey) { switch (mkBindMatches(k)) { case MK_NO_MATCH: continue; case MK_PARTIAL_MATCH: found = true; continue; case MK_FULL_MATCH: found = true; } } else if (!key.keyName.empty()) { - if (key.keyName != k.key) + if (key.keyName != k->key) continue; - } else if (k.keycode != 0) { - if (key.keycode != k.keycode) + } else if (k->keycode != 0) { + if (key.keycode != k->keycode) continue; - } else if (k.catchAll) { + } else if (k->catchAll) { if (found || key.submapAtPress != m_szCurrentSelectedSubmap) continue; } else { @@ -679,8 +672,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP // 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_NO_FLAGS); - const auto KBKEYLOWER = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_NO_FLAGS); + const auto KBKEYLOWER = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) { // Keysym failed to resolve from the key name of the currently iterated bind. @@ -697,8 +690,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP continue; } - if (pressed && k.release && !SPECIALDISPATCHER) { - if (k.nonConsuming) + if (pressed && k->release && !SPECIALDISPATCHER) { + if (k->nonConsuming) continue; found = true; // suppress the event @@ -707,7 +700,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP if (!pressed) { // Require mods to be matching when the key was first pressed. - if (key.modmaskAtPressTime != modmask && !k.ignoreMods) { + if (key.modmaskAtPressTime != modmask && !k->ignoreMods) { // Handle properly `bindr` where a key is itself a bind mod for example: // "bindr = SUPER, SUPER_L, exec, $launcher". // This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set @@ -716,8 +709,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime) continue; - } else if (!k.release && !SPECIALDISPATCHER) { - if (k.nonConsuming) + } else if (!k->release && !SPECIALDISPATCHER) { + if (k->nonConsuming) continue; found = true; // suppress the event @@ -725,25 +718,25 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } } - if (k.longPress) { + if (k->longPress) { const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); - m_pLastLongPressKeybind = &k; + m_pLastLongPressKeybind = k; continue; } - const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler); + const auto DISPATCHER = m_mDispatchers.find(k->mouse ? "mouse" : k->handler); if (SPECIALTRIGGERED && !pressed) - std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == &k; }); + std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == k; }); else if (SPECIALDISPATCHER && pressed) - m_vPressedSpecialBinds.push_back(&k); + m_vPressedSpecialBinds.push_back(k); // Should never happen, as we check in the ConfigManager, but oh well if (DISPATCHER == m_mDispatchers.end()) { - Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler); + Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k->handler); } else { // call the dispatcher Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key.keyName, key.keysym); @@ -751,27 +744,27 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP m_iPassPressed = (int)pressed; // if the dispatchers says to pass event then we will - if (k.handler == "mouse") - res = DISPATCHER->second((pressed ? "1" : "0") + k.arg); + if (k->handler == "mouse") + res = DISPATCHER->second((pressed ? "1" : "0") + k->arg); else - res = DISPATCHER->second(k.arg); + res = DISPATCHER->second(k->arg); m_iPassPressed = -1; - if (k.handler == "submap") { + if (k->handler == "submap") { found = true; // don't process keybinds on submap change. break; } } - if (k.repeat) { + if (k->repeat) { const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); - m_vActiveKeybinds.push_back(&k); + m_vActiveKeybinds.push_back(k); m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); } - if (!k.nonConsuming) + if (!k->nonConsuming) found = true; } @@ -792,17 +785,17 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) { // shadow disables keybinds after one has been triggered - for (auto& k : m_lKeybinds) { + for (auto& k : m_vKeybinds) { bool shadow = false; - if (k.handler == "global" || k.transparent) + if (k->handler == "global" || k->transparent) continue; // can't be shadowed - if (k.multiKey && (mkBindMatches(k) == MK_FULL_MATCH)) + if (k->multiKey && (mkBindMatches(k) == MK_FULL_MATCH)) shadow = true; else { - const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); for (auto const& pk : m_dPressedKeys) { @@ -815,7 +808,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3 } } - if (pk.keycode != 0 && pk.keycode == k.keycode) { + if (pk.keycode != 0 && pk.keycode == k->keycode) { shadow = true; if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) { @@ -826,7 +819,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3 } } - k.shadowed = shadow; + k->shadowed = shadow; } } @@ -1004,7 +997,7 @@ SDispatchResult CKeybindManager::kill(std::string args) { } void CKeybindManager::clearKeybinds() { - m_lKeybinds.clear(); + m_vKeybinds.clear(); } static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional floatState) { @@ -2182,8 +2175,8 @@ SDispatchResult CKeybindManager::setSubmap(std::string submap) { return {}; } - for (auto const& k : g_pKeybindManager->m_lKeybinds) { - if (k.submap == submap) { + for (const auto& k : g_pKeybindManager->m_vKeybinds) { + if (k->submap == submap) { m_szCurrentSelectedSubmap = submap; Debug::log(LOG, "Changed keybind submap to {}", submap); g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap}); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index d375db0f..1f60fdd2 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -104,7 +104,7 @@ class CKeybindManager { bool m_bGroupsLocked = false; - std::list m_lKeybinds; + std::vector> m_vKeybinds; //since we cant find keycode through keyname in xkb: //on sendshortcut call, we once search for keyname (e.g. "g") the correct keycode (e.g. 42) @@ -119,15 +119,15 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - std::vector m_vActiveKeybinds; - SKeybind* m_pLastLongPressKeybind = nullptr; + std::vector> m_vActiveKeybinds; + WP m_pLastLongPressKeybind; SP m_pLongPressTimer, m_pRepeatKeyTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0; uint32_t m_uLastMouseCode = 0; - std::vector m_vPressedSpecialBinds; + std::vector> m_vPressedSpecialBinds; int m_iPassPressed = -1; // used for pass @@ -137,7 +137,7 @@ class CKeybindManager { std::set m_sMkKeys = {}; std::set m_sMkMods = {}; - eMultiKeyCase mkBindMatches(const SKeybind); + eMultiKeyCase mkBindMatches(const SP); eMultiKeyCase mkKeysymSetMatches(const std::set, const std::set); bool handleInternalKeybinds(xkb_keysym_t); From 47a1650c4810ad3cb3e9f125cb0addf18aa7395c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 23:53:38 +0000 Subject: [PATCH 0283/1803] miscfunctions: move configStringToInt to std::expected --- src/config/ConfigManager.cpp | 54 +++++++++++++++++++++------------ src/debug/HyprCtl.cpp | 4 +-- src/desktop/LayerSurface.cpp | 2 +- src/desktop/Window.cpp | 8 ++--- src/helpers/MiscFunctions.cpp | 37 ++++++++++++++-------- src/helpers/MiscFunctions.hpp | 45 +++++++++++++-------------- src/managers/KeybindManager.cpp | 15 +++++---- src/plugins/HookSystem.cpp | 13 +++++--- 8 files changed, 106 insertions(+), 72 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1c025179..fe80a5ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -67,7 +67,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } try { - DATA->m_vColors.push_back(CColor(configStringToInt(var))); + DATA->m_vColors.push_back(CColor(*configStringToInt(var))); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); @@ -2615,7 +2615,14 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin const static std::string ruleOnCreatedEmpty = "on-created-empty:"; const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); - auto assignRule = [&](std::string rule) -> std::optional { +#define CHECK_OR_THROW(expr) \ + \ + auto X = expr; \ + if (!X) { \ + return "Failed parsing a workspace rule"; \ + } + + auto assignRule = [&](std::string rule) -> std::optional { size_t delim = std::string::npos; if ((delim = rule.find("gapsin:")) != std::string::npos) { CVarList varlist = CVarList(rule.substr(delim + 7), 0, ' '); @@ -2633,25 +2640,32 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin try { wsRule.borderSize = std::stoi(rule.substr(delim + 11)); } catch (...) { return "Error parsing workspace rule bordersize: {}", rule.substr(delim + 11); } - else if ((delim = rule.find("border:")) != std::string::npos) - wsRule.noBorder = !configStringToInt(rule.substr(delim + 7)); - else if ((delim = rule.find("shadow:")) != std::string::npos) - wsRule.noShadow = !configStringToInt(rule.substr(delim + 7)); - else if ((delim = rule.find("rounding:")) != std::string::npos) - wsRule.noRounding = !configStringToInt(rule.substr(delim + 9)); - else if ((delim = rule.find("decorate:")) != std::string::npos) - wsRule.decorate = configStringToInt(rule.substr(delim + 9)); - else if ((delim = rule.find("monitor:")) != std::string::npos) + else if ((delim = rule.find("border:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 7))) + wsRule.noBorder = !*X; + } else if ((delim = rule.find("shadow:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 7))) + wsRule.noShadow = !*X; + } else if ((delim = rule.find("rounding:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 9))) + wsRule.noRounding = !*X; + } else if ((delim = rule.find("decorate:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 9))) + wsRule.decorate = *X; + } else if ((delim = rule.find("monitor:")) != std::string::npos) wsRule.monitor = rule.substr(delim + 8); - else if ((delim = rule.find("default:")) != std::string::npos) - wsRule.isDefault = configStringToInt(rule.substr(delim + 8)); - else if ((delim = rule.find("persistent:")) != std::string::npos) - wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); - else if ((delim = rule.find("defaultName:")) != std::string::npos) + else if ((delim = rule.find("default:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 8))) + wsRule.isDefault = *X; + } else if ((delim = rule.find("persistent:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 11))) + wsRule.isPersistent = *X; + } else if ((delim = rule.find("defaultName:")) != std::string::npos) wsRule.defaultName = rule.substr(delim + 12); - else if ((delim = rule.find(ruleOnCreatedEmpty)) != std::string::npos) - wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmptyLen)); - else if ((delim = rule.find("layoutopt:")) != std::string::npos) { + else if ((delim = rule.find(ruleOnCreatedEmpty)) != std::string::npos) { + CHECK_OR_THROW(cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmptyLen))) + wsRule.onCreatedEmptyRunCmd = *X; + } else if ((delim = rule.find("layoutopt:")) != std::string::npos) { std::string opt = rule.substr(delim + 10); if (!opt.contains(":")) { // invalid @@ -2668,6 +2682,8 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin return {}; }; +#undef CHECK_OR_THROW + CVarList rulesList{rules, 0, ',', true}; for (auto const& r : rulesList) { const auto R = assignRule(r); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 1b94296f..4d3c2be4 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1286,7 +1286,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { return "ok"; } - const CColor COLOR = configStringToInt(vars[1]); + const CColor COLOR = configStringToInt(vars[1]).value_or(0); for (size_t i = 2; i < vars.size(); ++i) errorMessage += vars[i] + ' '; @@ -1539,7 +1539,7 @@ 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]).value_or(0); size_t msgidx = 4; float fontsize = 13.f; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index cd1c4742..40491123 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -400,7 +400,7 @@ void CLayerSurface::applyRules() { } else if (rule.rule.starts_with("xray")) { CVarList vars{rule.rule, 0, ' '}; try { - xray = configStringToInt(vars[1]); + xray = configStringToInt(vars[1]).value_or(false); } catch (...) {} } else if (rule.rule.starts_with("animation")) { CVarList vars{rule.rule, 2, 's'}; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e74e13a2..33e6a5f8 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -672,8 +672,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { // Basic form has only two colors, everything else can be parsed as a gradient if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { - m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority); - m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority); + m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); return; } @@ -685,9 +685,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } else if (token.contains("deg")) inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0); else if (active) - activeBorderGradient.m_vColors.push_back(configStringToInt(token)); + activeBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); else - inactiveBorderGradient.m_vColors.push_back(configStringToInt(token)); + inactiveBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); } // Includes sanity checks for the number of colors in each gradient diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 80681826..fa2f84ab 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -691,15 +691,15 @@ int64_t getPPIDof(int64_t pid) { #endif } -int64_t configStringToInt(const std::string& VALUE) { - auto parseHex = [](const std::string& value) -> int64_t { +std::expected configStringToInt(const std::string& VALUE) { + auto parseHex = [](const std::string& value) -> std::expected { try { size_t position; auto result = stoll(value, &position, 16); if (position == value.size()) return result; } catch (const std::exception&) {} - throw std::invalid_argument("invalid hex " + value); + return std::unexpected("invalid hex " + value); }; if (VALUE.starts_with("0x")) { // Values with 0x are hex @@ -718,18 +718,25 @@ int64_t configStringToInt(const std::string& VALUE) { auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); rolling = rolling.substr(rolling.find(',') + 1); uint8_t a = 0; + + if (!r || !g || !b) + return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); + try { a = std::round(std::stof(trim(rolling.substr(0, rolling.find(',')))) * 255.f); - } catch (std::exception& e) { throw std::invalid_argument("failed parsing " + VALUEWITHOUTFUNC); } + } catch (std::exception& e) { return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); } - return a * (Hyprlang::INT)0x1000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + return a * (Hyprlang::INT)0x1000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b; } else if (VALUEWITHOUTFUNC.length() == 8) { const auto RGBA = parseHex(VALUEWITHOUTFUNC); + + if (!RGBA) + return RGBA; // now we need to RGBA -> ARGB. The config holds ARGB only. - return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); + return (*RGBA >> 8) + 0x1000000 * (*RGBA & 0xFF); } - throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); + return std::unexpected("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); } else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) { const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5)); @@ -744,12 +751,16 @@ int64_t configStringToInt(const std::string& VALUE) { rolling = rolling.substr(rolling.find(',') + 1); auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); - return (Hyprlang::INT)0xFF000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + if (!r || !g || !b) + return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); + + return (Hyprlang::INT)0xFF000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b; } else if (VALUEWITHOUTFUNC.length() == 6) { - return parseHex(VALUEWITHOUTFUNC) + 0xFF000000; + auto r = parseHex(VALUEWITHOUTFUNC); + return r ? *r + 0xFF000000 : r; } - throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); + return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); } else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) { return 1; } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { @@ -757,14 +768,14 @@ int64_t configStringToInt(const std::string& VALUE) { } if (VALUE.empty() || !isNumber(VALUE, false)) - throw std::invalid_argument("cannot parse \"" + VALUE + "\" as an int."); + return std::unexpected("cannot parse \"" + VALUE + "\" as an int."); try { const auto RES = std::stoll(VALUE); return RES; - } catch (std::exception& e) { throw std::invalid_argument(std::string{"stoll threw: "} + e.what()); } + } catch (std::exception& e) { return std::unexpected(std::string{"stoll threw: "} + e.what()); } - return 0; + return std::unexpected("parse error"); } Vector2D configStringToVector2D(const std::string& VALUE) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 34b23746..bb686df4 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -6,6 +6,7 @@ #include "math/Math.hpp" #include #include +#include #include "../SharedDefs.hpp" #include "../macros.hpp" @@ -19,28 +20,28 @@ struct SWorkspaceIDName { std::string name; }; -std::string absolutePath(const std::string&, const std::string&); -void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); -void removeWLSignal(wl_listener*); -std::string escapeJSONStrings(const std::string& str); -bool isDirection(const std::string&); -bool isDirection(const char&); -SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); -std::optional cleanCmdForWorkspace(const std::string&, std::string); -float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); -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); -double normalizeAngleRad(double ang); -std::vector getBacktrace(); -void throwError(const std::string& err); -bool envEnabled(const std::string& env); -int allocateSHMFile(size_t len); -bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); -float stringToPercentage(const std::string& VALUE, const float REL); +std::string absolutePath(const std::string&, const std::string&); +void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); +void removeWLSignal(wl_listener*); +std::string escapeJSONStrings(const std::string& str); +bool isDirection(const std::string&); +bool isDirection(const char&); +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); +std::optional cleanCmdForWorkspace(const std::string&, std::string); +float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); +void logSystemInfo(); +std::string execAndGet(const char*); +int64_t getPPIDof(int64_t pid); +std::expected configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); +std::optional getPlusMinusKeywordResult(std::string in, float relative); +double normalizeAngleRad(double ang); +std::vector getBacktrace(); +void throwError(const std::string& err); +bool envEnabled(const std::string& env); +int allocateSHMFile(size_t len); +bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 995fee17..c9ca90e5 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2972,11 +2972,14 @@ SDispatchResult CKeybindManager::setProp(std::string args) { const auto TOKEN = vars[i]; if (TOKEN.ends_with("deg")) colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else - colorData.m_vColors.push_back(configStringToInt(TOKEN)); + else if (const auto V = configStringToInt(TOKEN); V) + colorData.m_vColors.push_back(*V); } - } else if (VAL != "-1") - colorData.m_vColors.push_back(configStringToInt(VAL)); + } else if (VAL != "-1") { + const auto V = configStringToInt(VAL); + if (V) + colorData.m_vColors.push_back(*V); + } if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); @@ -2993,8 +2996,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { if (VAL == "unset") search->second(PWINDOW)->unset(PRIORITY_SET_PROP); - else - *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); + else if (const auto V = configStringToInt(VAL); V) + *(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP); } else { return {.success = false, .error = "Prop not found"}; } diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 745b2593..69ca81cb 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -90,11 +90,14 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr std::string code = probe.assembly.substr(lastAsmNewline, probe.assembly.find("\n", lastAsmNewline) - lastAsmNewline); if (code.contains("%rip")) { - CVarList tokens{code, 0, 's'}; - size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; - size_t minusPresent = tokens[1][0] == '-' ? 1 : 0; - std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent)); - const int32_t OFFSET = (minusPresent ? -1 : 1) * configStringToInt(addr); + CVarList tokens{code, 0, 's'}; + size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; + size_t minusPresent = tokens[1][0] == '-' ? 1 : 0; + std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent)); + auto addrResult = configStringToInt(addr); + if (!addrResult) + return {}; + const int32_t OFFSET = (minusPresent ? -1 : 1) * *addrResult; if (OFFSET == 0) return {}; const uint64_t DESTINATION = currentAddress + OFFSET + len; From 67cee430061626ccd73dc6d30eed9db289053608 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 19 Nov 2024 01:16:11 +0000 Subject: [PATCH 0284/1803] internal: minor cleanups for color results --- src/debug/HyprCtl.cpp | 8 +++++--- src/managers/KeybindManager.cpp | 23 ++++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 4d3c2be4..7c0a9417 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1529,9 +1529,8 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { icon = std::stoi(ICON); } catch (std::exception& e) { return "invalid arg 1"; } - if (icon > ICON_NONE || icon < 0) { + if (icon > ICON_NONE || icon < 0) icon = ICON_NONE; - } const auto TIME = vars[2]; int time = 0; @@ -1539,7 +1538,10 @@ 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]).value_or(0); + const auto COLOR_RESULT = configStringToInt(vars[3]); + if (!COLOR_RESULT) + return "invalid arg 3"; + CColor color = *COLOR_RESULT; size_t msgidx = 4; float fontsize = 13.f; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c9ca90e5..75e2a7b3 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2920,6 +2920,9 @@ SDispatchResult CKeybindManager::event(std::string args) { return {}; } +#include +#include + SDispatchResult CKeybindManager::setProp(std::string args) { CVarList vars(args, 3, ' '); @@ -2972,14 +2975,17 @@ SDispatchResult CKeybindManager::setProp(std::string args) { const auto TOKEN = vars[i]; if (TOKEN.ends_with("deg")) colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else if (const auto V = configStringToInt(TOKEN); V) - colorData.m_vColors.push_back(*V); + else + configStringToInt(TOKEN).and_then([&colorData](const auto& e) { + colorData.m_vColors.push_back(e); + return std::result_of::type(1); + }); } - } else if (VAL != "-1") { - const auto V = configStringToInt(VAL); - if (V) - colorData.m_vColors.push_back(*V); - } + } else if (VAL != "-1") + configStringToInt(VAL).and_then([&colorData](const auto& e) { + colorData.m_vColors.push_back(e); + return std::result_of::type(1); + }); if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); @@ -2998,9 +3004,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { search->second(PWINDOW)->unset(PRIORITY_SET_PROP); else if (const auto V = configStringToInt(VAL); V) *(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP); - } else { + } else return {.success = false, .error = "Prop not found"}; - } } catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; } g_pCompositor->updateAllWindowsAnimatedDecorationValues(); From aa067a4cf12522ede1752dd2048ce67d07e903f1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 19 Nov 2024 21:40:16 +0000 Subject: [PATCH 0285/1803] xdg-shell: don't report invalid min/max sizes on unset fixes #8522 --- src/protocols/XDGShell.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 932882e9..f121070d 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -324,10 +324,14 @@ void CXDGToplevelResource::close() { } Vector2D CXDGToplevelResource::layoutMinSize() { + if (current.minSize.x <= 1 && current.minSize.y <= 1) + return {0, 0}; return owner ? current.minSize + owner->current.geometry.pos() : current.minSize; } Vector2D CXDGToplevelResource::layoutMaxSize() { + if (current.maxSize.x <= 1 && current.maxSize.y <= 1) + return {0, 0}; return owner ? current.maxSize + owner->current.geometry.pos() : current.maxSize; } From c4eda46d0ef022a17348623beec4154ba34af691 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 19 Nov 2024 22:07:25 +0000 Subject: [PATCH 0286/1803] xdg-shell: even more robust layout min/max size although I don't think any apps use this, but better safe than sorry --- src/protocols/XDGShell.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index f121070d..688d0006 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -324,15 +324,21 @@ void CXDGToplevelResource::close() { } Vector2D CXDGToplevelResource::layoutMinSize() { - if (current.minSize.x <= 1 && current.minSize.y <= 1) - return {0, 0}; - return owner ? current.minSize + owner->current.geometry.pos() : current.minSize; + Vector2D minSize; + if (current.minSize.x > 1) + minSize.x = owner ? current.minSize.x + owner->current.geometry.pos().x : current.minSize.x; + if (current.minSize.y > 1) + minSize.y = owner ? current.minSize.y + owner->current.geometry.pos().y : current.minSize.y; + return minSize; } Vector2D CXDGToplevelResource::layoutMaxSize() { - if (current.maxSize.x <= 1 && current.maxSize.y <= 1) - return {0, 0}; - return owner ? current.maxSize + owner->current.geometry.pos() : current.maxSize; + Vector2D maxSize; + if (current.maxSize.x > 1) + maxSize.x = owner ? current.maxSize.x + owner->current.geometry.pos().x : current.maxSize.x; + if (current.maxSize.y > 1) + maxSize.y = owner ? current.maxSize.y + owner->current.geometry.pos().y : current.maxSize.y; + return maxSize; } CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, SP surface_) : From e5fa017172156fa5c70fedeaee5f51eace9577c0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 20 Nov 2024 10:32:50 +0000 Subject: [PATCH 0287/1803] internal: fix some misused configStringToInt conversions fixes #8523 --- src/config/ConfigManager.cpp | 4 ++-- src/desktop/Window.cpp | 2 +- src/desktop/Workspace.cpp | 4 ++-- src/managers/KeybindManager.cpp | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fe80a5ab..357e7a60 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2101,13 +2101,13 @@ std::optional CConfigManager::handleAnimation(const std::string& co PANIM->second.pValues = &PANIM->second; // This helper casts strings like "1", "true", "off", "yes"... to int. - int64_t enabledInt = configStringToInt(ARGS[1]) == 1; + int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1; // Checking that the int is 1 or 0 because the helper can return integers out of range. if (enabledInt != 0 && enabledInt != 1) return "invalid animation on/off state"; - PANIM->second.internalEnabled = configStringToInt(ARGS[1]) == 1; + PANIM->second.internalEnabled = configStringToInt(ARGS[1]).value_or(0) == 1; if (PANIM->second.internalEnabled) { // speed diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 33e6a5f8..117d301c 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -707,7 +707,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { *(search->second(m_pSelf.lock())) = CWindowOverridableVar(true, priority); } else { try { - *(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]), priority); + *(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]).value_or(0), priority); } catch (...) {} } } else if (auto search = g_pConfigManager->miWindowProperties.find(VARS[0]); search != g_pConfigManager->miWindowProperties.end()) { diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 2e1e91f2..8cddbb6b 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -332,7 +332,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { const auto SHOULDBESPECIAL = configStringToInt(prop); - if ((bool)SHOULDBESPECIAL != m_bIsSpecialWorkspace) + if (SHOULDBESPECIAL && (bool)*SHOULDBESPECIAL != m_bIsSpecialWorkspace) return false; continue; } @@ -367,7 +367,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { const auto WANTSNAMED = configStringToInt(prop); - if (WANTSNAMED != (m_iID <= -1337)) + if (WANTSNAMED && *WANTSNAMED != (m_iID <= -1337)) return false; continue; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 75e2a7b3..be1e9534 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2961,13 +2961,13 @@ SDispatchResult CKeybindManager::setProp(std::string args) { CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); } else if (PROP == "alphaoverride") { PWINDOW->m_sWindowData.alpha = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP); } else if (PROP == "alphainactiveoverride") { PWINDOW->m_sWindowData.alphaInactive = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP); } else if (PROP == "alphafullscreenoverride") { PWINDOW->m_sWindowData.alphaFullscreen = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP); } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { CGradientValueData colorData = {}; if (vars.size() > 4) { @@ -2998,7 +2998,7 @@ SDispatchResult CKeybindManager::setProp(std::string args) { else if (VAL == "unset") pWindowDataElement->unset(PRIORITY_SET_PROP); else - *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); + *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL).value_or(0), PRIORITY_SET_PROP); } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { if (VAL == "unset") search->second(PWINDOW)->unset(PRIORITY_SET_PROP); From 940f7aa990dbc99815bab8d355999d8277534b17 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Nov 2024 11:02:21 +0000 Subject: [PATCH 0288/1803] renderer: fixup blur optimization considitons fixes #8531 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index fc17ef9f..42545bc1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -174,7 +174,6 @@ static void renderSurface(SP surface, int x, int y, void* da } const auto RDATA = (SRenderData*)data; - const bool BLUR = RDATA->blur && !TEXTURE->m_bOpaque; const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); @@ -183,6 +182,7 @@ static void renderSurface(SP surface, int x, int y, void* da auto PSURFACE = CWLSurface::fromResource(surface); const float ALPHA = RDATA->alpha * RDATA->fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); + const bool BLUR = RDATA->blur && (!TEXTURE->m_bOpaque || ALPHA < 1.F); CBox windowBox; if (RDATA->surface && surface == RDATA->surface) { From 943b3d467b0a77a6b67df01e78f5e4977486824f Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 22 Nov 2024 02:47:51 +0100 Subject: [PATCH 0289/1803] bezier: optimize setup of bezier curves (#8528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit avoid reallocations by resizing and copy the pVec into the resized m_dPoints, reduce the amount of calculations in baking to only do it once per iteration instead of twice. precompute in getYforT and getXforT return early in getYForPoint if x is equal or below 0. and use const references where we can. these changes we are now down to an average of "time to bake: 2.50µs." on my machine compared to before average of "time to bake: 11.15µs" --- src/helpers/BezierCurve.cpp | 39 ++++++++++++++++++++++++------------- src/helpers/BezierCurve.hpp | 8 ++++---- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/helpers/BezierCurve.cpp b/src/helpers/BezierCurve.cpp index ea567ad6..23fcd691 100644 --- a/src/helpers/BezierCurve.cpp +++ b/src/helpers/BezierCurve.cpp @@ -6,24 +6,27 @@ #include void CBezierCurve::setup(std::vector* pVec) { - m_dPoints.clear(); - const auto BEGIN = std::chrono::high_resolution_clock::now(); - m_dPoints.emplace_back(Vector2D(0, 0)); - - for (auto const& p : *pVec) { - m_dPoints.push_back(p); + // Avoid reallocations by reserving enough memory upfront + m_dPoints.resize(pVec->size() + 2); + m_dPoints[0] = Vector2D(0, 0); // Start point + size_t index = 1; // Start after the first element + for (const auto& vec : *pVec) { + if (index < m_dPoints.size() - 1) { // Bounds check to ensure safety + m_dPoints[index] = vec; + ++index; + } } - - m_dPoints.emplace_back(Vector2D(1, 1)); + m_dPoints.back() = Vector2D(1, 1); // End point RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_dPoints.size()); // bake BAKEDPOINTS points for faster lookups // T -> X ( / BAKEDPOINTS ) for (int i = 0; i < BAKEDPOINTS; ++i) { - m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS)); + float const t = (i + 1) / (float)BAKEDPOINTS; + m_aPointsBaked[i] = Vector2D(getXForT(t), getYForT(t)); } const auto ELAPSEDUS = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f; @@ -40,18 +43,26 @@ void CBezierCurve::setup(std::vector* pVec) { ELAPSEDUS, ELAPSEDCALCAVG); } -float CBezierCurve::getYForT(float t) { - return 3 * t * pow(1 - t, 2) * m_dPoints[1].y + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].y + pow(t, 3); +float CBezierCurve::getXForT(float const& t) { + float t2 = t * t; + float t3 = t2 * t; + + return 3 * t * (1 - t) * (1 - t) * m_dPoints[1].x + 3 * t2 * (1 - t) * m_dPoints[2].x + t3 * m_dPoints[3].x; } -float CBezierCurve::getXForT(float t) { - return 3 * t * pow(1 - t, 2) * m_dPoints[1].x + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].x + pow(t, 3); +float CBezierCurve::getYForT(float const& t) { + float t2 = t * t; + float t3 = t2 * t; + + return 3 * t * (1 - t) * (1 - t) * m_dPoints[1].y + 3 * t2 * (1 - t) * m_dPoints[2].y + t3 * m_dPoints[3].y; } // Todo: this probably can be done better and faster -float CBezierCurve::getYForPoint(float x) { +float CBezierCurve::getYForPoint(float const& x) { if (x >= 1.f) return 1.f; + if (x <= 0.f) + return 0.f; int index = 0; bool below = true; diff --git a/src/helpers/BezierCurve.hpp b/src/helpers/BezierCurve.hpp index 54af46a6..1a842f5a 100644 --- a/src/helpers/BezierCurve.hpp +++ b/src/helpers/BezierCurve.hpp @@ -16,13 +16,13 @@ class CBezierCurve { // this EXCLUDES the 0,0 and 1,1 points, void setup(std::vector* points); - float getYForT(float t); - float getXForT(float t); - float getYForPoint(float x); + float getYForT(float const& t); + float getXForT(float const& t); + float getYForPoint(float const& x); private: // this INCLUDES the 0,0 and 1,1 points. - std::deque m_dPoints; + std::vector m_dPoints; std::array m_aPointsBaked; }; From b1003445953474b967464d4d0878955d37498647 Mon Sep 17 00:00:00 2001 From: may <63159454+m4rch3n1ng@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:31:42 +0100 Subject: [PATCH 0290/1803] keybinds: actually suppress internal keybinds instead of passing them along (#8538) --- src/managers/KeybindManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index be1e9534..8cf39c1b 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -423,8 +423,10 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE); const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); + // handleInternalKeybinds returns true when the key should be suppressed, + // while this function returns true when the key event should be sent if (handleInternalKeybinds(internalKeysym)) - return true; + return false; const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); From a847bc67b1efcf3a0fa9c8a3a1da1a79743940c1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 22 Nov 2024 15:22:28 +0000 Subject: [PATCH 0291/1803] monitor: fix default focus when switching to a fs workspace --- src/helpers/Monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9ac48220..63268c8a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -629,7 +629,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace && !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - auto pWindow = pWorkspace->getLastFocusedWindow(); + auto pWindow = pWorkspace->m_bHasFullscreenWindow ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : pWorkspace->getLastFocusedWindow(); if (!pWindow) { if (*PFOLLOWMOUSE == 1) From 745a82ce8ab19d958e344f5925bb1dc8ea7d6a53 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 22 Nov 2024 16:01:02 +0000 Subject: [PATCH 0292/1803] core: workspace-related function cleanup / refactor CCompositor is massive, and has a lot of functions that could be better optimized if in CWorkspace --- src/Compositor.cpp | 182 ++++----------------------- src/Compositor.hpp | 13 -- src/config/ConfigManager.cpp | 4 +- src/debug/HyprCtl.cpp | 10 +- src/desktop/Window.cpp | 38 +++--- src/desktop/Workspace.cpp | 149 ++++++++++++++++++++-- src/desktop/Workspace.hpp | 20 +-- src/events/Windows.cpp | 12 +- src/helpers/MiscFunctions.cpp | 2 +- src/helpers/Monitor.cpp | 6 +- src/layout/DwindleLayout.cpp | 6 +- src/layout/IHyprLayout.cpp | 10 +- src/layout/MasterLayout.cpp | 2 +- src/managers/AnimationManager.cpp | 2 +- src/managers/KeybindManager.cpp | 30 +++-- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.cpp | 8 +- src/managers/input/Swipe.cpp | 13 +- src/render/Renderer.cpp | 18 +-- 19 files changed, 267 insertions(+), 260 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0e0c75a1..3fe5acec 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -833,6 +833,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular continue; + if (!w->m_pWorkspace) + continue; + const auto PWINDOWMONITOR = w->m_pMonitor.lock(); // to avoid focusing windows behind special workspaces from other monitors @@ -844,7 +847,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; } - if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && + if (w->m_bIsFloating && w->m_bIsMapped && w->m_pWorkspace->isVisible() && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect()) @@ -887,7 +890,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper const auto PWORKSPACE = getWorkspaceByID(WSPID); if (PWORKSPACE->m_bHasFullscreenWindow) - return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + return PWORKSPACE->getFullscreenWindow(); auto found = floating(false); if (found) @@ -898,6 +901,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; + if (!w->m_pWorkspace) + continue; + if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (w->hasPopupAt(pos)) @@ -909,6 +915,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; + if (!w->m_pWorkspace) + continue; + if (!w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; @@ -1070,7 +1079,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface const auto PMONITOR = pWindow->m_pMonitor.lock(); - if (!isWorkspaceVisible(pWindow->m_pWorkspace)) { + if (!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) { const auto PWORKSPACE = pWindow->m_pWorkspace; // This is to fix incorrect feedback on the focus history. PWORKSPACE->m_pLastFocusedWindow = pWindow; @@ -1247,30 +1256,6 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { return nullptr; } -PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == ID && w->isFullscreen()) - return w; - } - - return nullptr; -} - -bool CCompositor::isWorkspaceVisible(PHLWORKSPACE w) { - return valid(w) && w->m_bVisible; -} - -bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { - if (!valid(w)) - return false; - - const auto PMONITOR = w->m_pMonitor.lock(); - if (PMONITOR->activeSpecialWorkspace) - return PMONITOR->activeSpecialWorkspace->m_iID == w->m_iID; - - return PMONITOR->activeWorkspace->m_iID == w->m_iID; -} - PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) { for (auto const& w : m_vWorkspaces) { if (w->m_iID == id && !w->inert()) @@ -1295,37 +1280,6 @@ void CCompositor::sanityCheckWorkspaces() { } } -int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { - int no = 0; - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id || !w->m_bIsMapped) - continue; - if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) - continue; - if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) - continue; - no++; - } - - return no; -} - -int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { - int no = 0; - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id || !w->m_bIsMapped) - continue; - if (!w->m_sGroupData.head) - continue; - if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) - continue; - if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) - continue; - no++; - } - return no; -} - PHLWINDOW CCompositor::getUrgentWindow() { for (auto const& w : m_vWindows) { if (w->m_bIsMapped && w->m_bIsUrgent) @@ -1335,44 +1289,6 @@ PHLWINDOW CCompositor::getUrgentWindow() { return nullptr; } -bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent) - return true; - } - - return false; -} - -PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden()) - return w; - } - - return nullptr; -} - -PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { - const auto PWORKSPACE = getWorkspaceByID(id); - - if (!PWORKSPACE) - return nullptr; - - const auto PMONITOR = PWORKSPACE->m_pMonitor.lock(); - - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden()) - continue; - - const auto WINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); - - if (WINDOWIDEALBB.x <= PMONITOR->vecPosition.x + 1 && WINDOWIDEALBB.y <= PMONITOR->vecPosition.y + 1) - return w; - } - return nullptr; -} - bool CCompositor::isWindowActive(PHLWINDOW pWindow) { if (m_pLastWindow.expired() && !m_pLastFocus) return false; @@ -1560,7 +1476,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { // for tiled windows, we calc edges for (auto const& w : m_vWindows) { - if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) + if (w == pWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible()) continue; if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) @@ -1652,7 +1568,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { constexpr float THRESHOLD = 0.3 * M_PI; for (auto const& w : m_vWindows) { - if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) + if (w == pWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible()) continue; if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) @@ -1678,7 +1594,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { } if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow) - leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + leaderWindow = PWORKSPACE->getFullscreenWindow(); } if (leaderValue != -1) @@ -1871,15 +1787,6 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() { } } -void CCompositor::updateWorkspaceWindows(const int64_t& id) { - for (auto const& w : m_vWindows) { - if (!w->m_bIsMapped || w->workspaceID() != id) - continue; - - w->updateDynamicRules(); - } -} - void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // optimization static auto PACTIVECOL = CConfigValue("general:col.active_border"); @@ -2391,7 +2298,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); - forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID()); + PWORKSPACE->forceReportSizesToWindows(); g_pInputManager->recheckIdleInhibitorStatus(); @@ -2422,27 +2329,6 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) { return nullptr; } -void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id) - continue; - - w->updateWindowDecos(); - } -} - -void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { - const auto PWORKSPACE = getWorkspaceByID(id); - const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; - - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id) - continue; - - w->updateWindowData(WORKSPACERULE); - } -} - void CCompositor::scheduleFrameForMonitor(PHLMONITOR pMonitor, IOutput::scheduleFrameReason reason) { if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) return; @@ -2654,14 +2540,6 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con return Vector2D(X, Y); } -void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) { - g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); - } - } -} - PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmpty) { const auto NAME = name == "" ? std::to_string(id) : name; auto monID = monid; @@ -2679,21 +2557,6 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO return PWORKSPACE; } -void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) { - const auto PWORKSPACE = getWorkspaceByID(id); - - if (!PWORKSPACE) - return; - - if (isWorkspaceSpecial(id)) - return; - - Debug::log(LOG, "renameWorkspace: Renaming workspace {} to '{}'", id, name); - PWORKSPACE->m_szName = name; - - g_pEventManager->postEvent({"renameworkspace", std::to_string(PWORKSPACE->m_iID) + "," + PWORKSPACE->m_szName}); -} - void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { if (m_pLastMonitor == pMonitor) return; @@ -2758,8 +2621,8 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FSMODE_NONE); - const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); - const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true); + const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow(); + const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true); const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); @@ -2817,14 +2680,15 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FULLSCREENMODE); - g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); - g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID()); + pWorkspace->updateWindows(); + if (pWindow->m_pWorkspace) + pWindow->m_pWorkspace->updateWindows(); g_pCompositor->updateSuspendedStates(); } PHLWINDOW CCompositor::getForceFocus() { for (auto const& w : m_vWindows) { - if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace)) + if (!w->m_bIsMapped || w->isHidden() || !w->m_pWorkspace || !w->m_pWorkspace->isVisible()) continue; if (!w->m_bStayFocused) @@ -3002,7 +2866,7 @@ void CCompositor::updateSuspendedStates() { if (!w->m_bIsMapped) continue; - w->setSuspended(w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace)); + w->setSuspended(w->isHidden() || !w->m_pWorkspace || !w->m_pWorkspace->isVisible()); } } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 208b6ecf..c02be579 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -115,21 +115,11 @@ class CCompositor { PHLMONITOR getRealMonitorFromOutput(SP); PHLWINDOW getWindowFromSurface(SP); PHLWINDOW getWindowFromHandle(uint32_t); - bool isWorkspaceVisible(PHLWORKSPACE); - bool isWorkspaceVisibleNotCovered(PHLWORKSPACE); PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&); PHLWORKSPACE getWorkspaceByName(const std::string&); PHLWORKSPACE getWorkspaceByString(const std::string&); void sanityCheckWorkspaces(); - void updateWorkspaceWindowDecos(const WORKSPACEID&); - void updateWorkspaceWindowData(const WORKSPACEID&); - int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); - int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); PHLWINDOW getUrgentWindow(); - bool hasUrgentWindowOnWorkspace(const WORKSPACEID&); - PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&); - PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&); - PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&); bool isWindowActive(PHLWINDOW); void changeWindowZOrder(PHLWINDOW, bool); void cleanupFadingOut(const MONITORID& monid); @@ -142,7 +132,6 @@ class CCompositor { PHLMONITOR getMonitorInDirection(const char&); PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&); void updateAllWindowsAnimatedDecorationValues(); - void updateWorkspaceWindows(const WORKSPACEID& id); void updateWindowAnimatedDecorationValues(PHLWINDOW); MONITORID getNextAvailableMonitorID(std::string const& name); void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false); @@ -165,10 +154,8 @@ class CCompositor { PHLLS getLayerSurfaceFromSurface(SP); void closeWindow(PHLWINDOW); Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); - void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&); PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", bool isEmpty = true); // will be deleted next frame if left empty and unfocused! - void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); void setActiveMonitor(PHLMONITOR); bool isWorkspaceSpecial(const WORKSPACEID&); WORKSPACEID getNewSpecialID(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 357e7a60..f6734011 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -927,8 +927,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { for (auto const& w : g_pCompositor->m_vWorkspaces) { if (w->inert()) continue; - g_pCompositor->updateWorkspaceWindows(w->m_iID); - g_pCompositor->updateWorkspaceWindowData(w->m_iID); + w->updateWindows(); + w->updateWindowData(); } // Update window border colors diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 7c0a9417..11c16f0e 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -306,12 +306,12 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form "lastwindowtitle": "{}" }})#", w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), - escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), g_pCompositor->getWindowsOnWorkspace(w->m_iID), - ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); + escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), w->getWindows(), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), + (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); } else { return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, - w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", g_pCompositor->getWindowsOnWorkspace(w->m_iID), - (int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : ""); + w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", w->getWindows(), (int)w->m_bHasFullscreenWindow, + (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : ""); } } @@ -1764,7 +1764,7 @@ std::string CHyprCtl::getReply(std::string request) { } for (auto const& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || !g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) + if (!w->m_bIsMapped || !w->m_pWorkspace || !w->m_pWorkspace->isVisible()) continue; w->updateDynamicRules(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 117d301c..12e81b76 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -413,12 +413,12 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { setAnimationsToMove(); - g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID); - g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID); + OLDWORKSPACE->updateWindows(); + OLDWORKSPACE->updateWindowData(); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID()); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + pWorkspace->updateWindows(); + pWorkspace->updateWindowData(); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -437,7 +437,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { // update xwayland coords g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value()); - if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE->m_iID) == 0 && *PCLOSEONLASTSPECIAL) { + if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) PMONITOR->setSpecialWorkspace(nullptr); } @@ -516,7 +516,7 @@ void CWindow::onUnmap() { std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); - if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(workspaceID()) == 0 && onSpecialWorkspace()) { + if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) { const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace == m_pWorkspace) PMONITOR->setSpecialWorkspace(nullptr); @@ -527,8 +527,10 @@ void CWindow::onUnmap() { if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this) PMONITOR->solitaryClient.reset(); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -855,8 +857,10 @@ void CWindow::createGroup() { addWindowDeco(std::make_unique(m_pSelf.lock())); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -873,8 +877,10 @@ void CWindow::destroyGroup() { m_sGroupData.pNextWindow.reset(); m_sGroupData.head = false; updateWindowDecos(); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -909,8 +915,10 @@ void CWindow::destroyGroup() { } g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -1507,7 +1515,7 @@ void CWindow::onX11Configure(CBox box) { updateWindowDecos(); - if (!g_pCompositor->isWorkspaceVisible(m_pWorkspace)) + if (!m_pWorkspace || !m_pWorkspace->isVisible()) return; // further things are only for visible windows m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace; diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 8cddbb6b..7c3d47d7 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -422,11 +422,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { int count; if (wantsCountGroup) - count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); else - count = g_pCompositor->getWindowsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); if (count != from) return false; @@ -456,11 +456,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { WORKSPACEID count; if (wantsCountGroup) - count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); else - count = g_pCompositor->getWindowsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); if (std::clamp(count, from, to) != count) return false; @@ -525,3 +525,136 @@ bool CWorkspace::inert() { MONITORID CWorkspace::monitorID() { return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID; } + +PHLWINDOW CWorkspace::getFullscreenWindow() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace == m_pSelf && w->isFullscreen()) + return w; + } + + return nullptr; +} + +bool CWorkspace::isVisible() { + return m_bVisible; +} + +bool CWorkspace::isVisibleNotCovered() { + const auto PMONITOR = m_pMonitor.lock(); + if (PMONITOR->activeSpecialWorkspace) + return PMONITOR->activeSpecialWorkspace->m_iID == m_iID; + + return PMONITOR->activeWorkspace->m_iID == m_iID; +} + +int CWorkspace::getWindows(std::optional onlyTiled, std::optional onlyVisible) { + int no = 0; + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->workspaceID() != m_iID || !w->m_bIsMapped) + continue; + if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) + continue; + if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) + continue; + no++; + } + + return no; +} + +int CWorkspace::getGroups(std::optional onlyTiled, std::optional onlyVisible) { + int no = 0; + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->workspaceID() != m_iID || !w->m_bIsMapped) + continue; + if (!w->m_sGroupData.head) + continue; + if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) + continue; + if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) + continue; + no++; + } + return no; +} + +PHLWINDOW CWorkspace::getFirstWindow() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace == m_pSelf && w->m_bIsMapped && !w->isHidden()) + return w; + } + + return nullptr; +} + +PHLWINDOW CWorkspace::getTopLeftWindow() { + const auto PMONITOR = m_pMonitor.lock(); + + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) + continue; + + const auto WINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); + + if (WINDOWIDEALBB.x <= PMONITOR->vecPosition.x + 1 && WINDOWIDEALBB.y <= PMONITOR->vecPosition.y + 1) + return w; + } + return nullptr; +} + +bool CWorkspace::hasUrgentWindow() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace == m_pSelf && w->m_bIsMapped && w->m_bIsUrgent) + return true; + } + + return false; +} + +void CWorkspace::updateWindowDecos() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf) + continue; + + w->updateWindowDecos(); + } +} + +void CWorkspace::updateWindowData() { + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(m_pSelf.lock()); + + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf) + continue; + + w->updateWindowData(WORKSPACERULE); + } +} + +void CWorkspace::forceReportSizesToWindows() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) + continue; + + g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); + } +} + +void CWorkspace::rename(const std::string& name) { + if (g_pCompositor->isWorkspaceSpecial(m_iID)) + return; + + Debug::log(LOG, "CWorkspace::rename: Renaming workspace {} to '{}'", m_iID, name); + m_szName = name; + + g_pEventManager->postEvent({"renameworkspace", std::to_string(m_iID) + "," + m_szName}); +} + +void CWorkspace::updateWindows() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->m_pWorkspace != m_pSelf) + continue; + + w->updateDynamicRules(); + } +} diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 3ed9f50c..606485a2 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -63,23 +63,29 @@ class CWorkspace { // Inert: destroyed and invalid. If this is true, release the ptr you have. bool inert(); - void startAnim(bool in, bool left, bool instant = false); void setActive(bool on); - void moveToMonitor(const MONITORID&); MONITORID monitorID(); - PHLWINDOW getLastFocusedWindow(); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); - std::string getConfigName(); - bool matchesStaticSelector(const std::string& selector); - void markInert(); - SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const; + void updateWindowDecos(); + void updateWindowData(); + int getWindows(std::optional onlyTiled = {}, std::optional onlyVisible = {}); + int getGroups(std::optional onlyTiled = {}, std::optional onlyVisible = {}); + bool hasUrgentWindow(); + PHLWINDOW getFirstWindow(); + PHLWINDOW getTopLeftWindow(); + PHLWINDOW getFullscreenWindow(); + bool isVisible(); + bool isVisibleNotCovered(); + void rename(const std::string& name = ""); + void forceReportSizesToWindows(); + void updateWindows(); private: void init(PHLWORKSPACE self); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 73ab45c1..a607d7ce 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -509,7 +509,7 @@ void Events::listener_mapWindow(void* owner, void* data) { else if (*PNEWTAKESOVERFS == 1) requestedInternalFSMode = PWINDOW->m_pWorkspace->m_efFullscreenMode; else if (*PNEWTAKESOVERFS == 2) - g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); } if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus && @@ -531,7 +531,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!PWINDOW->m_bNoInitialFocus && (requestedInternalFSMode.has_value() || requestedClientFSMode.has_value() || requestedFSState.has_value())) { // fix fullscreen on requested (basically do a switcheroo) if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) - g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); PWINDOW->m_vRealPosition.warp(); PWINDOW->m_vRealSize.warp(); @@ -603,7 +603,8 @@ void Events::listener_mapWindow(void* owner, void* data) { // fix some xwayland apps that don't behave nicely PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; - g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); + if (PWINDOW->m_pWorkspace) + PWINDOW->m_pWorkspace->updateWindows(); if (PMONITOR && PWINDOW->isX11OverrideRedirect()) PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; @@ -699,7 +700,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pCompositor->setWindowFullscreenInternal(PWINDOWCANDIDATE, CURRENTFSMODE); } - if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->workspaceID()) == 0) + if (!PWINDOWCANDIDATE && PWINDOW->m_pWorkspace && PWINDOW->m_pWorkspace->getWindows() == 0) g_pInputManager->refocus(); g_pInputManager->sendMotionEventsToFocused(); @@ -729,7 +730,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pInputManager->recheckIdleInhibitorStatus(); // force report all sizes (QT sometimes has an issue with this) - g_pCompositor->forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID()); + if (PWINDOW->m_pWorkspace) + PWINDOW->m_pWorkspace->forceReportSizesToWindows(); // update lastwindow after focus PWINDOW->onUnmap(); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index fa2f84ab..dc181d4f 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -264,7 +264,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; while (++id < LONG_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); - if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { + if (!invalidWSes.contains(id) && (!PWORKSPACE || PWORKSPACE->getWindows() == 0)) { result.id = id; return result; } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 63268c8a..cbad959e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -629,17 +629,17 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace && !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - auto pWindow = pWorkspace->m_bHasFullscreenWindow ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : pWorkspace->getLastFocusedWindow(); + auto pWindow = pWorkspace->m_bHasFullscreenWindow ? pWorkspace->getFullscreenWindow() : pWorkspace->getLastFocusedWindow(); if (!pWindow) { if (*PFOLLOWMOUSE == 1) pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!pWindow) - pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID); + pWindow = pWorkspace->getTopLeftWindow(); if (!pWindow) - pWindow = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); + pWindow = pWorkspace->getFirstWindow(); } g_pCompositor->focusWindow(pWindow); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c3e394f3..864c8564 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -514,7 +514,7 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { if (pWorkspace->m_bHasFullscreenWindow) { // massive hack from the fullscreen func - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); + const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; @@ -1054,7 +1054,7 @@ void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) { std::swap(pRoot->children[0], pRoot->children[1]); // if the workspace is visible, recalculate layout - if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible()) pRoot->recalcSizePosRecursive(); } @@ -1094,7 +1094,7 @@ Vector2D CHyprDwindleLayout::predictSizeForNewWindowTiled() { PHLWINDOW candidate = g_pCompositor->m_pLastWindow.lock(); if (!candidate) - candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID); + candidate = g_pCompositor->m_pLastMonitor->activeWorkspace->getFirstWindow(); // create a fake node SDwindleNodeData node; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index af8b907c..22e1d947 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -187,7 +187,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { static auto PAUTOGROUP = CConfigValue("group:auto_group"); const PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? g_pCompositor->m_pLastWindow.lock() : - g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + (pWindow->m_pWorkspace ? pWindow->m_pWorkspace->getFirstWindow() : nullptr); const bool FLOATEDINTOTILED = pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating; const bool SWALLOWING = pWindow->m_pSwallowed || pWindow->m_bGroupSwallowed; @@ -714,7 +714,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { const auto PWORKSPACE = PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace; if (PWORKSPACE->m_bHasFullscreenWindow) - g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); // save real pos cuz the func applies the default 5,5 mid const auto PSAVEDPOS = pWindow->m_vRealPosition.goal(); @@ -803,7 +803,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // first of all, if this is a fullscreen workspace, if (PWORKSPACE->m_bHasFullscreenWindow) - return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->workspaceID()); + return PWORKSPACE->getFullscreenWindow(); if (pWindow->m_bIsFloating) { @@ -842,10 +842,10 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { auto pWindowCandidate = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!pWindowCandidate) - pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->workspaceID()); + pWindowCandidate = PWORKSPACE->getTopLeftWindow(); if (!pWindowCandidate) - pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + pWindowCandidate = PWORKSPACE->getFirstWindow(); if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_pMonitor != g_pCompositor->m_pLastMonitor) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 695dcc99..bf808627 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -298,7 +298,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (pWorkspace->m_bHasFullscreenWindow) { // massive hack from the fullscreen func - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); + const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index ceb594aa..68dbdda1 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -149,7 +149,7 @@ void CAnimationManager::tick() { animationsDisabled = animationsDisabled || PLAYER->noAnimations; } - const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? g_pCompositor->isWorkspaceVisible(PWINDOW->m_pWorkspace) : true; + const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? PWINDOW->m_pWorkspace->isVisible() : true; // beziers are with a switch unforto // TODO: maybe do something cleaner diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 8cf39c1b..a5327149 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1036,8 +1036,12 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional< g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW); } - g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); - g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID()); + + if (PWINDOW->m_pWorkspace) { + PWINDOW->m_pWorkspace->updateWindows(); + PWINDOW->m_pWorkspace->updateWindowData(); + } + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -1305,7 +1309,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } - POLDWS->m_pLastFocusedWindow = g_pCompositor->getFirstWindowOnWorkspace(POLDWS->m_iID); + POLDWS->m_pLastFocusedWindow = POLDWS->getFirstWindow(); if (pWorkspace->m_bIsSpecialWorkspace) pMonitor->setSpecialWorkspace(pWorkspace); @@ -1799,10 +1803,14 @@ SDispatchResult CKeybindManager::renameWorkspace(std::string args) { if (FIRSTSPACEPOS != std::string::npos) { int workspace = std::stoi(args.substr(0, FIRSTSPACEPOS)); std::string name = args.substr(FIRSTSPACEPOS + 1); - g_pCompositor->renameWorkspace(workspace, name); - } else { - g_pCompositor->renameWorkspace(std::stoi(args), ""); - } + if (const auto& PWS = g_pCompositor->getWorkspaceByID(workspace); PWS) + PWS->rename(name); + else + return {.success = false, .error = "No such workspace"}; + } else if (const auto& PWS = g_pCompositor->getWorkspaceByID(std::stoi(args)); PWS) + PWS->rename(""); + else + return {.success = false, .error = "No such workspace"}; } catch (std::exception& e) { Debug::log(ERR, "Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what()); return {.success = false, .error = std::format("Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what())}; @@ -2069,9 +2077,9 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) { if (g_pCompositor->m_pLastWindow.expired()) { // if we have a clear focus, find the first window and get the next focusable. - if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()) > 0) { - const auto PWINDOW = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()); - + const auto PWS = g_pCompositor->m_pLastMonitor->activeWorkspace; + if (PWS && PWS->getWindows() > 0) { + const auto PWINDOW = PWS->getFirstWindow(); switchToWindow(PWINDOW); } @@ -2117,7 +2125,7 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { } if (PWORKSPACE->m_bHasFullscreenWindow) { - const auto FSWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + const auto FSWINDOW = PWORKSPACE->getFullscreenWindow(); const auto FSMODE = PWORKSPACE->m_efFullscreenMode; if (PWINDOW->m_bIsFloating) { diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index a6f25142..7c91258e 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -63,7 +63,7 @@ void CInputManager::recheckIdleInhibitorStatus() { return; } - if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->isFullscreen() && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) { + if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->isFullscreen() && w->m_pWorkspace && w->m_pWorkspace->isVisible()) { PROTO::idle->setInhibit(true); return; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9110cd15..525ca954 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -294,7 +294,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { const auto PWORKSPACE = PMONITOR->activeWorkspace; const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN) { - pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + pFoundWindow = PWORKSPACE->getFullscreenWindow(); if (!pFoundWindow) { // what the fuck, somehow happens occasionally?? @@ -325,7 +325,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (pFoundWindow && !pFoundWindow->onSpecialWorkspace()) { - pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + pFoundWindow = PWORKSPACE->getFullscreenWindow(); } } else { // if we have a maximized window, allow focusing on a bar or something if in reserved area. @@ -339,7 +339,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen)) - pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + pFoundWindow = PWORKSPACE->getFullscreenWindow(); } } } @@ -1402,7 +1402,7 @@ void CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { foundSurface = nullptr; } - if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisibleNotCovered(g_pCompositor->m_pLastWindow->m_pWorkspace)) { + if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace && g_pCompositor->m_pLastWindow->m_pWorkspace->isVisibleNotCovered()) { // then the last focused window if we're on the same workspace as it const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); g_pCompositor->focusWindow(PLASTWINDOW); diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index ba0783fa..6cfe5a24 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -243,8 +243,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-SWIPEDISTANCE, (double)SWIPEDISTANCE); 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->getWindows() == 0 && workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID) || (m_sActiveSwipe.delta < 0 && m_sActiveSwipe.pWorkspaceBegin->m_iID <= workspaceIDLeft)) { m_sActiveSwipe.delta = 0; @@ -270,7 +269,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { else m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); + m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); return; } m_sActiveSwipe.delta = 0; @@ -297,7 +296,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } - g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); + PWORKSPACE->updateWindowDecos(); } else { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight); @@ -310,7 +309,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { else m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); + m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); return; } m_sActiveSwipe.delta = 0; @@ -337,12 +336,12 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } - g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); + PWORKSPACE->updateWindowDecos(); } g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); - g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); + m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); if (*PSWIPEFOREVER) { if (abs(m_sActiveSwipe.delta) >= SWIPEDISTANCE) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 42545bc1..57490d23 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -310,8 +310,8 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; // if the window is being moved to a workspace that is not invisible, and the alpha is > 0.F, render it. - if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && - !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && pWindow->m_pWorkspace && + !pWindow->m_pWorkspace->isVisible()) return true; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; @@ -324,18 +324,18 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { pWindow->m_fAlpha.value() == 0) return false; - if (!PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (!PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() && !PWINDOWWORKSPACE->isVisible()) return false; } if (pWindow->m_pMonitor == pMonitor) return true; - if (!g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_pMonitor != pMonitor) + if (!(!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) && pWindow->m_pMonitor != pMonitor) return false; // if not, check if it maybe is active on a different monitor. - if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */) + if (pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible() && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */) return !pWindow->isFullscreen(); // Do not draw fullscreen windows on other monitors if (pMonitor->activeSpecialWorkspace == pWindow->m_pWorkspace) @@ -376,7 +376,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { if (pWindow->m_bPinned || PWORKSPACE->m_bForceRendering) return true; - if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (PWORKSPACE && PWORKSPACE->isVisible()) return true; for (auto const& m : g_pCompositor->m_vMonitors) { @@ -591,7 +591,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe decorate = false; // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws - const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace); + const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && (!PWORKSPACE || !PWORKSPACE->isVisible()); const bool DONT_BLUR = pWindow->m_sWindowData.noBlur.valueOrDefault() || pWindow->m_sWindowData.RGBX.valueOrDefault() || pWindow->opaque(); renderdata.surface = pWindow->m_pWLSurface->resource(); @@ -933,7 +933,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA // Render layer surfaces below windows for monitor // if we have a fullscreen, opaque window that convers the screen, we can skip this. // TODO: check better with solitary after MR for tearing. - const auto PFULLWINDOW = pWorkspace ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : nullptr; + const auto PFULLWINDOW = pWorkspace ? pWorkspace->getFullscreenWindow() : nullptr; if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FSMODE_FULLSCREEN || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.value() != Vector2D{} || g_pHyprOpenGL->preBlurQueued()) { @@ -2639,7 +2639,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) return; - const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + const auto PCANDIDATE = PWORKSPACE->getFullscreenWindow(); if (!PCANDIDATE) return; // ???? From 00d6261cc06716eac6bdfc9d4426c3a54597098c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 23 Nov 2024 14:18:13 +0000 Subject: [PATCH 0293/1803] hyprpm: move temp files to XDG_RUNTIME_DIR avoid /tmp, it's cringe --- hyprpm/src/core/PluginManager.cpp | 44 ++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index db315193..fb3065b4 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -38,6 +38,18 @@ static std::string execAndGet(std::string cmd) { return proc.stdOut(); } +static std::string getTempRoot() { + static auto ENV = getenv("XDG_RUNTIME_DIR"); + if (!ENV) { + std::cerr << "\nERROR: XDG_RUNTIME_DIR not set!\n"; + exit(1); + } + + const auto STR = ENV + std::string{"/hyprpm/"}; + + return STR; +} + SHyprlandVersion CPluginManager::getHyprlandVersion() { static SHyprlandVersion ver; static bool once = false; @@ -84,7 +96,7 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { } bool CPluginManager::createSafeDirectory(const std::string& path) { - if (path.empty() || !path.starts_with("/tmp")) + if (path.empty() || !path.starts_with(getTempRoot())) return false; if (std::filesystem::exists(path)) @@ -142,17 +154,17 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.print(); - if (!std::filesystem::exists("/tmp/hyprpm")) { - std::filesystem::create_directory("/tmp/hyprpm"); - std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); - } else if (!std::filesystem::is_directory("/tmp/hyprpm")) { + if (!std::filesystem::exists(getTempRoot())) { + std::filesystem::create_directory(getTempRoot()); + std::filesystem::permissions(getTempRoot(), std::filesystem::perms::owner_all, std::filesystem::perm_options::replace); + } else if (!std::filesystem::is_directory(getTempRoot())) { std::println(stderr, "\n{}", failureString("Could not prepare working dir for hyprpm")); return false; } const std::string USERNAME = getpwuid(getuid())->pw_name; - m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; + m_szWorkingPluginDirectory = getTempRoot() + USERNAME; if (!createSafeDirectory(m_szWorkingPluginDirectory)) { std::println(stderr, "\n{}", failureString("Could not prepare working dir for repo")); @@ -161,7 +173,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(infoString("Cloning {}", url)); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME); + std::string ret = execAndGet(std::format("cd {} && git clone --recursive {} {}", getTempRoot(), url, USERNAME)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret)); @@ -413,9 +425,9 @@ bool CPluginManager::updateHeaders(bool force) { return false; } - if (!std::filesystem::exists("/tmp/hyprpm")) { - std::filesystem::create_directory("/tmp/hyprpm"); - std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); + if (!std::filesystem::exists(getTempRoot())) { + std::filesystem::create_directory(getTempRoot()); + std::filesystem::permissions(getTempRoot(), std::filesystem::perms::owner_all, std::filesystem::perm_options::replace); } if (!force && headersValid() == HEADERS_OK) { @@ -430,7 +442,7 @@ bool CPluginManager::updateHeaders(bool force) { progress.print(); const std::string USERNAME = getpwuid(getuid())->pw_name; - const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME; + const auto WORKINGDIR = getTempRoot() + "hyprland-" + USERNAME; if (!createSafeDirectory(WORKINGDIR)) { std::println("\n{}", failureString("Could not prepare working dir for hl")); @@ -448,12 +460,12 @@ bool CPluginManager::updateHeaders(bool force) { if (m_bVerbose && bShallow) progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE)); - std::string ret = - execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")); + std::string ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-{}{}", getTempRoot(), USERNAME, + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : ""))); if (!std::filesystem::exists(WORKINGDIR)) { progress.printMessageAbove(failureString("Clone failed. Retrying without shallow.")); - ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME); + ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/hyprland hyprland-{}", getTempRoot(), USERNAME)); } if (!std::filesystem::exists(WORKINGDIR + "/.git")) { @@ -577,7 +589,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.print(); const std::string USERNAME = getpwuid(getuid())->pw_name; - m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; + m_szWorkingPluginDirectory = getTempRoot() + USERNAME; for (auto const& repo : REPOS) { bool update = forceUpdateAll; @@ -592,7 +604,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(infoString("Cloning {}", repo.url)); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME); + std::string ret = execAndGet(std::format("cd {} && git clone --recursive {} {}", getTempRoot(), repo.url, USERNAME)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { std::println("{}", failureString("could not clone repo: shell returned: {}", ret)); From 451d7a41fc87529854c4116c96a7c6a46568a1ee Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 23 Nov 2024 09:29:29 -0500 Subject: [PATCH 0294/1803] renderer: add option to blur IME popups (#8521) --- src/config/ConfigDescriptions.hpp | 12 ++++++++++++ src/config/ConfigManager.cpp | 2 ++ src/render/Renderer.cpp | 11 ++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 2e3a6720..45379140 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -331,6 +331,18 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_FLOAT, .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, }, + SConfigOptionDescription{ + .value = "blur:input_methods", + .description = "whether to blur input methods (e.g. fcitx5)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "blur:input_methods_ignorealpha", + .description = "works like ignorealpha in layer rules. If pixel opacity is below set value, will not blur. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, + }, /* * animations: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f6734011..32f64f0a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -429,6 +429,8 @@ CConfigManager::CConfigManager() { 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:blur:input_methods", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:blur:input_methods_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}); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 57490d23..dae62851 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -850,12 +850,21 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim const auto SURF = pPopup->getSurface(); - renderdata.blur = false; renderdata.surface = SURF; renderdata.decorate = false; renderdata.w = SURF->current.size.x; renderdata.h = SURF->current.size.y; + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + static auto PBLURIMES = CConfigValue("decoration:blur:input_methods"); + static auto PBLURIGNOREA = CConfigValue("decoration:blur:input_methods_ignorealpha"); + + renderdata.blur = *PBLURIMES && *PBLUR; + if (renderdata.blur) { + g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; + g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURIGNOREA; + } + SURF->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); } From 65f66dcf0d38533a383212ca440fdea0163be276 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sat, 23 Nov 2024 22:32:13 +0800 Subject: [PATCH 0295/1803] binds: add option to allow fullscreening a pinned window (#8526) --- src/Compositor.cpp | 15 +++++++++++++-- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/desktop/Window.hpp | 3 +++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3fe5acec..53eaa467 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2245,7 +2245,8 @@ void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFull } void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenState state) { - static auto PDIRECTSCANOUT = CConfigValue("render:direct_scanout"); + static auto PDIRECTSCANOUT = CConfigValue("render:direct_scanout"); + static auto PALLOWPINFULLSCREEN = CConfigValue("binds:allow_pin_fullscreen"); if (!validMapped(PWINDOW) || g_pCompositor->m_bUnsafeState) return; @@ -2259,7 +2260,17 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal); const eFullscreenMode EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)state.internal); - const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())); + if (*PALLOWPINFULLSCREEN && !PWINDOW->m_bPinFullscreened && !PWINDOW->isFullscreen() && PWINDOW->m_bPinned) { + PWINDOW->m_bPinned = false; + PWINDOW->m_bPinFullscreened = true; + } + + const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())); + + if (*PALLOWPINFULLSCREEN && PWINDOW->m_bPinFullscreened && PWINDOW->isFullscreen() && !PWINDOW->m_bPinned && state.internal == FSMODE_NONE) { + PWINDOW->m_bPinned = true; + PWINDOW->m_bPinFullscreened = false; + } // TODO: update the state on syncFullscreen changes if (!CHANGEINTERNAL && PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault()) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 45379140..bb3d4e0e 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1206,6 +1206,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "binds:allow_pin_fullscreen", + .description = "Allows fullscreen to pinned windows, and restore their pinned status afterwards", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * xwayland: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 32f64f0a..3429db24 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -536,6 +536,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("binds:movefocus_cycles_fullscreen", Hyprlang::INT{1}); m_pConfig->addConfigValue("binds:disable_keybind_grabbing", Hyprlang::INT{0}); m_pConfig->addConfigValue("binds:window_direction_monitor_fallback", Hyprlang::INT{1}); + m_pConfig->addConfigValue("binds:allow_pin_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_fingers", Hyprlang::INT{3}); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index ac81e5ef..5dd59437 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -332,6 +332,9 @@ class CWindow { // For pinned (sticky) windows bool m_bPinned = false; + // For preserving pinned state when fullscreening a pinned window + bool m_bPinFullscreened = false; + // urgency hint bool m_bIsUrgent = false; From 54f57797e9d025db72777ccf4adb0ddb25125016 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Sat, 23 Nov 2024 09:36:28 -0500 Subject: [PATCH 0296/1803] snap: account for position of multiple monitors (#8543) --- src/layout/IHyprLayout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 22e1d947..8ff55d10 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -484,8 +484,8 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA const double BORDERDIFF = DRAGGINGBORDERSIZE - BORDERSIZE; const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecSize.x - BORDERSIZE}; - SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecSize.y - BORDERSIZE}; + SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecPosition.x + MON->vecSize.x - BORDERSIZE}; + SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecPosition.y + MON->vecSize.y - BORDERSIZE}; if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) { SNAP(sourceX.start, sourceX.end, monX.start); From 55ec8bd512605a014cc322d3419a9cfa72178340 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 24 Nov 2024 02:46:24 +0000 Subject: [PATCH 0297/1803] config: throw an error explicitly when parsing colors in gradients ref #8552 --- src/config/ConfigManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3429db24..ba0fdd9d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -67,7 +67,10 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } try { - DATA->m_vColors.push_back(CColor(*configStringToInt(var))); + const auto COL = configStringToInt(var); + if (!COL) + throw std::runtime_error(std::format("failed to parse {} as a color", var)); + DATA->m_vColors.push_back(CColor(COL.value())); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); From cc38e7e18fd762d5cdb34d06335223b7d7874106 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 24 Nov 2024 14:53:36 +0000 Subject: [PATCH 0298/1803] config: don't overwrite errors in gradients --- src/config/ConfigManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ba0fdd9d..c0f212cf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -79,7 +79,8 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** if (DATA->m_vColors.size() == 0) { Debug::log(WARN, "Error parsing gradient {}", V); - parseError = "Error parsing gradient " + V + ": No colors?"; + if (parseError.empty()) + parseError = "Error parsing gradient " + V + ": No colors?"; DATA->m_vColors.push_back(0); // transparent } From 1930a95000d336b76d18c0c95ef77e138c9a4cd0 Mon Sep 17 00:00:00 2001 From: Nabil Otsmane <44232317+nabil-otsmane@users.noreply.github.com> Date: Mon, 25 Nov 2024 01:50:35 +0100 Subject: [PATCH 0299/1803] shm: fix shm fd size check before creating or resizing shm_pool (#8572) * protocols: fix shm fd size check before creating or resizing shm_pool * added static to function --- src/protocols/core/Shm.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index a8c98bb0..708d41c3 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -1,6 +1,7 @@ #include "Shm.hpp" #include #include +#include #include #include "../../render/Texture.hpp" #include "../types/WLBuffer.hpp" @@ -99,10 +100,25 @@ void CSHMPool::resize(size_t size_) { LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd); } +static int shmIsSizeValid(int fd, size_t size) { + struct stat st; + if (fstat(fd, &st) == -1) { + LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd); + return 0; + } + + return (size_t)st.st_size >= size; +} + CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t size_) : resource(resource_) { if (!good()) return; + if (!shmIsSizeValid(fd_, size_)) { + resource_->error(-1, "The size of the file is not big enough for the shm pool"); + return; + } + pool = makeShared(fd_, size_); resource->setDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); @@ -113,6 +129,11 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t r->error(-1, "Shrinking a shm pool is illegal"); return; } + if (!shmIsSizeValid(pool->fd, size_)) { + r->error(-1, "The size of the file is not big enough for the shm pool"); + return; + } + pool->resize(size_); }); From 0ddb952d7a3d102e160eea93c68f0d366186cf73 Mon Sep 17 00:00:00 2001 From: Vladimir-csp <4061903+Vladimir-csp@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:18:50 +0300 Subject: [PATCH 0300/1803] hyprland-uwsm.desktop: Just reference plain entry (#8553) --- systemd/hyprland-uwsm.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/hyprland-uwsm.desktop b/systemd/hyprland-uwsm.desktop index 2ed1031b..e00f4aa2 100644 --- a/systemd/hyprland-uwsm.desktop +++ b/systemd/hyprland-uwsm.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Name=Hyprland (uwsm-managed) Comment=An intelligent dynamic tiling Wayland compositor -Exec=uwsm start -N Hyprland -D Hyprland -C An_intelligent_dynamic_tiling_Wayland_compositor -- Hyprland +Exec=uwsm start -- hyprland.desktop DesktopNames=Hyprland Type=Application From 268778823676ef2bbda42050d78946e1fc27fc31 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 25 Nov 2024 14:42:06 +0000 Subject: [PATCH 0301/1803] hyprctl: verify runtime dir exists in instances() ref #8579 --- hyprctl/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 1f7f8d74..4ee2d598 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -66,6 +66,11 @@ std::string getRuntimeDir() { std::vector instances() { std::vector result; + try { + if (!std::filesystem::exists(getRuntimeDir())) + return {}; + } catch (std::exception& e) { return {}; } + for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) { if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock")) continue; From 1fb720b62aeb474873ba43426ddc53afde1e6cdd Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Tue, 26 Nov 2024 07:52:43 -0600 Subject: [PATCH 0302/1803] seat: fix double scrolling in some applications (#8583) --- src/managers/SeatManager.cpp | 6 ++++-- src/protocols/core/Seat.cpp | 4 ++++ src/protocols/core/Seat.hpp | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index b40d6cad..665805f6 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -332,8 +332,10 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double p->sendAxisRelativeDirection(axis, relative); if (source == 0) { - p->sendAxisValue120(axis, value120); - p->sendAxisDiscrete(axis, discrete); + if (p->version() >= 8) + p->sendAxisValue120(axis, value120); + else + p->sendAxisDiscrete(axis, discrete); } else if (value == 0) p->sendAxisStop(timeMs, axis); } diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index d95e0e12..7c31b67c 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -136,6 +136,10 @@ CWLPointerResource::CWLPointerResource(SP resource_, SPstate.pointerFocus.lock(), {-1, -1} /* Coords don't really matter that much, they will be updated next move */); } +int CWLPointerResource::version() { + return resource->version(); +} + bool CWLPointerResource::good() { return resource->resource(); } diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 1b43dd04..b5670237 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -73,6 +73,7 @@ class CWLPointerResource { CWLPointerResource(SP resource_, SP owner_); bool good(); + int version(); void sendEnter(SP surface, const Vector2D& local); void sendLeave(); void sendMotion(uint32_t timeMs, const Vector2D& local); From e9a7fb8f91d23f1ac2671e55f74234dcec2ee1c6 Mon Sep 17 00:00:00 2001 From: Agent00Ming <107314235+Agent00Ming@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:17:45 -0500 Subject: [PATCH 0303/1803] renderer: fix incorrect early return (#8590) Co-authored-by: Agent_00Ming --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index dae62851..ca6ceba1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -331,7 +331,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { if (pWindow->m_pMonitor == pMonitor) return true; - if (!(!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) && pWindow->m_pMonitor != pMonitor) + if ((!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) && pWindow->m_pMonitor != pMonitor) return false; // if not, check if it maybe is active on a different monitor. From 5329298b522e3cc1201894909443775b00aeb336 Mon Sep 17 00:00:00 2001 From: Andre Toerien Date: Wed, 27 Nov 2024 21:59:00 +0200 Subject: [PATCH 0304/1803] sessionLock: don't send motion events on every surface commit (#8584) --- src/managers/SessionLockManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index c7a5934a..b7110990 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -31,7 +31,7 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur listeners.commit = surface_->events.commit.registerListener([this](std::any data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID); - if (mapped && pWlrSurface != g_pCompositor->m_pLastFocus) + if (mapped && !g_pCompositor->m_pLastFocus) g_pInputManager->simulateMouseMovement(); if (PMONITOR) From 8b51eeb7aef8b25de35a0d460f28f4d67c017866 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 28 Nov 2024 14:31:38 +0000 Subject: [PATCH 0305/1803] core: fix compilation outside stdlibc++ fixes #8603 --- src/managers/KeybindManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a5327149..7f10249a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2988,13 +2988,13 @@ SDispatchResult CKeybindManager::setProp(std::string args) { else configStringToInt(TOKEN).and_then([&colorData](const auto& e) { colorData.m_vColors.push_back(e); - return std::result_of::type(1); + return std::invoke_result_t(1); }); } } else if (VAL != "-1") configStringToInt(VAL).and_then([&colorData](const auto& e) { colorData.m_vColors.push_back(e); - return std::result_of::type(1); + return std::invoke_result_t(1); }); if (PROP == "activebordercolor") From 5963970be54c92fdebdbcebdeb76cf6de5e7e717 Mon Sep 17 00:00:00 2001 From: nyx Date: Thu, 28 Nov 2024 10:25:24 -0500 Subject: [PATCH 0306/1803] descriptions: change allow_pin_fullscreen value to false (#8592) --- src/config/ConfigDescriptions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index bb3d4e0e..e5918691 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1210,7 +1210,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "binds:allow_pin_fullscreen", .description = "Allows fullscreen to pinned windows, and restore their pinned status afterwards", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, + .data = SConfigOptionDescription::SBoolData{false}, }, /* From 22bf2853e6271932f073961f3dbeb0f9ff48493e Mon Sep 17 00:00:00 2001 From: Daringcuteseal Date: Thu, 28 Nov 2024 21:21:55 +0700 Subject: [PATCH 0307/1803] hyprpm: fix incomplete unmet dependencies message --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index fb3065b4..db3893b5 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -115,7 +115,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config")); return false; } @@ -421,7 +421,7 @@ bool CPluginManager::updateHeaders(bool force) { const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); + std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config")); return false; } From 8f83d29f00bfa89d1e8fe94b4dda98fe898b6b0e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 28 Nov 2024 23:51:53 +0000 Subject: [PATCH 0308/1803] renderer: restore discard mode after IME render pass ref #8555 --- src/render/Renderer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ca6ceba1..bba133d9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -859,6 +859,10 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim static auto PBLURIMES = CConfigValue("decoration:blur:input_methods"); static auto PBLURIGNOREA = CConfigValue("decoration:blur:input_methods_ignorealpha"); + // TODO: make push/pop methods for this. + const auto DM = g_pHyprOpenGL->m_RenderData.discardMode; + const auto DA = g_pHyprOpenGL->m_RenderData.discardOpacity; + renderdata.blur = *PBLURIMES && *PBLUR; if (renderdata.blur) { g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; @@ -866,6 +870,9 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim } SURF->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); + + g_pHyprOpenGL->m_RenderData.discardMode = DM; + g_pHyprOpenGL->m_RenderData.discardOpacity = DA; } void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, PHLMONITOR pMonitor, timespec* time) { From ef6b0c81c914bdc9b56c2674273698f065518993 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sun, 1 Dec 2024 00:40:23 +0800 Subject: [PATCH 0309/1803] cleanup: remove leftover var in ThreadManager.cpp (#8611) --- src/managers/ThreadManager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp index 6f8e0c9a..8666b3a6 100644 --- a/src/managers/ThreadManager.cpp +++ b/src/managers/ThreadManager.cpp @@ -3,8 +3,6 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" -int slowUpdate = 0; - int handleTimer(void* data) { const auto PTM = (CThreadManager*)data; @@ -27,4 +25,4 @@ CThreadManager::CThreadManager() { CThreadManager::~CThreadManager() { if (m_esConfigTimer) wl_event_source_remove(m_esConfigTimer); -} \ No newline at end of file +} From d26439a0fe5594fb26d5a3c01571f9490a9a2d2c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 30 Nov 2024 17:42:40 +0000 Subject: [PATCH 0310/1803] nix: update flake --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 969bc157..0db2ee60 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1731774881, - "narHash": "sha256-1Dxryiw8u2ejntxrrv3sMtIE8WHKxmlN4KeH+uMGbmc=", + "lastModified": 1731959031, + "narHash": "sha256-TGcvIjftziC1CjuiHCzrYDwmOoSFYIhdiKmLetzB5L0=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "b31a6a4da8199ae3489057db7d36069a70749a56", + "rev": "4468981c1c50999f315baa1508f0e53c4ee70c52", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1731702627, - "narHash": "sha256-+JeO9gevnXannQxMfR5xzZtF4sYmSlWkX/BPmPx0mWk=", + "lastModified": 1732288281, + "narHash": "sha256-XTU9B53IjGeJiJ7LstOhuxcRjCOFkQFl01H78sT9Lg4=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "e911361a687753bbbdfe3b6a9eab755ecaf1d9e1", + "rev": "b26f33cc1c8a7fd5076e19e2cce3f062dca6351c", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1731676054, - "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", + "lastModified": 1732758367, + "narHash": "sha256-RzaI1RO0UXqLjydtz3GAXSTzHkpb/lLD1JD8a0W4Wpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", + "rev": "fa42b5a5f401aab8a32bd33c9a4de0738180dc59", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1731363552, - "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", + "lastModified": 1732021966, + "narHash": "sha256-mnTbjpdqF0luOkou8ZFi2asa1N3AA2CchR/RqCNmsGE=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", + "rev": "3308484d1a443fc5bc92012435d79e80458fe43c", "type": "github" }, "original": { From 6d7544458d0fafcae410c1978a0cabce2fb4a346 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:14:35 -0600 Subject: [PATCH 0311/1803] cleanup: use doLater instead of adding idle event handlers (#8624) --- src/protocols/Tablet.cpp | 26 ++++++++++++-------------- src/protocols/Tablet.hpp | 7 +++---- src/protocols/XDGShell.cpp | 18 +++++++++--------- src/protocols/XDGShell.hpp | 8 ++++---- src/xwayland/Server.cpp | 12 ++++-------- 5 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index d7f741b9..7768402b 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -2,6 +2,7 @@ #include "../devices/Tablet.hpp" #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -162,11 +163,6 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP resource_, SP< }); } -CTabletToolV2Resource::~CTabletToolV2Resource() { - if (frameSource) - wl_event_source_remove(frameSource); -} - bool CTabletToolV2Resource::good() { return resource->resource(); } @@ -205,20 +201,22 @@ void CTabletToolV2Resource::sendData() { } void CTabletToolV2Resource::queueFrame() { - if (frameSource) + if (frameQueued) return; - frameSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, [](void* data) { ((CTabletToolV2Resource*)data)->sendFrame(false); }, this); + frameQueued = true; + g_pEventLoopManager->doLater([this]() { + if (!frameQueued || tool.expired() || inert) + return; + + sendFrame(); + }); } -void CTabletToolV2Resource::sendFrame(bool removeSource) { - if (frameSource) { - if (removeSource) - wl_event_source_remove(frameSource); - frameSource = nullptr; - } +void CTabletToolV2Resource::sendFrame() { + frameQueued = false; - if (!current) + if (!current || !resource) return; timespec now; diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 1ebcb1e5..8c99bee0 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -112,21 +112,20 @@ class CTabletV2Resource { class CTabletToolV2Resource { public: CTabletToolV2Resource(SP resource_, SP tool_, SP seat_); - ~CTabletToolV2Resource(); bool good(); void sendData(); void queueFrame(); - void sendFrame(bool removeSource = true); + void sendFrame(); bool current = false; WP lastSurf; WP tool; WP seat; - wl_event_source* frameSource = nullptr; - bool inert = false; // removed was sent + bool frameQueued = false; + bool inert = false; // removed was sent private: SP resource; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 688d0006..a542c394 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -469,8 +470,6 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPresetRole(); } @@ -484,22 +483,23 @@ SP CXDGSurfaceResource::fromResource(wl_resource* res) { return data ? data->self.lock() : nullptr; } -static void onConfigure(void* data) { - ((CXDGSurfaceResource*)data)->configure(); -} - uint32_t CXDGSurfaceResource::scheduleConfigure() { - if (configureSource) + if (configureScheduled) return scheduledSerial; - configureSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, onConfigure, this); scheduledSerial = wl_display_next_serial(g_pCompositor->m_sWLDisplay); + configureScheduled = true; + g_pEventLoopManager->doLater([this]() { configure(); }); + return scheduledSerial; } void CXDGSurfaceResource::configure() { - configureSource = nullptr; + if (!resource) + return; + + configureScheduled = false; resource->sendConfigure(scheduledSerial); } diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index ef847f3b..3b7d2d11 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -199,12 +199,12 @@ class CXDGSurfaceResource { void configure(); private: - SP resource; + SP resource; - uint32_t lastConfigureSerial = 0; - uint32_t scheduledSerial = 0; + uint32_t lastConfigureSerial = 0; + uint32_t scheduledSerial = 0; - wl_event_source* configureSource = nullptr; + bool configureScheduled = false; // std::vector> popups; diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index f356af18..390ce1f6 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -176,11 +176,6 @@ static bool openSockets(std::array& sockets, int display) { return true; } -static void startServer(void* data) { - if (!g_pXWayland->pServer->start()) - Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); -} - static int xwaylandReady(int fd, uint32_t mask, void* data) { return g_pXWayland->pServer->ready(fd, mask); } @@ -308,9 +303,10 @@ bool CXWaylandServer::create() { setenv("DISPLAY", displayName.c_str(), true); - // TODO: lazy mode - - idleSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::startServer, nullptr); + g_pEventLoopManager->doLater([this]() { + if (!start()) + Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); + }); return true; } From 10a9fec7fc8e77479a599985c776a8a184311cd6 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:32:32 +0300 Subject: [PATCH 0312/1803] master: make center ignore reserved areas (#8625) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/layout/MasterLayout.cpp | 13 +++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index e5918691..b95eeab1 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1596,6 +1596,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "master:center_ignores_reserved", + .description = "centers the master window on monitor ignoring reserved areas", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, SConfigOptionDescription{ .value = "master:smart_resizing", .description = diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c0f212cf..07de8c24 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -470,6 +470,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:mfact", {0.55f}); m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:orientation", {"left"}); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index bf808627..4f761973 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -328,6 +328,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { eOrientation orientation = getDynamicOrientation(pWorkspace); bool centerMasterWindow = false; static auto ALWAYSCENTER = CConfigValue("master:always_center_master"); + static auto PIGNORERESERVED = CConfigValue("master:center_ignores_reserved"); static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_iID); @@ -402,7 +403,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextX += WIDTH; } } else { // orientation left, right or center - float WIDTH = WSSIZE.x; + float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecSize.x : WSSIZE.x; float heightLeft = WSSIZE.y; int mastersLeft = MASTERS; float nextX = 0; @@ -414,7 +415,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (orientation == ORIENTATION_RIGHT) { nextX = WSSIZE.x - WIDTH; } else if (centerMasterWindow) { - nextX = (WSSIZE.x - WIDTH) / 2; + nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecSize.x : WSSIZE.x) - WIDTH) / 2; } for (auto& nd : m_lMasterNodesData) { @@ -431,7 +432,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = WSPOS + Vector2D(nextX, nextY); + nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecPosition : WSPOS) + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); mastersLeft--; @@ -506,7 +507,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextY += HEIGHT; } } else { // slaves for centered master window(s) - const float WIDTH = (WSSIZE.x - PMASTERNODE->size.x) / 2.0; + const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->vecSize.x : WSSIZE.x) - PMASTERNODE->size.x) / 2.0; float heightLeft = 0; float heightLeftL = WSSIZE.y; float heightLeftR = WSSIZE.y; @@ -543,7 +544,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { continue; if (onRight) { - nextX = WIDTH + PMASTERNODE->size.x; + nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->vecReservedTopLeft.x : 0); nextY = nextYR; heightLeft = heightLeftR; slavesLeft = slavesLeftR; @@ -568,7 +569,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } } - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->vecReservedBottomRight.x : PMONITOR->vecReservedTopLeft.x)) : WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); From 92186898c0ca1b3f72922b72c4af1723f0d9b888 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:31:22 +0000 Subject: [PATCH 0313/1803] version: add link versions for other utils (#8619) --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 13 ++++++++----- hyprpm/CMakeLists.txt | 4 ++-- meson.build | 6 ++++++ src/debug/HyprCtl.cpp | 10 +++++++--- src/meson.build | 6 +++--- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cbd8b0a..7e2a1fe6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,8 +104,14 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) +pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) +pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) +pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") +add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}") +add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}") +add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}") pkg_check_modules( deps @@ -123,10 +129,7 @@ pkg_check_modules( libdrm libinput gbm - gio-2.0 - hyprlang>=0.3.2 - hyprcursor>=0.1.7 - hyprutils>=0.2.3) + gio-2.0) find_package(hyprwayland-scanner 0.3.10 REQUIRED) @@ -244,7 +247,7 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps) +target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::deps) if(udis_dep_FOUND) target_link_libraries(Hyprland PkgConfig::udis_dep) else() diff --git a/hyprpm/CMakeLists.txt b/hyprpm/CMakeLists.txt index 65935638..22cb8caa 100644 --- a/hyprpm/CMakeLists.txt +++ b/hyprpm/CMakeLists.txt @@ -9,11 +9,11 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") set(CMAKE_CXX_STANDARD 23) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) +pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) add_executable(hyprpm ${SRCFILES}) -target_link_libraries(hyprpm PUBLIC PkgConfig::deps) +target_link_libraries(hyprpm PUBLIC PkgConfig::hyprpm_deps) # binary install(TARGETS hyprpm) diff --git a/meson.build b/meson.build index d825f184..39a5a6d0 100644 --- a/meson.build +++ b/meson.build @@ -32,7 +32,13 @@ if cpp_compiler.check_header('execinfo.h') endif aquamarine = dependency('aquamarine', version: '>=0.4.5') +hyprcursor = dependency('hyprcursor', version: '>=0.1.7') +hyprlang = dependency('hyprlang', version: '>= 0.3.2') +hyprutils = dependency('hyprutils', version: '>= 0.2.3') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') +add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp') +add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp') +add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.version())], language: 'cpp') xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 11c16f0e..6b62ec8d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -875,8 +875,9 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" "Date: {}\n" "Tag: {}, commits: {}\n" - "built against aquamarine {}\n\n\n", - HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION); + "built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n\n\n", + HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION, + HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); #if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND)) result += "no flags were set\n"; @@ -905,9 +906,12 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "tag": "{}", "commits": "{}", "buildAquamarine": "{}", + "buildHyprlang": "{}", + "buildHyprutils": "{}", + "buildHyprcursor": "{}", "flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, - GIT_COMMITS, AQUAMARINE_VERSION); + GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; diff --git a/src/meson.build b/src/meson.build index 2dbe2f44..61ca06d5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -9,14 +9,14 @@ executable( dependencies: [ server_protos, aquamarine, + hyprcursor, + hyprlang, + hyprutils, dependency('gbm'), dependency('xcursor'), dependency('wayland-server'), dependency('wayland-client'), dependency('cairo'), - dependency('hyprcursor', version: '>=0.1.7'), - dependency('hyprlang', version: '>= 0.3.2'), - dependency('hyprutils', version: '>= 0.2.3'), dependency('libdrm'), dependency('egl'), dependency('xkbcommon'), From 320144ae7288fe23686935ebb235d9fe0c900862 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:58:24 +0000 Subject: [PATCH 0314/1803] core: move colorspace handling to oklab (#8635) * Meson: add hyprgraphics * Nix: add hyprgraphics * CI/setup_base: get hyprgraphics-git --------- Co-authored-by: Mihai Fufezan --- .github/actions/setup_base/action.yml | 7 + CMakeLists.txt | 4 +- flake.lock | 27 +++ flake.nix | 7 + meson.build | 2 + nix/default.nix | 2 + nix/overlays.nix | 1 + src/Compositor.cpp | 10 +- src/config/ConfigDataValues.hpp | 22 ++- src/config/ConfigManager.cpp | 23 +-- src/config/ConfigManager.hpp | 2 +- src/debug/HyprCtl.cpp | 15 +- src/debug/HyprNotificationOverlay.cpp | 4 +- src/debug/HyprNotificationOverlay.hpp | 18 +- src/desktop/Window.cpp | 4 +- src/desktop/Window.hpp | 2 +- src/helpers/AnimatedVariable.hpp | 4 +- src/helpers/Color.cpp | 56 +++++-- src/helpers/Color.hpp | 48 ++++-- src/hyprerror/HyprError.cpp | 6 +- src/hyprerror/HyprError.hpp | 4 +- src/managers/AnimationManager.cpp | 55 +++++- src/managers/AnimationManager.hpp | 4 +- src/managers/KeybindManager.cpp | 2 +- src/managers/PointerManager.cpp | 2 +- src/meson.build | 1 + src/plugins/PluginAPI.cpp | 4 +- src/plugins/PluginAPI.hpp | 4 +- src/protocols/SinglePixel.cpp | 8 +- src/protocols/SinglePixel.hpp | 4 +- src/protocols/ToplevelExport.cpp | 4 +- src/render/OpenGL.cpp | 157 +++++++++++++++--- src/render/OpenGL.hpp | 13 +- src/render/Renderer.cpp | 20 +-- src/render/Shader.hpp | 10 +- .../decorations/CHyprBorderDecoration.cpp | 11 +- .../decorations/CHyprDropShadowDecoration.cpp | 10 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 24 +-- src/render/shaders/Border.hpp | 62 ++++++- 40 files changed, 492 insertions(+), 173 deletions(-) diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index 26660ce6..e22f514e 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -33,7 +33,9 @@ runs: libfontenc \ libglvnd \ libinput \ + libjxl \ libliftoff \ + libwebp \ libxcursor \ libxcvt \ libxfont2 \ @@ -69,6 +71,11 @@ runs: cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --install build + - name: Get hyprgraphics-git + shell: bash + run: | + git clone https://github.com/hyprwm/hyprgraphics && cd hyprgraphics && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprgraphics && cmake --install build + - name: Get hyprutils-git shell: bash run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e2a1fe6..aa0d4b03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,11 +107,13 @@ pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3) +pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}") add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}") add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}") +add_compile_definitions(HYPRGRAPHICS_VERSION="${hyprgraphics_dep_VERSION}") pkg_check_modules( deps @@ -247,7 +249,7 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::deps) +target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::hyprgraphics_dep PkgConfig::deps) if(udis_dep_FOUND) target_link_libraries(Hyprland PkgConfig::udis_dep) else() diff --git a/flake.lock b/flake.lock index 0db2ee60..23bd37a9 100644 --- a/flake.lock +++ b/flake.lock @@ -92,6 +92,32 @@ "type": "github" } }, + "hyprgraphics": { + "inputs": { + "hyprutils": [ + "hyprutils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1733248371, + "narHash": "sha256-FFLJzFTyNhS7tBEEECx0B8Ye/bpmxhFVEKlECgMLc6c=", + "owner": "hyprwm", + "repo": "hyprgraphics", + "rev": "cc95e5babc6065bc3ab4cd195429a9900836ef13", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprgraphics", + "type": "github" + } + }, "hyprland-protocols": { "inputs": { "nixpkgs": [ @@ -246,6 +272,7 @@ "inputs": { "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", + "hyprgraphics": "hyprgraphics", "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", "hyprutils": "hyprutils", diff --git a/flake.nix b/flake.nix index e3419ef8..f26f1c31 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,13 @@ inputs.hyprlang.follows = "hyprlang"; }; + hyprgraphics = { + url = "github:hyprwm/hyprgraphics"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + inputs.hyprutils.follows = "hyprutils"; + }; + hyprland-protocols = { url = "github:hyprwm/hyprland-protocols"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/meson.build b/meson.build index 39a5a6d0..c46b199c 100644 --- a/meson.build +++ b/meson.build @@ -33,10 +33,12 @@ endif aquamarine = dependency('aquamarine', version: '>=0.4.5') hyprcursor = dependency('hyprcursor', version: '>=0.1.7') +hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1') hyprlang = dependency('hyprlang', version: '>= 0.3.2') hyprutils = dependency('hyprutils', version: '>= 0.2.3') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp') +add_project_arguments(['-DHYPRGRAPHICS_VERSION="@0@"'.format(hyprgraphics.version())], language: 'cpp') add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp') add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.version())], language: 'cpp') diff --git a/nix/default.nix b/nix/default.nix index 69174d4d..dbe4879e 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -12,6 +12,7 @@ cairo, git, hyprcursor, + hyprgraphics, hyprland-protocols, hyprlang, hyprutils, @@ -113,6 +114,7 @@ in cairo git hyprcursor + hyprgraphics hyprland-protocols hyprlang hyprutils diff --git a/nix/overlays.nix b/nix/overlays.nix index a7106315..c2103f31 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -22,6 +22,7 @@ in { # Dependencies inputs.aquamarine.overlays.default inputs.hyprcursor.overlays.default + inputs.hyprgraphics.overlays.default inputs.hyprland-protocols.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 53eaa467..3573996d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1873,11 +1873,11 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // shadow if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { if (pWindow == m_pLastWindow) - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); + pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL); else - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); + pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); } else { - pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow + pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow } pWindow->updateWindowDecos(); @@ -2608,14 +2608,14 @@ void CCompositor::performUserChecks() { g_pHyprNotificationOverlay->addNotification( std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.", CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"), - CColor{}, 15000, ICON_WARNING); + CHyprColor{}, 15000, ICON_WARNING); } } if (g_pHyprOpenGL->failedAssetsNo > 0) { g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!", g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""), - CColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR); + CHyprColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR); } } diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index 37c9fc92..212f26fa 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -21,8 +21,9 @@ class ICustomConfigValueData { class CGradientValueData : public ICustomConfigValueData { public: CGradientValueData() {}; - CGradientValueData(CColor col) { + CGradientValueData(CHyprColor col) { m_vColors.push_back(col); + updateColorsOk(); }; virtual ~CGradientValueData() {}; @@ -30,14 +31,29 @@ class CGradientValueData : public ICustomConfigValueData { return CVD_TYPE_GRADIENT; } - void reset(CColor col) { + void reset(CHyprColor col) { m_vColors.clear(); m_vColors.emplace_back(col); m_fAngle = 0; + updateColorsOk(); + } + + void updateColorsOk() { + m_vColorsOkLabA.clear(); + for (auto& c : m_vColors) { + const auto OKLAB = c.asOkLab(); + m_vColorsOkLabA.emplace_back(OKLAB.l); + m_vColorsOkLabA.emplace_back(OKLAB.a); + m_vColorsOkLabA.emplace_back(OKLAB.b); + m_vColorsOkLabA.emplace_back(c.a); + } } /* Vector containing the colors */ - std::vector m_vColors; + std::vector m_vColors; + + /* Vector containing pure colors for shoving into opengl */ + std::vector m_vColorsOkLabA; /* Float corresponding to the angle (rad) */ float m_fAngle = 0; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 07de8c24..820844eb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -70,7 +70,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** const auto COL = configStringToInt(var); if (!COL) throw std::runtime_error(std::format("failed to parse {} as a color", var)); - DATA->m_vColors.push_back(CColor(COL.value())); + DATA->m_vColors.push_back(CHyprColor(COL.value())); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); @@ -85,6 +85,8 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** DATA->m_vColors.push_back(0); // transparent } + DATA->updateColorsOk(); + Hyprlang::CParseResult result; if (!parseError.empty()) result.setError(parseError.c_str()); @@ -676,7 +678,7 @@ CConfigManager::CConfigManager() { Debug::disableTime = reinterpret_cast(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr()); if (ERR.has_value()) - g_pHyprError->queueCreate(ERR.value(), CColor{1.0, 0.1, 0.1, 1.0}); + g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); } std::optional CConfigManager::generateConfig(std::string configPath) { @@ -883,14 +885,14 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { m_szConfigErrors = ""; if (result.error && !std::any_cast(m_pConfig->getConfigValue("debug:suppress_errors"))) - g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + g_pHyprError->queueCreate(result.getError(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) g_pHyprError->queueCreate( "Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland", - CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); + CHyprColor(1.0, 1.0, 70.0 / 255.0, 1.0)); else if (*PENABLEEXPLICIT != prevEnabledExplicit) - g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CHyprColor(0.9, 0.76, 0.221, 1.0)); else g_pHyprError->destroy(); @@ -948,7 +950,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { // manual crash if (std::any_cast(m_pConfig->getConfigValue("debug:manual_crash")) && !m_bManualCrashInitiated) { m_bManualCrashInitiated = true; - g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000, ICON_INFO); + g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CHyprColor(0), 5000, + ICON_INFO); } else if (m_bManualCrashInitiated && !std::any_cast(m_pConfig->getConfigValue("debug:manual_crash"))) { // cowabunga it is g_pHyprRenderer->initiateManualCrash(); @@ -1015,7 +1018,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: if (COMMAND.contains("explicit")) { if (*PENABLEEXPLICIT != prevEnabledExplicit) - g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CHyprColor(0.9, 0.76, 0.221, 1.0)); else g_pHyprError->destroy(); } @@ -1027,7 +1030,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: if (std::any_cast(m_pConfig->getConfigValue("debug:manual_crash")) && !m_bManualCrashInitiated) { m_bManualCrashInitiated = true; if (g_pHyprNotificationOverlay) { - g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000, + g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CHyprColor(0), 5000, ICON_INFO); } } else if (m_bManualCrashInitiated && !std::any_cast(m_pConfig->getConfigValue("debug:manual_crash"))) { @@ -1671,7 +1674,7 @@ SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std:: } void CConfigManager::addParseError(const std::string& err) { - g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); } PHLMONITOR CConfigManager::getBoundMonitorForWS(const std::string& wsname) { @@ -1716,7 +1719,7 @@ void CConfigManager::handlePluginLoads() { error << "\n" << path; } - g_pHyprError->queueCreate(error.str(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + g_pHyprError->queueCreate(error.str(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); } if (pluginsChanged) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 88b74b6e..a3b86e69 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -119,7 +119,7 @@ struct SConfigOptionDescription { }; struct SColorData { - CColor color; + CHyprColor color; }; struct SChoiceData { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 6b62ec8d..74b2a3a1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -875,9 +875,9 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" "Date: {}\n" "Tag: {}, commits: {}\n" - "built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n\n\n", + "built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n hyprgraphics {}\n\n\n", HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION, - HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); + HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); #if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND)) result += "no flags were set\n"; @@ -909,9 +909,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "buildHyprlang": "{}", "buildHyprutils": "{}", "buildHyprcursor": "{}", + "buildHyprgraphics": "{}", "flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, - GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); + GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; @@ -1290,7 +1291,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { return "ok"; } - const CColor COLOR = configStringToInt(vars[1]).value_or(0); + const CHyprColor COLOR = configStringToInt(vars[1]).value_or(0); for (size_t i = 2; i < vars.size(); ++i) errorMessage += vars[i] + ' '; @@ -1545,10 +1546,10 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { const auto COLOR_RESULT = configStringToInt(vars[3]); if (!COLOR_RESULT) return "invalid arg 3"; - CColor color = *COLOR_RESULT; + CHyprColor color = *COLOR_RESULT; - size_t msgidx = 4; - float fontsize = 13.f; + 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); diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index e46999e6..482db541 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -34,11 +34,11 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() { cairo_surface_destroy(m_pCairoSurface); } -void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) { +void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) { const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique()).get(); PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text; - PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color; + PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->started.reset(); PNOTIF->timeMs = timeMs; PNOTIF->icon = icon; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 0bba8b04..67603e49 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -19,17 +19,17 @@ enum eIconBackend { static const std::array, 3 /* backends */> ICONS_ARRAY = { std::array{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, std::array{"", "", "", "", "", "󰸞", ""}, std::array{"", "", "", "", "", ""}}; -static const std::array ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0}, - CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0}, - CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0}, - CColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0}, - CColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0}, - CColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0}, - CColor{0, 0, 0, 1.0}}; +static const std::array ICONS_COLORS = {CHyprColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0}, + CHyprColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0}, + CHyprColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0}, + CHyprColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0}, + CHyprColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0}, + CHyprColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0}, + CHyprColor{0, 0, 0, 1.0}}; struct SNotification { std::string text = ""; - CColor color; + CHyprColor color; CTimer started; float timeMs = 0; eIcons icon = ICON_NONE; @@ -42,7 +42,7 @@ class CHyprNotificationOverlay { ~CHyprNotificationOverlay(); void draw(PHLMONITOR pMonitor); - void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); + void addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); void dismissNotifications(const int amount); bool hasAny(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 12e81b76..b015d61f 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -674,8 +674,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { // Basic form has only two colors, everything else can be parsed as a gradient if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { - m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); - m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); + m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); return; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 5dd59437..672ff6ec 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -356,7 +356,7 @@ class CWindow { CAnimatedVariable m_fActiveInactiveAlpha; // animated shadow color - CAnimatedVariable m_cRealShadowColor; + CAnimatedVariable m_cRealShadowColor; // animated tint CAnimatedVariable m_fDimPercent; diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 6310afb7..7cea72a0 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -34,7 +34,7 @@ struct typeToANIMATEDVARTYPE_t { }; template <> -struct typeToANIMATEDVARTYPE_t { +struct typeToANIMATEDVARTYPE_t { static constexpr ANIMATEDVARTYPE value = AVARTYPE_COLOR; }; @@ -63,7 +63,7 @@ concept OneOf = (... or std::same_as); // 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; +concept Animable = OneOf; class CBaseAnimatedVariable { public: diff --git a/src/helpers/Color.cpp b/src/helpers/Color.cpp index f9a207bb..fe217c0f 100644 --- a/src/helpers/Color.cpp +++ b/src/helpers/Color.cpp @@ -5,22 +5,52 @@ #define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0) #define BLUE(c) ((double)(((c)) & 0xff) / 255.0) -CColor::CColor() {} +CHyprColor::CHyprColor() {} -CColor::CColor(float r, float g, float b, float a) { - this->r = r; - this->g = g; - this->b = b; - this->a = a; +CHyprColor::CHyprColor(float r_, float g_, float b_, float a_) { + r = r_; + g = g_; + b = b_; + a = a_; + + okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab(); } -CColor::CColor(uint64_t hex) { - this->r = RED(hex); - this->g = GREEN(hex); - this->b = BLUE(hex); - this->a = ALPHA(hex); +CHyprColor::CHyprColor(uint64_t hex) { + r = RED(hex); + g = GREEN(hex); + b = BLUE(hex); + a = ALPHA(hex); + + okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab(); } -uint32_t CColor::getAsHex() const { +CHyprColor::CHyprColor(const Hyprgraphics::CColor& color, float a_) { + const auto SRGB = color.asRgb(); + r = SRGB.r; + g = SRGB.g; + b = SRGB.b; + a = a_; + + okLab = color.asOkLab(); +} + +uint32_t CHyprColor::getAsHex() const { return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1; -} \ No newline at end of file +} + +Hyprgraphics::CColor::SSRGB CHyprColor::asRGB() const { + return {r, g, b}; +} + +Hyprgraphics::CColor::SOkLab CHyprColor::asOkLab() const { + return okLab; +} + +Hyprgraphics::CColor::SHSL CHyprColor::asHSL() const { + return Hyprgraphics::CColor(okLab).asHSL(); +} + +CHyprColor CHyprColor::stripA() const { + return {r, g, b, 1.F}; +} diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 32ed39ee..cf7f7943 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -1,35 +1,47 @@ #pragma once #include +#include +#include "../debug/Log.hpp" +#include "../macros.hpp" -class CColor { +class CHyprColor { public: - CColor(); - CColor(float r, float g, float b, float a); - CColor(uint64_t); - - float r = 0, g = 0, b = 0, a = 1.f; + CHyprColor(); + CHyprColor(float r, float g, float b, float a); + CHyprColor(const Hyprgraphics::CColor& col, float a); + CHyprColor(uint64_t); // AR32 - uint32_t getAsHex() const; + uint32_t getAsHex() const; + Hyprgraphics::CColor::SSRGB asRGB() const; + Hyprgraphics::CColor::SOkLab asOkLab() const; + Hyprgraphics::CColor::SHSL asHSL() const; + CHyprColor stripA() const; - CColor operator-(const CColor& c2) const { - return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a); + // + bool operator==(const CHyprColor& c2) const { + return c2.r == r && c2.g == g && c2.b == b && c2.a == a; } - CColor operator+(const CColor& c2) const { - return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a); + // stubs for the AnimationMgr + CHyprColor operator-(const CHyprColor& c2) const { + RASSERT(false, "CHyprColor: - is a STUB"); + return {}; } - CColor operator*(const float& v) const { - return CColor(r * v, g * v, b * v, a * v); + CHyprColor operator+(const CHyprColor& c2) const { + RASSERT(false, "CHyprColor: + is a STUB"); + return {}; } - bool operator==(const CColor& c2) const { - return r == c2.r && g == c2.g && b == c2.b && a == c2.a; + CHyprColor operator*(const float& c2) const { + RASSERT(false, "CHyprColor: * is a STUB"); + return {}; } - CColor stripA() const { - return {r, g, b, 1}; - } + double r = 0, g = 0, b = 0, a = 0; + + private: + Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation }; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 4761346e..74a3030c 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -33,7 +33,7 @@ CHyprError::~CHyprError() { m_fFadeOpacity.unregister(); } -void CHyprError::queueCreate(std::string message, const CColor& color) { +void CHyprError::queueCreate(std::string message, const CHyprColor& color) { m_szQueued = message; m_cQueued = color; } @@ -98,7 +98,7 @@ void CHyprError::createQueued() { cairo_stroke(CAIRO); // draw the text with a common font - const CColor textColor = CColor(0.9, 0.9, 0.9, 1.0); + const CHyprColor textColor = CHyprColor(0.9, 0.9, 0.9, 1.0); cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a); static auto fontFamily = CConfigValue("misc:font_family"); @@ -160,7 +160,7 @@ void CHyprError::createQueued() { m_bIsCreated = true; m_szQueued = ""; - m_cQueued = CColor(); + m_cQueued = CHyprColor(); g_pHyprRenderer->damageMonitor(PMONITOR); diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index a553614c..042dccd0 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -11,7 +11,7 @@ class CHyprError { CHyprError(); ~CHyprError(); - void queueCreate(std::string message, const CColor& color); + void queueCreate(std::string message, const CHyprColor& color); void draw(); void destroy(); @@ -21,7 +21,7 @@ class CHyprError { private: void createQueued(); std::string m_szQueued = ""; - CColor m_cQueued; + CHyprColor m_cQueued; bool m_bQueuedDestroy = false; bool m_bIsCreated = false; SP m_pTexture; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 68dbdda1..7525bf6b 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -8,6 +8,8 @@ #include "eventLoop/EventLoopManager.hpp" #include "../helpers/varlist/VarList.hpp" +#include + int wlTick(SP self, void* data) { if (g_pAnimationManager) g_pAnimationManager->onTicked(); @@ -154,7 +156,7 @@ void CAnimationManager::tick() { // beziers are with a switch unforto // TODO: maybe do something cleaner - auto updateVariable = [&](CAnimatedVariable& av) { + static const auto updateVariable = [&](CAnimatedVariable& av) { // for disabled anims just warp if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { av.warp(false); @@ -166,13 +168,50 @@ void CAnimationManager::tick() { return; } - const auto DELTA = av.m_Goal - av.m_Begun; const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); + const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER->second.getYForPoint(SPENT); + + const auto DELTA = av.m_Goal - av.m_Begun; if (BEZIER != m_mBezierCurves.end()) - av.m_Value = av.m_Begun + DELTA * BEZIER->second.getYForPoint(SPENT); + av.m_Value = av.m_Begun + DELTA * POINTY; else - av.m_Value = av.m_Begun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT); + av.m_Value = av.m_Begun + DELTA * POINTY; + }; + + static const auto updateColorVariable = [&](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 BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); + const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER->second.getYForPoint(SPENT); + + // convert both to OkLab, then lerp that, and convert back. + // This is not as fast as just lerping rgb, but it's WAY more precise... + // Use the CHyprColor cache for OkLab + + const auto& L1 = av.m_Begun.asOkLab(); + const auto& L2 = av.m_Goal.asOkLab(); + + static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; }; + + const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{ + .l = lerp(L1.l, L2.l, POINTY), + .a = lerp(L1.a, L2.a, POINTY), + .b = lerp(L1.b, L2.b, POINTY), + }; + + av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)}; + + return; }; switch (av->m_Type) { @@ -187,8 +226,8 @@ void CAnimationManager::tick() { break; } case AVARTYPE_COLOR: { - auto typedAv = static_cast*>(av); - updateVariable(*typedAv); + auto typedAv = static_cast*>(av); + updateColorVariable(*typedAv); break; } default: UNREACHABLE(); @@ -272,7 +311,7 @@ bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) { return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f; } -bool CAnimationManager::deltaSmallToFlip(const CColor& a, const CColor& b) { +bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) { return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f; } @@ -288,7 +327,7 @@ bool CAnimationManager::deltazero(const float& a, const float& b) { return a == b; } -bool CAnimationManager::deltazero(const CColor& a, const CColor& b) { +bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) { return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; } diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 601a38b3..3960f261 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -39,10 +39,10 @@ class CAnimationManager { private: bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b); - bool deltaSmallToFlip(const CColor& a, const CColor& b); + bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b); bool deltaSmallToFlip(const float& a, const float& b); bool deltazero(const Vector2D& a, const Vector2D& b); - bool deltazero(const CColor& a, const CColor& b); + bool deltazero(const CHyprColor& a, const CHyprColor& b); bool deltazero(const float& a, const float& b); std::unordered_map m_mBezierCurves; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7f10249a..cfb7453c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -275,7 +275,7 @@ void CKeybindManager::updateXKBTranslationState() { if (!PKEYMAP) { g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )", - CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); Debug::log(ERR, "[XKBTranslationState] Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 0580c9be..c0c190dd 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -505,7 +505,7 @@ SP CPointerManager::renderHWCursorBuffer(SPbind(); g_pHyprOpenGL->beginSimple(state->monitor.lock(), {0, 0, INT16_MAX, INT16_MAX}, RBO); - g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); + g_pHyprOpenGL->clear(CHyprColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize, diff --git a/src/meson.build b/src/meson.build index 61ca06d5..754cd55a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,6 +10,7 @@ executable( server_protos, aquamarine, hyprcursor, + hyprgraphics, hyprlang, hyprutils, dependency('gbm'), diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index ef3ae06a..1a7f25ab 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -71,7 +71,7 @@ APICALL bool HyprlandAPI::reloadConfig() { return true; } -APICALL bool HyprlandAPI::addNotification(HANDLE handle, const std::string& text, const CColor& color, const float timeMs) { +APICALL bool HyprlandAPI::addNotification(HANDLE handle, const std::string& text, const CHyprColor& color, const float timeMs) { auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); if (!PLUGIN) @@ -244,7 +244,7 @@ APICALL bool addNotificationV2(HANDLE handle, const std::unordered_map(iterator->second); + const auto COLOR = std::any_cast(iterator->second); // optional eIcons icon = ICON_NONE; diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 4dcf4ba5..bd257699 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -187,7 +187,7 @@ namespace HyprlandAPI { returns: true on success. False otherwise. */ - APICALL bool addNotification(HANDLE handle, const std::string& text, const CColor& color, const float timeMs); + APICALL bool addNotification(HANDLE handle, const std::string& text, const CHyprColor& color, const float timeMs); /* Creates a trampoline function hook to an internal hl func. @@ -251,7 +251,7 @@ namespace HyprlandAPI { data has to contain: - text: std::string or const char* - time: uint64_t - - color: CColor -> CColor(0) will apply the default color for the notification icon + - color: CHyprColor -> CHyprColor(0) will apply the default color for the notification icon data may contain: - icon: eIcons diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index d800539d..41771ce2 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -2,7 +2,7 @@ #include #include "render/Renderer.hpp" -CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { +CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col_) { LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); color = col_.getAsHex(); @@ -59,7 +59,7 @@ bool CSinglePixelBuffer::good() { return resource->good(); } -CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) { +CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color) { buffer = makeShared(id, client, color); if (!buffer->good()) @@ -89,8 +89,8 @@ CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SPsetOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { - CColor color{r / (float)std::numeric_limits::max(), g / (float)std::numeric_limits::max(), b / (float)std::numeric_limits::max(), - a / (float)std::numeric_limits::max()}; + CHyprColor color{r / (float)std::numeric_limits::max(), g / (float)std::numeric_limits::max(), b / (float)std::numeric_limits::max(), + a / (float)std::numeric_limits::max()}; const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared(id, resource->client(), color)); if (!RESOURCE->good()) { diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp index ab74825c..b20f582a 100644 --- a/src/protocols/SinglePixel.hpp +++ b/src/protocols/SinglePixel.hpp @@ -9,7 +9,7 @@ class CSinglePixelBuffer : public IHLBuffer { public: - CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col); + CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col); virtual ~CSinglePixelBuffer(); virtual Aquamarine::eBufferCapability caps(); @@ -33,7 +33,7 @@ class CSinglePixelBuffer : public IHLBuffer { class CSinglePixelBufferResource { public: - CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color); + CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color); ~CSinglePixelBufferResource(); bool good(); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 04c089d7..d00e9dce 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -255,7 +255,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) return false; - g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); + g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); // render client at 0,0 g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible @@ -308,7 +308,7 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) { if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock())) return false; - g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); + g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 9c00daee..9b878317 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -566,7 +566,11 @@ void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) { glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data()); std::string errorStr(errorLog.begin(), errorLog.end()); - g_pConfigManager->addParseError((program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr); + const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr; + + Debug::log(ERR, "Failed to link shader: {}", FULLERROR); + + g_pConfigManager->addParseError(FULLERROR); } GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic) { @@ -604,6 +608,8 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string return 0; } } else { + if (ok != GL_TRUE) + logShaderError(prog, true); RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!"); } @@ -627,6 +633,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return 0; } } else { + if (ok != GL_TRUE) + logShaderError(shader, false); RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!"); } @@ -1114,8 +1122,12 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); + m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); + m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length = glGetUniformLocation(prog, "gradient2Length"); m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle"); + m_RenderData.pCurrentMonData->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2"); + m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp"); m_RenderData.pCurrentMonData->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha"); m_RenderData.pCurrentMonData->m_bShadersInitialized = true; @@ -1167,7 +1179,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { m_sFinalScreenShader.posAttrib = glGetAttribLocation(m_sFinalScreenShader.program, "pos"); } -void CHyprOpenGLImpl::clear(const CColor& color) { +void CHyprOpenGLImpl::clear(const CHyprColor& color) { RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!"); TRACY_GPU_ZONE("RenderClear"); @@ -1231,12 +1243,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h scissor(&box, transform); } -void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) { +void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) { if (!m_RenderData.damage.empty()) renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA, bool xray) { +void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) { if (m_RenderData.damage.empty()) return; @@ -1258,7 +1270,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - renderRect(box, CColor(0, 0, 0, 0), round); + renderRect(box, CHyprColor(0, 0, 0, 0), round); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 0xFF); @@ -1283,7 +1295,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) { +void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRegion* damage, int round) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -1981,7 +1993,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->blurFB.bind(); - clear(CColor(0, 0, 0, 0)); + clear(CHyprColor(0, 0, 0, 0)); m_bEndFrame = true; // fix transformed renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false); @@ -2100,7 +2112,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA)) - renderRect(pBox, CColor(0, 0, 0, 0), round); + renderRect(pBox, CHyprColor(0, 0, 0, 0), round); else renderTexture(tex, pBox, a, round, true, true); // discard opaque glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -2184,12 +2196,107 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif - static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail - - glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColors.size(), (float*)grad.m_vColors.data()); - glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColors.size()); + glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColorsOkLabA.size(), (float*)grad.m_vColorsOkLabA.data()); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColorsOkLabA.size() / 4); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, 0); + + CBox transformedBox = *box; + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); + + const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); + const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); + + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); + + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib); + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib); + + if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { + CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; + damageClip.intersect(m_RenderData.damage); + + if (!damageClip.empty()) { + for (auto const& RECT : damageClip.getRects()) { + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + } else { + for (auto const& RECT : m_RenderData.damage.getRects()) { + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib); + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib); + + blend(BLEND); +} + +void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) { + RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); + RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); + + TRACY_GPU_ZONE("RenderBorder2"); + + if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault())) + return; + + CBox newBox = *box; + m_RenderData.renderModif.applyToBox(newBox); + + box = &newBox; + + if (borderSize < 1) + return; + + int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale); + scaledBorderSize = std::round(scaledBorderSize * m_RenderData.renderModif.combinedScale()); + + // adjust box + box->x -= scaledBorderSize; + box->y -= scaledBorderSize; + box->width += 2 * scaledBorderSize; + box->height += 2 * scaledBorderSize; + + round += round == 0 ? 0 : scaledBorderSize; + + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); + + const auto BLEND = m_bBlend; + blend(true); + + glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program); + +#ifndef GLES2 + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); +#else + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); +#endif + + glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad1.m_vColorsOkLabA.size(), (float*)grad1.m_vColorsOkLabA.data()); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad1.m_vColorsOkLabA.size() / 4); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad1.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); + glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2, grad2.m_vColorsOkLabA.size(), (float*)grad2.m_vColorsOkLabA.data()); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, grad2.m_vColorsOkLabA.size() / 4); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle2, (int)(grad2.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp, lerp); CBox transformedBox = *box; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, @@ -2253,7 +2360,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -2272,7 +2379,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr m_RenderData.currentFB = pFramebuffer; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true); @@ -2308,7 +2415,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { g_pHyprRenderer->m_bRenderingSnapshot = true; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -2322,7 +2429,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { const auto BLURVAL = **PBLUR; **PBLUR = 0; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); @@ -2355,7 +2462,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { g_pHyprRenderer->m_bRenderingSnapshot = true; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -2405,7 +2512,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault()) { 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.value())); + g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value())); g_pHyprRenderer->damageMonitor(PMONITOR); } @@ -2449,7 +2556,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow.lock(), "Tried to render shadow without a window!"); @@ -2568,7 +2675,7 @@ void CHyprOpenGLImpl::renderMirrored() { .translate(-monitor->vecTransformedSize / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) - clear(CColor(0, 0, 0, 0)); + clear(CHyprColor(0, 0, 0, 0)); renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false); @@ -2583,7 +2690,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const const auto FONTFAMILY = *PSPLASHFONT != STRVAL_EMPTY ? *PSPLASHFONT : *FALLBACKFONT; const auto FONTSIZE = (int)(size.y / 76); - const auto COLOR = CColor(*PSPLASHCOLOR); + const auto COLOR = CHyprColor(*PSPLASHCOLOR); PangoLayout* layoutText = pango_cairo_create_layout(CAIRO); PangoFontDescription* pangoFD = pango_font_description_new(); @@ -2671,7 +2778,7 @@ SP CHyprOpenGLImpl::loadAsset(const std::string& filename) { return tex; } -SP CHyprOpenGLImpl::renderText(const std::string& text, CColor col, int pt, bool italic) { +SP CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic) { SP tex = makeShared(); static auto FONT = CConfigValue("misc:font_family"); @@ -2804,7 +2911,7 @@ void CHyprOpenGLImpl::initAssets() { g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ? std::to_string(g_pCompositor->m_pAqBackend->session->vt) : "unknown"), - CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); + CHyprColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); // create the default background texture { @@ -2889,7 +2996,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; blend(true); - clear(CColor{0, 0, 0, 1}); + clear(CHyprColor{0, 0, 0, 1}); // first render the background if (m_pBackgroundTexture) { @@ -2981,7 +3088,7 @@ void CHyprOpenGLImpl::restoreMatrix() { void CHyprOpenGLImpl::bindOffMain() { m_RenderData.pCurrentMonData->offMainFB.bind(); - clear(CColor(0, 0, 0, 0)); + clear(CHyprColor(0, 0, 0, 0)); m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB; } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c594a7cc..6c0632dd 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -153,15 +153,16 @@ class CHyprOpenGLImpl { void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); void end(); - void renderRect(CBox*, const CColor&, int round = 0); - void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); - void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); + void renderRect(CBox*, const CHyprColor&, int round = 0); + void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false); + void renderRectWithDamage(CBox*, const CHyprColor&, CRegion* damage, int round = 0); void renderTexture(SP, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithDamage(SP, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, SP waitTimeline = nullptr, uint64_t waitPoint = 0); void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); + void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderTextureMatte(SP tex, CBox* pBox, CFramebuffer& matte); void setMonitorTransformEnabled(bool enabled); @@ -180,7 +181,7 @@ class CHyprOpenGLImpl { void renderSnapshot(PHLLS); bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); - void clear(const CColor&); + void clear(const CHyprColor&); void clearWithTex(); void scissor(const CBox*, bool transform = true); void scissor(const pixman_box32*, bool transform = true); @@ -289,7 +290,7 @@ class CHyprOpenGLImpl { void initEGL(bool gbm); EGLDeviceEXT eglDeviceFromDRMFD(int drmFD); SP loadAsset(const std::string& file); - SP renderText(const std::string& text, CColor col, int pt, bool italic = false); + SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false); void initAssets(); void initMissingAssetTexture(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bba133d9..7e44e64e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -619,7 +619,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault() && !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, CHyprColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); } renderdata.x += pWindow->m_vFloatingOffset.x; @@ -668,7 +668,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (!pWindow->m_sWindowData.noBlur.valueOrDefault() && 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, + g_pHyprOpenGL->renderRectWithBlur(&wb, CHyprColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow)); renderdata.blur = false; } @@ -780,7 +780,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) { 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 * pLayer->alpha.value())); + g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value())); } if (pLayer->fadingOut) { @@ -919,7 +919,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA g_pHyprOpenGL->blend(false); if (!canSkipBackBufferClear(pMonitor)) { if (*PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); + g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR)); else g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" } @@ -959,7 +959,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA g_pHyprOpenGL->blend(false); if (!canSkipBackBufferClear(pMonitor)) { if (*PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); + g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR)); else g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" } @@ -995,12 +995,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA 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, CHyprColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); } 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)); + g_pHyprOpenGL->renderRectWithBlur(&monbox, CHyprColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)); } break; @@ -1447,7 +1447,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { 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); + g_pHyprOpenGL->renderRect(&monrect, CHyprColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); damageBlinkCleanup = 1; } else if (*PDAMAGEBLINK) { damageBlinkCleanup++; @@ -2526,7 +2526,7 @@ std::tuple CHyprRenderer::getRenderTimes(PHLMONITOR pMonito static int handleCrashLoop(void* data) { - g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CColor(0), 5000, + g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CHyprColor(0), 5000, ICON_INFO); g_pHyprRenderer->m_fCrashingDistort += 0.5f; @@ -2540,7 +2540,7 @@ static int handleCrashLoop(void* data) { } void CHyprRenderer::initiateManualCrash() { - g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CColor(0), 5000, ICON_INFO); + g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CHyprColor(0), 5000, ICON_INFO); m_pCrashingLoop = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleCrashLoop, nullptr); wl_event_source_timer_update(m_pCrashingLoop, 1000); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index d5a312c3..eaf9da96 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -38,9 +38,13 @@ class CShader { GLint applyTint = -1; GLint tint = -1; - GLint gradient = -1; - GLint gradientLength = -1; - GLint angle = -1; + GLint gradient = -1; + GLint gradientLength = -1; + GLint angle = -1; + GLint gradient2 = -1; + GLint gradient2Length = -1; + GLint angle2 = -1; + GLint gradientLerp = -1; float initialTime = 0; GLint time = -1; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index d62e67c4..b0de4a64 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -60,7 +60,6 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { auto grad = m_pWindow->m_cRealBorderColor; const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); - 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.value() * M_PI * 2; @@ -70,12 +69,10 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { int borderSize = m_pWindow->getRealBorderSize(); const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; - g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1); - - if (ANIMATED) { - float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.value()); - g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2); - } + if (ANIMATED) + g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, grad, m_pWindow->m_fBorderFadeAnimationProgress.value(), ROUNDING, borderSize, a); + else + g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a); } eDecorationType CHyprBorderDecoration::getDecorationType() { diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 893ad498..39398878 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -93,7 +93,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (!validMapped(PWINDOW)) return; - if (PWINDOW->m_cRealShadowColor.value() == CColor(0, 0, 0, 0)) + if (PWINDOW->m_cRealShadowColor.value() == CHyprColor(0, 0, 0, 0)) return; // don't draw invisible shadows if (!PWINDOW->m_sWindowData.decorate.valueOrDefault()) @@ -181,13 +181,13 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { // build the matte // 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest. // first, clear region of interest with black (fully transparent) - g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0); + g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(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) - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); // render black window box ("clip") - g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); + g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); alphaSwapFB.bind(); @@ -215,7 +215,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; } -void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CColor color, float a) { +void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) { static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); g_pHyprOpenGL->blend(true); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 933ee0ef..650f8c92 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -34,7 +34,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; - void drawShadowInternal(CBox* box, int round, int range, CColor color, float a); + void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a); CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index b5189be5..937c913d 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -147,7 +147,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; - CColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; + CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; color.a *= a; g_pHyprOpenGL->renderRect(&rect, color); @@ -205,19 +205,19 @@ void CHyprGroupBarDecoration::invalidateTextures() { } CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) { - tex = makeShared(); - szContent = pWindow->m_szTitle; - pWindowOwner = pWindow; - const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); - const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE); + tex = makeShared(); + szContent = pWindow->m_szTitle; + pWindowOwner = pWindow; + const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); + const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE); - static auto FALLBACKFONT = CConfigValue("misc:font_family"); - static auto PTITLEFONTFAMILY = CConfigValue("group:groupbar:font_family"); - static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); - static auto PTEXTCOLOR = CConfigValue("group:groupbar:text_color"); + static auto FALLBACKFONT = CConfigValue("misc:font_family"); + 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 auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT; + const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR); + const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT; cairo_surface_destroy(LAYOUTSURFACE); diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index 1f4a1d97..acd3f3ff 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -17,12 +17,32 @@ uniform float radius; uniform float radiusOuter; uniform float thick; +// Gradients are in OkLabA!!!! {l, a, b, alpha} uniform vec4 gradient[10]; +uniform vec4 gradient2[10]; uniform int gradientLength; +uniform int gradient2Length; uniform float angle; +uniform float angle2; +uniform float gradientLerp; uniform float alpha; -vec4 getColorForCoord(vec2 normalizedCoord) { +float linearToGamma(float x) { + return x >= 0.0031308 ? 1.055 * pow(x, 0.416666666) - 0.055 : 12.92 * x; +} + +vec4 okLabAToSrgb(vec4 lab) { + float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0); + float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0); + float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0); + + return vec4(linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292), + linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)), + linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010), + lab[3]); +} + +vec4 getOkColorForCoordArray1(vec2 normalizedCoord) { if (gradientLength < 2) return gradient[0]; @@ -51,6 +71,46 @@ vec4 getColorForCoord(vec2 normalizedCoord) { return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress); } +vec4 getOkColorForCoordArray2(vec2 normalizedCoord) { + if (gradient2Length < 2) + return gradient2[0]; + + float finalAng = 0.0; + + if (angle2 > 4.71 /* 270 deg */) { + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = 6.28 - angle; + } else if (angle2 > 3.14 /* 180 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = angle - 3.14; + } else if (angle2 > 1.57 /* 90 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + finalAng = 3.14 - angle2; + } else { + finalAng = angle2; + } + + float sine = sin(finalAng); + + float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1); + int bottom = int(floor(progress)); + int top = bottom + 1; + + return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress); +} + +vec4 getColorForCoord(vec2 normalizedCoord) { + vec4 result1 = getOkColorForCoordArray1(normalizedCoord); + + if (gradient2Length <= 0) + return okLabAToSrgb(result1); + + vec4 result2 = getOkColorForCoordArray2(normalizedCoord); + + return okLabAToSrgb(mix(result1, result2, gradientLerp)); +} + void main() { highp vec2 pixCoord = vec2(gl_FragCoord); From f6ac755cf76750b8ee53389c54ef653590462c1c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 3 Dec 2024 21:15:25 +0000 Subject: [PATCH 0315/1803] cleanup: Revert use doLater instead of adding idle event handlers (#8624) This reverts commit 6d7544458d0fafcae410c1978a0cabce2fb4a346. --- src/protocols/Tablet.cpp | 26 ++++++++++++++------------ src/protocols/Tablet.hpp | 7 ++++--- src/protocols/XDGShell.cpp | 18 +++++++++--------- src/protocols/XDGShell.hpp | 8 ++++---- src/xwayland/Server.cpp | 12 ++++++++---- 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 7768402b..d7f741b9 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -2,7 +2,6 @@ #include "../devices/Tablet.hpp" #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" -#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -163,6 +162,11 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP resource_, SP< }); } +CTabletToolV2Resource::~CTabletToolV2Resource() { + if (frameSource) + wl_event_source_remove(frameSource); +} + bool CTabletToolV2Resource::good() { return resource->resource(); } @@ -201,22 +205,20 @@ void CTabletToolV2Resource::sendData() { } void CTabletToolV2Resource::queueFrame() { - if (frameQueued) + if (frameSource) return; - frameQueued = true; - g_pEventLoopManager->doLater([this]() { - if (!frameQueued || tool.expired() || inert) - return; - - sendFrame(); - }); + frameSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, [](void* data) { ((CTabletToolV2Resource*)data)->sendFrame(false); }, this); } -void CTabletToolV2Resource::sendFrame() { - frameQueued = false; +void CTabletToolV2Resource::sendFrame(bool removeSource) { + if (frameSource) { + if (removeSource) + wl_event_source_remove(frameSource); + frameSource = nullptr; + } - if (!current || !resource) + if (!current) return; timespec now; diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 8c99bee0..1ebcb1e5 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -112,20 +112,21 @@ class CTabletV2Resource { class CTabletToolV2Resource { public: CTabletToolV2Resource(SP resource_, SP tool_, SP seat_); + ~CTabletToolV2Resource(); bool good(); void sendData(); void queueFrame(); - void sendFrame(); + void sendFrame(bool removeSource = true); bool current = false; WP lastSurf; WP tool; WP seat; + wl_event_source* frameSource = nullptr; - bool frameQueued = false; - bool inert = false; // removed was sent + bool inert = false; // removed was sent private: SP resource; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index a542c394..688d0006 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,7 +3,6 @@ #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" -#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -470,6 +469,8 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPresetRole(); } @@ -483,23 +484,22 @@ SP CXDGSurfaceResource::fromResource(wl_resource* res) { return data ? data->self.lock() : nullptr; } +static void onConfigure(void* data) { + ((CXDGSurfaceResource*)data)->configure(); +} + uint32_t CXDGSurfaceResource::scheduleConfigure() { - if (configureScheduled) + if (configureSource) return scheduledSerial; + configureSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, onConfigure, this); scheduledSerial = wl_display_next_serial(g_pCompositor->m_sWLDisplay); - configureScheduled = true; - g_pEventLoopManager->doLater([this]() { configure(); }); - return scheduledSerial; } void CXDGSurfaceResource::configure() { - if (!resource) - return; - - configureScheduled = false; + configureSource = nullptr; resource->sendConfigure(scheduledSerial); } diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 3b7d2d11..ef847f3b 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -199,12 +199,12 @@ class CXDGSurfaceResource { void configure(); private: - SP resource; + SP resource; - uint32_t lastConfigureSerial = 0; - uint32_t scheduledSerial = 0; + uint32_t lastConfigureSerial = 0; + uint32_t scheduledSerial = 0; - bool configureScheduled = false; + wl_event_source* configureSource = nullptr; // std::vector> popups; diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 390ce1f6..f356af18 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -176,6 +176,11 @@ static bool openSockets(std::array& sockets, int display) { return true; } +static void startServer(void* data) { + if (!g_pXWayland->pServer->start()) + Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); +} + static int xwaylandReady(int fd, uint32_t mask, void* data) { return g_pXWayland->pServer->ready(fd, mask); } @@ -303,10 +308,9 @@ bool CXWaylandServer::create() { setenv("DISPLAY", displayName.c_str(), true); - g_pEventLoopManager->doLater([this]() { - if (!start()) - Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); - }); + // TODO: lazy mode + + idleSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::startServer, nullptr); return true; } From 3c617ce33c64cb43049489598b6391911eed7070 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 3 Dec 2024 22:58:30 +0000 Subject: [PATCH 0316/1803] internal: fixup some missed updateColorsOk() calls --- src/desktop/Window.cpp | 2 ++ src/managers/KeybindManager.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b015d61f..34682b32 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -692,6 +692,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { inactiveBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); } + activeBorderGradient.updateColorsOk(); + // Includes sanity checks for the number of colors in each gradient if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10) Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cfb7453c..153c3c0d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2997,6 +2997,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { return std::invoke_result_t(1); }); + colorData.updateColorsOk(); + if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); else From f9e4998a6d7713b19947b0db2c43ad88c5b71d80 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Wed, 4 Dec 2024 13:12:04 -0500 Subject: [PATCH 0317/1803] snap: check which corner is being grabbed for monitor snapping (#8637) --- src/layout/IHyprLayout.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 8ff55d10..cb1f064b 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -487,19 +487,23 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecPosition.x + MON->vecSize.x - BORDERSIZE}; SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecPosition.y + MON->vecSize.y - BORDERSIZE}; - if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && + (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE))) { SNAP(sourceX.start, sourceX.end, monX.start); snaps |= SNAP_LEFT; } - if (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && + (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE))) { SNAP(sourceX.end, sourceX.start, monX.end); snaps |= SNAP_RIGHT; } - if (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && + (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE))) { SNAP(sourceY.start, sourceY.end, monY.start); snaps |= SNAP_UP; } - if (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && + (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE))) { SNAP(sourceY.end, sourceY.start, monY.end); snaps |= SNAP_DOWN; } From 22f7d6f1424c296b297df87bf2accdfefac4af33 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 5 Dec 2024 01:59:29 +0000 Subject: [PATCH 0318/1803] core: add a few festive splashes adds two new 'special' splash types for xmas and new years. Activated based on local time. --- src/Compositor.cpp | 14 ++- src/helpers/Splashes.hpp | 184 +++++++++++++++++++++++---------------- 2 files changed, 120 insertions(+), 78 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3573996d..1261d003 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -206,11 +206,21 @@ CCompositor::~CCompositor() { } void CCompositor::setRandomSplash() { + auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto local = *localtime(&tt); + + const auto* SPLASHES = &NSplashes::SPLASHES; + + if (local.tm_mon + 1 == 12 && local.tm_mday >= 23 && local.tm_mday <= 27) // dec 23-27 + SPLASHES = &NSplashes::SPLASHES_CHRISTMAS; + if ((local.tm_mon + 1 == 12 && local.tm_mday >= 29) || (local.tm_mon + 1 == 1 && local.tm_mday <= 3)) + SPLASHES = &NSplashes::SPLASHES_NEWYEAR; + std::random_device dev; std::mt19937 engine(dev()); - std::uniform_int_distribution<> distribution(0, SPLASHES.size() - 1); + std::uniform_int_distribution<> distribution(0, SPLASHES->size() - 1); - m_szCurrentSplash = SPLASHES[distribution(engine)]; + m_szCurrentSplash = SPLASHES->at(distribution(engine)); } static std::vector> pendingOutputs; diff --git a/src/helpers/Splashes.hpp b/src/helpers/Splashes.hpp index 4a4fd022..2c74abb1 100644 --- a/src/helpers/Splashes.hpp +++ b/src/helpers/Splashes.hpp @@ -3,80 +3,112 @@ #include #include -inline const std::vector SPLASHES = { - // clang-format off - "Woo, animations!", - "It's like Hypr, but better.", - "Release 1.0 when?", - "It's not awesome, it's Hyprland!", - "\"I commit too often, people can't catch up lmao\" - Vaxry", - "This text is random.", - "\"There are reasons to not use rust.\" - Boga", - "Read the wiki.", - "\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry", - "h", - "\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry", - "Compile, wait for 20 minutes, notice a new commit, compile again.", - "To rice, or not to rice, that is the question.", - "Now available on Fedora!", - "\"Hyprland is so good it starts with a capital letter\" - Hazel", - "\"please make this message a splash\" - eriedaberrie", - "\"the only wayland compositor powered by fried chicken\" - raf", - "\"This will never get into Hyprland\" - Flafy", - "\"Hyprland only gives you up on -git\" - fazzi", - "Segmentation fault (core dumped)", - "\"disabling hyprland logo is a war crime\" - vaxry", - "some basic startup code", - "\"I think I am addicted to hyprland\" - mathisbuilder", - "\"hyprland is the most important package in the arch repos\" - jacekpoz", - "Thanks Brodie!", - "Thanks fufexan!", - "Thanks raf!", - "You can't use --splash to change this message :)", - "Hyprland will overtake Gnome in popularity by [insert year]", - // music reference / quote section - "J'remue le ciel, le jour, la nuit.", - "aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!", - "Wir sind schon sehr lang zusammen...", - "I see a red door and I want it painted black.", - "Take on me, take me on...", - "You spin me right round baby right round", - "Stayin' alive, stayin' alive", - "Say no way, say no way ya, no way!", - "Ground control to Major Tom...", - "Alors on danse", - "And all that I can see, is just a yellow lemon tree.", - "Got a one-way ticket to the blues", - "Is this the real life, is this just fantasy", - "What's in your head, in your head?", - "We're all living in America, America, America.", - "I'm still standing, better than I ever did", - "Here comes the sun, bringing you love and shining on everyone", - "Two trailer park girls go round the outside", - "With the lights out, it's less dangerous", - "Here we go back, this is the moment, tonight is the night", - "Now you're just somebody that I used to know...", - "Black bird, black moon, black sky", - "Some legends are told, some turn to dust or to gold", - "Your brain gets smart, but your head gets dumb.", - "Save your mercy for someone who needs it more", - "You're gonna hear my voice when I shout it out loud", - "Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm", - "Súbeme la radio que esta es mi canción", - "I'm beggin', beggin' you", - "Never gonna let you down (I am trying!)", - "\"I use Arch, btw\" - John Cena", - "\"Hyper\".replace(\"e\", \"\")", - "\"my win11 install runs hyprland that is true\" - raf", - "\"stop playing league loser\" - hyprBot", - "\"If it ain't broke, don't fix it\" - Lucascito_03", - "\"@vaxry how do i learn c++\" - flicko", - // - "Join the discord server!", - "Thanks ThatOneCalculator!", - "The AUR packages always work, except for the times they don't.", - "Funny animation compositor woo", - // - "2 years!" - // clang-format on +namespace NSplashes { + inline const std::vector SPLASHES = { + // clang-format off + "Woo, animations!", + "It's like Hypr, but better.", + "Release 1.0 when?", + "It's not awesome, it's Hyprland!", + "\"I commit too often, people can't catch up lmao\" - Vaxry", + "This text is random.", + "\"There are reasons to not use rust.\" - Boga", + "Read the wiki.", + "\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry", + "h", + "\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry", + "Compile, wait for 20 minutes, notice a new commit, compile again.", + "To rice, or not to rice, that is the question.", + "Now available on Fedora!", + "\"Hyprland is so good it starts with a capital letter\" - Hazel", + "\"please make this message a splash\" - eriedaberrie", + "\"the only wayland compositor powered by fried chicken\" - raf", + "\"This will never get into Hyprland\" - Flafy", + "\"Hyprland only gives you up on -git\" - fazzi", + "Segmentation fault (core dumped)", + "\"disabling hyprland logo is a war crime\" - vaxry", + "some basic startup code", + "\"I think I am addicted to hyprland\" - mathisbuilder", + "\"hyprland is the most important package in the arch repos\" - jacekpoz", + "Thanks Brodie!", + "Thanks fufexan!", + "Thanks raf!", + "You can't use --splash to change this message :)", + "Hyprland will overtake Gnome in popularity by [insert year]", + // music reference / quote section + "J'remue le ciel, le jour, la nuit.", + "aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!", + "Wir sind schon sehr lang zusammen...", + "I see a red door and I want it painted black.", + "Take on me, take me on...", + "You spin me right round baby right round", + "Stayin' alive, stayin' alive", + "Say no way, say no way ya, no way!", + "Ground control to Major Tom...", + "Alors on danse", + "And all that I can see, is just a yellow lemon tree.", + "Got a one-way ticket to the blues", + "Is this the real life, is this just fantasy", + "What's in your head, in your head?", + "We're all living in America, America, America.", + "I'm still standing, better than I ever did", + "Here comes the sun, bringing you love and shining on everyone", + "Two trailer park girls go round the outside", + "With the lights out, it's less dangerous", + "Here we go back, this is the moment, tonight is the night", + "Now you're just somebody that I used to know...", + "Black bird, black moon, black sky", + "Some legends are told, some turn to dust or to gold", + "Your brain gets smart, but your head gets dumb.", + "Save your mercy for someone who needs it more", + "You're gonna hear my voice when I shout it out loud", + "Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm", + "Súbeme la radio que esta es mi canción", + "I'm beggin', beggin' you", + "Never gonna let you down (I am trying!)", + "\"I use Arch, btw\" - John Cena", + "\"Hyper\".replace(\"e\", \"\")", + "\"my win11 install runs hyprland that is true\" - raf", + "\"stop playing league loser\" - hyprBot", + "\"If it ain't broke, don't fix it\" - Lucascito_03", + "\"@vaxry how do i learn c++\" - flicko", + // + "Join the discord server!", + "Thanks ThatOneCalculator!", + "The AUR packages always work, except for the times they don't.", + "Funny animation compositor woo", + // + "2 years!" + // clang-format on + }; + + inline const std::vector SPLASHES_CHRISTMAS = { + // clang-format off + "Merry Christmas!", + "Merry Xmas!", + "Ho ho ho", + "Santa was here", + // clang-format on + }; + + // ONLY valid near new years. + inline static int newYear = []() -> int { + auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto local = *localtime(&tt); + + if (local.tm_mon < 8 /* decided with a fair die I promise. */) + return local.tm_year + 1900; + return local.tm_year + 1901; + }(); + + inline const std::vector SPLASHES_NEWYEAR = { + // clang-format off + "Happy new Year!", + "[New year] will be the year of the Linux desktop!", + "[New year] will be the year of the Hyprland desktop!", + std::format("{} will be the year of the Linux desktop!", newYear), + std::format("{} will be the year of the Hyprland desktop!", newYear), + std::format("Let's make {} even better than {}!", newYear, newYear - 1), + // clang-format on + }; }; \ No newline at end of file From ceef4fb3a5efe1617790f56e2701846a21c2533d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 5 Dec 2024 03:36:50 +0000 Subject: [PATCH 0319/1803] core: feeling a bit quirky today. --- src/helpers/Splashes.hpp | 49 +++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/helpers/Splashes.hpp b/src/helpers/Splashes.hpp index 2c74abb1..3ae59956 100644 --- a/src/helpers/Splashes.hpp +++ b/src/helpers/Splashes.hpp @@ -35,6 +35,30 @@ namespace NSplashes { "Thanks raf!", "You can't use --splash to change this message :)", "Hyprland will overtake Gnome in popularity by [insert year]", + "Designed in California - Assembled in China", + "\"something