diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 285a15a1..e3e97bef 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -5,18 +5,21 @@ body: - type: markdown attributes: value: | - Before opening a new issue, take a moment to search through the current open ones. + ## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists. --- - type: dropdown id: type attributes: - label: Bug or Regression? - description: Is this a bug or a regression? + label: Regression? + description: | + Regression means that something used to work but no longer does. + **BEFORE CONTINUING**, please check if this bug is a regression or not, and if it is, we need you to bisect with the help of the wiki: https://wiki.hyprland.org/Crashes-and-Bugs/#bisecting-an-issue + multiple: true options: - - Bug - - Regression + - "Yes" + - "No" validations: required: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aa2bf5c..632621ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo pixman-1 libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm - hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.1 + hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.4 ) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/flake.lock b/flake.lock index 94fc9d90..cb1f7875 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1718368322, - "narHash": "sha256-VfMg3RsnRLQzbq0hFIh1dCM09b5C/F/qPFUOgU/CRi0=", + "lastModified": 1718450675, + "narHash": "sha256-jpsns6buS4bK+1sF8sL8AaixAiCRjA+nldTKvcwmvUs=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "dd3a853c8239d1c3f3f37de7d2b8ae4b4f3840df", + "rev": "66d5b46ff94efbfa6fa3d1d1b66735f1779c34a6", "type": "github" }, "original": { @@ -38,11 +38,11 @@ ] }, "locked": { - "lastModified": 1691753796, - "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "lastModified": 1714869498, + "narHash": "sha256-vbLVOWvQqo4n1yvkg/Q70VTlPbMmTiCQfNTgcWDCfJM=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "rev": "e06482e0e611130cd1929f75e8c1cf679e57d161", "type": "github" }, "original": { @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1718271409, - "narHash": "sha256-8KvVqtApNt4FWTdn1TqVvw00rpqyG9UuUPA2ilPVD1U=", + "lastModified": 1718804078, + "narHash": "sha256-CqRZne63BpYlPd/i8lXV0UInUt59oKogiwdVtBRHt60=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8e10e0626fb26a14b859b3811b6ed7932400c86e", + "rev": "4f1351295c55a8f51219b25aa4a6497a067989d0", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1718318537, - "narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=", + "lastModified": 1718530797, + "narHash": "sha256-pup6cYwtgvzDpvpSCFh1TEUjw2zkNpk8iolbKnyFmmU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420", + "rev": "b60ebf54c15553b393d144357375ea956f89e9a9", "type": "github" }, "original": { @@ -179,11 +179,11 @@ ] }, "locked": { - "lastModified": 1718272114, - "narHash": "sha256-KsX7sAwkEFpXiwyjt0HGTnnrUU58wW1jlzj5IA/LRz8=", + "lastModified": 1718619174, + "narHash": "sha256-FWW68AVYmB91ZDQnhLMBNCUUTCjb1ZpO2k2KIytHtkA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "24be4a26f0706e456fca1b61b8c79f7486a9e86d", + "rev": "c7894aa54f9a7dbd16df5cd24d420c8af22d5623", "type": "github" }, "original": { diff --git a/hyprctl/hyprctl.zsh b/hyprctl/hyprctl.zsh index 6babd835..1a4cc187 100644 --- a/hyprctl/hyprctl.zsh +++ b/hyprctl/hyprctl.zsh @@ -1,3 +1,5 @@ +#compdef hyprctl + _hyprctl_cmd_2 () { hyprctl monitors | grep Monitor | awk '{ print $2 }' } diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index f5de041b..2bd325e3 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -141,7 +141,7 @@ int rollingRead(const int socket) { int request(std::string arg, int minArgs = 0, bool needRoll = false) { const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); - auto t = timeval{.tv_sec = 0, .tv_usec = 100000}; + auto t = timeval{.tv_sec = 1, .tv_usec = 0}; setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)); const auto ARGS = std::count(arg.begin(), arg.end(), ' '); @@ -191,6 +191,8 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) { sizeWritten = read(SERVERSOCKET, buffer, 8192); if (sizeWritten < 0) { + if (errno == EWOULDBLOCK) + log("Hyprland IPC didn't respond in time\n"); log("Couldn't read (5)"); return 5; } diff --git a/nix/default.nix b/nix/default.nix index 0493abc1..a2302688 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -11,6 +11,7 @@ expat, fribidi, git, + hwdata, hyprcursor, hyprlang, hyprutils, @@ -18,26 +19,28 @@ jq, libGL, libdatrie, + libdisplay-info, libdrm, libexecinfo, libinput, + libliftoff, libselinux, libsepol, libthai, libuuid, libxkbcommon, mesa, + meson, pango, pciutils, pcre2, python3, + seatd, systemd, tomlplusplus, - udis86, wayland, wayland-protocols, wayland-scanner, - wlroots, xorg, xwayland, debug ? false, @@ -76,23 +79,21 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov sed -i "s#@PREFIX@/##g" hyprland.pc.in ''; + COMMITS = commit; DATE = date; + DIRTY = lib.optionalString (commit == "") "dirty"; HASH = commit; - DIRTY = if commit == "" then "dirty" else ""; - nativeBuildInputs = lib.concatLists [ - [ - hyprwayland-scanner - jq - makeWrapper - cmake - ninja - pkg-config - python3 - wayland-scanner - ] - # introduce this later so that cmake takes precedence - wlroots.nativeBuildInputs + nativeBuildInputs = [ + hyprwayland-scanner + jq + makeWrapper + cmake + meson # for wlroots + ninja + pkg-config + python3 # for udis86 + wayland-scanner ]; outputs = [ @@ -102,14 +103,13 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov ]; buildInputs = lib.concatLists [ - wlroots.buildInputs - udis86.buildInputs [ cairo expat fribidi git - hyprcursor.dev + hwdata + hyprcursor hyprlang hyprutils libGL @@ -128,12 +128,18 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov tomlplusplus wayland wayland-protocols + # for wlroots + seatd + libdisplay-info + libliftoff ] (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals enableXWayland [ xorg.libxcb xorg.libXdmcp xorg.xcbutil + xorg.xcbutilerrors + xorg.xcbutilrenderutil xorg.xcbutilwm xwayland ]) @@ -145,6 +151,9 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov then "Debug" else "RelWithDebInfo"; + # we want as much debug info as possible + dontStrip = debug; + cmakeFlags = [ (lib.cmakeBool "NO_XWAYLAND" (!enableXWayland)) (lib.cmakeBool "LEGACY_RENDERER" legacyRenderer) @@ -164,11 +173,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov passthru.providedSessions = ["hyprland"]; - meta = with lib; { + meta = { homepage = "https://github.com/hyprwm/Hyprland"; - description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; - license = licenses.bsd3; - platforms = wlroots.meta.platforms; + description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; + license = lib.licenses.bsd3; + platforms = lib.platforms.linux; mainProgram = "Hyprland"; }; } diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2f972335..c607dfb6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -29,6 +29,7 @@ using namespace Hyprutils::String; #include #include +#include int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal {}", signo); @@ -70,6 +71,37 @@ void handleUserSignal(int sig) { } } +void CCompositor::bumpNofile() { + if (!getrlimit(RLIMIT_NOFILE, &m_sOriginalNofile)) + Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", m_sOriginalNofile.rlim_cur, m_sOriginalNofile.rlim_max); + else { + Debug::log(ERR, "Failed to get NOFILE rlimits"); + m_sOriginalNofile.rlim_max = 0; + return; + } + + rlimit newLimit = m_sOriginalNofile; + + newLimit.rlim_cur = newLimit.rlim_max; + + if (setrlimit(RLIMIT_NOFILE, &newLimit) < 0) { + Debug::log(ERR, "Failed bumping NOFILE limits higher"); + m_sOriginalNofile.rlim_max = 0; + return; + } + + if (!getrlimit(RLIMIT_NOFILE, &newLimit)) + Debug::log(LOG, "New rlimit: soft -> {}, hard -> {}", newLimit.rlim_cur, newLimit.rlim_max); +} + +void CCompositor::restoreNofile() { + if (m_sOriginalNofile.rlim_max <= 0) + return; + + if (setrlimit(RLIMIT_NOFILE, &m_sOriginalNofile) < 0) + Debug::log(ERR, "Failed restoring NOFILE limits"); +} + CCompositor::CCompositor() { m_iHyprlandPID = getpid(); @@ -131,6 +163,8 @@ CCompositor::CCompositor() { setRandomSplash(); Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash); + + bumpNofile(); } CCompositor::~CCompositor() { @@ -1391,8 +1425,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (!PMONITOR) return nullptr; // ?? - const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? wlr_box{(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y} : - pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved(); const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y); const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height); @@ -1615,8 +1648,7 @@ PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) { } try { - std::string name = ""; - return getWorkspaceByID(getWorkspaceIDFromString(str, name)); + return getWorkspaceByID(getWorkspaceIDNameFromString(str).id); } catch (std::exception& e) { Debug::log(ERR, "Error in getWorkspaceByString, invalid id"); } return nullptr; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 242c3b13..5a1d8a64 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "defines.hpp" #include "debug/Log.hpp" @@ -81,6 +82,8 @@ class CCompositor { void cleanup(); void createLockFile(); void removeLockFile(); + void bumpNofile(); + void restoreNofile(); WP m_pLastFocus; PHLWINDOWREF m_pLastWindow; @@ -190,8 +193,9 @@ class CCompositor { void initManagers(eManagersInitStage stage); void prepareFallbackOutput(); - uint64_t m_iHyprlandPID = 0; - wl_event_source* m_critSigSource = nullptr; + uint64_t m_iHyprlandPID = 0; + wl_event_source* m_critSigSource = nullptr; + rlimit m_sOriginalNofile = {0}; }; inline std::unique_ptr g_pCompositor; diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 1b4876bb..2a1546c6 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -1,7 +1,11 @@ #pragma once -#include "helpers/Vector2D.hpp" +#include "helpers/math/Math.hpp" #include +#include +#include + +using namespace Hyprutils::Math; enum eIcons { ICON_WARNING = 0, @@ -37,29 +41,6 @@ struct SCallbackInfo { bool cancelled = false; /* on cancellable events, will cancel the event. */ }; -struct SWindowDecorationExtents { - Vector2D topLeft; - Vector2D bottomRight; - - // - SWindowDecorationExtents operator*(const double& scale) const { - return SWindowDecorationExtents{topLeft * scale, bottomRight * scale}; - } - - SWindowDecorationExtents round() { - return {topLeft.round(), bottomRight.round()}; - } - - bool operator==(const SWindowDecorationExtents& other) const { - return topLeft == other.topLeft && bottomRight == other.bottomRight; - } - - void addExtents(const SWindowDecorationExtents& other) { - topLeft = topLeft.getComponentMax(other.topLeft); - bottomRight = bottomRight.getComponentMax(other.bottomRight); - } -}; - enum eHyprCtlOutputFormat { FORMAT_NORMAL = 0, FORMAT_JSON diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c0ee1277..55e44754 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -982,7 +982,8 @@ float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& } Vector2D CConfigManager::getDeviceVec(const std::string& dev, const std::string& v, const std::string& fallback) { - return std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + auto vec = std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + return {vec.x, vec.y}; } std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v, const std::string& fallback) { @@ -1814,14 +1815,13 @@ std::optional CConfigManager::handleMonitor(const std::string& comm newrule.vrr = std::stoi(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "workspace") { - std::string name = ""; - int wsId = getWorkspaceIDFromString(ARGS[argno + 1], name); + const auto& [id, name] = getWorkspaceIDNameFromString(ARGS[argno + 1]); SWorkspaceRule wsRule; wsRule.monitor = newrule.name; wsRule.workspaceString = ARGS[argno + 1]; + wsRule.workspaceId = id; wsRule.workspaceName = name; - wsRule.workspaceId = wsId; m_dWorkspaceRules.emplace_back(wsRule); argno++; @@ -2369,11 +2369,11 @@ std::optional CConfigManager::handleBlurLS(const std::string& comma std::optional CConfigManager::handleWorkspaceRules(const std::string& command, const std::string& value) { // This can either be the monitor or the workspace identifier - const auto FIRST_DELIM = value.find_first_of(','); + const auto FIRST_DELIM = value.find_first_of(','); - std::string name = ""; - auto first_ident = trim(value.substr(0, FIRST_DELIM)); - int id = getWorkspaceIDFromString(first_ident, name); + auto first_ident = trim(value.substr(0, FIRST_DELIM)); + + const auto& [id, name] = getWorkspaceIDNameFromString(first_ident); auto rules = value.substr(FIRST_DELIM + 1); SWorkspaceRule wsRule; diff --git a/src/config/ConfigValue.hpp b/src/config/ConfigValue.hpp index 72accd67..fc8abb4b 100644 --- a/src/config/ConfigValue.hpp +++ b/src/config/ConfigValue.hpp @@ -11,7 +11,7 @@ template class CConfigValue { public: CConfigValue(const std::string& val) { - const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val.c_str()); + const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val); p_ = PVHYPRLANG->getDataStaticPtr(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 70b886f2..b0a0c477 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -209,6 +210,7 @@ static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "name": "{}" }}, "floating": {}, + "pseudo": {}, "monitor": {}, "class": "{}", "title": "{}", @@ -227,22 +229,22 @@ static std::string 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"), (int64_t)w->m_iMonitorID, - 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"), (w->m_bIsFullscreen ? "true" : "false"), - (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0), w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), - getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); + 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), + escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), + (w->m_bIsFullscreen ? "true" : "false"), (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0), + w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } else { - return std::format("Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " - "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " - "{}\n\txwayland: {}\n\tpinned: " - "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\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, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, - w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, - (w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), (int)w->m_bFakeFullscreenState, getGroupedData(w, format), - getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); + return std::format( + "Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " + "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " + "{}\n\txwayland: {}\n\tpinned: " + "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\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_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), + (int)w->m_bFakeFullscreenState, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } } @@ -1784,13 +1786,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) { std::array readBuffer; - fd_set fdset; - FD_ZERO(&fdset); - FD_SET(ACCEPTEDCONNECTION, &fdset); - timeval timeout = {.tv_sec = 0, .tv_usec = 5000}; - auto success = select(ACCEPTEDCONNECTION + 1, &fdset, nullptr, nullptr, &timeout); + // + pollfd pollfds[1] = { + { + .fd = ACCEPTEDCONNECTION, + .events = POLLIN, + }, + }; - if (success <= 0) { + int ret = poll(pollfds, 1, 5000); + + if (ret <= 0) { close(ACCEPTEDCONNECTION); return 0; } diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index aec3853e..3f8bb579 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -131,7 +131,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { textW /= PANGO_SCALE; textH /= PANGO_SCALE; - const auto NOTIFSIZE = Vector2D{textW + 20 + iconW + 2 * ICONPADFORNOTIF, textH + 10}; + const auto NOTIFSIZE = Vector2D{textW + 20.0 + iconW + 2 * ICONPADFORNOTIF, textH + 10.0}; // draw rects cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 64eeead1..9a891531 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -412,9 +412,9 @@ void CLayerSurface::startAnimation(bool in, bool instant) { } const std::array edgePoints = { - PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0}, + PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0.0}, PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y}, - PMONITOR->vecPosition + Vector2D{0, PMONITOR->vecSize.y}, + PMONITOR->vecPosition + Vector2D{0.0, PMONITOR->vecSize.y}, PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, }; diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index c7a09b40..97335d27 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -86,7 +86,7 @@ CRegion CWLSurface::logicalDamage() const { return {}; CRegion damage = m_pResource->accumulateCurrentBufferDamage(); - damage.transform(m_pResource->current.transform, m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); + damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); damage.scale(1.0 / m_pResource->current.scale); const auto VPSIZE = getViewporterCorrectedSize(); diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 4ba381a9..447f4582 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -1,7 +1,7 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" class CSubsurface; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index d153b344..e67a3357 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -104,7 +104,7 @@ CWindow::~CWindow() { std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return !other.first.lock() || other.first.lock().get() == this; }); } -SWindowDecorationExtents CWindow::getFullWindowExtents() { +SBoxExtents CWindow::getFullWindowExtents() { if (m_bFadingOut) return m_eOriginalClosedExtents; @@ -116,9 +116,9 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; } - SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; + SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; - const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock()); + const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock()); if (EXTENTS.topLeft.x > maxExtents.topLeft.x) maxExtents.topLeft.x = EXTENTS.topLeft.x; @@ -224,7 +224,7 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } - SWindowDecorationExtents EXTENTS = {{0, 0}, {0, 0}}; + SBoxExtents EXTENTS = {{0, 0}, {0, 0}}; if (properties & RESERVED_EXTENTS) EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock())); if (properties & INPUT_EXTENTS) @@ -242,7 +242,7 @@ CBox CWindow::getWindowMainSurfaceBox() { return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; } -SWindowDecorationExtents CWindow::getFullWindowReservedArea() { +SBoxExtents CWindow::getFullWindowReservedArea() { return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock()); } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 16bf297c..6bfdbc50 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -6,7 +6,7 @@ #include "../config/ConfigDataValues.hpp" #include "../defines.hpp" #include "../helpers/AnimatedVariable.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/TagKeeper.hpp" #include "../macros.hpp" @@ -62,18 +62,22 @@ class IWindowTransformer; template class CWindowOverridableVar { public: - CWindowOverridableVar(T val) { + CWindowOverridableVar(T const& val) { value = val; } ~CWindowOverridableVar() = default; - CWindowOverridableVar& operator=(CWindowOverridableVar other) { - if (locked) + CWindowOverridableVar& operator=(CWindowOverridableVar const& other) { + // Self-assignment check + if (this == &other) return *this; - locked = other.locked; - value = other.value; + // Check if the current object is locked + if (!locked) { + locked = other.locked; + value = other.value; + } return *this; } @@ -85,36 +89,36 @@ class CWindowOverridableVar { return other; } - void forceSetIgnoreLocked(T val, bool lock = false) { + void forceSetIgnoreLocked(T const& val, bool lock = false) { value = val; locked = lock; } - T operator*(T& other) { + T operator*(T const& other) { return value * other; } - T operator+(T& other) { + T operator+(T const& other) { return value + other; } - bool operator==(T& other) { + bool operator==(T const& other) { return other == value; } - bool operator>=(T& other) { + bool operator>=(T const& other) { return value >= other; } - bool operator<=(T& other) { + bool operator<=(T const& other) { return value <= other; } - bool operator>(T& other) { + bool operator>(T const& other) { return value > other; } - bool operator<(T& other) { + bool operator<(T const& other) { return value < other; } @@ -306,7 +310,7 @@ class CWindow { bool m_bReadyToDelete = false; Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in Vector2D m_vOriginalClosedSize; // drawing the closing animations - SWindowDecorationExtents m_eOriginalClosedExtents; + SBoxExtents m_eOriginalClosedExtents; bool m_bAnimatingIn = false; // For pinned (sticky) windows @@ -382,75 +386,75 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SWindowDecorationExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - CBox getWindowMainSurfaceBox(); - CBox getWindowIdealBoundingBoxIgnoreReserved(); - void addWindowDeco(std::unique_ptr deco); - void updateWindowDecos(); - void removeWindowDeco(IHyprWindowDecoration* deco); - void uncacheWindowDecos(); - bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); - pid_t getPID(); - IHyprWindowDecoration* getDecorationByType(eDecorationType); - void removeDecorationByType(eDecorationType); - void updateToplevel(); - void updateSurfaceScaleTransformDetails(bool force = false); - void moveToWorkspace(PHLWORKSPACE); - PHLWINDOW X11TransientFor(); - void onUnmap(); - void onMap(); - void setHidden(bool hidden); - bool isHidden(); - void applyDynamicRule(const SWindowRule& r); - void updateDynamicRules(); - SWindowDecorationExtents getFullWindowReservedArea(); - Vector2D middle(); - bool opaque(); - float rounding(); - bool canBeTorn(); - bool shouldSendFullscreenState(); - void setSuspended(bool suspend); - bool visibleOnMonitor(CMonitor* pMonitor); - int workspaceID(); - bool onSpecialWorkspace(); - void activate(bool force = false); - int surfacesCount(); + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); + CBox getWindowMainSurfaceBox(); + CBox getWindowIdealBoundingBoxIgnoreReserved(); + void addWindowDeco(std::unique_ptr deco); + void updateWindowDecos(); + void removeWindowDeco(IHyprWindowDecoration* deco); + void uncacheWindowDecos(); + bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); + pid_t getPID(); + IHyprWindowDecoration* getDecorationByType(eDecorationType); + void removeDecorationByType(eDecorationType); + void updateToplevel(); + void updateSurfaceScaleTransformDetails(bool force = false); + void moveToWorkspace(PHLWORKSPACE); + PHLWINDOW X11TransientFor(); + void onUnmap(); + void onMap(); + void setHidden(bool hidden); + bool isHidden(); + void applyDynamicRule(const SWindowRule& r); + void updateDynamicRules(); + SBoxExtents getFullWindowReservedArea(); + Vector2D middle(); + bool opaque(); + float rounding(); + bool canBeTorn(); + bool shouldSendFullscreenState(); + void setSuspended(bool suspend); + bool visibleOnMonitor(CMonitor* pMonitor); + int workspaceID(); + bool onSpecialWorkspace(); + void activate(bool force = false); + int surfacesCount(); - int getRealBorderSize(); - void updateSpecialRenderData(); - void updateSpecialRenderData(const struct SWorkspaceRule&); + int getRealBorderSize(); + void updateSpecialRenderData(); + void updateSpecialRenderData(const struct SWorkspaceRule&); - void onBorderAngleAnimEnd(void* ptr); - bool isInCurvedCorner(double x, double y); - bool hasPopupAt(const Vector2D& pos); - int popupsCount(); + void onBorderAngleAnimEnd(void* ptr); + bool isInCurvedCorner(double x, double y); + bool hasPopupAt(const Vector2D& pos); + int popupsCount(); - void applyGroupRules(); - void createGroup(); - void destroyGroup(); - PHLWINDOW getGroupHead(); - PHLWINDOW getGroupTail(); - PHLWINDOW getGroupCurrent(); - PHLWINDOW getGroupPrevious(); - PHLWINDOW getGroupWindowByIndex(int); - int getGroupSize(); - bool canBeGroupedInto(PHLWINDOW pWindow); - void setGroupCurrent(PHLWINDOW pWindow); - void insertWindowToGroup(PHLWINDOW pWindow); - void updateGroupOutputs(); - void switchWithWindowInGroup(PHLWINDOW pWindow); - void setAnimationsToMove(); - void onWorkspaceAnimUpdate(); - void onUpdateState(); - void onUpdateMeta(); - void onX11Configure(CBox box); - void onResourceChangeX11(); - std::string fetchTitle(); - std::string fetchClass(); - void warpCursor(); - PHLWINDOW getSwallower(); + void applyGroupRules(); + void createGroup(); + void destroyGroup(); + PHLWINDOW getGroupHead(); + PHLWINDOW getGroupTail(); + PHLWINDOW getGroupCurrent(); + PHLWINDOW getGroupPrevious(); + PHLWINDOW getGroupWindowByIndex(int); + int getGroupSize(); + bool canBeGroupedInto(PHLWINDOW pWindow); + void setGroupCurrent(PHLWINDOW pWindow); + void insertWindowToGroup(PHLWINDOW pWindow); + void updateGroupOutputs(); + void switchWithWindowInGroup(PHLWINDOW pWindow); + void setAnimationsToMove(); + void onWorkspaceAnimUpdate(); + void onUpdateState(); + void onUpdateMeta(); + void onX11Configure(CBox box); + void onResourceChangeX11(); + std::string fetchTitle(); + std::string fetchClass(); + void warpCursor(); + PHLWINDOW getSwallower(); // listeners void onAck(uint32_t serial); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index ed09fbc0..34db914e 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -57,6 +57,13 @@ void CWorkspace::init(PHLWORKSPACE self) { EMIT_HOOK_EVENT("createWorkspace", this); } +SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const { + if (perMonitor) + return m_sPrevWorkspacePerMonitor; + + return m_sPrevWorkspace; +} + CWorkspace::~CWorkspace() { m_vRenderOffset.unregister(); @@ -104,24 +111,24 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { if (ANIMSTYLE.starts_with("slidefadevert")) { if (in) { m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); + m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); m_fAlpha = 1.f; m_vRenderOffset = Vector2D(0, 0); } else { m_fAlpha.setValueAndWarp(1.f); m_fAlpha = 0.f; - m_vRenderOffset = Vector2D(0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); + m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); } } else { if (in) { m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0)); + m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0)); m_fAlpha = 1.f; m_vRenderOffset = Vector2D(0, 0); } else { m_fAlpha.setValueAndWarp(1.f); m_fAlpha = 0.f; - m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0); + m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0); } } } else if (ANIMSTYLE == "fade") { @@ -142,10 +149,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE)); + m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(0, left ? -YDISTANCE : YDISTANCE); + m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); } } else { // fallback is slide @@ -155,10 +162,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0)); + m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0); + m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); } } @@ -196,7 +203,7 @@ PHLWINDOW CWorkspace::getLastFocusedWindow() { void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { if (!prev) { - m_sPrevWorkspace.iID = -1; + m_sPrevWorkspace.id = -1; m_sPrevWorkspace.name = ""; return; } @@ -206,8 +213,13 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { return; } - m_sPrevWorkspace.iID = prev->m_iID; + m_sPrevWorkspace.id = prev->m_iID; m_sPrevWorkspace.name = prev->m_szName; + + if (prev->m_iMonitorID == m_iMonitorID) { + m_sPrevWorkspacePerMonitor.id = prev->m_iID; + m_sPrevWorkspacePerMonitor.name = prev->m_szName; + } } std::string CWorkspace::getConfigName() { @@ -228,9 +240,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { return true; if (isNumber(selector)) { - - std::string wsname = ""; - int wsid = getWorkspaceIDFromString(selector, wsname); + const auto& [wsid, wsname] = getWorkspaceIDNameFromString(selector); if (wsid == WORKSPACE_INVALID) return false; diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 17431215..ab3907aa 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -4,6 +4,7 @@ #include #include "../defines.hpp" #include "DesktopTypes.hpp" +#include "helpers/MiscFunctions.hpp" enum eFullscreenMode : int8_t { FULLSCREEN_INVALID = -1, @@ -25,17 +26,14 @@ class CWorkspace { int m_iID = -1; std::string m_szName = ""; uint64_t m_iMonitorID = -1; - // Previous workspace ID is stored during a workspace change, allowing travel + // Previous workspace ID and name is stored during a workspace change, allowing travel // to the previous workspace. - struct SPrevWorkspaceData { - int iID = -1; - std::string name = ""; - } m_sPrevWorkspace; + SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; - bool m_bHasFullscreenWindow = false; - eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; + bool m_bHasFullscreenWindow = false; + eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; - wl_array m_wlrCoordinateArr; + wl_array m_wlrCoordinateArr; // for animations CAnimatedVariable m_vRenderOffset; @@ -63,21 +61,23 @@ class CWorkspace { bool m_bPersistent = false; // Inert: destroyed and invalid. If this is true, release the ptr you have. - bool inert(); + bool inert(); - void startAnim(bool in, bool left, bool instant = false); - void setActive(bool on); + void startAnim(bool in, bool left, bool instant = false); + void setActive(bool on); - void moveToMonitor(const int&); + void moveToMonitor(const int&); - PHLWINDOW getLastFocusedWindow(); - void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); + PHLWINDOW getLastFocusedWindow(); + void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); - std::string getConfigName(); + std::string getConfigName(); - bool matchesStaticSelector(const std::string& selector); + bool matchesStaticSelector(const std::string& selector); - void markInert(); + void markInert(); + + SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const; private: void init(PHLWORKSPACE self); diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index ec58ff5b..b1757a18 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -3,7 +3,7 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index e2347c95..b2995b2f 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -3,7 +3,7 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" struct wlr_pointer; diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index 5929be02..b9cbf2ae 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -3,7 +3,7 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" struct wlr_touch; diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 1805f3ba..ada2cf89 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -3,8 +3,8 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" struct wlr_tablet; struct wlr_tablet_tool; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index d37ba12b..bb1197e5 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -293,8 +293,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (WORKSPACEARGS[WORKSPACEARGS.size() - 1].starts_with("silent")) workspaceSilent = true; - std::string requestedWorkspaceName; - const int REQUESTEDWORKSPACEID = getWorkspaceIDFromString(WORKSPACEARGS.join(" ", 0, workspaceSilent ? WORKSPACEARGS.size() - 1 : 0), requestedWorkspaceName); + const auto& [REQUESTEDWORKSPACEID, requestedWorkspaceName] = getWorkspaceIDNameFromString(WORKSPACEARGS.join(" ", 0, workspaceSilent ? WORKSPACEARGS.size() - 1 : 0)); if (REQUESTEDWORKSPACEID != WORKSPACE_INVALID) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 5c63032e..073cf65b 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "Vector2D.hpp" +#include "math/Math.hpp" #include "Color.hpp" #include "../defines.hpp" #include "../debug/Log.hpp" diff --git a/src/helpers/BezierCurve.hpp b/src/helpers/BezierCurve.hpp index fb11d52b..54af46a6 100644 --- a/src/helpers/BezierCurve.hpp +++ b/src/helpers/BezierCurve.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "Vector2D.hpp" +#include "math/Math.hpp" constexpr int BAKEDPOINTS = 255; constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS; diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp deleted file mode 100644 index 4b7f5726..00000000 --- a/src/helpers/Box.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "Box.hpp" - -#include -#include - -wlr_box CBox::wlr() { - CBox rounded = roundInternal(); - m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h}; - return m_bWlrBox; -} - -wlr_box* CBox::pWlr() { - CBox rounded = roundInternal(); - m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h}; - return &m_bWlrBox; -} - -CBox& CBox::scale(double scale) { - x *= scale; - y *= scale; - w *= scale; - h *= scale; - - return *this; -} - -CBox& CBox::scale(const Vector2D& scale) { - x *= scale.x; - y *= scale.y; - w *= scale.x; - h *= scale.y; - - return *this; -} - -CBox& CBox::translate(const Vector2D& vec) { - x += vec.x; - y += vec.y; - - return *this; -} - -Vector2D CBox::middle() const { - return Vector2D{x + w / 2.0, y + h / 2.0}; -} - -bool CBox::containsPoint(const Vector2D& vec) const { - return VECINRECT(vec, x, y, x + w, y + h); -} - -bool CBox::empty() const { - return w == 0 || h == 0; -} - -CBox& CBox::applyFromWlr() { - x = m_bWlrBox.x; - y = m_bWlrBox.y; - w = m_bWlrBox.width; - h = m_bWlrBox.height; - - return *this; -} - -CBox& CBox::round() { - float newW = x + w - std::round(x); - float newH = y + h - std::round(y); - x = std::round(x); - y = std::round(y); - w = std::round(newW); - h = std::round(newH); - - return *this; -} - -CBox& CBox::transform(const wl_output_transform t, double w, double h) { - wlr_box_transform(&m_bWlrBox, pWlr(), t, w, h); - applyFromWlr(); - - return *this; -} - -CBox& CBox::addExtents(const SWindowDecorationExtents& e) { - x -= e.topLeft.x; - y -= e.topLeft.y; - w += e.topLeft.x + e.bottomRight.x; - h += e.topLeft.y + e.bottomRight.y; - - return *this; -} - -CBox& CBox::scaleFromCenter(double scale) { - double oldW = w, oldH = h; - - w *= scale; - h *= scale; - - x -= (w - oldW) / 2.0; - y -= (h - oldH) / 2.0; - - return *this; -} - -CBox& CBox::expand(const double& value) { - x -= value; - y -= value; - w += value * 2.0; - h += value * 2.0; - - if (w <= 0 || h <= 0) { - w = 0; - h = 0; - } - - return *this; -} - -CBox& CBox::noNegativeSize() { - w = std::clamp(w, 0.0, std::numeric_limits::infinity()); - h = std::clamp(h, 0.0, std::numeric_limits::infinity()); - - return *this; -} - -CBox CBox::intersection(const CBox& other) const { - const float newX = std::max(x, other.x); - const float newY = std::max(y, other.y); - const float newBottom = std::min(y + h, other.y + other.h); - const float newRight = std::min(x + w, other.x + other.w); - float newW = newRight - newX; - float newH = newBottom - newY; - - if (newW <= 0 || newH <= 0) { - newW = 0; - newH = 0; - } - - return {newX, newY, newW, newH}; -} - -bool CBox::overlaps(const CBox& other) const { - return (other.x + other.w >= x) && (x + w >= other.x) && (other.y + other.h >= y) && (y + h >= other.y); -} - -bool CBox::inside(const CBox& bound) const { - return bound.x < x && bound.y < y && x + w < bound.x + bound.w && y + h < bound.y + bound.h; -} - -CBox CBox::roundInternal() { - float newW = x + w - std::floor(x); - float newH = y + h - std::floor(y); - - return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)}; -} - -CBox CBox::copy() const { - return CBox{*this}; -} - -Vector2D CBox::pos() const { - return {x, y}; -} - -Vector2D CBox::size() const { - return {w, h}; -} - -Vector2D CBox::closestPoint(const Vector2D& vec) const { - if (containsPoint(vec)) - return vec; - - Vector2D nv = vec; - nv.x = std::clamp(nv.x, x, x + w); - nv.y = std::clamp(nv.y, y, y + h); - return nv; -} - -SWindowDecorationExtents CBox::extentsFrom(const CBox& small) { - return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}}; -} diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp deleted file mode 100644 index 57df2154..00000000 --- a/src/helpers/Box.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include "Vector2D.hpp" -#include "../SharedDefs.hpp" -#include "../includes.hpp" - -class CBox { - public: - CBox(double x_, double y_, double w_, double h_) { - x = x_; - y = y_; - w = w_; - h = h_; - } - - CBox() { - w = 0; - h = 0; - } - - CBox(const wlr_box& box) { - x = box.x; - y = box.y; - w = box.width; - h = box.height; - } - - CBox(const double d) { - x = d; - y = d; - w = d; - h = d; - } - - CBox(const Vector2D& pos, const Vector2D& size) { - x = pos.x; - y = pos.y; - w = size.x; - h = size.y; - } - - wlr_box wlr(); - wlr_box* pWlr(); - - CBox& applyFromWlr(); - CBox& scale(double scale); - CBox& scaleFromCenter(double scale); - CBox& scale(const Vector2D& scale); - CBox& translate(const Vector2D& vec); - CBox& round(); - CBox& transform(const wl_output_transform t, double w, double h); - CBox& addExtents(const SWindowDecorationExtents& e); - CBox& expand(const double& value); - CBox& noNegativeSize(); - - CBox copy() const; - CBox intersection(const CBox& other) const; - bool overlaps(const CBox& other) const; - bool inside(const CBox& bound) const; - - SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box - - Vector2D middle() const; - Vector2D pos() const; - Vector2D size() const; - Vector2D closestPoint(const Vector2D& vec) const; - - bool containsPoint(const Vector2D& vec) const; - bool empty() const; - - double x = 0, y = 0; - union { - double w; - double width; - }; - union { - double h; - double height; - }; - - double rot = 0; /* rad, ccw */ - - // - bool operator==(const CBox& rhs) const { - return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; - } - - private: - CBox roundInternal(); - - wlr_box m_bWlrBox; -}; diff --git a/src/helpers/DamageRing.cpp b/src/helpers/DamageRing.cpp new file mode 100644 index 00000000..093e7ca6 --- /dev/null +++ b/src/helpers/DamageRing.cpp @@ -0,0 +1,52 @@ +#include "DamageRing.hpp" + +void CDamageRing::setSize(const Vector2D& size_) { + if (size_ == size) + return; + + size = size_; + + damageEntire(); +} + +bool CDamageRing::damage(const CRegion& rg) { + CRegion clipped = rg.copy().intersect(CBox{{}, size}); + if (clipped.empty()) + return false; + + current.add(clipped); + return true; +} + +void CDamageRing::damageEntire() { + damage(CBox{{}, size}); +} + +void CDamageRing::rotate() { + previousIdx = (previousIdx + DAMAGE_RING_PREVIOUS_LEN - 1) % DAMAGE_RING_PREVIOUS_LEN; + + previous[previousIdx] = current; + current.clear(); +} + +CRegion CDamageRing::getBufferDamage(int age) { + if (age <= 0 || age > DAMAGE_RING_PREVIOUS_LEN + 1) + return CBox{{}, size}; + + CRegion damage = current; + + for (int i = 0; i < age - 1; ++i) { + int j = (previousIdx + i) % DAMAGE_RING_PREVIOUS_LEN; + damage.add(previous.at(j)); + } + + // don't return a ludicrous amount of rects + if (damage.getRects().size() > 8) + return damage.getExtents(); + + return damage; +} + +bool CDamageRing::hasChanged() { + return !current.empty(); +} diff --git a/src/helpers/DamageRing.hpp b/src/helpers/DamageRing.hpp new file mode 100644 index 00000000..ae85c453 --- /dev/null +++ b/src/helpers/DamageRing.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "./math/Math.hpp" +#include + +constexpr static int DAMAGE_RING_PREVIOUS_LEN = 2; + +class CDamageRing { + public: + void setSize(const Vector2D& size_); + bool damage(const CRegion& rg); + void damageEntire(); + void rotate(); + CRegion getBufferDamage(int age); + bool hasChanged(); + + private: + Vector2D size; + CRegion current; + std::array previous; + size_t previousIdx = 0; +}; diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 08c3ca63..5251002c 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -2,6 +2,7 @@ #include #include "../includes.hpp" #include "debug/Log.hpp" +#include "../macros.hpp" /* DRM formats are LE, while OGL is BE. The two primary formats diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index b86f44dd..a1ef53f5 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "Vector2D.hpp" +#include "math/Math.hpp" typedef uint32_t DRMFormat; typedef uint32_t SHMFormat; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 821f3231..aa034254 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -214,37 +214,36 @@ bool isDirection(const char& arg) { return arg == 'l' || arg == 'r' || arg == 'u' || arg == 'd' || arg == 't' || arg == 'b'; } -int getWorkspaceIDFromString(const std::string& in, std::string& outName) { - int result = WORKSPACE_INVALID; +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + SWorkspaceIDName result = {WORKSPACE_INVALID, ""}; + if (in.starts_with("special")) { - outName = "special:special"; + result.name = "special:special"; if (in.length() > 8) { const auto NAME = in.substr(8); + const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME); - const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME); - - outName = "special:" + NAME; - - return WS ? WS->m_iID : g_pCompositor->getNewSpecialID(); + return {WS ? WS->m_iID : g_pCompositor->getNewSpecialID(), "special:" + NAME}; } - return SPECIAL_WORKSPACE_START; + result.id = SPECIAL_WORKSPACE_START; + return result; } else if (in.starts_with("name:")) { const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1); const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME); if (!WORKSPACE) { - result = g_pCompositor->getNextAvailableNamedWorkspace(); + result.id = g_pCompositor->getNextAvailableNamedWorkspace(); } else { - result = WORKSPACE->m_iID; + result.id = WORKSPACE->m_iID; } - outName = WORKSPACENAME; + result.name = WORKSPACENAME; } else if (in.starts_with("empty")) { const bool same_mon = in.substr(5).contains("m"); const bool next = in.substr(5).contains("n"); if ((same_mon || next) && !g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Empty monitor workspace on monitor null!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } std::set invalidWSes; @@ -259,41 +258,42 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; while (++id < INT_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); - if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) - return id; + if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { + result.id = id; + return result; + } } } else if (in.starts_with("prev")) { if (!g_pCompositor->m_pLastMonitor) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; const auto PWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; if (!valid(PWORKSPACE)) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.iID); + const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.id); if (!PLASTWORKSPACE) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - outName = PLASTWORKSPACE->m_szName; - return PLASTWORKSPACE->m_iID; + return {PLASTWORKSPACE->m_iID, PLASTWORKSPACE->m_szName}; } else { if (in[0] == 'r' && (in[1] == '-' || in[1] == '+' || in[1] == '~') && isNumber(in.substr(2))) { bool absolute = in[1] == '~'; if (!g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(absolute ? 2 : 1), 0); if (!PLUSMINUSRESULT.has_value()) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - result = (int)PLUSMINUSRESULT.value(); + result.id = (int)PLUSMINUSRESULT.value(); - int remains = (int)result; + int remains = (int)result.id; std::set invalidWSes; @@ -330,13 +330,13 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { // traverse valid workspaces until we reach the remains if ((size_t)remains < namedWSes.size()) { - result = namedWSes[remains]; + result.id = namedWSes[remains]; } else { remains -= namedWSes.size(); - result = 0; + result.id = 0; while (remains >= 0) { - result++; - if (!invalidWSes.contains(result)) { + result.id++; + if (!invalidWSes.contains(result.id)) { remains--; } } @@ -430,14 +430,14 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { finalWSID = curID; } } - result = finalWSID; + result.id = finalWSID; } - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(result); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(result.id); if (PWORKSPACE) - outName = g_pCompositor->getWorkspaceByID(result)->m_szName; + result.name = g_pCompositor->getWorkspaceByID(result.id)->m_szName; else - outName = std::to_string(result); + result.name = std::to_string(result.id); } else if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+' || in[1] == '~') && isNumber(in.substr(2))) { bool onAllMonitors = in[0] == 'e'; @@ -445,19 +445,19 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { if (!g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } // monitor relative const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(absolute ? 2 : 1), 0); if (!PLUSMINUSRESULT.has_value()) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - result = (int)PLUSMINUSRESULT.value(); + result.id = (int)PLUSMINUSRESULT.value(); // result now has +/- what we should move on mon - int remains = (int)result; + int remains = (int)result.id; std::vector validWSes; for (auto& ws : g_pCompositor->m_vWorkspaces) { @@ -505,30 +505,30 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { } } - result = validWSes[currentItem]; - outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName; + result.id = validWSes[currentItem]; + result.name = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName; } else { if (in[0] == '+' || in[0] == '-') { if (g_pCompositor->m_pLastMonitor) { const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspaceID()); if (!PLUSMINUSRESULT.has_value()) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - result = std::max((int)PLUSMINUSRESULT.value(), 1); + result.id = std::max((int)PLUSMINUSRESULT.value(), 1); } else { Debug::log(ERR, "Relative workspace on no mon!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } } else if (isNumber(in)) - result = std::max(std::stoi(in), 1); + result.id = std::max(std::stoi(in), 1); else { // maybe name const auto PWORKSPACE = g_pCompositor->getWorkspaceByName(in); if (PWORKSPACE) - result = PWORKSPACE->m_iID; + result.id = PWORKSPACE->m_iID; } - outName = std::to_string(result); + result.name = std::to_string(result.id); } } @@ -762,7 +762,7 @@ Vector2D configStringToVector2D(const std::string& VALUE) { if (std::getline(iss, token)) throw std::invalid_argument("Invalid string format"); - return Vector2D(x, y); + return Vector2D((double)x, (double)y); } double normalizeAngleRad(double ang) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index feb0380b..33be7965 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "Vector2D.hpp" +#include "math/Math.hpp" #include #include @@ -13,13 +13,18 @@ struct SCallstackFrameInfo { std::string desc; }; +struct SWorkspaceIDName { + int id = -1; + 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&); -int getWorkspaceIDFromString(const std::string&, std::string&); +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(); @@ -42,4 +47,4 @@ template // because any suck format specifier will cause a compilation error // this is actually what std::format in stdlib does return std::vformat(fmt.get(), std::make_format_args(args...)); -} \ No newline at end of file +} diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 58687e09..199b1c5d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -6,6 +6,7 @@ #include "../devices/ITouch.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" +#include "../managers/PointerManager.hpp" #include using namespace Hyprutils::String; @@ -16,12 +17,10 @@ int ratHandler(void* data) { } CMonitor::CMonitor() : state(this) { - wlr_damage_ring_init(&damage); + ; } CMonitor::~CMonitor() { - wlr_damage_ring_finish(&damage); - hyprListener_monitorDestroy.removeCallback(); hyprListener_monitorFrame.removeCallback(); hyprListener_monitorStateRequest.removeCallback(); @@ -161,7 +160,7 @@ void CMonitor::onConnect(bool noRule) { if (!state.commit()) Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit"); - wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y); + damage.setSize(vecTransformedSize); Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output); @@ -248,6 +247,9 @@ void CMonitor::onDisconnect(bool destroy) { // remove mirror if (pMirrorOf) { pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + + // unlock software for mirrored monitor + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); pMirrorOf = nullptr; } @@ -341,9 +343,9 @@ 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) { - wlr_damage_ring_add_whole(&damage); + damage.damageEntire(); g_pCompositor->scheduleFrameForMonitor(this); - } else if (wlr_damage_ring_add(&damage, rg)) + } else if (damage.damage(rg)) g_pCompositor->scheduleFrameForMonitor(this); } @@ -354,11 +356,11 @@ 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) { - wlr_damage_ring_add_whole(&damage); + damage.damageEntire(); g_pCompositor->scheduleFrameForMonitor(this); } - if (wlr_damage_ring_add_box(&damage, const_cast(box)->pWlr())) + if (damage.damage(*box)) g_pCompositor->scheduleFrameForMonitor(this); } @@ -373,7 +375,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { // keep requested minimum refresh rate if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { // damage whole screen because some previous cursor box damages were skipped - wlr_damage_ring_add_whole(&damage); + damage.damageEntire(); return false; } @@ -413,20 +415,25 @@ int CMonitor::findAvailableDefaultWS() { void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { // Workspace std::string newDefaultWorkspaceName = ""; - int64_t WORKSPACEID = g_pConfigManager->getDefaultWorkspaceFor(szName).empty() ? - findAvailableDefaultWS() : - getWorkspaceIDFromString(g_pConfigManager->getDefaultWorkspaceFor(szName), newDefaultWorkspaceName); + int64_t wsID = WORKSPACE_INVALID; + if (g_pConfigManager->getDefaultWorkspaceFor(szName).empty()) + wsID = findAvailableDefaultWS(); + else { + const auto ws = getWorkspaceIDNameFromString(g_pConfigManager->getDefaultWorkspaceFor(szName)); + wsID = ws.id; + newDefaultWorkspaceName = ws.name; + } - if (WORKSPACEID == WORKSPACE_INVALID || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) { - WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1; - newDefaultWorkspaceName = std::to_string(WORKSPACEID); + if (wsID == WORKSPACE_INVALID || (wsID >= SPECIAL_WORKSPACE_START && wsID <= -2)) { + wsID = g_pCompositor->m_vWorkspaces.size() + 1; + newDefaultWorkspaceName = std::to_string(wsID); Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"{}\" is invalid.", g_pConfigManager->getDefaultWorkspaceFor(szName)); } - auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); + auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(wsID); - Debug::log(LOG, "New monitor: WORKSPACEID {}, exists: {}", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr)); + Debug::log(LOG, "New monitor: WORKSPACEID {}, exists: {}", wsID, (int)(PNEWWORKSPACE != nullptr)); if (PNEWWORKSPACE) { // workspace exists, move it to the newly connected monitor @@ -436,9 +443,9 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { PNEWWORKSPACE->startAnim(true, true, true); } else { if (newDefaultWorkspaceName == "") - newDefaultWorkspaceName = std::to_string(WORKSPACEID); + newDefaultWorkspaceName = std::to_string(wsID); - PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(WORKSPACEID, ID, newDefaultWorkspaceName)); + PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(wsID, ID, newDefaultWorkspaceName)); } activeWorkspace = PNEWWORKSPACE; @@ -469,6 +476,9 @@ void CMonitor::setMirror(const std::string& mirrorOf) { if (pMirrorOf) { pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + + // unlock software for mirrored monitor + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); } pMirrorOf = nullptr; @@ -538,6 +548,9 @@ void CMonitor::setMirror(const std::string& mirrorOf) { g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get()); g_pCompositor->sanityCheckWorkspaces(); + + // Software lock mirrored monitor + g_pPointerManager->lockSoftwareForMonitor(PMIRRORMON); } events.modeChanged.emit(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index c59e00ac..8a2acdaf 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -8,9 +8,10 @@ #include #include #include "Timer.hpp" -#include "Region.hpp" +#include "math/Math.hpp" #include #include "signal/Signal.hpp" +#include "DamageRing.hpp" // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs { @@ -60,33 +61,32 @@ class CMonitor { CMonitor(); ~CMonitor(); - Vector2D vecPosition = Vector2D(-1, -1); // means unset - Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset - Vector2D vecSize = Vector2D(0, 0); - Vector2D vecPixelSize = Vector2D(0, 0); - Vector2D vecTransformedSize = Vector2D(0, 0); + Vector2D vecPosition = Vector2D(-1, -1); // means unset + Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset + Vector2D vecSize = Vector2D(0, 0); + Vector2D vecPixelSize = Vector2D(0, 0); + Vector2D vecTransformedSize = Vector2D(0, 0); - bool primary = false; + bool primary = false; - uint64_t ID = -1; - PHLWORKSPACE activeWorkspace = nullptr; - PHLWORKSPACE activeSpecialWorkspace = nullptr; - float setScale = 1; // scale set by cfg - float scale = 1; // real scale + uint64_t ID = -1; + PHLWORKSPACE activeWorkspace = nullptr; + PHLWORKSPACE activeSpecialWorkspace = nullptr; + float setScale = 1; // scale set by cfg + float scale = 1; // real scale - std::string szName = ""; - std::string szDescription = ""; - std::string szShortDescription = ""; + std::string szName = ""; + std::string szDescription = ""; + std::string szShortDescription = ""; - Vector2D vecReservedTopLeft = Vector2D(0, 0); - Vector2D vecReservedBottomRight = Vector2D(0, 0); + Vector2D vecReservedTopLeft = Vector2D(0, 0); + Vector2D vecReservedBottomRight = Vector2D(0, 0); - drmModeModeInfo customDrmMode = {}; + drmModeModeInfo customDrmMode = {}; - CMonitorState state; + CMonitorState state; + CDamageRing damage; - // WLR stuff - wlr_damage_ring damage; wlr_output* output = nullptr; float refreshRate = 60; int framesToSkip = 0; diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp deleted file mode 100644 index 9e572b34..00000000 --- a/src/helpers/Region.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "Region.hpp" -extern "C" { -#include -#include -} - -constexpr const int64_t MAX_REGION_SIDE = 10000000; - -CRegion::CRegion() { - pixman_region32_init(&m_rRegion); -} - -CRegion::CRegion(const pixman_region32_t* const ref) { - pixman_region32_init(&m_rRegion); - pixman_region32_copy(&m_rRegion, ref); -} - -CRegion::CRegion(double x, double y, double w, double h) { - pixman_region32_init_rect(&m_rRegion, x, y, w, h); -} - -CRegion::CRegion(wlr_box* box) { - pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height); -} - -CRegion::CRegion(const CBox& box) { - pixman_region32_init_rect(&m_rRegion, box.x, box.y, box.w, box.h); -} - -CRegion::CRegion(pixman_box32_t* box) { - pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); -} - -CRegion::CRegion(const CRegion& other) { - pixman_region32_init(&m_rRegion); - pixman_region32_copy(&m_rRegion, const_cast(&other)->pixman()); -} - -CRegion::CRegion(CRegion&& other) { - pixman_region32_init(&m_rRegion); - pixman_region32_copy(&m_rRegion, other.pixman()); -} - -CRegion::~CRegion() { - pixman_region32_fini(&m_rRegion); -} - -CRegion& CRegion::clear() { - pixman_region32_clear(&m_rRegion); - return *this; -} - -CRegion& CRegion::set(const CRegion& other) { - pixman_region32_copy(&m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::add(const CRegion& other) { - pixman_region32_union(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::add(double x, double y, double w, double h) { - pixman_region32_union_rect(&m_rRegion, &m_rRegion, x, y, w, h); - return *this; -} - -CRegion& CRegion::add(const CBox& other) { - pixman_region32_union_rect(&m_rRegion, &m_rRegion, other.x, other.y, other.w, other.h); - return *this; -} - -CRegion& CRegion::subtract(const CRegion& other) { - pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::intersect(const CRegion& other) { - pixman_region32_intersect(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::intersect(double x, double y, double w, double h) { - pixman_region32_intersect_rect(&m_rRegion, &m_rRegion, x, y, w, h); - return *this; -} - -CRegion& CRegion::invert(pixman_box32_t* box) { - pixman_region32_inverse(&m_rRegion, &m_rRegion, box); - return *this; -} - -CRegion& CRegion::invert(const CBox& box) { - pixman_box32 pixmanBox = {box.x, box.y, box.w + box.x, box.h + box.y}; - return this->invert(&pixmanBox); -} - -CRegion& CRegion::translate(const Vector2D& vec) { - pixman_region32_translate(&m_rRegion, vec.x, vec.y); - return *this; -} - -CRegion& CRegion::transform(const wl_output_transform t, double w, double h) { - wlr_region_transform(&m_rRegion, &m_rRegion, t, w, h); - return *this; -} - -CRegion& CRegion::rationalize() { - intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2}); - return *this; -} - -CRegion CRegion::copy() const { - return CRegion(*this); -} - -CRegion& CRegion::scale(float scale) { - wlr_region_scale(&m_rRegion, &m_rRegion, scale); - return *this; -} - -CRegion& CRegion::scale(const Vector2D& scale) { - wlr_region_scale_xy(&m_rRegion, &m_rRegion, scale.x, scale.y); - return *this; -} - -std::vector CRegion::getRects() const { - std::vector result; - - int rectsNum = 0; - const auto RECTSARR = pixman_region32_rectangles(&m_rRegion, &rectsNum); - - result.assign(RECTSARR, RECTSARR + rectsNum); - - return result; -} - -CBox CRegion::getExtents() { - pixman_box32_t* box = pixman_region32_extents(&m_rRegion); - return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1}; -} - -bool CRegion::containsPoint(const Vector2D& vec) const { - return pixman_region32_contains_point(&m_rRegion, vec.x, vec.y, nullptr); -} - -bool CRegion::empty() const { - return !pixman_region32_not_empty(&m_rRegion); -} - -Vector2D CRegion::closestPoint(const Vector2D& vec) const { - if (containsPoint(vec)) - return vec; - - double bestDist = __FLT_MAX__; - Vector2D leader = vec; - - for (auto& box : getRects()) { - double x = 0, y = 0; - - if (vec.x >= box.x2) - x = box.x2 - 1; - else if (vec.x < box.x1) - x = box.x1; - else - x = vec.x; - - if (vec.y >= box.y2) - y = box.y2 - 1; - else if (vec.y < box.y1) - y = box.y1; - else - y = vec.y; - - double distance = pow(x, 2) + pow(y, 2); - if (distance < bestDist) { - bestDist = distance; - leader = {x, y}; - } - } - - return leader; -} \ No newline at end of file diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp deleted file mode 100644 index 42693c21..00000000 --- a/src/helpers/Region.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include -#include -#include "Vector2D.hpp" -#include "Box.hpp" - -struct wlr_box; - -class CRegion { - public: - /* Create an empty region */ - CRegion(); - /* Create from a reference. Copies, does not own. */ - CRegion(const pixman_region32_t* const ref); - /* Create from a box */ - CRegion(double x, double y, double w, double h); - /* Create from a wlr_box */ - CRegion(wlr_box* box); - /* Create from a CBox */ - CRegion(const CBox& box); - /* Create from a pixman_box32_t */ - CRegion(pixman_box32_t* box); - - CRegion(const CRegion&); - CRegion(CRegion&&); - - ~CRegion(); - - CRegion& operator=(CRegion&& other) { - pixman_region32_copy(&m_rRegion, other.pixman()); - return *this; - } - - CRegion& operator=(CRegion& other) { - pixman_region32_copy(&m_rRegion, other.pixman()); - return *this; - } - - CRegion& clear(); - CRegion& set(const CRegion& other); - CRegion& add(const CRegion& other); - CRegion& add(double x, double y, double w, double h); - CRegion& add(const CBox& other); - CRegion& subtract(const CRegion& other); - CRegion& intersect(const CRegion& other); - CRegion& intersect(double x, double y, double w, double h); - CRegion& translate(const Vector2D& vec); - CRegion& transform(const wl_output_transform t, double w, double h); - CRegion& invert(pixman_box32_t* box); - CRegion& invert(const CBox& box); - CRegion& scale(float scale); - CRegion& scale(const Vector2D& scale); - CRegion& rationalize(); - CBox getExtents(); - bool containsPoint(const Vector2D& vec) const; - bool empty() const; - Vector2D closestPoint(const Vector2D& vec) const; - CRegion copy() const; - - std::vector getRects() const; - - // - pixman_region32_t* pixman() { - return &m_rRegion; - } - - private: - pixman_region32_t m_rRegion; -}; diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp deleted file mode 100644 index 6f96d686..00000000 --- a/src/helpers/Vector2D.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "Vector2D.hpp" -#include -#include - -Vector2D::Vector2D(double xx, double yy) { - x = xx; - y = yy; -} - -Vector2D::Vector2D() { - x = 0; - y = 0; -} - -Vector2D::Vector2D(const Hyprlang::VEC2& ref) { - x = ref.x; - y = ref.y; -} - -Vector2D::~Vector2D() {} - -double Vector2D::normalize() { - // get max abs - const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y); - - x /= max; - y /= max; - - return max; -} - -Vector2D Vector2D::floor() const { - return Vector2D(std::floor(x), std::floor(y)); -} - -Vector2D Vector2D::round() const { - return Vector2D(std::round(x), std::round(y)); -} - -Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) const { - return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y)); -} - -double Vector2D::distance(const Vector2D& other) const { - return std::sqrt(distanceSq(other)); -} - -double Vector2D::distanceSq(const Vector2D& other) const { - return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y); -} - -double Vector2D::size() const { - return std::sqrt(x * x + y * y); -} - -Vector2D Vector2D::getComponentMax(const Vector2D& other) const { - return Vector2D(std::max(this->x, other.x), std::max(this->y, other.y)); -} diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp deleted file mode 100644 index 0f1440c3..00000000 --- a/src/helpers/Vector2D.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include -#include -#include "../macros.hpp" -#include - -class Vector2D { - public: - Vector2D(double, double); - Vector2D(); - ~Vector2D(); - Vector2D(const Hyprlang::VEC2&); - - double x = 0; - double y = 0; - - // returns the scale - double normalize(); - - Vector2D operator+(const Vector2D& a) const { - return Vector2D(this->x + a.x, this->y + a.y); - } - Vector2D operator-(const Vector2D& a) const { - return Vector2D(this->x - a.x, this->y - a.y); - } - Vector2D operator-() const { - return Vector2D(-this->x, -this->y); - } - Vector2D operator*(const double& a) const { - return Vector2D(this->x * a, this->y * a); - } - Vector2D operator/(const double& a) const { - return Vector2D(this->x / a, this->y / a); - } - - bool operator==(const Vector2D& a) const { - return a.x == x && a.y == y; - } - - bool operator!=(const Vector2D& a) const { - return a.x != x || a.y != y; - } - - Vector2D operator*(const Vector2D& a) const { - return Vector2D(this->x * a.x, this->y * a.y); - } - - Vector2D operator/(const Vector2D& a) const { - return Vector2D(this->x / a.x, this->y / a.y); - } - - bool operator>(const Vector2D& a) const { - return this->x > a.x && this->y > a.y; - } - - bool operator<(const Vector2D& a) const { - return this->x < a.x && this->y < a.y; - } - Vector2D& operator+=(const Vector2D& a) { - this->x += a.x; - this->y += a.y; - return *this; - } - Vector2D& operator-=(const Vector2D& a) { - this->x -= a.x; - this->y -= a.y; - return *this; - } - Vector2D& operator*=(const Vector2D& a) { - this->x *= a.x; - this->y *= a.y; - return *this; - } - Vector2D& operator/=(const Vector2D& a) { - this->x /= a.x; - this->y /= a.y; - return *this; - } - Vector2D& operator*=(const double& a) { - this->x *= a; - this->y *= a; - return *this; - } - Vector2D& operator/=(const double& a) { - this->x /= a; - this->y /= a; - return *this; - } - - double distance(const Vector2D& other) const; - double distanceSq(const Vector2D& other) const; - double size() const; - Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const; - - Vector2D floor() const; - Vector2D round() const; - - Vector2D getComponentMax(const Vector2D& other) const; -}; - -/** - format specification - - 'j', as json array - - 'X', same as std::format("{}x{}", vec.x, vec.y) - - number, floating point precision, use `0` to format as integer -*/ -template -struct std::formatter : std::formatter { - bool formatJson = false; - bool formatX = false; - std::string precision = ""; - FORMAT_PARSE(FORMAT_FLAG('j', formatJson) // - FORMAT_FLAG('X', formatX) // - FORMAT_NUMBER(precision), - Vector2D) - - template - auto format(const Vector2D& vec, FormatContext& ctx) const { - std::string formatString = precision.empty() ? "{}" : std::format("{{:.{}f}}", precision); - - if (formatJson) - formatString = std::format("[{0}, {0}]", formatString); - else if (formatX) - formatString = std::format("{0}x{0}", formatString); - else - formatString = std::format("[Vector2D: x: {0}, y: {0}]", formatString); - try { - string buf = std::vformat(formatString, std::make_format_args(vec.x, vec.y)); - return std::format_to(ctx.out(), "{}", buf); - } catch (std::format_error& e) { return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y); } - } -}; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 247aa8f0..6b25e76d 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -8,7 +8,7 @@ #include "AnimatedVariable.hpp" #include "../desktop/WLSurface.hpp" #include "signal/Signal.hpp" -#include "Region.hpp" +#include "math/Math.hpp" class CMonitor; class IPointer; @@ -51,6 +51,9 @@ struct SRenderData { PHLWINDOW pWindow; bool popup = false; + + // counts how many surfaces this pass has rendered + int surfaceCounter = 0; }; struct SSwipeGesture { diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp index 978ff034..2ea5c0b6 100644 --- a/src/helpers/WLListener.cpp +++ b/src/helpers/WLListener.cpp @@ -18,7 +18,7 @@ void handleWrapped(wl_listener* listener, void* data) { g_pWatchdog->endWatching(); } -CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function callback, void* pOwner) { +CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function const& callback, void* pOwner) { initCallback(pSignal, callback, pOwner); } @@ -44,7 +44,7 @@ bool CHyprWLListener::isConnected() { return !wl_list_empty(&m_swWrapper.m_sListener.link); } -void CHyprWLListener::initCallback(wl_signal* pSignal, std::function callback, void* pOwner, std::string author) { +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; diff --git a/src/helpers/WLListener.hpp b/src/helpers/WLListener.hpp index d5d925b0..621458e6 100644 --- a/src/helpers/WLListener.hpp +++ b/src/helpers/WLListener.hpp @@ -6,7 +6,7 @@ class CHyprWLListener { public: - CHyprWLListener(wl_signal*, std::function, void* owner); + CHyprWLListener(wl_signal*, std::function const&, void* owner); CHyprWLListener(); ~CHyprWLListener(); @@ -15,7 +15,7 @@ class CHyprWLListener { CHyprWLListener& operator=(const CHyprWLListener&) = delete; CHyprWLListener& operator=(CHyprWLListener&&) = delete; - void initCallback(wl_signal*, std::function, void* owner, std::string author = ""); + void initCallback(wl_signal*, std::function const&, void* owner, std::string author = ""); void removeCallback(); diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp new file mode 100644 index 00000000..560f29c9 --- /dev/null +++ b/src/helpers/math/Math.cpp @@ -0,0 +1,221 @@ +#include "Math.hpp" +#include +#include + +Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { + switch (t) { + case WL_OUTPUT_TRANSFORM_NORMAL: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; + case WL_OUTPUT_TRANSFORM_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_180; + case WL_OUTPUT_TRANSFORM_90: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_90; + case WL_OUTPUT_TRANSFORM_270: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_270; + case WL_OUTPUT_TRANSFORM_FLIPPED: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_180; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_270; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_90; + default: break; + } + return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; +} + +static 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)); +} + +static 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)); +} + +static 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)); +} + +static 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); +} + +static 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); +} + +static 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); +} + +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, + }}, +}; + +static void matrixTransform(float mat[9], eTransform transform) { + matrixMultiply(mat, mat, transforms.at(transform).data()); +} + +static void matrixProjection(float mat[9], int width, int height, eTransform transform) { + memset(mat, 0, sizeof(*mat) * 9); + + const float* t = transforms.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); +} diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp new file mode 100644 index 00000000..4aa65c93 --- /dev/null +++ b/src/helpers/math/Math.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +// includes box and vector as well +#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]); diff --git a/src/includes.hpp b/src/includes.hpp index dbae7635..afec078a 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -53,7 +53,6 @@ extern "C" { #include #include #include -#include #include #include #include @@ -110,6 +109,4 @@ extern "C" { #define XWAYLAND true #endif -#include "helpers/Vector2D.hpp" -#include "helpers/Box.hpp" #include "SharedDefs.hpp" diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 172a157b..cbeaa420 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -180,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; - const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top); + const auto OFFSETTOPLEFT = Vector2D((double)(DISPLAYLEFT ? gapsOut.left : gapsIn.left), (double)(DISPLAYTOP ? gapsOut.top : gapsIn.top)); - const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom); + const auto OFFSETBOTTOMRIGHT = Vector2D((double)(DISPLAYRIGHT ? gapsOut.right : gapsIn.right), (double)(DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom)); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; @@ -912,11 +912,11 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, switch (dir[0]) { case 't': - case 'u': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.f, -1}; break; + case 'u': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.0, -1.0}; break; case 'd': - case 'b': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.f, pWindow->m_vSize.y + 1}; break; - case 'l': focalPoint = pWindow->m_vPosition + Vector2D{-1, pWindow->m_vSize.y / 2.f}; break; - case 'r': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x + 1, pWindow->m_vSize.y / 2.f}; break; + case 'b': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.0, pWindow->m_vSize.y + 1.0}; break; + case 'l': focalPoint = pWindow->m_vPosition + Vector2D{-1.0, pWindow->m_vSize.y / 2.0}; break; + case 'r': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x + 1.0, pWindow->m_vSize.y / 2.0}; break; default: UNREACHABLE(); } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index b4270bb8..c6a7a66c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -428,9 +428,9 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (m_eGrabbedCorner == CORNER_TOPLEFT) newPos = newPos - newSize + m_vBeginDragSizeXY; else if (m_eGrabbedCorner == CORNER_TOPRIGHT) - newPos = newPos + Vector2D(0, (m_vBeginDragSizeXY - newSize).y); + newPos = newPos + Vector2D(0.0, (m_vBeginDragSizeXY - newSize).y); else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) - newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0); + newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0.0); CBox wb = {newPos, newSize}; wb.round(); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index c5784c74..965c0ed7 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -689,9 +689,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; - const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top); + const auto OFFSETTOPLEFT = Vector2D((double)(DISPLAYLEFT ? gapsOut.left : gapsIn.left), (double)(DISPLAYTOP ? gapsOut.top : gapsIn.top)); - const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom); + const auto OFFSETBOTTOMRIGHT = Vector2D((double)(DISPLAYRIGHT ? gapsOut.right : gapsIn.right), (double)(DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom)); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; diff --git a/src/macros.hpp b/src/macros.hpp index cca088d8..67f6301b 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -24,7 +24,8 @@ #define STRVAL_EMPTY "[[EMPTY]]" -#define WORKSPACE_INVALID -1L +#define WORKSPACE_INVALID -1L +#define WORKSPACE_NOT_CHANGED -101 #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ @@ -98,3 +99,10 @@ ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })(), err); \ } \ } + +#define HYPRUTILS_FORWARD(ns, name) \ + namespace Hyprutils { \ + namespace ns { \ + class name; \ + } \ + } diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 74fe4117..9d6668c9 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -25,7 +25,7 @@ int wlTick(SP self, void* data) { } CAnimationManager::CAnimationManager() { - std::vector points = {Vector2D(0, 0.75f), Vector2D(0.15f, 1.f)}; + std::vector points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; m_mBezierCurves["default"].setup(&points); m_pAnimationTimer = SP(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr)); @@ -36,7 +36,7 @@ void CAnimationManager::removeAllBeziers() { m_mBezierCurves.clear(); // add the default one - std::vector points = {Vector2D(0, 0.75f), Vector2D(0.15f, 1.f)}; + std::vector points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; m_mBezierCurves["default"].setup(&points); } @@ -336,9 +336,9 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y); else if (force == "left") - posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); else if (force == "right") - posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y); @@ -360,16 +360,16 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo if (DISPLAYBOTTOM && DISPLAYTOP) { if (DISPLAYLEFT && DISPLAYRIGHT) { - posOffset = GOALPOS + Vector2D(0, GOALSIZE.y); + posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); } else if (DISPLAYLEFT) { - posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); } else { - posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); } } else if (DISPLAYTOP) { - posOffset = GOALPOS - Vector2D(0, GOALSIZE.y); + posOffset = GOALPOS - Vector2D(0.0, GOALSIZE.y); } else if (DISPLAYBOTTOM) { - posOffset = GOALPOS + Vector2D(0, GOALSIZE.y); + posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); } else { if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f) posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y); diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 4430d0f4..daa4f4be 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -149,9 +149,10 @@ void CCursorManager::setXCursor(const std::string& name) { auto image = xcursor->images[0]; - m_vCursorBuffers.emplace_back(std::make_unique(image->buffer, Vector2D{image->width, image->height}, Vector2D{image->hotspot_x, image->hotspot_y})); + m_vCursorBuffers.emplace_back( + std::make_unique(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{image->hotspot_x, image->hotspot_y} / scale, scale); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale); if (m_vCursorBuffers.size() > 1) wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); @@ -256,8 +257,8 @@ void CCursorManager::setXWaylandCursor() { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); } else if (const auto XCURSOR = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left_ptr", 1); XCURSOR) { - g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {XCURSOR->images[0]->width, XCURSOR->images[0]->height}, - {XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y}); + g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {(int)XCURSOR->images[0]->width, (int)XCURSOR->images[0]->height}, + {(double)XCURSOR->images[0]->hotspot_x, (double)XCURSOR->images[0]->hotspot_y}); } else Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 6fbff636..3ee98ca6 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -4,7 +4,8 @@ #include #include #include "../includes.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/memory/Memory.hpp" struct wlr_buffer; struct wlr_xcursor_manager; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 14fadf02..bfcea3da 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -5,6 +5,7 @@ #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "KeybindManager.hpp" +#include "Compositor.hpp" #include "TokenManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" @@ -636,6 +637,12 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi if (found || key.submapAtPress != m_szCurrentSelectedSubmap) continue; } else { + // in this case, we only have the keysym to go off. + // if the keysym failed resolving, we can't do anything. It's likely missing + // from the keymap. + if (key.keysym == 0) + return false; + // 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); @@ -884,6 +891,7 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { } if (child == 0) { // run in child + g_pCompositor->restoreNofile(); sigset_t set; sigemptyset(&set); @@ -1010,21 +1018,42 @@ void CKeybindManager::centerWindow(std::string args) { } void CKeybindManager::toggleActivePseudo(std::string args) { - const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow.lock(); + PHLWINDOW PWINDOW = nullptr; - if (!ACTIVEWINDOW) + if (args != "active" && args.length() > 1) + PWINDOW = g_pCompositor->getWindowByRegex(args); + else + PWINDOW = g_pCompositor->m_pLastWindow.lock(); + + if (!PWINDOW) return; - ACTIVEWINDOW->m_bIsPseudotiled = !ACTIVEWINDOW->m_bIsPseudotiled; + PWINDOW->m_bIsPseudotiled = !PWINDOW->m_bIsPseudotiled; - if (!ACTIVEWINDOW->m_bIsFullscreen) - g_pLayoutManager->getCurrentLayout()->recalculateWindow(ACTIVEWINDOW); + if (!PWINDOW->m_bIsFullscreen) + g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); +} + +SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE) { + if (!args.starts_with("previous")) { + return getWorkspaceIDNameFromString(args); + } + + const SWorkspaceIDName PPREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); + // Do nothing if there's no previous workspace, otherwise switch to it. + if (PPREVWS.id == -1) { + Debug::log(LOG, "No previous workspace to change to"); + return {WORKSPACE_NOT_CHANGED, ""}; + } + + const auto ID = PCURRENTWORKSPACE->m_iID; + if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) + return {ID, PWORKSPACETOCHANGETO->m_szName}; + + return {ID, PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; } void CKeybindManager::changeworkspace(std::string args) { - int workspaceToChangeTo = 0; - std::string workspaceName = ""; - // Workspace_back_and_forth being enabled means that an attempt to switch to // the current workspace will instead switch to the previous. static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); @@ -1037,43 +1066,31 @@ void CKeybindManager::changeworkspace(std::string args) { return; const auto PCURRENTWORKSPACE = PMONITOR->activeWorkspace; - const bool EXPLICITPREVIOUS = args.starts_with("previous"); - - if (args.starts_with("previous")) { - // Do nothing if there's no previous workspace, otherwise switch to it. - if (PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1) { - Debug::log(LOG, "No previous workspace to change to"); - return; - } else { - workspaceToChangeTo = PCURRENTWORKSPACE->m_iID; - - if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PCURRENTWORKSPACE->m_sPrevWorkspace.iID); PWORKSPACETOCHANGETO) - workspaceName = PWORKSPACETOCHANGETO->m_szName; - else - workspaceName = - PCURRENTWORKSPACE->m_sPrevWorkspace.name.empty() ? std::to_string(PCURRENTWORKSPACE->m_sPrevWorkspace.iID) : PCURRENTWORKSPACE->m_sPrevWorkspace.name; - } - } else { - workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName); - } + const bool EXPLICITPREVIOUS = args.contains("previous"); + const auto& [workspaceToChangeTo, workspaceName] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE); if (workspaceToChangeTo == WORKSPACE_INVALID) { Debug::log(ERR, "Error in changeworkspace, invalid value"); return; } - const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; + if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) { + return; + } - if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1)) + const auto PREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); + + const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; + if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PREVWS.id == -1)) return; g_pInputManager->unconstrainMouse(); g_pInputManager->m_bEmptyFocusCursorSet = false; - auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.iID : workspaceToChangeTo); + auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PREVWS.id : workspaceToChangeTo); if (!pWorkspaceToChangeTo) - pWorkspaceToChangeTo = g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.iID : workspaceToChangeTo, PMONITOR->ID, - BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.name : workspaceName); + pWorkspaceToChangeTo = + g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PREVWS.id : workspaceToChangeTo, PMONITOR->ID, BISWORKSPACECURRENT ? PREVWS.name : workspaceName); if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_bIsSpecialWorkspace) { PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo); @@ -1156,10 +1173,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { if (!PWINDOW) return; - // hack - std::string workspaceName; - const auto WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); - + const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args); if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace"); return; @@ -1220,10 +1234,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { if (!PWINDOW) return; - std::string workspaceName = ""; - - const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); - + const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args); if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "Error in moveActiveToWorkspaceSilent, invalid value"); return; @@ -1689,8 +1700,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { return; } - std::string workspaceName; - const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName); + const int WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); @@ -1708,9 +1718,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { } void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { - std::string workspaceName; - int workspaceID = getWorkspaceIDFromString(args, workspaceName); - + int workspaceID = getWorkspaceIDNameFromString(args).id; if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); return; @@ -1733,14 +1741,13 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { } static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); + const auto PREVWS = pWorkspace->getPrevWorkspaceIDName(false); - if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && pWorkspace->m_sPrevWorkspace.iID != -1) { - const int PREVWORKSPACEID = pWorkspace->m_sPrevWorkspace.iID; - const auto PREVWORKSPACENAME = pWorkspace->m_sPrevWorkspace.name; + if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) { // Workspace to focus is previous workspace - pWorkspace = g_pCompositor->getWorkspaceByID(PREVWORKSPACEID); + pWorkspace = g_pCompositor->getWorkspaceByID(PREVWS.id); if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(PREVWORKSPACEID, PCURRMONITOR->ID, PREVWORKSPACENAME); + pWorkspace = g_pCompositor->createNewWorkspace(PREVWS.id, PCURRMONITOR->ID, PREVWS.name); workspaceID = pWorkspace->m_iID; } @@ -1763,9 +1770,7 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { } void CKeybindManager::toggleSpecialWorkspace(std::string args) { - std::string workspaceName = ""; - int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName); - + const auto& [workspaceID, workspaceName] = getWorkspaceIDNameFromString("special:" + args); if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { Debug::log(ERR, "Invalid workspace passed to special"); return; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 1c98bbe0..973b7e27 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -164,6 +164,15 @@ void CPointerManager::unlockSoftwareAll() { updateCursorBackend(); } +void CPointerManager::lockSoftwareForMonitor(CMonitor* Monitor) { + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->ID == Monitor->ID) { + lockSoftwareForMonitor(m); + return; + } + } +} + void CPointerManager::lockSoftwareForMonitor(SP mon) { auto state = stateFor(mon); state->softwareLocks++; @@ -172,6 +181,15 @@ void CPointerManager::lockSoftwareForMonitor(SP mon) { updateCursorBackend(); } +void CPointerManager::unlockSoftwareForMonitor(CMonitor* Monitor) { + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->ID == Monitor->ID) { + unlockSoftwareForMonitor(m); + return; + } + } +} + void CPointerManager::unlockSoftwareForMonitor(SP mon) { auto state = stateFor(mon); state->softwareLocks--; @@ -577,7 +595,7 @@ Vector2D CPointerManager::transformedHotspot(SP pMonitor) { return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}} - .transform(wlr_output_transform_invert(pMonitor->transform), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height) + .transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height) .pos(); } diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 1e386797..545b76fb 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -3,8 +3,8 @@ #include "../devices/IPointer.hpp" #include "../devices/ITouch.hpp" #include "../devices/Tablet.hpp" -#include "../helpers/Box.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" #include @@ -43,6 +43,8 @@ class CPointerManager { void lockSoftwareForMonitor(SP pMonitor); void unlockSoftwareForMonitor(SP pMonitor); + void lockSoftwareForMonitor(CMonitor* pMonitor); + void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index 1a1df1d5..43ebe8b5 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -5,7 +5,7 @@ #include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/signal/Signal.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include "../protocols/types/DataDevice.hpp" #include diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index 3151aedb..f6e5c8be 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -3,7 +3,7 @@ #include "../../helpers/WLListener.hpp" #include "../../desktop/WLSurface.hpp" #include "../../macros.hpp" -#include "../../helpers/Box.hpp" +#include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" class CInputMethodPopupV2; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index a605fea7..775881cd 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -63,10 +63,9 @@ void CInputManager::endWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); // commit - std::string wsname = ""; - auto workspaceIDLeft = getWorkspaceIDFromString((*PSWIPEUSER ? "r-1" : "m-1"), wsname); - auto workspaceIDRight = getWorkspaceIDFromString((*PSWIPEUSER ? "r+1" : "m+1"), wsname); - const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); + auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; + auto workspaceIDRight = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r+1" : "m+1")).id; + const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); // If we've been swiping off the right end with PSWIPENEW enabled, there is // no workspace there yet, and we need to choose an ID for a new one now. @@ -109,16 +108,16 @@ void CInputManager::endWorkspaceSwipe() { if (PWORKSPACEL) { if (VERTANIMS) - PWORKSPACEL->m_vRenderOffset = Vector2D{0, -YDISTANCE}; + PWORKSPACEL->m_vRenderOffset = Vector2D{0.0, -YDISTANCE}; else - PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0}; + PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0.0}; } } else if (PWORKSPACER) { // to right if (VERTANIMS) - PWORKSPACER->m_vRenderOffset = Vector2D{0, YDISTANCE}; + PWORKSPACER->m_vRenderOffset = Vector2D{0.0, YDISTANCE}; else - PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0}; + PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0.0}; } m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); @@ -141,9 +140,9 @@ void CInputManager::endWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, YDISTANCE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0.0); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -167,9 +166,9 @@ void CInputManager::endWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -YDISTANCE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, -YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0.0); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -232,9 +231,8 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(d)) / (m_sActiveSwipe.speedPoints + 1); m_sActiveSwipe.speedPoints++; - std::string wsname = ""; - auto workspaceIDLeft = getWorkspaceIDFromString((*PSWIPEUSER ? "r-1" : "m-1"), wsname); - auto workspaceIDRight = getWorkspaceIDFromString((*PSWIPEUSER ? "r+1" : "m+1"), wsname); + auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; + auto workspaceIDRight = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r+1" : "m+1")).id; if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) { m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe @@ -269,9 +267,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -293,11 +291,11 @@ void CInputManager::updateWorkspaceSwipe(double delta) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); @@ -309,9 +307,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -333,11 +331,11 @@ void CInputManager::updateWorkspaceSwipe(double delta) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 61a664b9..79e08af9 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -2,7 +2,7 @@ #include "../../helpers/WLListener.hpp" #include "../../macros.hpp" -#include "../../helpers/Box.hpp" +#include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" #include diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 83db5f85..4dcf4ba5 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -29,6 +29,7 @@ Feel like the API is missing something you'd like to use in your plugin? Open an #include #include #include +#include typedef struct { std::string name; diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index d4b105cb..fd66ba5e 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -82,7 +82,7 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPsetSetSize([this](CZwlrLayerSurfaceV1* r, uint32_t x, uint32_t y) { pending.committed |= STATE_SIZE; - pending.desiredSize = {x, y}; + pending.desiredSize = {(int)x, (int)y}; }); resource->setSetAnchor([this](CZwlrLayerSurfaceV1* r, zwlrLayerSurfaceV1Anchor anchor) { diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 7fa14447..6d29248a 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -6,7 +6,7 @@ #include #include "WaylandProtocol.hpp" #include "wlr-layer-shell-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "types/SurfaceRole.hpp" diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index c7b78a5b..a17fa6cd 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -165,8 +165,15 @@ SP CPointerConstraint::owner() { } CRegion CPointerConstraint::logicConstraintRegion() { - CRegion rg = region; - const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); + CRegion rg = region; + const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); + + // if region wasn't set in pointer-constraints request take surface region + if (rg.empty() && SURFBOX.has_value()) { + rg.set(SURFBOX.value()); + return rg; + } + const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{}; rg.translate(CONSTRAINTPOS); return rg; diff --git a/src/protocols/PointerConstraints.hpp b/src/protocols/PointerConstraints.hpp index 8a78de99..faf28b32 100644 --- a/src/protocols/PointerConstraints.hpp +++ b/src/protocols/PointerConstraints.hpp @@ -7,8 +7,8 @@ #include #include "WaylandProtocol.hpp" #include "pointer-constraints-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" class CWLSurface; diff --git a/src/protocols/PointerGestures.hpp b/src/protocols/PointerGestures.hpp index 33c2bace..f907a49f 100644 --- a/src/protocols/PointerGestures.hpp +++ b/src/protocols/PointerGestures.hpp @@ -4,7 +4,7 @@ #include #include "WaylandProtocol.hpp" #include "pointer-gestures-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" class CPointerGestureSwipe { public: diff --git a/src/protocols/RelativePointer.hpp b/src/protocols/RelativePointer.hpp index 93446e85..453ce157 100644 --- a/src/protocols/RelativePointer.hpp +++ b/src/protocols/RelativePointer.hpp @@ -5,7 +5,7 @@ #include #include "WaylandProtocol.hpp" #include "relative-pointer-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" class CRelativePointer { public: diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 0c4eac86..8a6285a1 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -279,7 +279,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r } int ow, oh; wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); - PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round(); + PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), ow, oh).scale(PFRAME->pMonitor->scale).round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); @@ -556,9 +556,10 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) return false; - CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} - .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlr_output_transform_invert(frame->pMonitor->output->transform), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); + CBox monbox = + CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} + .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->output->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index c61395c9..58f13c1a 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -5,7 +5,7 @@ #include #include "WaylandProtocol.hpp" #include "tablet-v2.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" class CTablet; class CTabletTool; diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index 3959e72b..9f6284dc 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -7,7 +7,7 @@ #include "WaylandProtocol.hpp" #include "text-input-unstable-v3.hpp" #include "../helpers/signal/Signal.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" class CWLSurfaceResource; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 80f9defa..287538b5 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -202,7 +202,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; int ow, oh; wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); - PFRAME->box.transform(PMONITOR->transform, ow, oh).round(); + PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), ow, oh).round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index dddc3bca..9c56df93 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -514,13 +514,13 @@ CXDGPositionerRules::CXDGPositionerRules(SP positioner) static Vector2D pointForAnchor(const CBox& box, const Vector2D& predictionSize, xdgPositionerAnchor anchor) { switch (anchor) { - case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, 0}; - case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, box.size().y}; - case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F - predictionSize.y / 2.F}; - case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.F}; + case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.0 - predictionSize.x / 2.0, 0.0}; + case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.0 - predictionSize.x / 2.0, box.size().y}; + case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0.0, box.size().y / 2.0 - predictionSize.y / 2.0}; + case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.0}; case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos(); - case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0, box.size().y}; - case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0}; + case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0.0, box.size().y}; + case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0.0}; case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y}; default: return box.pos(); } @@ -539,30 +539,33 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa if (success) return predictedBox.translate(-parentCoord - constraint.pos()); + CBox test = predictedBox; + if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)) { // attempt to flip - const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; - const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; + const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; + const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; + auto countEdges = [constraint](const CBox& test) -> int { + int edgeCount = 0; + edgeCount += test.x < constraint.x ? 1 : 0; + edgeCount += test.x + test.w > constraint.x + constraint.w ? 1 : 0; + edgeCount += test.y < constraint.y ? 1 : 0; + edgeCount += test.y + test.h > constraint.y + constraint.h ? 1 : 0; + return edgeCount; + }; + int edgeCount = countEdges(test); - CBox test = predictedBox; - success = true; - if (flipX && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}).expand(-1).inside(constraint)) - test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}); - else if (flipY && test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint)) - test.translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}); - else if (flipX && flipY && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint)) - test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}); - else - success = false; + if (flipX && edgeCount > countEdges(test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0.0}))) + test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0.0}); + if (flipY && edgeCount > countEdges(test.copy().translate(Vector2D{0.0, -predictedBox.h - state.anchorRect.h}))) + test.translate(Vector2D{0.0, -predictedBox.h - state.anchorRect.h}); + + success = test.copy().expand(-1).inside(constraint); if (success) return test.translate(-parentCoord - constraint.pos()); } - // if flips fail, we will slide and remember. - // if the positioner is allowed to resize, then resize the slid thing. - CBox test = predictedBox; - // for slide and resize, defines the padding around the edge for the positioned // surface. constexpr int EDGE_PADDING = 4; @@ -575,10 +578,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa //const bool gravityLeft = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT; //const bool gravityTop = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_TOP || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_RIGHT; - const bool leftEdgeOut = predictedBox.x < constraint.x; - const bool topEdgeOut = predictedBox.y < constraint.y; - const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w; - const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h; + const bool leftEdgeOut = test.x < constraint.x; + const bool topEdgeOut = test.y < constraint.y; + const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; + const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; // TODO: this isn't truly conformant. if (leftEdgeOut && slideX) @@ -600,10 +603,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa const bool resizeX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X; const bool resizeY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y; - const bool leftEdgeOut = predictedBox.x < constraint.x; - const bool topEdgeOut = predictedBox.y < constraint.y; - const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w; - const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h; + const bool leftEdgeOut = test.x < constraint.x; + const bool topEdgeOut = test.y < constraint.y; + const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; + const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; // TODO: this isn't truly conformant. if (leftEdgeOut && resizeX) { diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index d60db86a..da551718 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -6,8 +6,8 @@ #include #include "WaylandProtocol.hpp" #include "xdg-shell.hpp" -#include "../helpers/Vector2D.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "types/SurfaceRole.hpp" diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index db6e3258..4bce3f58 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -277,8 +277,26 @@ void CWLSurfaceResource::resetRole() { } void CWLSurfaceResource::bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data) { - for (auto& n : nodes) { + std::vector> nodes2; + + // first, gather all nodes below + for (auto& n : nodes) { + std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); }); + // subsurfaces is sorted lowest -> highest + for (auto& c : n->subsurfaces) { + if (c->zIndex >= 0) + break; + nodes2.push_back(c->surface.lock()); + } + } + + if (!nodes2.empty()) + bfHelper(nodes2, fn, data); + + nodes2.clear(); + + for (auto& n : nodes) { Vector2D offset = {}; if (n->role->role() == SURFACE_ROLE_SUBSURFACE) { auto subsurface = (CWLSubsurfaceResource*)n->role.get(); @@ -288,11 +306,10 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std fn(n, offset, data); } - std::vector> nodes2; - for (auto& n : nodes) { - std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); }); for (auto& c : n->subsurfaces) { + if (c->zIndex < 0) + continue; nodes2.push_back(c->surface.lock()); } } @@ -404,7 +421,7 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size; - return surfaceDamage.scale(current.scale).transform(wlr_output_transform_invert(current.transform), trc.x, trc.y).add(current.bufferDamage); + return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(wlr_output_transform_invert(current.transform)), trc.x, trc.y).add(current.bufferDamage); } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index f50144bf..2f276719 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -14,7 +14,7 @@ #include "../WaylandProtocol.hpp" #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -#include "../../helpers/Region.hpp" +#include "../../helpers/math/Math.hpp" #include "../types/Buffer.hpp" #include "../types/SurfaceRole.hpp" diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index e54d3633..9634d569 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -12,20 +12,8 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPsetDestroy([this](CWlDataOffer* r) { - if (!dead && (recvd || accepted)) - PROTO::data->completeDrag(); - else - PROTO::data->abortDrag(); - PROTO::data->destroyResource(this); - }); - resource->setOnDestroy([this](CWlDataOffer* r) { - if (!dead && (recvd || accepted)) - PROTO::data->completeDrag(); - else - PROTO::data->abortDrag(); - PROTO::data->destroyResource(this); - }); + resource->setDestroy([this](CWlDataOffer* r) { PROTO::data->destroyResource(this); }); + resource->setOnDestroy([this](CWlDataOffer* r) { PROTO::data->destroyResource(this); }); resource->setAccept([this](CWlDataOffer* r, uint32_t serial, const char* mime) { if (!source) { @@ -210,7 +198,7 @@ CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : reso pClient = resource->client(); - resource->setSetSelection([this](CWlDataDevice* r, wl_resource* sourceR, uint32_t serial) { + resource->setSetSelection([](CWlDataDevice* r, wl_resource* sourceR, uint32_t serial) { auto source = sourceR ? CWLDataSourceResource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "Reset selection received"); @@ -226,7 +214,7 @@ CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : reso g_pSeatManager->setCurrentSelection(source); }); - resource->setStartDrag([this](CWlDataDevice* r, wl_resource* sourceR, wl_resource* origin, wl_resource* icon, uint32_t serial) { + resource->setStartDrag([](CWlDataDevice* r, wl_resource* sourceR, wl_resource* origin, wl_resource* icon, uint32_t serial) { auto source = CWLDataSourceResource::fromResource(sourceR); if (!source) { LOGM(ERR, "No source in drag"); @@ -552,7 +540,7 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource } void CWLDataDeviceProtocol::updateDrag() { - if (!dnd.currentSource) + if (!dndActive()) return; if (dnd.focusedDevice) @@ -607,14 +595,13 @@ void CWLDataDeviceProtocol::dropDrag() { } dnd.focusedDevice->sendDrop(); + dnd.focusedDevice->sendLeave(); resetDndState(); if (dnd.overriddenCursor) g_pInputManager->unsetCursorImage(); dnd.overriddenCursor = false; - - g_pInputManager->simulateMouseMovement(); } bool CWLDataDeviceProtocol::wasDragSuccessful() { @@ -635,16 +622,19 @@ bool CWLDataDeviceProtocol::wasDragSuccessful() { void CWLDataDeviceProtocol::completeDrag() { resetDndState(); - if (!dnd.focusedDevice || !dnd.currentSource) + if (!dnd.focusedDevice && !dnd.currentSource) return; - dnd.currentSource->sendDndDropPerformed(); - dnd.currentSource->sendDndFinished(); + if (dnd.currentSource) { + dnd.currentSource->sendDndDropPerformed(); + dnd.currentSource->sendDndFinished(); + } dnd.focusedDevice.reset(); dnd.currentSource.reset(); g_pInputManager->simulateMouseMovement(); + g_pSeatManager->resendEnterEvents(); } void CWLDataDeviceProtocol::abortDrag() { @@ -654,16 +644,19 @@ void CWLDataDeviceProtocol::abortDrag() { g_pInputManager->unsetCursorImage(); dnd.overriddenCursor = false; - if (!dnd.focusedDevice || !dnd.currentSource) + if (!dnd.focusedDevice && !dnd.currentSource) return; - dnd.focusedDevice->sendLeave(); - dnd.currentSource->cancelled(); + if (dnd.focusedDevice) + dnd.focusedDevice->sendLeave(); + if (dnd.currentSource) + dnd.currentSource->cancelled(); dnd.focusedDevice.reset(); dnd.currentSource.reset(); g_pInputManager->simulateMouseMovement(); + g_pSeatManager->resendEnterEvents(); } void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 5b31559f..22bb9376 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -15,7 +15,7 @@ #include #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -#include "../../helpers/Vector2D.hpp" +#include "../../helpers/math/Math.hpp" #include "../types/DataDevice.hpp" class CWLDataDeviceResource; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index be05955c..f578292a 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -1,5 +1,6 @@ #include "Seat.hpp" #include "Compositor.hpp" +#include "DataDevice.hpp" #include "../../devices/IKeyboard.hpp" #include "../../managers/SeatManager.hpp" #include "../../config/ConfigValue.hpp" @@ -128,6 +129,18 @@ void CWLPointerResource::sendLeave() { if (!owner || !currentSurface) return; + // release all buttons unless we have a dnd going on in which case + // the events shall be lost. + if (!PROTO::data->dndActive()) { + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + for (auto& b : pressedButtons) { + sendButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, b, WL_POINTER_BUTTON_STATE_RELEASED); + } + } + + pressedButtons.clear(); + resource->sendLeave(g_pSeatManager->nextSerial(owner.lock()), currentSurface->getResource().get()); currentSurface.reset(); listeners.destroySurface.reset(); @@ -144,6 +157,19 @@ void CWLPointerResource::sendButton(uint32_t timeMs, uint32_t button, wl_pointer if (!owner || !currentSurface) return; + if (state == WL_POINTER_BUTTON_STATE_RELEASED && std::find(pressedButtons.begin(), pressedButtons.end(), button) == pressedButtons.end()) { + LOGM(ERR, "sendButton release on a non-pressed button"); + return; + } else if (state == WL_POINTER_BUTTON_STATE_PRESSED && std::find(pressedButtons.begin(), pressedButtons.end(), button) != pressedButtons.end()) { + LOGM(ERR, "sendButton press on a non-pressed button"); + return; + } + + if (state == WL_POINTER_BUTTON_STATE_RELEASED) + std::erase(pressedButtons, button); + else if (state == WL_POINTER_BUTTON_STATE_PRESSED) + pressedButtons.emplace_back(button); + resource->sendButton(g_pSeatManager->nextSerial(owner.lock()), timeMs, button, state); } diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 625d3a98..09b36056 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -15,7 +15,7 @@ #include #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -#include "../../helpers/Vector2D.hpp" +#include "../../helpers/math/Math.hpp" constexpr const char* HL_SEAT_NAME = "Hyprland"; @@ -76,6 +76,8 @@ class CWLPointerResource { SP resource; WP currentSurface; + std::vector pressedButtons; + struct { CHyprSignalListener destroySurface; } listeners; diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 687e2031..70a8b208 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -13,7 +13,7 @@ #include "../WaylandProtocol.hpp" #include "wayland.hpp" #include "../types/Buffer.hpp" -#include "../../helpers/Vector2D.hpp" +#include "../../helpers/math/Math.hpp" class CWLSHMPoolResource; diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index d407636c..cbc4063a 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -23,15 +23,29 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPsubsurfaces, self.lock()); + auto pushAboveIndex = [this](int idx) -> void { + for (auto& c : parent->subsurfaces) { + if (c->zIndex >= idx) + c->zIndex++; + } + }; + + std::erase_if(parent->subsurfaces, [this](const auto& e) { return e == self || !e; }); auto it = std::find(parent->subsurfaces.begin(), parent->subsurfaces.end(), SURF); if (it == parent->subsurfaces.end()) { - LOGM(ERR, "Invalid surface reference in placeAbove"); - parent->subsurfaces.emplace_back(self.lock()); - } else - parent->subsurfaces.insert(it, self.lock()); + LOGM(ERR, "Invalid surface reference in placeAbove, likely parent"); + pushAboveIndex(1); + parent->subsurfaces.emplace_back(self); + zIndex = 1; + } else { + pushAboveIndex((*it)->zIndex); + zIndex = (*it)->zIndex; + parent->subsurfaces.emplace_back(self); + } + + std::sort(parent->subsurfaces.begin(), parent->subsurfaces.end(), [](const auto& a, const auto& b) { return a->zIndex < b->zIndex; }); }); resource->setPlaceBelow([this](CWlSubsurface* r, wl_resource* surf) { @@ -40,15 +54,29 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPsubsurfaces, self.lock()); + auto pushBelowIndex = [this](int idx) -> void { + for (auto& c : parent->subsurfaces) { + if (c->zIndex <= idx) + c->zIndex--; + } + }; + + std::erase_if(parent->subsurfaces, [this](const auto& e) { return e == self || !e; }); auto it = std::find(parent->subsurfaces.begin(), parent->subsurfaces.end(), SURF); if (it == parent->subsurfaces.end()) { - LOGM(ERR, "Invalid surface reference in placeBelow"); - parent->subsurfaces.emplace_back(self.lock()); - } else - parent->subsurfaces.insert(it--, self.lock()); + LOGM(ERR, "Invalid surface reference in placeBelow, likely parent"); + pushBelowIndex(-1); + parent->subsurfaces.emplace_back(self); + zIndex = -1; + } else { + pushBelowIndex((*it)->zIndex); + zIndex = (*it)->zIndex; + parent->subsurfaces.emplace_back(self); + } + + std::sort(parent->subsurfaces.begin(), parent->subsurfaces.end(), [](const auto& a, const auto& b) { return a->zIndex < b->zIndex; }); }); listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { diff --git a/src/protocols/core/Subcompositor.hpp b/src/protocols/core/Subcompositor.hpp index abcfbf6d..824f0ffc 100644 --- a/src/protocols/core/Subcompositor.hpp +++ b/src/protocols/core/Subcompositor.hpp @@ -35,6 +35,8 @@ class CWLSubsurfaceResource : public ISurfaceRole { WP self; + int zIndex = 1; // by default, it's above + struct { CSignal destroy; } events; diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index f26328e9..7c3a9886 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -3,7 +3,7 @@ #include "../../render/Renderer.hpp" #include "../../helpers/Format.hpp" -CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) : attrs(attrs_) { +CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_) : attrs(attrs_) { g_pHyprRenderer->makeEGLCurrent(); listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) { diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index dac89493..d07840b7 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -4,7 +4,7 @@ class CDMABuffer : public IWLBuffer { public: - CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs_); + CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_); virtual ~CDMABuffer(); virtual eBufferCapability caps(); diff --git a/src/protocols/types/SurfaceRole.hpp b/src/protocols/types/SurfaceRole.hpp index 05c0ea66..faaf70ee 100644 --- a/src/protocols/types/SurfaceRole.hpp +++ b/src/protocols/types/SurfaceRole.hpp @@ -11,4 +11,5 @@ enum eSurfaceRole { class ISurfaceRole { public: virtual eSurfaceRole role() = 0; + virtual ~ISurfaceRole() = default; }; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 5d8d6b83..3178ab8c 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -916,7 +916,7 @@ void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { int w, h; wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h); - const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform); + const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); newBox.transform(TR, w, h); } @@ -1006,8 +1006,8 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1025,7 +1025,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); CBox transformedBox = *box; - transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1097,9 +1097,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB static auto PDT = CConfigValue("debug:damage_tracking"); // get transform - const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1185,7 +1185,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB } CBox transformedBox = newBox; - transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1260,9 +1260,9 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1314,9 +1314,9 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1372,10 +1372,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glDisable(GL_STENCIL_TEST); // get transforms for the full monitor - const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); float matrix[9]; CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.monitorProjection.data()); + projectBox(matrix, MONITORBOX, TRANSFORM, 0, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1870,8 +1870,8 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1896,7 +1896,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); CBox transformedBox = *box; - transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -2176,8 +2176,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -2258,7 +2258,7 @@ void CHyprOpenGLImpl::renderMirrored() { CBox monbox = {0, 0, mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale}; // transform box as it will be drawn on a transformed projection - monbox.transform(mirrored->transform, mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale); + monbox.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale); monbox.x = (monitor->vecTransformedSize.x - monbox.w) / 2; monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c6e173e5..814b80fe 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -4,7 +4,7 @@ #include "../helpers/Monitor.hpp" #include "../helpers/Color.hpp" #include "../helpers/Timer.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/Format.hpp" #include #include diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 19b646a4..4fc751ff 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,6 +1,6 @@ #include "Renderer.hpp" #include "../Compositor.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" #include #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" @@ -209,7 +209,10 @@ static void renderSurface(SP surface, int x, int y, void* da else g_pHyprOpenGL->blend(true); - if (RDATA->surface && surface == RDATA->surface) { + // FIXME: This is wrong and will bug the blur out as shit if the first surface + // 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) { if (RDATA->blur) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); else @@ -235,6 +238,9 @@ static void renderSurface(SP surface, int x, int y, void* da g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.useNearestNeighbor = NEARESTNEIGHBORSET; + + // up the counter so that we dont blur any surfaces above this one + RDATA->surfaceCounter++; } bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { @@ -602,6 +608,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec renderdata.blur = false; } + renderdata.surfaceCounter = 0; pWindow->m_pWLSurface->resource()->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); @@ -658,6 +665,8 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; + renderdata.surfaceCounter = 0; + pWindow->m_pPopupHead->breadthfirst( [](CPopup* popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) @@ -743,6 +752,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time renderdata.dontRound = true; renderdata.popup = true; renderdata.blur = pLayer->forceBlurPopups; + renderdata.surfaceCounter = 0; if (popups) { pLayer->popupHead->breadthfirst( [](CPopup* popup, void* data) { @@ -1236,7 +1246,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { clock_gettime(CLOCK_MONOTONIC, &now); // check the damage - bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); + bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged(); if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1404,7 +1414,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->state.wlr()->tearing_page_flip = shouldTear; if (!pMonitor->state.commit()) { - wlr_damage_ring_add_whole(&pMonitor->damage); + pMonitor->damage.damageEntire(); return; } @@ -1498,15 +1508,15 @@ void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) { // taken from Sway. // this is just too much of a spaghetti for me to understand -static void applyExclusive(wlr_box& usableArea, uint32_t anchor, int32_t exclusive, int32_t marginTop, int32_t marginRight, int32_t marginBottom, int32_t marginLeft) { +static void applyExclusive(CBox& usableArea, uint32_t anchor, int32_t exclusive, int32_t marginTop, int32_t marginRight, int32_t marginBottom, int32_t marginLeft) { if (exclusive <= 0) { return; } struct { uint32_t singular_anchor; uint32_t anchor_triplet; - int* positive_axis; - int* negative_axis; + double* positive_axis; + double* negative_axis; int margin; } edges[] = { // Top @@ -1630,9 +1640,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgeometry = box; - applyExclusive(*usableArea->pWlr(), PSTATE->anchor, PSTATE->exclusive, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); - - usableArea->applyFromWlr(); + applyExclusive(*usableArea, PSTATE->anchor, PSTATE->exclusive, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); if (Vector2D{box.width, box.height} != OLDSIZE) ls->layerSurface->configure(box.size()); @@ -1810,7 +1818,7 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; wlr_region_scale(transformed.pixman(), transformed.pixman(), scale); - transformed.transform(mirrored->transform, mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale); + transformed.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale); transformed.translate(Vector2D(monbox.x, monbox.y)); mirror->addDamage(&transformed); @@ -2224,7 +2232,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (pMonitor->createdByUser) { CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - transformedBox.transform(wlr_output_transform_invert(pMonitor->output->transform), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->output->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } @@ -2237,7 +2245,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // updato wlroots g_pCompositor->arrangeMonitors(); - wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + pMonitor->damage.setSize(pMonitor->vecTransformedSize); // Set scale for all surfaces on this monitor, needed for some clients // but not on unsafe state to avoid crashes @@ -2443,9 +2451,14 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pW } void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace) { - CRegion rg; + CRegion rg; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + static auto PBLURSIZE = CConfigValue("decoration:blur:size"); + static auto PBLURPASSES = CConfigValue("decoration:blur:passes"); + const auto BLURRADIUS = *PBLUR ? (*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)) : 0; for (auto& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != pWorkspace) @@ -2460,7 +2473,8 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWork CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; - box.scale(PMONITOR->scale); + box.scale(PMONITOR->scale).expand(-BLURRADIUS); + g_pHyprOpenGL->m_RenderData.renderModif.applyToBox(box); rg.add(box); @@ -2601,13 +2615,15 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return true; } + int bufferAge = 0; + if (!buffer) { if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) { Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName); return false; } - m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, nullptr); + m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge); if (!m_pCurrentWlrBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); return false; @@ -2626,8 +2642,10 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return false; } - if (mode == RENDER_MODE_NORMAL) - wlr_damage_ring_rotate_buffer(&pMonitor->damage, m_pCurrentWlrBuffer, damage.pixman()); + if (mode == RENDER_MODE_NORMAL) { + damage = pMonitor->damage.getBufferDamage(bufferAge); + pMonitor->damage.rotate(); + } m_pCurrentRenderbuffer->bind(); if (simple) diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6adca72a..8f404c88 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -6,7 +6,7 @@ #include "OpenGL.hpp" #include "Renderbuffer.hpp" #include "../helpers/Timer.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" struct SMonitorRule; class CWorkspace; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index aef8e4ac..5560db97 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -55,7 +55,7 @@ CTexture::CTexture(wlr_texture* tex) { else m_iType = TEXTURE_EXTERNAL; - m_vSize = Vector2D(tex->width, tex->height); + m_vSize = Vector2D((int)tex->width, (int)tex->height); } CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) { diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index fa1ca4fe..c80e943d 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -4,7 +4,7 @@ class IWLBuffer; struct SDMABUFAttrs; -class CRegion; +HYPRUTILS_FORWARD(Math, CRegion); enum TEXTURETYPE { TEXTURE_INVALID, // Invalid diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 3fa0946e..8ad3263e 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -26,16 +26,16 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual std::string getDisplayName(); private: - SWindowDecorationExtents m_seExtents; - SWindowDecorationExtents m_seReportedExtents; + SBoxExtents m_seExtents; + SBoxExtents m_seReportedExtents; - PHLWINDOWREF m_pWindow; + PHLWINDOWREF m_pWindow; - Vector2D m_vLastWindowPos; - Vector2D m_vLastWindowSize; + Vector2D m_vLastWindowPos; + Vector2D m_vLastWindowSize; - CBox m_bAssignedGeometry = {0}; + CBox m_bAssignedGeometry = {0}; - CBox assignedBoxGlobal(); - bool doesntWantBorders(); + CBox assignedBoxGlobal(); + bool doesntWantBorders(); }; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index fba279cc..6893d78c 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -130,7 +130,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) { const float SHADOWSCALE = std::clamp(*PSHADOWSCALE, 0.f, 1.f); // scale the box in relation to the center of the box - fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET); + fullBox.scaleFromCenter(SHADOWSCALE).translate({(*PSHADOWOFFSET).x, (*PSHADOWOFFSET).y}); updateWindow(PWINDOW); m_vLastWindowPos += WORKSPACEOFFSET; diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 06319cb7..ecd5a47b 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -26,14 +26,14 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual std::string getDisplayName(); private: - SWindowDecorationExtents m_seExtents; - SWindowDecorationExtents m_seReportedExtents; + SBoxExtents m_seExtents; + SBoxExtents m_seReportedExtents; - PHLWINDOWREF m_pWindow; + PHLWINDOWREF m_pWindow; - Vector2D m_vLastWindowPos; - Vector2D m_vLastWindowSize; + Vector2D m_vLastWindowPos; + Vector2D m_vLastWindowSize; - CBox m_bLastWindowBox = {0}; - CBox m_bLastWindowBoxWithDecos = {0}; + CBox m_bLastWindowBox = {0}; + CBox m_bLastWindowBoxWithDecos = {0}; }; diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 1af24717..bfb15d5c 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -48,7 +48,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual std::string getDisplayName(); private: - SWindowDecorationExtents m_seExtents; + SBoxExtents m_seExtents; CBox m_bAssignedBox = {0}; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 17f6d913..d66a5760 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -33,11 +33,11 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW if (EDGESNO == 1) { if (TOP) - return wb.pos() + Vector2D{wb.size().x / 2.0, 0}; + return wb.pos() + Vector2D{wb.size().x / 2.0, 0.0}; else if (BOTTOM) return wb.pos() + Vector2D{wb.size().x / 2.0, wb.size().y}; else if (LEFT) - return wb.pos() + Vector2D{0, wb.size().y / 2.0}; + return wb.pos() + Vector2D{0.0, wb.size().y / 2.0}; else if (RIGHT) return wb.pos() + Vector2D{wb.size().x, wb.size().y / 2.0}; UNREACHABLE(); @@ -45,11 +45,11 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW if (TOP && LEFT) return wb.pos(); if (TOP && RIGHT) - return wb.pos() + Vector2D{wb.size().x, 0}; + return wb.pos() + Vector2D{wb.size().x, 0.0}; if (BOTTOM && RIGHT) return wb.pos() + wb.size(); if (BOTTOM && LEFT) - return wb.pos() + Vector2D{0, wb.size().y}; + return wb.pos() + Vector2D{0.0, wb.size().y}; UNREACHABLE(); } UNREACHABLE(); @@ -234,26 +234,26 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { } else if (LEFT) { pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, -stickyOffsetYT}; pos.x -= desiredSize; - size = {desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; + size = {(double)desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; if (SOLID) stickyOffsetXL += desiredSize; } else if (RIGHT) { - pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, -stickyOffsetYT}; - size = {desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; + pos = wb.pos() + Vector2D{wb.size().x, 0.0} - EDGEPOINT + Vector2D{stickyOffsetXR, -stickyOffsetYT}; + size = {(double)desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; if (SOLID) stickyOffsetXR += desiredSize; } else if (TOP) { pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYT}; pos.y -= desiredSize; - size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, desiredSize}; + size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, (double)desiredSize}; if (SOLID) stickyOffsetYT += desiredSize; } else { - pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYB}; - size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, desiredSize}; + pos = wb.pos() + Vector2D{0.0, wb.size().y} - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYB}; + size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, (double)desiredSize}; if (SOLID) stickyOffsetYB += desiredSize; @@ -271,7 +271,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { } } - if (WINDOWDATA->extents != SWindowDecorationExtents{{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}) { + if (WINDOWDATA->extents != SBoxExtents{{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}) { WINDOWDATA->extents = {{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}; g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); } @@ -286,14 +286,14 @@ void CDecorationPositioner::onWindowMap(PHLWINDOW pWindow) { m_mWindowDatas[pWindow] = {}; } -SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow) { +SBoxExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow) { try { const auto E = m_mWindowDatas.at(pWindow); return E.reserved; } catch (std::out_of_range& e) { return {}; } } -SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { +SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { CBox accum = pWindow->getWindowMainSurfaceBox(); for (auto& data : m_vWindowPositioningDatas) { @@ -317,7 +317,7 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(PHLWI decoBox.translate(EDGEPOINT); } - SWindowDecorationExtents extentsToAdd; + SBoxExtents extentsToAdd; if (decoBox.x < accum.x) extentsToAdd.topLeft.x = accum.x - decoBox.x; @@ -355,7 +355,7 @@ CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { decoBox.translate(EDGEPOINT); } - SWindowDecorationExtents extentsToAdd; + SBoxExtents extentsToAdd; if (decoBox.x < accum.x) extentsToAdd.topLeft.x = accum.x - decoBox.x; diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index 880dc3f8..27e56f0b 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "../../helpers/Box.hpp" +#include "../../helpers/math/Math.hpp" #include "../../desktop/DesktopTypes.hpp" class CWindow; @@ -37,7 +37,7 @@ struct SDecorationPositioningInfo { eDecorationPositioningPolicy policy = DECORATION_POSITION_ABSOLUTE; uint32_t edges = 0; // enum eDecorationEdges uint32_t priority = 10; // priority, decos will be evaluated high -> low - SWindowDecorationExtents desiredExtents; + SBoxExtents desiredExtents; bool reserved = false; // if true, geometry will use reserved area }; @@ -62,14 +62,14 @@ class CDecorationPositioner { Vector2D getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pWindow); // called on resize, or insert/removal of a new deco - void onWindowUpdate(PHLWINDOW pWindow); - void uncacheDecoration(IHyprWindowDecoration* deco); - SWindowDecorationExtents getWindowDecorationReserved(PHLWINDOW pWindow); - SWindowDecorationExtents getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly = false); - CBox getBoxWithIncludedDecos(PHLWINDOW pWindow); - void repositionDeco(IHyprWindowDecoration* deco); - CBox getWindowDecorationBox(IHyprWindowDecoration* deco); - void forceRecalcFor(PHLWINDOW pWindow); + void onWindowUpdate(PHLWINDOW pWindow); + void uncacheDecoration(IHyprWindowDecoration* deco); + SBoxExtents getWindowDecorationReserved(PHLWINDOW pWindow); + SBoxExtents getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly = false); + CBox getBoxWithIncludedDecos(PHLWINDOW pWindow); + void repositionDeco(IHyprWindowDecoration* deco); + CBox getWindowDecorationBox(IHyprWindowDecoration* deco); + void forceRecalcFor(PHLWINDOW pWindow); private: struct SWindowPositioningData { @@ -81,10 +81,10 @@ class CDecorationPositioner { }; struct SWindowData { - Vector2D lastWindowSize = {}; - SWindowDecorationExtents reserved = {}; - SWindowDecorationExtents extents = {}; - bool needsRecalc = false; + Vector2D lastWindowSize = {}; + SBoxExtents reserved = {}; + SBoxExtents extents = {}; + bool needsRecalc = false; }; std::map m_mWindowDatas; diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 2346106f..a58560f3 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -2,7 +2,7 @@ #include #include "../../defines.hpp" -#include "../../helpers/Region.hpp" +#include "../../helpers/math/Math.hpp" #include "DecorationPositioner.hpp" enum eDecorationType { diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index 98e0701b..f4059ee1 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -49,10 +49,16 @@ std::vector CXDataSource::mimes() { void CXDataSource::send(const std::string& mime, uint32_t fd) { xcb_atom_t mimeAtom = 0; - for (size_t i = 0; i < mimeTypes.size(); ++i) { - if (mimeTypes.at(i) == mime) { - mimeAtom = mimeAtoms.at(i); - break; + if (mime == "text/plain") + mimeAtom = HYPRATOMS["TEXT"]; + else if (mime == "text/plain;charset=utf-8") + mimeAtom = HYPRATOMS["UTF8_STRING"]; + else { + for (size_t i = 0; i < mimeTypes.size(); ++i) { + if (mimeTypes.at(i) == mime) { + mimeAtom = mimeAtoms.at(i); + break; + } } } diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 0cdac1d5..61eee984 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -2,7 +2,8 @@ #include "../helpers/WLListener.hpp" #include "../helpers/signal/Signal.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/memory/Memory.hpp" +#include "../helpers/math/Math.hpp" #include class CWLSurfaceResource; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 719adcb9..aa38910f 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1,4 +1,4 @@ -#include "helpers/Vector2D.hpp" +#include "helpers/math/Math.hpp" #ifndef NO_XWAYLAND #include "XWayland.hpp" @@ -1034,16 +1034,16 @@ void CXWM::initSelection() { } void CXWM::setClipboardToWayland(SXSelection& sel) { - sel.dataSource = makeShared(sel); - if (sel.dataSource->mimes().empty()) { + auto source = makeShared(sel); + if (source->mimes().empty()) { Debug::log(ERR, "[xwm] can't set clipboard: no MIMEs"); - sel.dataSource.reset(); + return; } - if (sel.dataSource) { - Debug::log(LOG, "[xwm] X clipboard at {:x} takes clipboard", (uintptr_t)sel.dataSource.get()); - g_pSeatManager->setCurrentSelection(sel.dataSource); - } + sel.dataSource = source; + + Debug::log(LOG, "[xwm] X clipboard at {:x} takes clipboard", (uintptr_t)sel.dataSource.get()); + g_pSeatManager->setCurrentSelection(sel.dataSource); } void CXWM::getTransferData(SXSelection& sel) { diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 6456c71b..88606416 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -1,6 +1,7 @@ #pragma once #include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index c7981251..d1cc4421 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -2,6 +2,7 @@ #include #include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" #include "XSurface.hpp" @@ -29,10 +30,8 @@ class CXWayland { } events; }; -inline std::unique_ptr g_pXWayland; +inline std::unique_ptr g_pXWayland; -#define HYPRATOM(name) \ - { name, 0 } inline std::unordered_map HYPRATOMS = { HYPRATOM("_NET_SUPPORTED"), HYPRATOM("_NET_SUPPORTING_WM_CHECK"),