From e1cbf35efb73f78c9f85bed44a71f886317bbe44 Mon Sep 17 00:00:00 2001 From: Youwen Wu Date: Wed, 21 Aug 2024 16:03:42 -0700 Subject: [PATCH] fix: get better patch? --- ...x-dmabuf-allow-on-split-node-systems.patch | 28 - ...renderer-pass-custom-modelines-to-aq.patch | 38 - ...ate-suspendstate-on-window-move-7396.patch | 28 - .../0004-screencopy-nuke-unused-stuff.patch | 34 - ...05-protocol-fix-logm-template-checks.patch | 25 - ...6-screencopy-fix-10b-format-r-b-flip.patch | 27 - .../0007-flake-update-aquamarine.patch | 31 - ...rpm-hyprctl-update-shell-completions.patch | 1254 ---- ...ng-header-for-libc-after-92744b5b9aa.patch | 30 - ...-examples-more-systemd-examples-7409.patch | 49 - ...void-crash-on-wayland-output-removal.patch | 25 - ...ngling-references-to-old-monitors-be.patch | 146 - ...nfig-fix-typo-in-default-config-7446.patch | 50 - ...to-control-which-window-to-focus-on-.patch | 70 - ...put-dont-cast-enum-out-of-range-7448.patch | 27 - ...mations-add-workspace-in-out-configs.patch | 96 - ...clude-xcursor-regardless-of-xwayland.patch | 29 - .../callisto/0018-Fix-static-asan-patch.patch | 38 - hosts/callisto/0019-Fix-Makefile-too.patch | 28 - ...surface-dont-rollover-on-size_t-7451.patch | 28 - hosts/callisto/asahi-fix.patch | 5080 +++++++++++++++++ hosts/callisto/configuration.nix | 21 +- 22 files changed, 5081 insertions(+), 2101 deletions(-) delete mode 100644 hosts/callisto/0001-linux-dmabuf-allow-on-split-node-systems.patch delete mode 100644 hosts/callisto/0002-renderer-pass-custom-modelines-to-aq.patch delete mode 100644 hosts/callisto/0003-compositor-update-suspendstate-on-window-move-7396.patch delete mode 100644 hosts/callisto/0004-screencopy-nuke-unused-stuff.patch delete mode 100644 hosts/callisto/0005-protocol-fix-logm-template-checks.patch delete mode 100644 hosts/callisto/0006-screencopy-fix-10b-format-r-b-flip.patch delete mode 100644 hosts/callisto/0007-flake-update-aquamarine.patch delete mode 100644 hosts/callisto/0008-hyprpm-hyprctl-update-shell-completions.patch delete mode 100644 hosts/callisto/0009-config-add-missing-header-for-libc-after-92744b5b9aa.patch delete mode 100644 hosts/callisto/0010-examples-more-systemd-examples-7409.patch delete mode 100644 hosts/callisto/0011-monitors-avoid-crash-on-wayland-output-removal.patch delete mode 100644 hosts/callisto/0012-monitor-avoid-dangling-references-to-old-monitors-be.patch delete mode 100644 hosts/callisto/0013-example-config-fix-typo-in-default-config-7446.patch delete mode 100644 hosts/callisto/0014-core-add-option-to-control-which-window-to-focus-on-.patch delete mode 100644 hosts/callisto/0015-output-dont-cast-enum-out-of-range-7448.patch delete mode 100644 hosts/callisto/0016-animations-add-workspace-in-out-configs.patch delete mode 100644 hosts/callisto/0017-Nix-include-xcursor-regardless-of-xwayland.patch delete mode 100644 hosts/callisto/0018-Fix-static-asan-patch.patch delete mode 100644 hosts/callisto/0019-Fix-Makefile-too.patch delete mode 100644 hosts/callisto/0020-layersurface-dont-rollover-on-size_t-7451.patch create mode 100644 hosts/callisto/asahi-fix.patch diff --git a/hosts/callisto/0001-linux-dmabuf-allow-on-split-node-systems.patch b/hosts/callisto/0001-linux-dmabuf-allow-on-split-node-systems.patch deleted file mode 100644 index 21e5af2..0000000 --- a/hosts/callisto/0001-linux-dmabuf-allow-on-split-node-systems.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 279ec1c291021479b050c83a0435ac7076c1aee0 Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Sun, 18 Aug 2024 19:51:54 +0200 -Subject: [PATCH 01/20] linux-dmabuf: allow on split-node systems - -ref #7364 ---- - src/protocols/LinuxDMABUF.cpp | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp -index 3cdb5b34..32625792 100644 ---- a/src/protocols/LinuxDMABUF.cpp -+++ b/src/protocols/LinuxDMABUF.cpp -@@ -490,9 +490,8 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const - return; - } - } else { -- LOGM(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); -+ LOGM(ERR, "DRM device {} has no render node, disabling linux dmabuf checks", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); - drmFreeDevice(&device); -- removeGlobal(); - } - }); - } --- -2.45.2 - diff --git a/hosts/callisto/0002-renderer-pass-custom-modelines-to-aq.patch b/hosts/callisto/0002-renderer-pass-custom-modelines-to-aq.patch deleted file mode 100644 index b501fc9..0000000 --- a/hosts/callisto/0002-renderer-pass-custom-modelines-to-aq.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 50348a3ddbb6bc3367300c9bba2ff682e4a356e3 Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Sun, 18 Aug 2024 20:19:13 +0200 -Subject: [PATCH 02/20] renderer: pass custom modelines to aq - -ref #7390 ---- - src/render/Renderer.cpp | 14 +++----------- - 1 file changed, 3 insertions(+), 11 deletions(-) - -diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp -index b363c287..c2ecbbf3 100644 ---- a/src/render/Renderer.cpp -+++ b/src/render/Renderer.cpp -@@ -1994,17 +1994,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR - if (pMonitor->output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM) { - Debug::log(ERR, "Tried to set custom modeline on non-DRM output"); - fail = true; -- } else { -- // FIXME: -- // auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode); -- // if (mode) { -- // wlr_output_state_set_mode(pMonitor->state.wlr(), mode); -- // pMonitor->customDrmMode = RULE->drmMode; -- // } else { -- // Debug::log(ERR, "wlr_drm_connector_add_mode failed"); -- // fail = true; -- // } -- } -+ } else -+ pMonitor->output->state->setCustomMode(makeShared( -+ Aquamarine::SOutputMode{.pixelSize = {RULE->drmMode.hdisplay, RULE->drmMode.vdisplay}, .refreshRate = RULE->drmMode.vrefresh, .modeInfo = RULE->drmMode})); - } else - pMonitor->output->state->setCustomMode(makeShared(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE})); - --- -2.45.2 - diff --git a/hosts/callisto/0003-compositor-update-suspendstate-on-window-move-7396.patch b/hosts/callisto/0003-compositor-update-suspendstate-on-window-move-7396.patch deleted file mode 100644 index 0138d99..0000000 --- a/hosts/callisto/0003-compositor-update-suspendstate-on-window-move-7396.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5afc4dc42e2409da62b7bcdf0ead90329e8d7a92 Mon Sep 17 00:00:00 2001 -From: Tom Englund -Date: Sun, 18 Aug 2024 21:02:46 +0200 -Subject: [PATCH 03/20] compositor: update suspendstate on window move (#7396) - -hyprctl dispatch -- movetoworkspacesilent x,"^kitty$" where X is the -current workspace makes kitty stops updating until current workspace is -changed while it is on the screen. update the suspend state after it has -been moved. ---- - src/Compositor.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/Compositor.cpp b/src/Compositor.cpp -index 9d247a56..1437a653 100644 ---- a/src/Compositor.cpp -+++ b/src/Compositor.cpp -@@ -2737,6 +2737,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor - - g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); - g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID()); -+ g_pCompositor->updateSuspendedStates(); - } - - PHLWINDOW CCompositor::getForceFocus() { --- -2.45.2 - diff --git a/hosts/callisto/0004-screencopy-nuke-unused-stuff.patch b/hosts/callisto/0004-screencopy-nuke-unused-stuff.patch deleted file mode 100644 index 48c4f6f..0000000 --- a/hosts/callisto/0004-screencopy-nuke-unused-stuff.patch +++ /dev/null @@ -1,34 +0,0 @@ -From bf611fbbf3183e6f96529d79189be56189a46e1b Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Sun, 18 Aug 2024 22:40:21 +0200 -Subject: [PATCH 04/20] screencopy: nuke unused stuff - ---- - src/protocols/Screencopy.cpp | 11 ----------- - 1 file changed, 11 deletions(-) - -diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp -index f246f6dd..8a7fd567 100644 ---- a/src/protocols/Screencopy.cpp -+++ b/src/protocols/Screencopy.cpp -@@ -38,17 +38,6 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t - - g_pHyprRenderer->makeEGLCurrent(); - -- if (g_pHyprOpenGL->m_mMonitorRenderResources.contains(pMonitor)) { -- const auto& RDATA = g_pHyprOpenGL->m_mMonitorRenderResources.at(pMonitor); -- // bind the fb for its format. Suppress gl errors. --#ifndef GLES2 -- glBindFramebuffer(GL_READ_FRAMEBUFFER, RDATA.offloadFB.m_iFb); --#else -- glBindFramebuffer(GL_FRAMEBUFFER, RDATA.offloadFB.m_iFb); --#endif -- } else -- LOGM(ERR, "No RDATA in screencopy???"); -- - shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor); - if (shmFormat == DRM_FORMAT_INVALID) { - LOGM(ERR, "No format supported by renderer in capture output"); --- -2.45.2 - diff --git a/hosts/callisto/0005-protocol-fix-logm-template-checks.patch b/hosts/callisto/0005-protocol-fix-logm-template-checks.patch deleted file mode 100644 index 5f7ca00..0000000 --- a/hosts/callisto/0005-protocol-fix-logm-template-checks.patch +++ /dev/null @@ -1,25 +0,0 @@ -From fa12efdd2aae6851305245f16a801fb571fbe2c1 Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Sun, 18 Aug 2024 22:54:47 +0200 -Subject: [PATCH 05/20] protocol: fix logm template checks - ---- - src/protocols/WaylandProtocol.hpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp -index 0fa8daab..87c75ed8 100644 ---- a/src/protocols/WaylandProtocol.hpp -+++ b/src/protocols/WaylandProtocol.hpp -@@ -32,7 +32,7 @@ - } else if (level == LOG || level == INFO || level == TRACE) { \ - oss << "[" << EXTRACT_CLASS_NAME() << "] "; \ - } \ -- if constexpr (std::is_same_v) { \ -+ if constexpr (std::tuple_size::value == 1 && std::is_same_v) { \ - oss << __VA_ARGS__; \ - Debug::log(level, oss.str()); \ - } else { \ --- -2.45.2 - diff --git a/hosts/callisto/0006-screencopy-fix-10b-format-r-b-flip.patch b/hosts/callisto/0006-screencopy-fix-10b-format-r-b-flip.patch deleted file mode 100644 index 4e81e66..0000000 --- a/hosts/callisto/0006-screencopy-fix-10b-format-r-b-flip.patch +++ /dev/null @@ -1,27 +0,0 @@ -From f4045ab8d032186b7c5409cd9f05eeaa813320ba Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Sun, 18 Aug 2024 22:57:21 +0200 -Subject: [PATCH 06/20] screencopy: fix 10b format r/b flip - ---- - src/protocols/Screencopy.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp -index 8a7fd567..b25d9456 100644 ---- a/src/protocols/Screencopy.cpp -+++ b/src/protocols/Screencopy.cpp -@@ -46,6 +46,10 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t - return; - } - -+ // TODO: hack, we can't bit flip so we'll format flip heh, GL_BGRA_EXT wont work here -+ if (shmFormat == DRM_FORMAT_XRGB2101010 || shmFormat == DRM_FORMAT_ARGB2101010) -+ shmFormat = DRM_FORMAT_XBGR2101010; -+ - const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(shmFormat); - if (!PSHMINFO) { - LOGM(ERR, "No pixel format supported by renderer in capture output"); --- -2.45.2 - diff --git a/hosts/callisto/0007-flake-update-aquamarine.patch b/hosts/callisto/0007-flake-update-aquamarine.patch deleted file mode 100644 index dfd9aaf..0000000 --- a/hosts/callisto/0007-flake-update-aquamarine.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 11dfb8397becca85cad078dd31bf043d1c40ceac Mon Sep 17 00:00:00 2001 -From: diniamo -Date: Sun, 18 Aug 2024 20:43:04 +0200 -Subject: [PATCH 07/20] flake: update aquamarine - ---- - flake.lock | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/flake.lock b/flake.lock -index c70d31d1..97016819 100644 ---- a/flake.lock -+++ b/flake.lock -@@ -16,11 +16,11 @@ - ] - }, - "locked": { -- "lastModified": 1723920171, -- "narHash": "sha256-dVCMrAe+D/5S91erhwQj2DSzHOVzAanWqoy+vPWB9DY=", -+ "lastModified": 1724006173, -+ "narHash": "sha256-1ROh0buuxiMyc6eIb3CIbJsmYO7PhLqSYs55mOx1XTk=", - "owner": "hyprwm", - "repo": "aquamarine", -- "rev": "71d49670fe246cdaff4860b0effba0ab9f163b72", -+ "rev": "7f8df01d4297b9068a9592400f16044602844f86", - "type": "github" - }, - "original": { --- -2.45.2 - diff --git a/hosts/callisto/0008-hyprpm-hyprctl-update-shell-completions.patch b/hosts/callisto/0008-hyprpm-hyprctl-update-shell-completions.patch deleted file mode 100644 index 320884a..0000000 --- a/hosts/callisto/0008-hyprpm-hyprctl-update-shell-completions.patch +++ /dev/null @@ -1,1254 +0,0 @@ -From 83d88fa56467a2b749fb2320e1595281107bd326 Mon Sep 17 00:00:00 2001 -From: loseardes77 -Date: Sun, 18 Aug 2024 22:25:23 +0200 -Subject: [PATCH 08/20] hyprpm, hyprctl: update shell completions - ---- - hyprctl/hyprctl.bash | 87 ++++++------ - hyprctl/hyprctl.fish | 309 ++++++++++++++++++++++-------------------- - hyprctl/hyprctl.usage | 20 ++- - hyprctl/hyprctl.zsh | 269 +++++++++++++++++++----------------- - hyprpm/hyprpm.bash | 58 ++++---- - hyprpm/hyprpm.fish | 91 +++++++------ - hyprpm/hyprpm.usage | 4 +- - hyprpm/hyprpm.zsh | 46 ++++--- - 8 files changed, 474 insertions(+), 410 deletions(-) - -diff --git a/hyprctl/hyprctl.bash b/hyprctl/hyprctl.bash -index c69cca21..e26e623e 100644 ---- a/hyprctl/hyprctl.bash -+++ b/hyprctl/hyprctl.bash -@@ -1,17 +1,17 @@ --_hyprctl_cmd_2 () { -+_hyprctl_cmd_1 () { - hyprctl monitors | awk '/Monitor/{ print $2 }' - } - - _hyprctl_cmd_3 () { -- hyprpm list | awk '/Plugin/{ print $4 }' -+ hyprctl clients | awk '/class/{print $2}' - } - --_hyprctl_cmd_0 () { -- hyprctl clients | awk '/class/{ print $2 }' -+_hyprctl_cmd_2 () { -+ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' - } - --_hyprctl_cmd_1 () { -- hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' -+_hyprctl_cmd_0 () { -+ hyprpm list | awk '/Plugin/{print $4}' - } - - _hyprctl () { -@@ -23,25 +23,25 @@ _hyprctl () { - local words cword - _get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword - -- local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow") -- -+ declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize) - declare -A literal_transitions -- literal_transitions[0]="([105]=1 [75]=2 [33]=3 [35]=4 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [111]=4 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [88]=4 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [98]=4 [99]=2 [27]=2 [28]=14 [102]=2 [104]=4)" -- literal_transitions[3]="([73]=17 [13]=2 [32]=17 [55]=17 [56]=17 [91]=17 [106]=2 [123]=2 [77]=1 [16]=2 [126]=17 [3]=1 [5]=2 [64]=17 [131]=2 [133]=17 [81]=17 [134]=17 [84]=17 [31]=17 [49]=2 [12]=2 [86]=17 [10]=17 [87]=17 [141]=17)" -- literal_transitions[7]="([105]=1 [75]=2 [33]=3 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [99]=2 [27]=2 [28]=14 [102]=2)" -- literal_transitions[8]="([101]=2 [130]=2 [132]=2 [0]=2 [74]=2 [36]=2 [108]=2 [109]=2 [38]=2 [110]=2 [4]=2 [79]=2 [40]=2 [80]=2 [113]=2 [6]=2 [42]=2 [43]=2 [82]=2 [83]=2 [47]=2 [48]=2 [9]=2 [50]=2 [51]=2 [53]=2 [11]=2 [112]=2 [89]=2 [118]=2 [57]=2 [92]=2 [58]=2 [93]=2 [94]=2 [61]=2 [62]=2 [128]=2 [95]=2 [63]=2 [20]=2 [97]=2 [22]=2 [23]=2 [65]=2 [66]=2 [135]=2 [136]=2 [24]=2 [26]=2 [69]=2 [100]=2 [70]=2 [140]=2 [29]=2 [71]=2)" -- literal_transitions[9]="([117]=20 [114]=16)" -- literal_transitions[11]="([103]=2)" -- literal_transitions[13]="([21]=1 [119]=1 [30]=1 [139]=1 [121]=1 [44]=1 [72]=1)" -- literal_transitions[14]="([39]=2)" -- literal_transitions[15]="([138]=2 [96]=2)" -- literal_transitions[17]="([18]=2 [7]=2)" -- literal_transitions[18]="([76]=19)" -- literal_transitions[19]="([34]=4 [45]=4)" -- literal_transitions[20]="([8]=2 [67]=2 [14]=2 [137]=2)" -- -- declare -A match_anything_transitions -- match_anything_transitions=([1]=2 [0]=7 [6]=2 [15]=2 [10]=2 [5]=15 [14]=18 [7]=7 [2]=18 [16]=2 [12]=2 [11]=18) -+ literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)" -+ literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)" -+ literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)" -+ literal_transitions[6]="([126]=2)" -+ literal_transitions[10]="([56]=2)" -+ literal_transitions[11]="([9]=2)" -+ literal_transitions[12]="([14]=19 [80]=22)" -+ literal_transitions[13]="([142]=2)" -+ literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)" -+ literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)" -+ literal_transitions[16]="([40]=2 [44]=2)" -+ literal_transitions[17]="([7]=23)" -+ literal_transitions[18]="([31]=2 [149]=2)" -+ literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)" -+ literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)" -+ literal_transitions[23]="([57]=21 [110]=21)" -+ declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1) - declare -A subword_transitions - - local state=0 -@@ -79,21 +79,9 @@ _hyprctl () { - done - - -- local prefix="${words[$cword]}" -- -- local shortest_suffix="$word" -- for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do -- local char="${COMP_WORDBREAKS:$i:1}" -- local candidate="${word##*$char}" -- if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then -- shortest_suffix=$candidate -- fi -- done -- local superfluous_prefix="" -- if [[ "$shortest_suffix" != "$word" ]]; then -- local superfluous_prefix=${word%$shortest_suffix} -- fi -+ local -a matches=() - -+ local prefix="${words[$cword]}" - if [[ -v "literal_transitions[$state]" ]]; then - local state_transitions_initializer=${literal_transitions[$state]} - declare -A state_transitions -@@ -102,25 +90,38 @@ _hyprctl () { - for literal_id in "${!state_transitions[@]}"; do - local literal="${literals[$literal_id]}" - if [[ $literal = "${prefix}"* ]]; then -- local completion=${literal#"$superfluous_prefix"} -- COMPREPLY+=("$completion ") -+ matches+=("$literal ") - fi - done - fi - declare -A commands -- commands=([5]=1 [16]=2 [12]=3 [10]=0) -+ commands=([7]=0 [22]=1 [8]=3 [5]=2) - if [[ -v "commands[$state]" ]]; then - local command_id=${commands[$state]} - local completions=() -- mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1) -+ readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1) - for item in "${completions[@]}"; do - if [[ $item = "${prefix}"* ]]; then -- COMPREPLY+=("$item") -+ matches+=("$item") - fi - done - fi - - -+ local shortest_suffix="$prefix" -+ for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do -+ local char="${COMP_WORDBREAKS:$i:1}" -+ local candidate=${prefix##*$char} -+ if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then -+ shortest_suffix=$candidate -+ fi -+ done -+ local superfluous_prefix="" -+ if [[ "$shortest_suffix" != "$prefix" ]]; then -+ local superfluous_prefix=${prefix%$shortest_suffix} -+ fi -+ COMPREPLY=("${matches[@]#$superfluous_prefix}") -+ - return 0 - } - -diff --git a/hyprctl/hyprctl.fish b/hyprctl/hyprctl.fish -index c5c03e49..11309416 100644 ---- a/hyprctl/hyprctl.fish -+++ b/hyprctl/hyprctl.fish -@@ -1,21 +1,21 @@ --function _hyprctl_3 -+function _hyprctl_2 - set 1 $argv[1] - hyprctl monitors | awk '/Monitor/{ print $2 }' - end - - function _hyprctl_4 - set 1 $argv[1] -- hyprpm list | awk '/Plugin/{ print $4 }' -+ hyprctl clients | awk '/class/{print $2}' - end - --function _hyprctl_1 -+function _hyprctl_3 - set 1 $argv[1] -- hyprctl clients | awk '/class/{ print $2 }' -+ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' - end - --function _hyprctl_2 -+function _hyprctl_1 - set 1 $argv[1] -- hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' -+ hyprpm list | awk '/Plugin/{print $4}' - end - - function _hyprctl -@@ -29,145 +29,160 @@ function _hyprctl - set COMP_CWORD (count $COMP_WORDS) - end - -- set --local literals "cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow" -- -- set --local descriptions -- set descriptions[1] "Focus the next window on a workspace" -- set descriptions[3] "Get the current cursor pos in global layout coordinates" -- set descriptions[5] "Rename a workspace" -- set descriptions[7] "Focus the first window matching" -- set descriptions[10] "Swap the focused window with the next window" -- set descriptions[12] "Move the active window" -- set descriptions[16] "List the layers" -- set descriptions[18] "List active outputs with their properties" -- set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it" -- set descriptions[21] "Set the current window's floating state to false" -- set descriptions[22] "ERROR" -- set descriptions[23] "Focus a monitor" -- set descriptions[24] "Swap the active window with another window" -- set descriptions[25] "Move the active window out of a group" -- set descriptions[26] "Send a notification using the built-in Hyprland notification system" -- set descriptions[27] "Move the cursor to a specified position" -- set descriptions[28] "Set the cursor theme and reloads the cursor manager" -- set descriptions[29] "Set the hyprctl error string" -- set descriptions[30] "Move the active workspace to a monitor" -- set descriptions[31] "CONFUSED" -- set descriptions[34] "Set a property of a window" -- set descriptions[35] "Specify the Hyprland instance" -- set descriptions[36] "Disable output" -- set descriptions[37] "Toggle the current window's floating state" -- set descriptions[38] "Get the list of defined workspace rules" -- set descriptions[39] "Move the focused window to a workspace" -- set descriptions[41] "Temporarily enable or disable binds:ignore_group_lock" -- set descriptions[42] "List all workspaces with their properties" -- set descriptions[43] "Swap the active window with the next or previous in a group" -- set descriptions[44] "Close a specified window" -- set descriptions[45] "WARNING" -- set descriptions[46] "Specify the Hyprland instance" -- set descriptions[47] "List all registered binds" -- set descriptions[48] "Move the active window in a direction or to a monitor" -- set descriptions[49] "Change the split ratio" -- set descriptions[51] "Prohibit the active window from becoming or being inserted into group" -- set descriptions[52] "Change the workspace" -- set descriptions[53] "List all current config parsing errors" -- set descriptions[54] "Toggle the current active window into a group" -- set descriptions[55] "Get the config option status (values)" -- set descriptions[58] "Close the active window" -- set descriptions[59] "Pass the key to a specified window" -- set descriptions[60] "List all decorations and their info" -- set descriptions[61] "List all connected keyboards and mice" -- set descriptions[62] "Switch focus from current to previously focused window" -- set descriptions[63] "Change the current mapping group" -- set descriptions[64] "Execute a Global Shortcut using the GlobalShortcuts portal" -- set descriptions[66] "Force the renderer to reload all resources and outputs" -- set descriptions[67] "Move a selected window" -- set descriptions[69] "Print the Hyprland version: flags, commit and branch of build" -- set descriptions[70] "Set all monitors' DPMS status" -- set descriptions[71] "Resize the active window" -- set descriptions[72] "Move the active window into a group" -- set descriptions[73] "OK" -- set descriptions[75] "Set the current window's floating state to true" -- set descriptions[76] "Print tail of the log" -- set descriptions[79] "List all layouts available (including plugin ones)" -- set descriptions[80] "Move a workspace to a monitor" -- set descriptions[81] "Execute a shell command" -- set descriptions[83] "Modify the window stack order of the active or specified window" -- set descriptions[84] "Toggle the focused window's internal fullscreen state" -- set descriptions[86] "Issue a keyword to call a config keyword dynamically" -- set descriptions[89] "Disable output" -- set descriptions[90] "Pin a window" -- set descriptions[91] "Allows adding/removing fake outputs to a specific backend" -- set descriptions[93] "Toggle a special workspace on/off" -- set descriptions[94] "Toggle the focused window's fullscreen state" -- set descriptions[95] "Toggle the current window to always be opaque" -- set descriptions[96] "Focus the requested workspace" -- set descriptions[98] "Switch to the next window in a group" -- set descriptions[99] "Output in JSON format" -- set descriptions[100] "List all running Hyprland instances and their info" -- set descriptions[101] "Execute a raw shell command" -- set descriptions[102] "Exit the compositor with no questions asked" -- set descriptions[103] "List all windows with their properties" -- set descriptions[105] "Execute a batch of commands separated by ;" -- set descriptions[106] "Dismiss all or up to amount of notifications" -- set descriptions[108] "Set the xkb layout index for a keyboard" -- set descriptions[109] "Move window doesnt switch to the workspace" -- set descriptions[110] "Apply a tag to the window" -- set descriptions[111] "Behave as moveintogroup" -- set descriptions[112] "Refresh state after issuing the command" -- set descriptions[113] "Move the focus in a direction" -- set descriptions[114] "Focus the urgent window or the last window" -- set descriptions[116] "Get the active workspace name and its properties" -- set descriptions[117] "Issue a dispatch to call a keybind dispatcher with an arg" -- set descriptions[119] "Center the active window" -- set descriptions[120] "HINT" -- set descriptions[121] "Interact with hyprpaper if present" -- set descriptions[122] "No Icon" -- set descriptions[123] "Force reload the config" -- set descriptions[125] "Print system info" -- set descriptions[126] "Interact with a plugin" -- set descriptions[128] "Get the active window name and its properties" -- set descriptions[129] "Swap the active workspaces between two monitors" -- set descriptions[130] "Print the current random splash" -- set descriptions[131] "On shortcut X sends shortcut Y to a specified window" -- set descriptions[133] "Lock the focused group" -- set descriptions[136] "Lock the groups" -- set descriptions[137] "Move the cursor to the corner of the active window" -- set descriptions[140] "INFO" -- set descriptions[141] "Resize a selected window" -- -- set --local literal_transitions -- set literal_transitions[1] "set inputs 106 76 34 36 2 3 79 108 38 112 42 47 116 86 117 53 89 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 99 100 28 29 103 105; set tos 2 3 4 5 3 3 3 6 3 5 3 3 3 7 9 3 5 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 5 3 3 15 3 5" -- set literal_transitions[4] "set inputs 74 14 33 56 57 92 107 124 78 17 127 4 6 65 132 134 82 135 85 32 50 13 87 11 88 142; set tos 18 3 18 18 18 18 3 3 2 3 18 2 3 18 3 18 18 18 18 18 3 3 18 18 18 18" -- set literal_transitions[8] "set inputs 106 76 34 2 3 79 108 38 42 47 116 86 117 53 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 100 28 29 103; set tos 2 3 4 3 3 3 6 3 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 3 3 15 3" -- set literal_transitions[9] "set inputs 102 131 133 1 75 37 109 110 39 111 5 80 41 81 114 7 43 44 83 84 48 49 10 51 52 54 12 113 90 119 58 93 59 94 95 62 63 129 96 64 21 98 23 24 66 67 136 137 25 27 70 101 71 141 30 72; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3" -- set literal_transitions[10] "set inputs 118 115; set tos 21 17" -- set literal_transitions[12] "set inputs 104; set tos 3" -- set literal_transitions[14] "set inputs 22 120 31 140 122 45 73; set tos 2 2 2 2 2 2 2" -- set literal_transitions[15] "set inputs 40; set tos 3" -- set literal_transitions[16] "set inputs 139 97; set tos 3 3" -- set literal_transitions[18] "set inputs 19 8; set tos 3 3" -- set literal_transitions[19] "set inputs 77; set tos 20" -- set literal_transitions[20] "set inputs 35 46; set tos 5 5" -- set literal_transitions[21] "set inputs 9 68 15 138; set tos 3 3 3 3" -- -- set --local match_anything_transitions_from 2 1 7 16 11 6 15 8 3 17 13 12 -- set --local match_anything_transitions_to 3 8 3 3 3 16 19 8 19 3 3 19 -- -- set --local state 1 -- set --local word_index 2 -+ set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize" -+ -+ set descriptions -+ set descriptions[1] "Resize the active window" -+ set descriptions[2] "Fullscreen" -+ set descriptions[3] "Switch to the next window in a group" -+ set descriptions[4] "Refresh state after issuing the command" -+ set descriptions[5] "Move the active window into a group" -+ set descriptions[7] "CONFUSED" -+ set descriptions[9] "Print system info" -+ set descriptions[11] "List all layouts available (including plugin ones)" -+ set descriptions[12] "Set a property of a window" -+ set descriptions[14] "Set the xkb layout index for a keyboard" -+ set descriptions[16] "Prohibit the active window from becoming or being inserted into group" -+ set descriptions[19] "Execute a shell command" -+ set descriptions[20] "Set the cursor theme and reloads the cursor manager" -+ set descriptions[22] "Focus the urgent window or the last window" -+ set descriptions[23] "Get the list of defined workspace rules" -+ set descriptions[24] "Move the active workspace to a monitor" -+ set descriptions[25] "Move window doesnt switch to the workspace" -+ set descriptions[26] "Interact with hyprpaper if present" -+ set descriptions[29] "Swap the active window with the next or previous in a group" -+ set descriptions[30] "Move the cursor to the corner of the active window" -+ set descriptions[31] "Move a selected window" -+ set descriptions[33] "Move the active window in a direction or to a monitor" -+ set descriptions[34] "Lists all global shortcuts" -+ set descriptions[35] "List all windows with their properties" -+ set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock" -+ set descriptions[38] "Print the current random splash" -+ set descriptions[39] "Execute a raw shell command" -+ set descriptions[40] "List active outputs with their properties" -+ set descriptions[43] "Disable output" -+ set descriptions[44] "Gets the current config info about animations and beziers" -+ set descriptions[47] "Change the split ratio" -+ set descriptions[48] "Move the active window" -+ set descriptions[49] "Pass the key to a specified window" -+ set descriptions[50] "Swap the focused window with the next window" -+ set descriptions[51] "List all connected keyboards and mice" -+ set descriptions[52] "List the layers" -+ set descriptions[54] "Lock the focused group" -+ set descriptions[55] "OK" -+ set descriptions[56] "Move a workspace to a monitor" -+ set descriptions[58] "Specify the Hyprland instance" -+ set descriptions[59] "Disable output" -+ set descriptions[61] "Pin a window" -+ set descriptions[62] "WARNING" -+ set descriptions[63] "INFO" -+ set descriptions[66] "Set the current window's floating state to true" -+ set descriptions[69] "On shortcut X sends shortcut Y to a specified window" -+ set descriptions[70] "List all workspaces with their properties" -+ set descriptions[71] "Focus the next window on a workspace" -+ set descriptions[72] "Modify the window stack order of the active or specified window" -+ set descriptions[73] "Toggle the current active window into a group" -+ set descriptions[74] "Lock the groups" -+ set descriptions[76] "Set all monitors' DPMS status" -+ set descriptions[77] "Switch focus from current to previously focused window" -+ set descriptions[78] "No Icon" -+ set descriptions[79] "Execute a batch of commands separated by ;" -+ set descriptions[80] "Send a notification using the built-in Hyprland notification system" -+ set descriptions[82] "List all running Hyprland instances and their info" -+ set descriptions[83] "Maximize no fullscreen" -+ set descriptions[84] "Maximize and fullscreen" -+ set descriptions[85] "Move the active window out of a group" -+ set descriptions[86] "Close the active window" -+ set descriptions[87] "HINT" -+ set descriptions[88] "Move the focused window to a workspace" -+ set descriptions[89] "Move the cursor to a specified position" -+ set descriptions[90] "List all current config parsing errors" -+ set descriptions[91] "Close a specified window" -+ set descriptions[92] "Swap the active window with another window" -+ set descriptions[93] "Apply a tag to the window" -+ set descriptions[94] "Force the renderer to reload all resources and outputs" -+ set descriptions[95] "Center the active window" -+ set descriptions[97] "Focus the first window matching" -+ set descriptions[98] "Set the hyprctl error string" -+ set descriptions[101] "List all registered binds" -+ set descriptions[102] "Print the Hyprland version: flags, commit and branch of build" -+ set descriptions[103] "Prints the help message" -+ set descriptions[104] "Toggle a special workspace on/off" -+ set descriptions[105] "Toggle the focused window's fullscreen state" -+ set descriptions[107] "None" -+ set descriptions[108] "Issue a keyword to call a config keyword dynamically" -+ set descriptions[109] "Toggle the current window to always be opaque" -+ set descriptions[110] "ERROR" -+ set descriptions[111] "Specify the Hyprland instance" -+ set descriptions[112] "Toggle the current window's floating state" -+ set descriptions[113] "Rename a workspace" -+ set descriptions[115] "Get the active workspace name and its properties" -+ set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it" -+ set descriptions[119] "Allows adding/removing fake outputs to a specific backend" -+ set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal" -+ set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg" -+ set descriptions[122] "Force reload the config" -+ set descriptions[124] "Output in JSON format" -+ set descriptions[125] "Emits a custom event to socket2" -+ set descriptions[126] "Prints the help message" -+ set descriptions[128] "Current" -+ set descriptions[129] "Get the active window name and its properties" -+ set descriptions[131] "Dismiss all or up to amount of notifications" -+ set descriptions[132] "Focus a monitor" -+ set descriptions[133] "Move the focus in a direction" -+ set descriptions[134] "Interact with a plugin" -+ set descriptions[135] "Exit the compositor with no questions asked" -+ set descriptions[136] "Change the workspace" -+ set descriptions[137] "Sets the focused window’s fullscreen mode and the one sent to the client" -+ set descriptions[138] "Get the config option status (values)" -+ set descriptions[141] "List all decorations and their info" -+ set descriptions[142] "Set the current window's floating state to false" -+ set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges" -+ set descriptions[145] "Resize a selected window" -+ set descriptions[146] "Toggle the focused window's internal fullscreen state" -+ set descriptions[147] "Print tail of the log" -+ set descriptions[148] "Swap the active workspaces between two monitors" -+ set descriptions[149] "Change the current mapping group" -+ set descriptions[151] "Behave as moveintogroup" -+ set descriptions[152] "Get the current cursor pos in global layout coordinates" -+ set descriptions[154] "Focus the requested workspace" -+ -+ set literal_transitions -+ set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13" -+ set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3" -+ set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17" -+ set literal_transitions[7] "set inputs 127; set tos 3" -+ set literal_transitions[11] "set inputs 57; set tos 3" -+ set literal_transitions[12] "set inputs 10; set tos 3" -+ set literal_transitions[13] "set inputs 15 81; set tos 20 23" -+ set literal_transitions[14] "set inputs 143; set tos 3" -+ set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3" -+ set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5" -+ set literal_transitions[17] "set inputs 41 45; set tos 3 3" -+ set literal_transitions[18] "set inputs 8; set tos 24" -+ set literal_transitions[19] "set inputs 32 150; set tos 3 3" -+ set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3" -+ set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3" -+ set literal_transitions[24] "set inputs 58 111; set tos 22 22" -+ -+ set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2 -+ set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2 -+ -+ set state 1 -+ set word_index 2 - while test $word_index -lt $COMP_CWORD -- set --local -- word $COMP_WORDS[$word_index] -+ set -- word $COMP_WORDS[$word_index] - - if set --query literal_transitions[$state] && test -n $literal_transitions[$state] -- set --local --erase inputs -- set --local --erase tos -+ set --erase inputs -+ set --erase tos - eval $literal_transitions[$state] - - if contains -- $word $literals -- set --local literal_matched 0 -+ set literal_matched 0 - for literal_id in (seq 1 (count $literals)) - if test $literals[$literal_id] = $word -- set --local index (contains --index -- $literal_id $inputs) -+ set index (contains --index -- $literal_id $inputs) - set state $tos[$index] - set word_index (math $word_index + 1) - set literal_matched 1 -@@ -181,7 +196,7 @@ function _hyprctl - end - - if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state] -- set --local index (contains --index -- $state $match_anything_transitions_from) -+ set index (contains --index -- $state $match_anything_transitions_from) - set state $match_anything_transitions_to[$index] - set word_index (math $word_index + 1) - continue -@@ -191,8 +206,8 @@ function _hyprctl - end - - if set --query literal_transitions[$state] && test -n $literal_transitions[$state] -- set --local --erase inputs -- set --local --erase tos -+ set --erase inputs -+ set --erase tos - eval $literal_transitions[$state] - for literal_id in $inputs - if test -n $descriptions[$literal_id] -@@ -203,14 +218,14 @@ function _hyprctl - end - end - -- set command_states 6 17 13 11 -- set command_ids 2 3 4 1 -+ set command_states 8 23 9 6 -+ set command_ids 1 2 4 3 - if contains $state $command_states -- set --local index (contains --index $state $command_states) -- set --local function_id $command_ids[$index] -- set --local function_name _hyprctl_$function_id -- set --local --erase inputs -- set --local --erase tos -+ set index (contains --index $state $command_states) -+ set function_id $command_ids[$index] -+ set function_name _hyprctl_$function_id -+ set --erase inputs -+ set --erase tos - $function_name "$COMP_WORDS[$COMP_CWORD]" - end - -diff --git a/hyprctl/hyprctl.usage b/hyprctl/hyprctl.usage -index 298d253e..b2c55682 100644 ---- a/hyprctl/hyprctl.usage -+++ b/hyprctl/hyprctl.usage -@@ -2,13 +2,14 @@ - # Repo: https://github.com/adaszko/complgen - # Generate completion scripts: "complgen aot --bash-script hyprctl.bash --fish-script hyprctl.fish --zsh-script hyprctl.zsh ./hyprctl.usage" - --hyprctl []... -+hyprctl []... - - ::= (-i | --instance) "Specify the Hyprland instance" - | (-j) "Output in JSON format" - | (-r) "Refresh state after issuing the command" - | (--batch) "Execute a batch of commands separated by ;" - | (-q | --quiet) "Disable output" -+ | (-h | --help) "Prints the help message" - ; - - ::= {{{ hyprctl clients | awk '/class/{print $2}' }}}; -@@ -59,16 +60,18 @@ hyprctl []... - - ::= (activewindow) "Get the active window name and its properties" - | (activeworkspace) "Get the active workspace name and its properties" -+ | (animations) "Gets the current config info about animations and beziers" - | (binds) "List all registered binds" - | (clients) "List all windows with their properties" - | (configerrors) "List all current config parsing errors" - | (cursorpos) "Get the current cursor pos in global layout coordinates" - | (decorations ) "List all decorations and their info" -+ | (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges" - | (devices) "List all connected keyboards and mice" - | (dismissnotify ) "Dismiss all or up to amount of notifications" - | (dispatch ) "Issue a dispatch to call a keybind dispatcher with an arg" - | (getoption) "Get the config option status (values)" -- | (globalshortcuts) "" -+ | (globalshortcuts) "Lists all global shortcuts" - | (hyprpaper) "Interact with hyprpaper if present" - | (instances) "List all running Hyprland instances and their info" - | (keyword ) "Issue a keyword to call a config keyword dynamically" -@@ -79,8 +82,8 @@ hyprctl []... - | (notify ) "Send a notification using the built-in Hyprland notification system" - | (output (create (wayland | x11 | headless | auto) | remove )) "Allows adding/removing fake outputs to a specific backend" - | (plugin ) "Interact with a plugin" -- | (reload) "Force reload the config" -- | (rollinglog) "Print tail of the log" -+ | (reload [config-only]) "Force reload the config" -+ | (rollinglog [-f]) "Print tail of the log" - | (setcursor) "Set the cursor theme and reloads the cursor manager" - | (seterror [disable]) "Set the hyprctl error string" - | (setprop ) "Set a property of a window" -@@ -92,6 +95,13 @@ hyprctl []... - | (workspaces) "List all workspaces with their properties" - ; - -+ ::= (-1) "Current" -+ | (0) "None" -+ | (1) "Maximize no fullscreen" -+ | (2) "Fullscreen" -+ | (3) "Maximize and fullscreen" -+ ; -+ - ::= (exec) "Execute a shell command" - | (execr) "Execute a raw shell command" - | (pass) "Pass the key to a specified window" -@@ -106,6 +116,7 @@ hyprctl []... - | (settiled) "Set the current window's floating state to false" - | (fullscreen) "Toggle the focused window's fullscreen state" - | (fakefullscreen) "Toggle the focused window's internal fullscreen state" -+ | (fullscreenstate ) "Sets the focused window’s fullscreen mode and the one sent to the client" - | (dpms) "Set all monitors' DPMS status" - | (pin) "Pin a window" - | (movefocus) "Move the focus in a direction" -@@ -148,4 +159,5 @@ hyprctl []... - | (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock" - | (global) "Execute a Global Shortcut using the GlobalShortcuts portal" - | (submap) "Change the current mapping group" -+ | (event) "Emits a custom event to socket2" - ; -diff --git a/hyprctl/hyprctl.zsh b/hyprctl/hyprctl.zsh -index aeac9663..9a858100 100644 ---- a/hyprctl/hyprctl.zsh -+++ b/hyprctl/hyprctl.zsh -@@ -1,145 +1,160 @@ - #compdef hyprctl - --_hyprctl_cmd_2 () { -+_hyprctl_cmd_1 () { - hyprctl monitors | awk '/Monitor/{ print $2 }' - } - - _hyprctl_cmd_3 () { -- hyprpm list | awk '/Plugin/{ print $4 }' -+ hyprctl clients | awk '/class/{print $2}' - } - --_hyprctl_cmd_0 () { -- hyprctl clients | awk '/class/{ print $2 }' -+_hyprctl_cmd_2 () { -+ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' - } - --_hyprctl_cmd_1 () { -- hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' -+_hyprctl_cmd_0 () { -+ hyprpm list | awk '/Plugin/{print $4}' - } - - _hyprctl () { -- local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow") -+ local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize") - - local -A descriptions -- descriptions[1]="Focus the next window on a workspace" -- descriptions[3]="Get the current cursor pos in global layout coordinates" -- descriptions[5]="Rename a workspace" -- descriptions[7]="Focus the first window matching" -- descriptions[10]="Swap the focused window with the next window" -- descriptions[12]="Move the active window" -- descriptions[16]="List the layers" -- descriptions[18]="List active outputs with their properties" -- descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it" -- descriptions[21]="Set the current window's floating state to false" -- descriptions[22]="ERROR" -- descriptions[23]="Focus a monitor" -- descriptions[24]="Swap the active window with another window" -- descriptions[25]="Move the active window out of a group" -- descriptions[26]="Send a notification using the built-in Hyprland notification system" -- descriptions[27]="Move the cursor to a specified position" -- descriptions[28]="Set the cursor theme and reloads the cursor manager" -- descriptions[29]="Set the hyprctl error string" -- descriptions[30]="Move the active workspace to a monitor" -- descriptions[31]="CONFUSED" -- descriptions[34]="Set a property of a window" -- descriptions[35]="Specify the Hyprland instance" -- descriptions[36]="Disable output" -- descriptions[37]="Toggle the current window's floating state" -- descriptions[38]="Get the list of defined workspace rules" -- descriptions[39]="Move the focused window to a workspace" -- descriptions[41]="Temporarily enable or disable binds:ignore_group_lock" -- descriptions[42]="List all workspaces with their properties" -- descriptions[43]="Swap the active window with the next or previous in a group" -- descriptions[44]="Close a specified window" -- descriptions[45]="WARNING" -- descriptions[46]="Specify the Hyprland instance" -- descriptions[47]="List all registered binds" -- descriptions[48]="Move the active window in a direction or to a monitor" -- descriptions[49]="Change the split ratio" -- descriptions[51]="Prohibit the active window from becoming or being inserted into group" -- descriptions[52]="Change the workspace" -- descriptions[53]="List all current config parsing errors" -- descriptions[54]="Toggle the current active window into a group" -- descriptions[55]="Get the config option status (values)" -- descriptions[58]="Close the active window" -- descriptions[59]="Pass the key to a specified window" -- descriptions[60]="List all decorations and their info" -- descriptions[61]="List all connected keyboards and mice" -- descriptions[62]="Switch focus from current to previously focused window" -- descriptions[63]="Change the current mapping group" -- descriptions[64]="Execute a Global Shortcut using the GlobalShortcuts portal" -- descriptions[66]="Force the renderer to reload all resources and outputs" -- descriptions[67]="Move a selected window" -- descriptions[69]="Print the Hyprland version: flags, commit and branch of build" -- descriptions[70]="Set all monitors' DPMS status" -- descriptions[71]="Resize the active window" -- descriptions[72]="Move the active window into a group" -- descriptions[73]="OK" -- descriptions[75]="Set the current window's floating state to true" -- descriptions[76]="Print tail of the log" -- descriptions[79]="List all layouts available (including plugin ones)" -- descriptions[80]="Move a workspace to a monitor" -- descriptions[81]="Execute a shell command" -- descriptions[83]="Modify the window stack order of the active or specified window" -- descriptions[84]="Toggle the focused window's internal fullscreen state" -- descriptions[86]="Issue a keyword to call a config keyword dynamically" -- descriptions[89]="Disable output" -- descriptions[90]="Pin a window" -- descriptions[91]="Allows adding/removing fake outputs to a specific backend" -- descriptions[93]="Toggle a special workspace on/off" -- descriptions[94]="Toggle the focused window's fullscreen state" -- descriptions[95]="Toggle the current window to always be opaque" -- descriptions[96]="Focus the requested workspace" -- descriptions[98]="Switch to the next window in a group" -- descriptions[99]="Output in JSON format" -- descriptions[100]="List all running Hyprland instances and their info" -- descriptions[101]="Execute a raw shell command" -- descriptions[102]="Exit the compositor with no questions asked" -- descriptions[103]="List all windows with their properties" -- descriptions[105]="Execute a batch of commands separated by ;" -- descriptions[106]="Dismiss all or up to amount of notifications" -- descriptions[108]="Set the xkb layout index for a keyboard" -- descriptions[109]="Move window doesnt switch to the workspace" -- descriptions[110]="Apply a tag to the window" -- descriptions[111]="Behave as moveintogroup" -- descriptions[112]="Refresh state after issuing the command" -- descriptions[113]="Move the focus in a direction" -- descriptions[114]="Focus the urgent window or the last window" -- descriptions[116]="Get the active workspace name and its properties" -- descriptions[117]="Issue a dispatch to call a keybind dispatcher with an arg" -- descriptions[119]="Center the active window" -- descriptions[120]="HINT" -- descriptions[121]="Interact with hyprpaper if present" -- descriptions[122]="No Icon" -- descriptions[123]="Force reload the config" -- descriptions[125]="Print system info" -- descriptions[126]="Interact with a plugin" -- descriptions[128]="Get the active window name and its properties" -- descriptions[129]="Swap the active workspaces between two monitors" -- descriptions[130]="Print the current random splash" -- descriptions[131]="On shortcut X sends shortcut Y to a specified window" -- descriptions[133]="Lock the focused group" -- descriptions[136]="Lock the groups" -- descriptions[137]="Move the cursor to the corner of the active window" -- descriptions[140]="INFO" -- descriptions[141]="Resize a selected window" -+ descriptions[1]="Resize the active window" -+ descriptions[2]="Fullscreen" -+ descriptions[3]="Switch to the next window in a group" -+ descriptions[4]="Refresh state after issuing the command" -+ descriptions[5]="Move the active window into a group" -+ descriptions[7]="CONFUSED" -+ descriptions[9]="Print system info" -+ descriptions[11]="List all layouts available (including plugin ones)" -+ descriptions[12]="Set a property of a window" -+ descriptions[14]="Set the xkb layout index for a keyboard" -+ descriptions[16]="Prohibit the active window from becoming or being inserted into group" -+ descriptions[19]="Execute a shell command" -+ descriptions[20]="Set the cursor theme and reloads the cursor manager" -+ descriptions[22]="Focus the urgent window or the last window" -+ descriptions[23]="Get the list of defined workspace rules" -+ descriptions[24]="Move the active workspace to a monitor" -+ descriptions[25]="Move window doesnt switch to the workspace" -+ descriptions[26]="Interact with hyprpaper if present" -+ descriptions[29]="Swap the active window with the next or previous in a group" -+ descriptions[30]="Move the cursor to the corner of the active window" -+ descriptions[31]="Move a selected window" -+ descriptions[33]="Move the active window in a direction or to a monitor" -+ descriptions[34]="Lists all global shortcuts" -+ descriptions[35]="List all windows with their properties" -+ descriptions[37]="Temporarily enable or disable binds:ignore_group_lock" -+ descriptions[38]="Print the current random splash" -+ descriptions[39]="Execute a raw shell command" -+ descriptions[40]="List active outputs with their properties" -+ descriptions[43]="Disable output" -+ descriptions[44]="Gets the current config info about animations and beziers" -+ descriptions[47]="Change the split ratio" -+ descriptions[48]="Move the active window" -+ descriptions[49]="Pass the key to a specified window" -+ descriptions[50]="Swap the focused window with the next window" -+ descriptions[51]="List all connected keyboards and mice" -+ descriptions[52]="List the layers" -+ descriptions[54]="Lock the focused group" -+ descriptions[55]="OK" -+ descriptions[56]="Move a workspace to a monitor" -+ descriptions[58]="Specify the Hyprland instance" -+ descriptions[59]="Disable output" -+ descriptions[61]="Pin a window" -+ descriptions[62]="WARNING" -+ descriptions[63]="INFO" -+ descriptions[66]="Set the current window's floating state to true" -+ descriptions[69]="On shortcut X sends shortcut Y to a specified window" -+ descriptions[70]="List all workspaces with their properties" -+ descriptions[71]="Focus the next window on a workspace" -+ descriptions[72]="Modify the window stack order of the active or specified window" -+ descriptions[73]="Toggle the current active window into a group" -+ descriptions[74]="Lock the groups" -+ descriptions[76]="Set all monitors' DPMS status" -+ descriptions[77]="Switch focus from current to previously focused window" -+ descriptions[78]="No Icon" -+ descriptions[79]="Execute a batch of commands separated by ;" -+ descriptions[80]="Send a notification using the built-in Hyprland notification system" -+ descriptions[82]="List all running Hyprland instances and their info" -+ descriptions[83]="Maximize no fullscreen" -+ descriptions[84]="Maximize and fullscreen" -+ descriptions[85]="Move the active window out of a group" -+ descriptions[86]="Close the active window" -+ descriptions[87]="HINT" -+ descriptions[88]="Move the focused window to a workspace" -+ descriptions[89]="Move the cursor to a specified position" -+ descriptions[90]="List all current config parsing errors" -+ descriptions[91]="Close a specified window" -+ descriptions[92]="Swap the active window with another window" -+ descriptions[93]="Apply a tag to the window" -+ descriptions[94]="Force the renderer to reload all resources and outputs" -+ descriptions[95]="Center the active window" -+ descriptions[97]="Focus the first window matching" -+ descriptions[98]="Set the hyprctl error string" -+ descriptions[101]="List all registered binds" -+ descriptions[102]="Print the Hyprland version: flags, commit and branch of build" -+ descriptions[103]="Prints the help message" -+ descriptions[104]="Toggle a special workspace on/off" -+ descriptions[105]="Toggle the focused window's fullscreen state" -+ descriptions[107]="None" -+ descriptions[108]="Issue a keyword to call a config keyword dynamically" -+ descriptions[109]="Toggle the current window to always be opaque" -+ descriptions[110]="ERROR" -+ descriptions[111]="Specify the Hyprland instance" -+ descriptions[112]="Toggle the current window's floating state" -+ descriptions[113]="Rename a workspace" -+ descriptions[115]="Get the active workspace name and its properties" -+ descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it" -+ descriptions[119]="Allows adding/removing fake outputs to a specific backend" -+ descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal" -+ descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg" -+ descriptions[122]="Force reload the config" -+ descriptions[124]="Output in JSON format" -+ descriptions[125]="Emits a custom event to socket2" -+ descriptions[126]="Prints the help message" -+ descriptions[128]="Current" -+ descriptions[129]="Get the active window name and its properties" -+ descriptions[131]="Dismiss all or up to amount of notifications" -+ descriptions[132]="Focus a monitor" -+ descriptions[133]="Move the focus in a direction" -+ descriptions[134]="Interact with a plugin" -+ descriptions[135]="Exit the compositor with no questions asked" -+ descriptions[136]="Change the workspace" -+ descriptions[137]="Sets the focused window’s fullscreen mode and the one sent to the client" -+ descriptions[138]="Get the config option status (values)" -+ descriptions[141]="List all decorations and their info" -+ descriptions[142]="Set the current window's floating state to false" -+ descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges" -+ descriptions[145]="Resize a selected window" -+ descriptions[146]="Toggle the focused window's internal fullscreen state" -+ descriptions[147]="Print tail of the log" -+ descriptions[148]="Swap the active workspaces between two monitors" -+ descriptions[149]="Change the current mapping group" -+ descriptions[151]="Behave as moveintogroup" -+ descriptions[152]="Get the current cursor pos in global layout coordinates" -+ descriptions[154]="Focus the requested workspace" - - local -A literal_transitions -- literal_transitions[1]="([106]=2 [76]=3 [34]=4 [36]=5 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [112]=5 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [89]=5 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [99]=5 [100]=3 [28]=3 [29]=15 [103]=3 [105]=5)" -- literal_transitions[4]="([74]=18 [14]=3 [33]=18 [56]=18 [57]=18 [92]=18 [107]=3 [124]=3 [78]=2 [17]=3 [127]=18 [4]=2 [6]=3 [65]=18 [132]=3 [134]=18 [82]=18 [135]=18 [85]=18 [32]=18 [50]=3 [13]=3 [87]=18 [11]=18 [88]=18 [142]=18)" -- literal_transitions[8]="([106]=2 [76]=3 [34]=4 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [100]=3 [28]=3 [29]=15 [103]=3)" -- literal_transitions[9]="([102]=3 [131]=3 [133]=3 [1]=3 [75]=3 [37]=3 [109]=3 [110]=3 [39]=3 [111]=3 [5]=3 [80]=3 [41]=3 [81]=3 [114]=3 [7]=3 [43]=3 [44]=3 [83]=3 [84]=3 [48]=3 [49]=3 [10]=3 [51]=3 [52]=3 [54]=3 [12]=3 [113]=3 [90]=3 [119]=3 [58]=3 [93]=3 [59]=3 [94]=3 [95]=3 [62]=3 [63]=3 [129]=3 [96]=3 [64]=3 [21]=3 [98]=3 [23]=3 [24]=3 [66]=3 [67]=3 [136]=3 [137]=3 [25]=3 [27]=3 [70]=3 [101]=3 [71]=3 [141]=3 [30]=3 [72]=3)" -- literal_transitions[10]="([118]=21 [115]=17)" -- literal_transitions[12]="([104]=3)" -- literal_transitions[14]="([22]=2 [120]=2 [31]=2 [140]=2 [122]=2 [45]=2 [73]=2)" -- literal_transitions[15]="([40]=3)" -- literal_transitions[16]="([139]=3 [97]=3)" -- literal_transitions[18]="([19]=3 [8]=3)" -- literal_transitions[19]="([77]=20)" -- literal_transitions[20]="([35]=5 [46]=5)" -- literal_transitions[21]="([9]=3 [68]=3 [15]=3 [138]=3)" -+ literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)" -+ literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)" -+ literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)" -+ literal_transitions[7]="([127]=3)" -+ literal_transitions[11]="([57]=3)" -+ literal_transitions[12]="([10]=3)" -+ literal_transitions[13]="([15]=20 [81]=23)" -+ literal_transitions[14]="([143]=3)" -+ literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)" -+ literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)" -+ literal_transitions[17]="([41]=3 [45]=3)" -+ literal_transitions[18]="([8]=24)" -+ literal_transitions[19]="([32]=3 [150]=3)" -+ literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)" -+ literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)" -+ literal_transitions[24]="([58]=22 [111]=22)" - - local -A match_anything_transitions -- match_anything_transitions=([2]=3 [1]=8 [7]=3 [16]=3 [11]=3 [6]=16 [15]=19 [8]=8 [3]=19 [17]=3 [13]=3 [12]=19) -+ match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2) - - declare -A subword_transitions - -@@ -199,7 +214,7 @@ _hyprctl () { - fi - done - fi -- local -A commands=([6]=1 [17]=2 [13]=3 [11]=0) -+ local -A commands=([8]=0 [23]=1 [9]=3 [6]=2) - - if [[ -v "commands[$state]" ]]; then - local command_id=${commands[$state]} -@@ -252,4 +267,8 @@ _hyprctl () { - return 0 - } - --compdef _hyprctl hyprctl -+if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then -+ compdef _hyprctl hyprctl -+else -+ _hyprctl -+fi -diff --git a/hyprpm/hyprpm.bash b/hyprpm/hyprpm.bash -index ffc33e19..3c2bc90b 100644 ---- a/hyprpm/hyprpm.bash -+++ b/hyprpm/hyprpm.bash -@@ -2,6 +2,10 @@ _hyprpm_cmd_0 () { - hyprpm list | awk '/Plugin/{print $4}' - } - -+_hyprpm_cmd_1 () { -+ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' -+} -+ - _hyprpm () { - if [[ $(type -t _get_comp_words_by_ref) != function ]]; then - echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed -@@ -11,16 +15,13 @@ _hyprpm () { - local words cword - _get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword - -- local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f") -- -+ declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f) - declare -A literal_transitions -- literal_transitions[0]="([9]=6 [2]=2 [7]=6 [8]=6 [4]=6 [10]=2 [11]=3 [5]=2 [13]=6 [3]=3 [14]=2 [15]=6 [6]=2)" -- literal_transitions[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)" -- literal_transitions[4]="([1]=5)" -- literal_transitions[5]="([0]=6 [12]=6)" -- -- declare -A match_anything_transitions -- match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1) -+ literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)" -+ literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)" -+ literal_transitions[5]="([2]=6)" -+ literal_transitions[6]="([1]=7 [14]=7)" -+ declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1) - declare -A subword_transitions - - local state=0 -@@ -58,21 +59,9 @@ _hyprpm () { - done - - -- local prefix="${words[$cword]}" -- -- local shortest_suffix="$word" -- for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do -- local char="${COMP_WORDBREAKS:$i:1}" -- local candidate="${word##*$char}" -- if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then -- shortest_suffix=$candidate -- fi -- done -- local superfluous_prefix="" -- if [[ "$shortest_suffix" != "$word" ]]; then -- local superfluous_prefix=${word%$shortest_suffix} -- fi -+ local -a matches=() - -+ local prefix="${words[$cword]}" - if [[ -v "literal_transitions[$state]" ]]; then - local state_transitions_initializer=${literal_transitions[$state]} - declare -A state_transitions -@@ -81,25 +70,38 @@ _hyprpm () { - for literal_id in "${!state_transitions[@]}"; do - local literal="${literals[$literal_id]}" - if [[ $literal = "${prefix}"* ]]; then -- local completion=${literal#"$superfluous_prefix"} -- COMPREPLY+=("$completion ") -+ matches+=("$literal ") - fi - done - fi - declare -A commands -- commands=([3]=0) -+ commands=([3]=0 [2]=1) - if [[ -v "commands[$state]" ]]; then - local command_id=${commands[$state]} - local completions=() -- mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1) -+ readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1) - for item in "${completions[@]}"; do - if [[ $item = "${prefix}"* ]]; then -- COMPREPLY+=("$item") -+ matches+=("$item") - fi - done - fi - - -+ local shortest_suffix="$prefix" -+ for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do -+ local char="${COMP_WORDBREAKS:$i:1}" -+ local candidate=${prefix##*$char} -+ if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then -+ shortest_suffix=$candidate -+ fi -+ done -+ local superfluous_prefix="" -+ if [[ "$shortest_suffix" != "$prefix" ]]; then -+ local superfluous_prefix=${prefix%$shortest_suffix} -+ fi -+ COMPREPLY=("${matches[@]#$superfluous_prefix}") -+ - return 0 - } - -diff --git a/hyprpm/hyprpm.fish b/hyprpm/hyprpm.fish -index 7be4f224..82561bd8 100644 ---- a/hyprpm/hyprpm.fish -+++ b/hyprpm/hyprpm.fish -@@ -3,6 +3,11 @@ function _hyprpm_1 - hyprpm list | awk '/Plugin/{print $4}' - end - -+function _hyprpm_2 -+ set 1 $argv[1] -+ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' -+end -+ - function _hyprpm - set COMP_LINE (commandline --cut-at-cursor) - -@@ -14,49 +19,51 @@ function _hyprpm - set COMP_CWORD (count $COMP_WORDS) - end - -- set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f" -+ set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f" - -- set --local descriptions -- set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)" -- set descriptions[3] "List all installed plugins" -+ set descriptions -+ set descriptions[1] "Disable shallow cloning of Hyprland sources" -+ set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)" - set descriptions[4] "Unload a plugin" -- set descriptions[5] "Show help menu" -- set descriptions[6] "Check and update all plugins if needed" -- set descriptions[7] "Install a new plugin repository from git" -- set descriptions[8] "Enable too much loggin" -+ set descriptions[5] "List all installed plugins" -+ set descriptions[6] "Show help menu" -+ set descriptions[7] "Check and update all plugins if needed" -+ set descriptions[8] "Install a new plugin repository from git" - set descriptions[9] "Enable too much loggin" -- set descriptions[10] "Force an operation ignoring checks (e.g. update -f)" -- set descriptions[11] "Remove a plugin repository" -- set descriptions[12] "Load a plugin" -- set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)" -- set descriptions[14] "Show help menu" -- set descriptions[15] "Reload all plugins" -- set descriptions[16] "Force an operation ignoring checks (e.g. update -f)" -- -- set --local literal_transitions -- set literal_transitions[1] "set inputs 10 3 8 9 5 11 12 6 14 4 15 16 7; set tos 7 3 7 7 7 3 4 3 7 4 3 7 3" -- set literal_transitions[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3" -- set literal_transitions[5] "set inputs 2; set tos 6" -- set literal_transitions[6] "set inputs 1 13; set tos 7 7" -- -- set --local match_anything_transitions_from 4 3 1 2 -- set --local match_anything_transitions_to 3 5 2 2 -- -- set --local state 1 -- set --local word_index 2 -+ set descriptions[10] "Enable too much loggin" -+ set descriptions[11] "Force an operation ignoring checks (e.g. update -f)" -+ set descriptions[12] "Disable shallow cloning of Hyprland sources" -+ set descriptions[13] "Remove a plugin repository" -+ set descriptions[14] "Load a plugin" -+ set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)" -+ set descriptions[16] "Show help menu" -+ set descriptions[17] "Reload all plugins" -+ set descriptions[18] "Force an operation ignoring checks (e.g. update -f)" -+ -+ set literal_transitions -+ set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8" -+ set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5" -+ set literal_transitions[6] "set inputs 3; set tos 7" -+ set literal_transitions[7] "set inputs 2 15; set tos 8 8" -+ -+ set match_anything_transitions_from 2 5 4 3 1 -+ set match_anything_transitions_to 2 6 5 5 2 -+ -+ set state 1 -+ set word_index 2 - while test $word_index -lt $COMP_CWORD -- set --local -- word $COMP_WORDS[$word_index] -+ set -- word $COMP_WORDS[$word_index] - - if set --query literal_transitions[$state] && test -n $literal_transitions[$state] -- set --local --erase inputs -- set --local --erase tos -+ set --erase inputs -+ set --erase tos - eval $literal_transitions[$state] - - if contains -- $word $literals -- set --local literal_matched 0 -+ set literal_matched 0 - for literal_id in (seq 1 (count $literals)) - if test $literals[$literal_id] = $word -- set --local index (contains --index -- $literal_id $inputs) -+ set index (contains --index -- $literal_id $inputs) - set state $tos[$index] - set word_index (math $word_index + 1) - set literal_matched 1 -@@ -70,7 +77,7 @@ function _hyprpm - end - - if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state] -- set --local index (contains --index -- $state $match_anything_transitions_from) -+ set index (contains --index -- $state $match_anything_transitions_from) - set state $match_anything_transitions_to[$index] - set word_index (math $word_index + 1) - continue -@@ -80,8 +87,8 @@ function _hyprpm - end - - if set --query literal_transitions[$state] && test -n $literal_transitions[$state] -- set --local --erase inputs -- set --local --erase tos -+ set --erase inputs -+ set --erase tos - eval $literal_transitions[$state] - for literal_id in $inputs - if test -n $descriptions[$literal_id] -@@ -92,14 +99,14 @@ function _hyprpm - end - end - -- set command_states 4 -- set command_ids 1 -+ set command_states 4 3 -+ set command_ids 1 2 - if contains $state $command_states -- set --local index (contains --index $state $command_states) -- set --local function_id $command_ids[$index] -- set --local function_name _hyprpm_$function_id -- set --local --erase inputs -- set --local --erase tos -+ set index (contains --index $state $command_states) -+ set function_id $command_ids[$index] -+ set function_name _hyprpm_$function_id -+ set --erase inputs -+ set --erase tos - $function_name "$COMP_WORDS[$COMP_CWORD]" - end - -diff --git a/hyprpm/hyprpm.usage b/hyprpm/hyprpm.usage -index 369c9d2b..24e631c5 100644 ---- a/hyprpm/hyprpm.usage -+++ b/hyprpm/hyprpm.usage -@@ -5,10 +5,11 @@ hyprpm []... - | (--help | -h) "Show help menu" - | (--verbose | -v) "Enable too much loggin" - | (--force | -f) "Force an operation ignoring checks (e.g. update -f)" -+ | (--no-shallow | -s) "Disable shallow cloning of Hyprland sources" - ; - - ::= (add) "Install a new plugin repository from git" -- | (remove) "Remove a plugin repository" -+ | (remove ) "Remove a plugin repository" - | (update) "Check and update all plugins if needed" - | (list) "List all installed plugins" - | (enable ) "Load a plugin" -@@ -17,3 +18,4 @@ hyprpm []... - ; - - ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}}; -+ ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}}; -diff --git a/hyprpm/hyprpm.zsh b/hyprpm/hyprpm.zsh -index 854e8426..859c5313 100644 ---- a/hyprpm/hyprpm.zsh -+++ b/hyprpm/hyprpm.zsh -@@ -4,34 +4,40 @@ _hyprpm_cmd_0 () { - hyprpm list | awk '/Plugin/{print $4}' - } - -+_hyprpm_cmd_1 () { -+ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' -+} -+ - _hyprpm () { -- local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f") -+ local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f") - - local -A descriptions -- descriptions[1]="Send a hyprland notification for important events (e.g. load fail)" -- descriptions[3]="List all installed plugins" -+ descriptions[1]="Disable shallow cloning of Hyprland sources" -+ descriptions[2]="Send a hyprland notification for important events (e.g. load fail)" - descriptions[4]="Unload a plugin" -- descriptions[5]="Show help menu" -- descriptions[6]="Check and update all plugins if needed" -- descriptions[7]="Install a new plugin repository from git" -- descriptions[8]="Enable too much loggin" -+ descriptions[5]="List all installed plugins" -+ descriptions[6]="Show help menu" -+ descriptions[7]="Check and update all plugins if needed" -+ descriptions[8]="Install a new plugin repository from git" - descriptions[9]="Enable too much loggin" -- descriptions[10]="Force an operation ignoring checks (e.g. update -f)" -- descriptions[11]="Remove a plugin repository" -- descriptions[12]="Load a plugin" -- descriptions[13]="Send a hyprland notification for important events (e.g. load fail)" -- descriptions[14]="Show help menu" -- descriptions[15]="Reload all plugins" -- descriptions[16]="Force an operation ignoring checks (e.g. update -f)" -+ descriptions[10]="Enable too much loggin" -+ descriptions[11]="Force an operation ignoring checks (e.g. update -f)" -+ descriptions[12]="Disable shallow cloning of Hyprland sources" -+ descriptions[13]="Remove a plugin repository" -+ descriptions[14]="Load a plugin" -+ descriptions[15]="Send a hyprland notification for important events (e.g. load fail)" -+ descriptions[16]="Show help menu" -+ descriptions[17]="Reload all plugins" -+ descriptions[18]="Force an operation ignoring checks (e.g. update -f)" - - local -A literal_transitions -- literal_transitions[1]="([10]=7 [3]=3 [8]=7 [9]=7 [5]=7 [11]=3 [12]=4 [6]=3 [14]=7 [4]=4 [15]=3 [16]=7 [7]=3)" -- literal_transitions[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)" -- literal_transitions[5]="([2]=6)" -- literal_transitions[6]="([1]=7 [13]=7)" -+ literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)" -+ literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)" -+ literal_transitions[6]="([3]=7)" -+ literal_transitions[7]="([2]=8 [15]=8)" - - local -A match_anything_transitions -- match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2) -+ match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2) - - declare -A subword_transitions - -@@ -91,7 +97,7 @@ _hyprpm () { - fi - done - fi -- local -A commands=([4]=0) -+ local -A commands=([4]=0 [3]=1) - - if [[ -v "commands[$state]" ]]; then - local command_id=${commands[$state]} --- -2.45.2 - diff --git a/hosts/callisto/0009-config-add-missing-header-for-libc-after-92744b5b9aa.patch b/hosts/callisto/0009-config-add-missing-header-for-libc-after-92744b5b9aa.patch deleted file mode 100644 index 7398c37..0000000 --- a/hosts/callisto/0009-config-add-missing-header-for-libc-after-92744b5b9aa.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 33015546c62a7b73793d62983a84b097362cec1a Mon Sep 17 00:00:00 2001 -From: Jan Beich -Date: Mon, 19 Aug 2024 12:46:36 +0000 -Subject: [PATCH 09/20] config: add missing header for libc++ after - 92744b5b9aa3 (#7403) - -In file included from src/pch/pch.hpp:1: -In file included from src/Compositor.hpp:11: -src/config/ConfigManager.hpp:147:10: error: no template named 'variant' in namespace 'std' - 147 | std::variant data; - | ~~~~~^ ---- - src/config/ConfigManager.hpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp -index 4241031b..4d087753 100644 ---- a/src/config/ConfigManager.hpp -+++ b/src/config/ConfigManager.hpp -@@ -6,6 +6,7 @@ - #include "../debug/Log.hpp" - #include - #include "../defines.hpp" -+#include - #include - #include - #include --- -2.45.2 - diff --git a/hosts/callisto/0010-examples-more-systemd-examples-7409.patch b/hosts/callisto/0010-examples-more-systemd-examples-7409.patch deleted file mode 100644 index 66bc866..0000000 --- a/hosts/callisto/0010-examples-more-systemd-examples-7409.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 01e3da4d51927427860368c88a523f47c479b710 Mon Sep 17 00:00:00 2001 -From: JL2210 -Date: Mon, 19 Aug 2024 09:02:09 -0400 -Subject: [PATCH 10/20] examples: more systemd examples (#7409) - -These allow launching hyprland with a systemd service. They provide -graphical-session.target which allows enabling services such as the -ones for Waybar and Mako. ---- - example/hyprland-session.service | 14 ++++++++++++++ - example/hyprland-systemd.desktop | 5 +++++ - 2 files changed, 19 insertions(+) - create mode 100644 example/hyprland-session.service - create mode 100644 example/hyprland-systemd.desktop - -diff --git a/example/hyprland-session.service b/example/hyprland-session.service -new file mode 100644 -index 00000000..7d33f5b3 ---- /dev/null -+++ b/example/hyprland-session.service -@@ -0,0 +1,14 @@ -+[Unit] -+Description=Hyprland - Tiling compositor with the looks -+Documentation=man:Hyprland(1) -+BindsTo=graphical-session.target -+Before=graphical-session.target -+Wants=graphical-session-pre.target -+After=graphical-session-pre.target -+ -+[Service] -+Type=notify -+ExecStart=/usr/bin/Hyprland -+ExecStop=/usr/bin/hyprctl dispatch exit -+Restart=on-failure -+Slice=session.slice -diff --git a/example/hyprland-systemd.desktop b/example/hyprland-systemd.desktop -new file mode 100644 -index 00000000..b36a87b2 ---- /dev/null -+++ b/example/hyprland-systemd.desktop -@@ -0,0 +1,5 @@ -+[Desktop Entry] -+Name=Hyprland -+Comment=An intelligent dynamic tiling Wayland compositor -+Exec=systemctl --user start --wait hyprland-session -+Type=Application --- -2.45.2 - diff --git a/hosts/callisto/0011-monitors-avoid-crash-on-wayland-output-removal.patch b/hosts/callisto/0011-monitors-avoid-crash-on-wayland-output-removal.patch deleted file mode 100644 index 0a4350a..0000000 --- a/hosts/callisto/0011-monitors-avoid-crash-on-wayland-output-removal.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 272d9048706379201b761c3159c24a20cd62fad1 Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Mon, 19 Aug 2024 18:36:06 +0200 -Subject: [PATCH 11/20] monitors: avoid crash on wayland output removal - ---- - src/events/Monitors.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp -index b2778062..60fb5bef 100644 ---- a/src/events/Monitors.cpp -+++ b/src/events/Monitors.cpp -@@ -98,7 +98,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) { - if (!pMonitor) - return; - -- Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name); -+ Debug::log(LOG, "Destroy called for monitor {}", pMonitor->szName); - - pMonitor->onDisconnect(true); - --- -2.45.2 - diff --git a/hosts/callisto/0012-monitor-avoid-dangling-references-to-old-monitors-be.patch b/hosts/callisto/0012-monitor-avoid-dangling-references-to-old-monitors-be.patch deleted file mode 100644 index 71d818e..0000000 --- a/hosts/callisto/0012-monitor-avoid-dangling-references-to-old-monitors-be.patch +++ /dev/null @@ -1,146 +0,0 @@ -From c86db7bbb0cf14d4955ee3a4d13c0ed9f8a0e0ae Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Mon, 19 Aug 2024 18:44:22 +0200 -Subject: [PATCH 12/20] monitor: avoid dangling references to old monitors - being undestroyed - -ref #7414 ---- - src/Compositor.cpp | 3 +-- - src/events/Events.hpp | 1 - - src/events/Monitors.cpp | 25 ------------------------- - src/helpers/Monitor.cpp | 21 +++++++++++++++++---- - src/helpers/Monitor.hpp | 2 +- - 5 files changed, 19 insertions(+), 33 deletions(-) - -diff --git a/src/Compositor.cpp b/src/Compositor.cpp -index 1437a653..75c22743 100644 ---- a/src/Compositor.cpp -+++ b/src/Compositor.cpp -@@ -2935,7 +2935,7 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { - - void CCompositor::onNewMonitor(SP output) { - // add it to real -- auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); -+ auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared(output)); - if (std::string("HEADLESS-1") == output->name) { - g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); - output->name = "FALLBACK"; // we are allowed to do this :) -@@ -2944,7 +2944,6 @@ void CCompositor::onNewMonitor(SP output) { - Debug::log(LOG, "New output with name {}", output->name); - - PNEWMONITOR->szName = output->name; -- PNEWMONITOR->output = output; - PNEWMONITOR->self = PNEWMONITOR; - const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; - PNEWMONITOR->ID = FALLBACK ? MONITOR_INVALID : g_pCompositor->getNextAvailableMonitorID(output->name); -diff --git a/src/events/Events.hpp b/src/events/Events.hpp -index 8e73f54a..0af16f64 100644 ---- a/src/events/Events.hpp -+++ b/src/events/Events.hpp -@@ -27,7 +27,6 @@ namespace Events { - - // Monitor part 2 the sequel - DYNLISTENFUNC(monitorFrame); -- DYNLISTENFUNC(monitorDestroy); - DYNLISTENFUNC(monitorStateRequest); - DYNLISTENFUNC(monitorDamage); - DYNLISTENFUNC(monitorNeedsFrame); -diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp -index 60fb5bef..9d2210f6 100644 ---- a/src/events/Monitors.cpp -+++ b/src/events/Monitors.cpp -@@ -85,31 +85,6 @@ void Events::listener_monitorFrame(void* owner, void* data) { - } - } - --void Events::listener_monitorDestroy(void* owner, void* data) { -- CMonitor* pMonitor = (CMonitor*)owner; -- -- for (auto& m : g_pCompositor->m_vRealMonitors) { -- if (m->output == pMonitor->output) { -- pMonitor = m.get(); -- break; -- } -- } -- -- if (!pMonitor) -- return; -- -- Debug::log(LOG, "Destroy called for monitor {}", pMonitor->szName); -- -- pMonitor->onDisconnect(true); -- -- pMonitor->output = nullptr; -- pMonitor->m_bRenderingInitPassed = false; -- -- Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName); -- -- std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == pMonitor; }); --} -- - void Events::listener_monitorNeedsFrame(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - -diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp -index 9542d2c4..2c6282e1 100644 ---- a/src/helpers/Monitor.cpp -+++ b/src/helpers/Monitor.cpp -@@ -25,7 +25,7 @@ int ratHandler(void* data) { - return 1; - } - --CMonitor::CMonitor() : state(this) { -+CMonitor::CMonitor(SP output_) : state(this), output(output_) { - ; - } - -@@ -40,16 +40,29 @@ void CMonitor::onConnect(bool noRule) { - outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); - } - -- listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); -- listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); -- listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); -+ listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); -+ listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); - listeners.needsFrame = - output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); -+ - listeners.presented = output->events.present.registerListener([this](std::any d) { - auto E = std::any_cast(d); - PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); - }); - -+ listeners.destroy = output->events.destroy.registerListener([this](std::any d) { -+ Debug::log(LOG, "Destroy called for monitor {}", szName); -+ -+ onDisconnect(true); -+ -+ output = nullptr; -+ m_bRenderingInitPassed = false; -+ -+ Debug::log(LOG, "Removing monitor {} from realMonitors", szName); -+ -+ std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == this; }); -+ }); -+ - listeners.state = output->events.state.registerListener([this](std::any d) { - auto E = std::any_cast(d); - -diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp -index dcfcb63b..01a5d28d 100644 ---- a/src/helpers/Monitor.hpp -+++ b/src/helpers/Monitor.hpp -@@ -59,7 +59,7 @@ class CMonitorState { - - class CMonitor { - public: -- CMonitor(); -+ CMonitor(SP output); - ~CMonitor(); - - Vector2D vecPosition = Vector2D(-1, -1); // means unset --- -2.45.2 - diff --git a/hosts/callisto/0013-example-config-fix-typo-in-default-config-7446.patch b/hosts/callisto/0013-example-config-fix-typo-in-default-config-7446.patch deleted file mode 100644 index d4f8796..0000000 --- a/hosts/callisto/0013-example-config-fix-typo-in-default-config-7446.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 4eff224a7f6f4baa5600f687d6f2ef4ad8340ad3 Mon Sep 17 00:00:00 2001 -From: Ali Atashrooz -Date: Wed, 21 Aug 2024 13:54:02 +0330 -Subject: [PATCH 13/20] example/config: fix typo in default config (#7446) - -* Update hyprland.conf - -* Update defaultConfig.hpp ---- - example/hyprland.conf | 6 +++--- - src/config/defaultConfig.hpp | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/example/hyprland.conf b/example/hyprland.conf -index f69309c2..d55d25fd 100644 ---- a/example/hyprland.conf -+++ b/example/hyprland.conf -@@ -169,9 +169,9 @@ device { - } - - --#################### --### KEYBINDINGSS ### --#################### -+################### -+### KEYBINDINGS ### -+################### - - # See https://wiki.hyprland.org/Configuring/Keywords/ - $mainMod = SUPER # Sets "Windows" key as main modifier -diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp -index 98b617d0..59265fee 100644 ---- a/src/config/defaultConfig.hpp -+++ b/src/config/defaultConfig.hpp -@@ -182,9 +182,9 @@ device { - } - - --#################### --### KEYBINDINGSS ### --#################### -+################### -+### KEYBINDINGS ### -+################### - - # See https://wiki.hyprland.org/Configuring/Keywords/ - $mainMod = SUPER # Sets "Windows" key as main modifier --- -2.45.2 - diff --git a/hosts/callisto/0014-core-add-option-to-control-which-window-to-focus-on-.patch b/hosts/callisto/0014-core-add-option-to-control-which-window-to-focus-on-.patch deleted file mode 100644 index 87f66a7..0000000 --- a/hosts/callisto/0014-core-add-option-to-control-which-window-to-focus-on-.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 946ed1f32ae8e3840d1b3bb04c6e048ca7501fba Mon Sep 17 00:00:00 2001 -From: ParaN3xus <136563585+ParaN3xus@users.noreply.github.com> -Date: Wed, 21 Aug 2024 18:24:42 +0800 -Subject: [PATCH 14/20] core: add option to control which window to focus on - close (#7368) - ---- - src/config/ConfigDescriptions.hpp | 9 ++++++++- - src/config/ConfigManager.cpp | 1 + - src/events/Windows.cpp | 7 ++++++- - 3 files changed, 15 insertions(+), 2 deletions(-) - -diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp -index 3c830132..73b995ae 100644 ---- a/src/config/ConfigDescriptions.hpp -+++ b/src/config/ConfigDescriptions.hpp -@@ -453,6 +453,13 @@ inline static const std::vector CONFIG_OPTIONS = { - .type = CONFIG_OPTION_INT, - .data = SConfigOptionDescription::SRangeData{1, 0, 3}, - }, -+ SConfigOptionDescription{ -+ .value = "input:focus_on_close", -+ .description = "Controls the window focus behavior when a window is closed. When set to 0, focus will shift to the next window candidate. When set to 1, focus will shift " -+ "to the window under the cursor.", -+ .type = CONFIG_OPTION_CHOICE, -+ .data = SConfigOptionDescription::SChoiceData{0, "next,cursor"}, -+ }, - SConfigOptionDescription{ - .value = "input:mouse_refocus", - .description = "if disabled, mouse focus won't switch to the hovered window unless the mouse crosses a window boundary when follow_mouse=1.", -@@ -1341,4 +1348,4 @@ inline static const std::vector CONFIG_OPTIONS = { - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, - }, --}; -\ No newline at end of file -+}; -diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp -index 1856bd49..155b75d3 100644 ---- a/src/config/ConfigManager.cpp -+++ b/src/config/ConfigManager.cpp -@@ -449,6 +449,7 @@ CConfigManager::CConfigManager() { - m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1}); - - m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1}); -+ m_pConfig->addConfigValue("input:focus_on_close", Hyprlang::INT{0}); - m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1}); - m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0}); - m_pConfig->addConfigValue("input:off_window_axis_events", Hyprlang::INT{1}); -diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp -index 2eb7038f..e4e3900b 100644 ---- a/src/events/Windows.cpp -+++ b/src/events/Windows.cpp -@@ -648,7 +648,12 @@ void Events::listener_unmapWindow(void* owner, void* data) { - - // refocus on a new window if needed - if (wasLastWindow) { -- const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW); -+ static auto FOCUSONCLOSE = CConfigValue("input:focus_on_close"); -+ PHLWINDOW PWINDOWCANDIDATE = nullptr; -+ if (*FOCUSONCLOSE) -+ PWINDOWCANDIDATE = (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)); -+ else -+ PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW); - - Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE); - --- -2.45.2 - diff --git a/hosts/callisto/0015-output-dont-cast-enum-out-of-range-7448.patch b/hosts/callisto/0015-output-dont-cast-enum-out-of-range-7448.patch deleted file mode 100644 index 3a5a041..0000000 --- a/hosts/callisto/0015-output-dont-cast-enum-out-of-range-7448.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 3e7325af57c4670ebea65d2669f49526819c2260 Mon Sep 17 00:00:00 2001 -From: Tom Englund -Date: Wed, 21 Aug 2024 12:52:40 +0200 -Subject: [PATCH 15/20] output: dont cast enum out of range (#7448) - -avoid casting non typed enum out of range, looks like -WL_OUTPUT_MODE_CURRENT was the intention here. ---- - src/protocols/core/Output.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp -index 878d1484..8d0b0121 100644 ---- a/src/protocols/core/Output.cpp -+++ b/src/protocols/core/Output.cpp -@@ -55,7 +55,7 @@ void CWLOutputResource::updateState() { - if (resource->version() >= 2) - resource->sendScale(std::ceil(monitor->scale)); - -- resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); -+ resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); - - if (resource->version() >= 2) - resource->sendDone(); --- -2.45.2 - diff --git a/hosts/callisto/0016-animations-add-workspace-in-out-configs.patch b/hosts/callisto/0016-animations-add-workspace-in-out-configs.patch deleted file mode 100644 index 154fe07..0000000 --- a/hosts/callisto/0016-animations-add-workspace-in-out-configs.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 883463f9dd7f1cdc68c3e32017c0a71ccbe39b26 Mon Sep 17 00:00:00 2001 -From: vaxerski -Date: Wed, 21 Aug 2024 14:37:50 +0200 -Subject: [PATCH 16/20] animations: add workspace in/out configs - ---- - src/config/ConfigManager.cpp | 10 +++++++++- - src/desktop/Workspace.cpp | 12 ++++++++++-- - src/managers/AnimationManager.cpp | 2 +- - 3 files changed, 20 insertions(+), 4 deletions(-) - -diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp -index 155b75d3..e2ae2c47 100644 ---- a/src/config/ConfigManager.cpp -+++ b/src/config/ConfigManager.cpp -@@ -724,7 +724,6 @@ void CConfigManager::setDefaultAnimationVars() { - INITANIMCFG("fade"); - INITANIMCFG("border"); - INITANIMCFG("borderangle"); -- INITANIMCFG("workspaces"); - - // windows - INITANIMCFG("windowsIn"); -@@ -745,7 +744,12 @@ void CConfigManager::setDefaultAnimationVars() { - // border - - // workspaces -+ INITANIMCFG("workspaces"); -+ INITANIMCFG("workspacesIn"); -+ INITANIMCFG("workspacesOut"); - INITANIMCFG("specialWorkspace"); -+ INITANIMCFG("specialWorkspaceIn"); -+ INITANIMCFG("specialWorkspaceOut"); - } - - // init the values -@@ -774,7 +778,11 @@ void CConfigManager::setDefaultAnimationVars() { - CREATEANIMCFG("fadeLayersIn", "fadeLayers"); - CREATEANIMCFG("fadeLayersOut", "fadeLayers"); - -+ CREATEANIMCFG("workspacesIn", "workspaces"); -+ CREATEANIMCFG("workspacesOut", "workspaces"); - CREATEANIMCFG("specialWorkspace", "workspaces"); -+ CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace"); -+ CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace"); - } - - std::optional CConfigManager::resetHLConfig() { -diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp -index d9ac7927..a9412e6d 100644 ---- a/src/desktop/Workspace.cpp -+++ b/src/desktop/Workspace.cpp -@@ -22,10 +22,11 @@ CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bo - void CWorkspace::init(PHLWORKSPACE self) { - m_pSelf = self; - -- m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), -+ m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : -+ g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), - self, AVARDAMAGE_ENTIRE); - m_fAlpha.create(AVARTYPE_FLOAT, -- m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), self, -+ m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self, - AVARDAMAGE_ENTIRE); - m_fAlpha.setValueAndWarp(1.f); - -@@ -81,6 +82,13 @@ CWorkspace::~CWorkspace() { - } - - void CWorkspace::startAnim(bool in, bool left, bool instant) { -+ if (!instant) { -+ const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out"); -+ -+ m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); -+ m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); -+ } -+ - const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; - static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); - -diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp -index dcc7a45f..beb880be 100644 ---- a/src/managers/AnimationManager.cpp -+++ b/src/managers/AnimationManager.cpp -@@ -471,7 +471,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config, - } - - return "unknown style"; -- } else if (config == "workspaces" || config == "specialWorkspace") { -+ } else if (config.starts_with("workspaces") || config.starts_with("specialWorkspace")) { - if (style == "slide" || style == "slidevert" || style == "fade") - return ""; - else if (style.starts_with("slidefade")) { --- -2.45.2 - diff --git a/hosts/callisto/0017-Nix-include-xcursor-regardless-of-xwayland.patch b/hosts/callisto/0017-Nix-include-xcursor-regardless-of-xwayland.patch deleted file mode 100644 index 46f91d4..0000000 --- a/hosts/callisto/0017-Nix-include-xcursor-regardless-of-xwayland.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 1b1ecf77e0c195460eb5335652d65de6fd83cf7b Mon Sep 17 00:00:00 2001 -From: Mihai Fufezan -Date: Wed, 21 Aug 2024 22:37:28 +0300 -Subject: [PATCH 17/20] Nix: include xcursor regardless of xwayland - ---- - nix/default.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nix/default.nix b/nix/default.nix -index 9bae9d83..c8eaf731 100644 ---- a/nix/default.nix -+++ b/nix/default.nix -@@ -136,11 +136,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov - tomlplusplus - wayland - wayland-protocols -+ xorg.libXcursor - ] - (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) - (lib.optionals enableXWayland [ - xorg.libxcb -- xorg.libXcursor - xorg.libXdmcp - xorg.xcbutil - xorg.xcbutilerrors --- -2.45.2 - diff --git a/hosts/callisto/0018-Fix-static-asan-patch.patch b/hosts/callisto/0018-Fix-static-asan-patch.patch deleted file mode 100644 index 25c8c3e..0000000 --- a/hosts/callisto/0018-Fix-static-asan-patch.patch +++ /dev/null @@ -1,38 +0,0 @@ -From c5786be695224c2d2771854436844b88a6b48fc5 Mon Sep 17 00:00:00 2001 -From: James R Larrowe -Date: Tue, 20 Aug 2024 13:36:41 -0400 -Subject: [PATCH 18/20] Fix static asan patch - ---- - scripts/hyprlandStaticAsan.diff | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/scripts/hyprlandStaticAsan.diff b/scripts/hyprlandStaticAsan.diff -index e74eb6ab..b352d65d 100644 ---- a/scripts/hyprlandStaticAsan.diff -+++ b/scripts/hyprlandStaticAsan.diff -@@ -1,13 +1,13 @@ - diff --git a/CMakeLists.txt b/CMakeLists.txt --index f54cdf5d..ad7c3e73 100755 -+index f26a5c3c..3dfef333 100644 - --- a/CMakeLists.txt - +++ b/CMakeLists.txt --@@ -130,6 +130,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) -- message(STATUS "Enabling ASan") -+@@ -143,6 +143,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) -+ message(STATUS "Enabling ASan") - -- target_link_libraries(Hyprland asan) --+ pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi) --+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep) -- target_compile_options(Hyprland PUBLIC -fsanitize=address) -- endif() -+ target_link_libraries(Hyprland asan) -++ pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi) -++ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep) -+ target_compile_options(Hyprland PUBLIC -fsanitize=address) -+ endif() - --- -2.45.2 - diff --git a/hosts/callisto/0019-Fix-Makefile-too.patch b/hosts/callisto/0019-Fix-Makefile-too.patch deleted file mode 100644 index 9f00c16..0000000 --- a/hosts/callisto/0019-Fix-Makefile-too.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 8162fae37728b3ae2b1a82a32663e76c59c4ce61 Mon Sep 17 00:00:00 2001 -From: James R Larrowe -Date: Tue, 20 Aug 2024 13:54:51 -0400 -Subject: [PATCH 19/20] Fix Makefile too - -... did this ever work? ---- - Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index adf6fbe8..bc7b750b 100644 ---- a/Makefile -+++ b/Makefile -@@ -87,8 +87,8 @@ asan: - #git reset --hard - - @echo -en "If you want to apply a patch, input its path (leave empty for none):\n" -- @read patchvar -- @if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi -+ @read patchvar; \ -+ if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi - - git clone --recursive https://gitlab.freedesktop.org/wayland/wayland - cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd .. --- -2.45.2 - diff --git a/hosts/callisto/0020-layersurface-dont-rollover-on-size_t-7451.patch b/hosts/callisto/0020-layersurface-dont-rollover-on-size_t-7451.patch deleted file mode 100644 index a9d552d..0000000 --- a/hosts/callisto/0020-layersurface-dont-rollover-on-size_t-7451.patch +++ /dev/null @@ -1,28 +0,0 @@ -From cae937c51bd220d6676c6027d05ea51fc3c821bb Mon Sep 17 00:00:00 2001 -From: Tom Englund -Date: Wed, 21 Aug 2024 23:05:03 +0200 -Subject: [PATCH 20/20] layersurface: dont rollover on size_t (#7451) - -unneded rollover on size_t if force equals -1 ---- - src/desktop/LayerSurface.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp -index c352fa74..8fd448ef 100644 ---- a/src/desktop/LayerSurface.cpp -+++ b/src/desktop/LayerSurface.cpp -@@ -432,8 +432,8 @@ void CLayerSurface::startAnimation(bool in, bool instant) { - PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, - }; - -- float closest = std::numeric_limits::max(); -- size_t leader = force; -+ float closest = std::numeric_limits::max(); -+ int leader = force; - if (leader == -1) { - for (size_t i = 0; i < 4; ++i) { - float dist = MIDDLE.distance(edgePoints[i]); --- -2.45.2 - diff --git a/hosts/callisto/asahi-fix.patch b/hosts/callisto/asahi-fix.patch new file mode 100644 index 0000000..3fe6661 --- /dev/null +++ b/hosts/callisto/asahi-fix.patch @@ -0,0 +1,5080 @@ +diff --git a/.gitignore b/.gitignore +index 78f794fc..2e158a4e 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -37,3 +37,5 @@ gmon.out + PKGBUILD + + src/version.h ++hyprpm/Makefile ++hyprctl/Makefile +diff --git a/CMakeLists.txt b/CMakeLists.txt +index fc8eafd5..f26a5c3c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -62,7 +62,7 @@ else() + endif() + + include_directories(. "src/" "subprojects/udis86/" "protocols/") +-set(CMAKE_CXX_STANDARD 23) ++set(CMAKE_CXX_STANDARD 26) + add_compile_options( + -Wall + -Wextra +@@ -117,6 +117,7 @@ pkg_check_modules( + libliftoff + libudev + gbm ++ gio-2.0 + hyprlang>=0.3.2 + hyprcursor>=0.1.7 + hyprutils>=0.2.1) +@@ -329,7 +330,7 @@ install( + CODE "execute_process( \ + COMMAND ${CMAKE_COMMAND} -E create_symlink \ + ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ +- ${CMAKE_INSTALL_FULL_BINDIR}/hyprland ++ \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \ + )") + + # session file +diff --git a/README.md b/README.md +index fc2bd206..f271c29c 100644 +--- a/README.md ++++ b/README.md +@@ -1,6 +1,6 @@ +
+ +-banner ++banner + +
+ +@@ -125,7 +125,6 @@ easy IPC, much more QoL stuff than other compositors and more... + + + +-[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg + [Preview A]: https://i.ibb.co/C1yTb0r/falf.png + [Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png + [Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png +diff --git a/flake.lock b/flake.lock +index 5c384d4d..c70d31d1 100644 +--- a/flake.lock ++++ b/flake.lock +@@ -16,11 +16,11 @@ + ] + }, + "locked": { +- "lastModified": 1722347739, +- "narHash": "sha256-rAoh+K6KG+b1DwSWtqRVocdojnH6nGk6q07mNltoUSM=", ++ "lastModified": 1723920171, ++ "narHash": "sha256-dVCMrAe+D/5S91erhwQj2DSzHOVzAanWqoy+vPWB9DY=", + "owner": "hyprwm", + "repo": "aquamarine", +- "rev": "7c3565f9bedc7cb601cc0baa14792247e4dc1d5a", ++ "rev": "71d49670fe246cdaff4860b0effba0ab9f163b72", + "type": "github" + }, + "original": { +@@ -42,11 +42,11 @@ + ] + }, + "locked": { +- "lastModified": 1721330371, +- "narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=", ++ "lastModified": 1722623071, ++ "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=", + "owner": "hyprwm", + "repo": "hyprcursor", +- "rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc", ++ "rev": "912d56025f03d41b1ad29510c423757b4379eb1c", + "type": "github" + }, + "original": { +@@ -116,11 +116,11 @@ + ] + }, + "locked": { +- "lastModified": 1722098849, +- "narHash": "sha256-D3wIZlBNh7LuZ0NaoCpY/Pvu+xHxIVtSN+KkWZYvvVs=", ++ "lastModified": 1722869141, ++ "narHash": "sha256-0KU4qhyMp441qfwbirNg3+wbm489KnEjXOz2I/RbeFs=", + "owner": "hyprwm", + "repo": "hyprutils", +- "rev": "5dcbbc1e3de40b2cecfd2007434d86e924468f1f", ++ "rev": "0252fd13e78e60fb0da512a212e56007515a49f7", + "type": "github" + }, + "original": { +@@ -154,11 +154,11 @@ + }, + "nixpkgs": { + "locked": { +- "lastModified": 1722185531, +- "narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=", ++ "lastModified": 1723637854, ++ "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", + "owner": "NixOS", + "repo": "nixpkgs", +- "rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d", ++ "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", + "type": "github" + }, + "original": { +diff --git a/flake.nix b/flake.nix +index 9c20b3f5..9e1e3ab4 100644 +--- a/flake.nix ++++ b/flake.nix +@@ -95,7 +95,7 @@ + devShells = eachSystem (system: { + default = + pkgsFor.${system}.mkShell.override { +- stdenv = pkgsFor.${system}.gcc13Stdenv; ++ stdenv = pkgsFor.${system}.gcc14Stdenv; + } { + name = "hyprland-shell"; + nativeBuildInputs = with pkgsFor.${system}; [ +diff --git a/hyprctl/Makefile b/hyprctl/Makefile +deleted file mode 100644 +index 9798320c..00000000 +--- a/hyprctl/Makefile ++++ /dev/null +@@ -1,4 +0,0 @@ +-all: +- $(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl +-clean: +- rm ./hyprctl +diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp +index 336d479e..5d5113b8 100644 +--- a/hyprctl/main.cpp ++++ b/hyprctl/main.cpp +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + using namespace Hyprutils::String; + + #include "Strings.hpp" +@@ -113,7 +114,7 @@ int rollingRead(const int socket) { + + constexpr size_t BUFFER_SIZE = 8192; + std::array buffer = {0}; +- int sizeWritten = 0; ++ long sizeWritten = 0; + std::cout << "[hyprctl] reading from socket following up log:" << std::endl; + while (!sigintReceived) { + sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); +diff --git a/meson.build b/meson.build +index 886f4f9c..6a9b7ac5 100644 +--- a/meson.build ++++ b/meson.build +@@ -6,7 +6,7 @@ project('Hyprland', 'cpp', 'c', + 'optimization=3', + 'buildtype=release', + 'debug=false', +- 'cpp_std=c++23', ++ 'cpp_std=c++26', + ]) + + datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' +@@ -34,6 +34,8 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland')) + xcb_res_dep = dependency('xcb-res', required: get_option('xwayland')) + xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) + ++gio_dep = dependency('gio-2.0', required:true) ++ + cmake = import('cmake') + udis = cmake.subproject('udis86') + udis86 = udis.dependency('libudis86') +diff --git a/nix/default.nix b/nix/default.nix +index e4e12f43..9bae9d83 100644 +--- a/nix/default.nix ++++ b/nix/default.nix +@@ -71,6 +71,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov + src = lib.cleanSource ../.; + }; + ++ patches = [ ++ # forces GCC to use -std=c++26 ++ ./stdcxx.patch ++ ]; ++ + postPatch = '' + # Fix hardcoded paths to /usr installation + sed -i "s#/usr#$out#" src/render/OpenGL.cpp +diff --git a/nix/overlays.nix b/nix/overlays.nix +index d8979b45..36206f46 100644 +--- a/nix/overlays.nix ++++ b/nix/overlays.nix +@@ -31,7 +31,7 @@ in { + date = mkDate (self.lastModifiedDate or "19700101"); + in { + hyprland = final.callPackage ./default.nix { +- stdenv = final.gcc13Stdenv; ++ stdenv = final.gcc14Stdenv; + version = "${version}+date=${date}_${self.shortRev or "dirty"}"; + commit = self.rev or ""; + inherit date; +diff --git a/nix/stdcxx.patch b/nix/stdcxx.patch +new file mode 100644 +index 00000000..032e494d +--- /dev/null ++++ b/nix/stdcxx.patch +@@ -0,0 +1,12 @@ ++diff --git a/CMakeLists.txt b/CMakeLists.txt ++index cfbd431f..73e8e0c2 100644 ++--- a/CMakeLists.txt +++++ b/CMakeLists.txt ++@@ -64,6 +64,7 @@ endif() ++ include_directories(. "src/" "subprojects/udis86/" "protocols/") ++ set(CMAKE_CXX_STANDARD 26) ++ add_compile_options( +++ -std=c++26 ++ -Wall ++ -Wextra ++ -Wno-unused-parameter +diff --git a/src/Compositor.cpp b/src/Compositor.cpp +index 49408597..9d247a56 100644 +--- a/src/Compositor.cpp ++++ b/src/Compositor.cpp +@@ -305,6 +305,10 @@ void CCompositor::initServer(std::string socketName, int socketFd) { + + setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); + setenv("XDG_SESSION_TYPE", "wayland", 1); ++ if (!getenv("XDG_CURRENT_DESKTOP")) { ++ setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1); ++ m_bDesktopEnvSet = true; ++ } + + initManagers(STAGE_BASICINIT); + +@@ -393,6 +397,7 @@ void CCompositor::initAllSignals() { + } + + g_pConfigManager->m_bWantsMonitorReload = true; ++ g_pCursorManager->syncGsettings(); + } else { + Debug::log(LOG, "Session got deactivated!"); + +@@ -421,9 +426,10 @@ void CCompositor::cleanEnvironment() { + // in main + unsetenv("HYPRLAND_CMD"); + unsetenv("XDG_BACKEND"); +- unsetenv("XDG_CURRENT_DESKTOP"); ++ if (m_bDesktopEnvSet) ++ unsetenv("XDG_CURRENT_DESKTOP"); + +- if (m_pAqBackend->hasSession()) { ++ if (m_pAqBackend->hasSession() && !envEnabled("HYPRLAND_NO_SD_VARS")) { + const auto CMD = + #ifdef USES_SYSTEMD + "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " +@@ -552,6 +558,10 @@ void CCompositor::initManagers(eManagersInitStage stage) { + + g_pConfigManager->init(); + g_pWatchdog = std::make_unique(); // requires config ++ // wait for watchdog to initialize to not hit data races in reading config values. ++ while (!g_pWatchdog->m_bWatchdogInitialized) { ++ std::this_thread::yield(); ++ } + + Debug::log(LOG, "Creating the PointerManager!"); + g_pPointerManager = std::make_unique(); +@@ -649,7 +659,11 @@ void CCompositor::prepareFallbackOutput() { + void CCompositor::startCompositor() { + signal(SIGPIPE, SIG_IGN); + +- if (m_pAqBackend->hasSession() /* Session-less Hyprland usually means a nest, don't update the env in that case */) { ++ if ( ++ /* Session-less Hyprland usually means a nest, don't update the env in that case */ ++ m_pAqBackend->hasSession() && ++ /* Activation environment management is not disabled */ ++ !envEnabled("HYPRLAND_NO_SD_VARS")) { + const auto CMD = + #ifdef USES_SYSTEMD + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " +@@ -683,9 +697,9 @@ void CCompositor::startCompositor() { + g_pEventLoopManager->enterLoop(); + } + +-CMonitor* CCompositor::getMonitorFromID(const int& id) { ++CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) { + for (auto& m : m_vMonitors) { +- if (m->ID == (uint64_t)id) { ++ if (m->ID == id) { + return m.get(); + } + } +@@ -845,8 +859,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper + if (properties & FLOATING_ONLY) + return floating(false); + +- const int64_t WORKSPACEID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); +- const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID); ++ const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); ++ const auto PWORKSPACE = getWorkspaceByID(WSPID); + + if (PWORKSPACE->m_bHasFullscreenWindow) + return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); +@@ -860,7 +874,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper + if (special != w->onSpecialWorkspace()) + continue; + +- if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && ++ if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && + !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { + if (w->hasPopupAt(pos)) + return w; +@@ -872,7 +886,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper + continue; + + CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; +- if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && ++ if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && + !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) + return w; + } +@@ -1207,7 +1221,7 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { + return nullptr; + } + +-PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const int& ID) { ++PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) { + for (auto& w : m_vWindows) { + if (w->workspaceID() == ID && w->isFullscreen()) + return w; +@@ -1231,7 +1245,7 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { + return PMONITOR->activeWorkspace->m_iID == w->m_iID; + } + +-PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) { ++PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) { + for (auto& w : m_vWorkspaces) { + if (w->m_iID == id && !w->inert()) + return w; +@@ -1255,7 +1269,7 @@ void CCompositor::sanityCheckWorkspaces() { + } + } + +-int CCompositor::getWindowsOnWorkspace(const int& id, std::optional onlyTiled, std::optional onlyVisible) { ++int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { + int no = 0; + for (auto& w : m_vWindows) { + if (w->workspaceID() != id || !w->m_bIsMapped) +@@ -1270,7 +1284,7 @@ int CCompositor::getWindowsOnWorkspace(const int& id, std::optional onlyTi + return no; + } + +-int CCompositor::getGroupsOnWorkspace(const int& id, std::optional onlyTiled, std::optional onlyVisible) { ++int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { + int no = 0; + for (auto& w : m_vWindows) { + if (w->workspaceID() != id || !w->m_bIsMapped) +@@ -1295,7 +1309,7 @@ PHLWINDOW CCompositor::getUrgentWindow() { + return nullptr; + } + +-bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) { ++bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) { + for (auto& w : m_vWindows) { + if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent) + return true; +@@ -1304,7 +1318,7 @@ bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) { + return false; + } + +-PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) { ++PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) { + for (auto& w : m_vWindows) { + if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden()) + return w; +@@ -1313,7 +1327,7 @@ PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) { + return nullptr; + } + +-PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const int& id) { ++PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { + const auto PWORKSPACE = getWorkspaceByID(id); + + if (!PWORKSPACE) +@@ -1401,12 +1415,12 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { + } + } + +-void CCompositor::cleanupFadingOut(const int& monid) { ++void CCompositor::cleanupFadingOut(const MONITORID& monid) { + for (auto& ww : m_vWindowsFadingOut) { + + auto w = ww.lock(); + +- if (w->m_iMonitorID != (long unsigned int)monid) ++ if (w->m_iMonitorID != monid) + continue; + + if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { +@@ -1702,8 +1716,8 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl + return nullptr; + } + +-int CCompositor::getNextAvailableNamedWorkspace() { +- int lowest = -1337 + 1; ++WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { ++ WORKSPACEID lowest = -1337 + 1; + for (auto& w : m_vWorkspaces) { + if (w->m_iID < -1 && w->m_iID < lowest) + lowest = w->m_iID; +@@ -1927,18 +1941,18 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { + pWindow->updateWindowDecos(); + } + +-int CCompositor::getNextAvailableMonitorID(std::string const& name) { ++MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { + // reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor + if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; })) + return m_mMonitorIDMap[name]; + + // otherwise, find minimum available ID that is not in the map +- std::unordered_set usedIDs; ++ std::unordered_set usedIDs; + for (auto const& monitor : m_vRealMonitors) { + usedIDs.insert(monitor->ID); + } + +- uint64_t nextID = 0; ++ MONITORID nextID = 0; + while (usedIDs.count(nextID) > 0) { + nextID++; + } +@@ -2078,7 +2092,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { + return m_vMonitors[currentPlace].get(); + } else if (isNumber(name)) { + // change by ID +- int monID = -1; ++ MONITORID monID = MONITOR_INVALID; + try { + monID = std::stoi(name); + } catch (std::exception& e) { +@@ -2087,7 +2101,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { + return nullptr; + } + +- if (monID > -1 && monID < (int)m_vMonitors.size()) { ++ if (monID > -1 && monID < (MONITORID)m_vMonitors.size()) { + return getMonitorFromID(monID); + } else { + Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1"); +@@ -2121,7 +2135,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon + const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false; + + // fix old mon +- int nextWorkspaceOnMonitorID = -1; ++ WORKSPACEID nextWorkspaceOnMonitorID = WORKSPACE_INVALID; + if (!SWITCHINGISACTIVE) + nextWorkspaceOnMonitorID = pWorkspace->m_iID; + else { +@@ -2132,7 +2146,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon + } + } + +- if (nextWorkspaceOnMonitorID == -1) { ++ if (nextWorkspaceOnMonitorID == WORKSPACE_INVALID) { + nextWorkspaceOnMonitorID = 1; + + while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool { +@@ -2219,9 +2233,9 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon + EMIT_HOOK_EVENT("moveWorkspace", (std::vector{pWorkspace, pMonitor})); + } + +-bool CCompositor::workspaceIDOutOfBounds(const int64_t& id) { +- int64_t lowestID = INT64_MAX; +- int64_t highestID = INT64_MIN; ++bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) { ++ WORKSPACEID lowestID = INT64_MAX; ++ WORKSPACEID highestID = INT64_MIN; + + for (auto& w : m_vWorkspaces) { + if (w->m_bIsSpecialWorkspace) +@@ -2370,7 +2384,7 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) { + return nullptr; + } + +-void CCompositor::updateWorkspaceWindowDecos(const int& id) { ++void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) { + for (auto& w : m_vWindows) { + if (w->workspaceID() != id) + continue; +@@ -2379,7 +2393,7 @@ void CCompositor::updateWorkspaceWindowDecos(const int& id) { + } + } + +-void CCompositor::updateWorkspaceWindowData(const int& id) { ++void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { + const auto PWORKSPACE = getWorkspaceByID(id); + const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; + +@@ -2599,7 +2613,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con + return Vector2D(X, Y); + } + +-void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { ++void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) { + for (auto& w : m_vWindows) { + if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) { + g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); +@@ -2607,7 +2621,7 @@ void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { + } + } + +-PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name, bool isEmtpy) { ++PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmtpy) { + const auto NAME = name == "" ? std::to_string(id) : name; + auto monID = monid; + +@@ -2625,7 +2639,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, co + return PWORKSPACE; + } + +-void CCompositor::renameWorkspace(const int& id, const std::string& name) { ++void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) { + const auto PWORKSPACE = getWorkspaceByID(id); + + if (!PWORKSPACE) +@@ -2656,12 +2670,12 @@ void CCompositor::setActiveMonitor(CMonitor* pMonitor) { + m_pLastMonitor = pMonitor->self; + } + +-bool CCompositor::isWorkspaceSpecial(const int& id) { ++bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) { + return id >= SPECIAL_WORKSPACE_START && id <= -2; + } + +-int CCompositor::getNewSpecialID() { +- int highest = SPECIAL_WORKSPACE_START; ++WORKSPACEID CCompositor::getNewSpecialID() { ++ WORKSPACEID highest = SPECIAL_WORKSPACE_START; + for (auto& ws : m_vWorkspaces) { + if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) { + highest = ws->m_iID; +@@ -2918,39 +2932,6 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { + return {}; + } + +-static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { +- static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); +- static auto firstMonitorAdded = std::chrono::system_clock::now(); +- static bool cursorDefaultDone = false; +- static bool firstLaunch = true; +- +- const auto POS = PNEWMONITOR->middle(); +- +- // by default, cursor should be set to first monitor detected +- // this is needed as a default if the monitor given in config above doesn't exist +- if (firstLaunch) { +- firstLaunch = false; +- g_pCompositor->warpCursorTo(POS, true); +- g_pInputManager->refocus(); +- } +- +- if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY) +- return; +- +- // after 10s, don't set cursor to default monitor +- auto timePassedSec = std::chrono::duration_cast(std::chrono::system_clock::now() - firstMonitorAdded); +- if (timePassedSec.count() > 10) { +- cursorDefaultDone = true; +- return; +- } +- +- if (*PCURSORMONITOR == monitorName) { +- cursorDefaultDone = true; +- g_pCompositor->warpCursorTo(POS, true); +- g_pInputManager->refocus(); +- } +-} +- + void CCompositor::onNewMonitor(SP output) { + // add it to real + auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); +@@ -2965,7 +2946,7 @@ void CCompositor::onNewMonitor(SP output) { + PNEWMONITOR->output = output; + PNEWMONITOR->self = PNEWMONITOR; + const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; +- PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name); ++ PNEWMONITOR->ID = FALLBACK ? MONITOR_INVALID : g_pCompositor->getNextAvailableMonitorID(output->name); + PNEWMONITOR->isUnsafeFallback = FALLBACK; + + EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); +@@ -2986,11 +2967,9 @@ void CCompositor::onNewMonitor(SP output) { + g_pConfigManager->m_bWantsMonitorReload = true; + g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); + +- checkDefaultCursorWarp(PNEWMONITOR, output->name); +- + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_iMonitorID == PNEWMONITOR->ID) { +- w->m_iLastSurfaceMonitorID = -1; ++ w->m_iLastSurfaceMonitorID = MONITOR_INVALID; + w->updateSurfaceScaleTransformDetails(); + } + } +diff --git a/src/Compositor.hpp b/src/Compositor.hpp +index 295935c4..a570a06e 100644 +--- a/src/Compositor.hpp ++++ b/src/Compositor.hpp +@@ -46,55 +46,56 @@ class CCompositor { + CCompositor(); + ~CCompositor(); + +- wl_display* m_sWLDisplay; +- wl_event_loop* m_sWLEventLoop; +- int m_iDRMFD = -1; +- bool m_bInitialized = false; +- SP m_pAqBackend; +- +- std::string m_szHyprTempDataRoot = ""; +- +- std::string m_szWLDisplaySocket = ""; +- std::string m_szInstanceSignature = ""; +- std::string m_szInstancePath = ""; +- std::string m_szCurrentSplash = "error"; +- +- std::vector> m_vMonitors; +- std::vector> m_vRealMonitors; // for all monitors, even those turned off +- std::vector m_vWindows; +- std::vector m_vLayers; +- std::vector m_vWorkspaces; +- std::vector m_vWindowsFadingOut; +- std::vector m_vSurfacesFadingOut; +- +- std::unordered_map m_mMonitorIDMap; +- +- void initServer(std::string socketName, int socketFd); +- void startCompositor(); +- void stopCompositor(); +- void cleanup(); +- void createLockFile(); +- void removeLockFile(); +- void bumpNofile(); +- void restoreNofile(); +- +- WP m_pLastFocus; +- PHLWINDOWREF m_pLastWindow; +- WP m_pLastMonitor; +- +- std::vector m_vWindowFocusHistory; // first element is the most recently focused. +- +- bool m_bReadyToProcess = false; +- bool m_bSessionActive = true; +- bool m_bDPMSStateON = true; +- bool m_bUnsafeState = false; // unsafe state is when there is no monitors. +- bool m_bNextIsUnsafe = false; +- CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state +- bool m_bIsShuttingDown = false; ++ wl_display* m_sWLDisplay; ++ wl_event_loop* m_sWLEventLoop; ++ int m_iDRMFD = -1; ++ bool m_bInitialized = false; ++ SP m_pAqBackend; ++ ++ std::string m_szHyprTempDataRoot = ""; ++ ++ std::string m_szWLDisplaySocket = ""; ++ std::string m_szInstanceSignature = ""; ++ std::string m_szInstancePath = ""; ++ std::string m_szCurrentSplash = "error"; ++ ++ std::vector> m_vMonitors; ++ std::vector> m_vRealMonitors; // for all monitors, even those turned off ++ std::vector m_vWindows; ++ std::vector m_vLayers; ++ std::vector m_vWorkspaces; ++ std::vector m_vWindowsFadingOut; ++ std::vector m_vSurfacesFadingOut; ++ ++ std::unordered_map m_mMonitorIDMap; ++ ++ void initServer(std::string socketName, int socketFd); ++ void startCompositor(); ++ void stopCompositor(); ++ void cleanup(); ++ void createLockFile(); ++ void removeLockFile(); ++ void bumpNofile(); ++ void restoreNofile(); ++ ++ WP m_pLastFocus; ++ PHLWINDOWREF m_pLastWindow; ++ WP m_pLastMonitor; ++ ++ std::vector m_vWindowFocusHistory; // first element is the most recently focused. ++ ++ bool m_bReadyToProcess = false; ++ bool m_bSessionActive = true; ++ bool m_bDPMSStateON = true; ++ bool m_bUnsafeState = false; // unsafe state is when there is no monitors. ++ bool m_bNextIsUnsafe = false; ++ CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state ++ bool m_bIsShuttingDown = false; ++ bool m_bDesktopEnvSet = false; + + // ------------------------------------------------- // + +- CMonitor* getMonitorFromID(const int&); ++ CMonitor* getMonitorFromID(const MONITORID&); + CMonitor* getMonitorFromName(const std::string&); + CMonitor* getMonitorFromDesc(const std::string&); + CMonitor* getMonitorFromCursor(); +@@ -114,38 +115,38 @@ class CCompositor { + PHLWINDOW getWindowFromHandle(uint32_t); + bool isWorkspaceVisible(PHLWORKSPACE); + bool isWorkspaceVisibleNotCovered(PHLWORKSPACE); +- PHLWORKSPACE getWorkspaceByID(const int&); ++ PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&); + PHLWORKSPACE getWorkspaceByName(const std::string&); + PHLWORKSPACE getWorkspaceByString(const std::string&); + void sanityCheckWorkspaces(); +- void updateWorkspaceWindowDecos(const int&); +- void updateWorkspaceWindowData(const int&); +- int getWindowsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); +- int getGroupsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); ++ void updateWorkspaceWindowDecos(const WORKSPACEID&); ++ void updateWorkspaceWindowData(const WORKSPACEID&); ++ int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); ++ int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); + PHLWINDOW getUrgentWindow(); +- bool hasUrgentWindowOnWorkspace(const int&); +- PHLWINDOW getFirstWindowOnWorkspace(const int&); +- PHLWINDOW getTopLeftWindowOnWorkspace(const int&); +- PHLWINDOW getFullscreenWindowOnWorkspace(const int&); ++ bool hasUrgentWindowOnWorkspace(const WORKSPACEID&); ++ PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&); ++ PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&); ++ PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&); + bool isWindowActive(PHLWINDOW); + void changeWindowZOrder(PHLWINDOW, bool); +- void cleanupFadingOut(const int& monid); ++ void cleanupFadingOut(const MONITORID& monid); + PHLWINDOW getWindowInDirection(PHLWINDOW, char); + PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); + PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); +- int getNextAvailableNamedWorkspace(); ++ WORKSPACEID getNextAvailableNamedWorkspace(); + bool isPointOnAnyMonitor(const Vector2D&); + bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); + CMonitor* getMonitorInDirection(const char&); + CMonitor* getMonitorInDirection(CMonitor*, const char&); + void updateAllWindowsAnimatedDecorationValues(); +- void updateWorkspaceWindows(const int64_t& id); ++ void updateWorkspaceWindows(const WORKSPACEID& id); + void updateWindowAnimatedDecorationValues(PHLWINDOW); +- int getNextAvailableMonitorID(std::string const& name); ++ MONITORID getNextAvailableMonitorID(std::string const& name); + void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); + void swapActiveWorkspaces(CMonitor*, CMonitor*); + CMonitor* getMonitorFromString(const std::string&); +- bool workspaceIDOutOfBounds(const int64_t&); ++ bool workspaceIDOutOfBounds(const WORKSPACEID&); + void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); + void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); + void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state); +@@ -162,12 +163,13 @@ class CCompositor { + PHLLS getLayerSurfaceFromSurface(SP); + void closeWindow(PHLWINDOW); + Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); +- void forceReportSizesToWindowsOnWorkspace(const int&); +- PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! +- void renameWorkspace(const int&, const std::string& name = ""); ++ void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&); ++ PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", ++ bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! ++ void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); + void setActiveMonitor(CMonitor*); +- bool isWorkspaceSpecial(const int&); +- int getNewSpecialID(); ++ bool isWorkspaceSpecial(const WORKSPACEID&); ++ WORKSPACEID getNewSpecialID(); + void performUserChecks(); + void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace); + PHLWINDOW getForceFocus(); +diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp +index 2a1546c6..9bee7150 100644 +--- a/src/SharedDefs.hpp ++++ b/src/SharedDefs.hpp +@@ -52,4 +52,8 @@ struct SHyprCtlCommand { + std::function fn; + }; + ++typedef int64_t WINDOWID; ++typedef int64_t MONITORID; ++typedef int64_t WORKSPACEID; ++ + typedef std::function HOOK_CALLBACK_FN; +diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp +new file mode 100644 +index 00000000..3c830132 +--- /dev/null ++++ b/src/config/ConfigDescriptions.hpp +@@ -0,0 +1,1344 @@ ++#pragma once ++ ++#include "ConfigManager.hpp" ++ ++inline static const std::vector CONFIG_OPTIONS = { ++ ++ /* ++ * general: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "general:border_size", ++ .description = "size of the border around windows", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 20}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:no_border_on_floating", ++ .description = "disable borders for floating windows", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:gaps_in", ++ .description = "gaps between windows\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{"5"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:gaps_out", ++ .description = "gaps between windows and monitor edges\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{"20"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:gaps_workspaces", ++ .description = "gaps between workspaces. Stacks with gaps_out.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 100}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.inactive_border", ++ .description = "border color for inactive windows", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0xff444444"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.active_border", ++ .description = "border color for the active window", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0xffffffff"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.nogroup_border", ++ .description = "inactive border color for window that cannot be added to a group (see denywindowfromgroup dispatcher)", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0xffffaaff"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.nogroup_border_active", ++ .description = "active border color for window that cannot be added to a group", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0xffff00ff"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:layout", ++ .description = "which layout to use. [dwindle/master]", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{"dwindle"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:no_focus_fallback", ++ .description = "if true, will not fall back to the next available window when moving focus in a direction where no window was found", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:resize_on_border", ++ .description = "enables resizing windows by clicking and dragging on borders and gaps", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:extend_border_grab_area", ++ .description = "extends the area around the border where you can click and drag on, only used when general:resize_on_border is on.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{15, 0, 100}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:hover_icon_on_border", ++ .description = "show a cursor icon when hovering over borders, only used when general:resize_on_border is on.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:allow_tearing", ++ .description = "master switch for allowing tearing to occur. See the Tearing page.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:resize_corner", ++ .description = "force floating windows to use a specific corner when being resized (1-4 going clockwise from top left, 0 to disable)", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 4}, ++ }, ++ ++ /* ++ * decoration: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "decoration:rounding", ++ .description = "rounded corners' radius (in layout px)", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 20}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:active_opacity", ++ .description = "opacity of active windows. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:inactive_opacity", ++ .description = "opacity of inactive windows. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:fullscreen_opacity", ++ .description = "opacity of fullscreen windows. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:drop_shadow", ++ .description = "enable drop shadows on windows", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:shadow_range", ++ .description = "Shadow range (size) in layout px", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{4, 0, 100}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:shadow_render_power", ++ .description = "in what power to render the falloff (more power, the faster the falloff) [1 - 4]", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{3, 1, 4}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:shadow_ignore_window", ++ .description = "if true, the shadow will not be rendered behind the window itself, only around it.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:col.shadow", ++ .description = "shadow's color. Alpha dictates shadow's opacity.", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0xee1a1a1a}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:col.shadow_inactive", ++ .description = "inactive shadow color. (if not set, will fall back to col.shadow)", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:shadow_offset", ++ .description = "shadow's rendering offset.", ++ .type = CONFIG_OPTION_VECTOR, ++ .data = SConfigOptionDescription::SVectorData{{}, {-250, -250}, {250, 250}}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:shadow_scale", ++ .description = "shadow's scale. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:dim_inactive", ++ .description = "enables dimming of inactive windows", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:dim_strength", ++ .description = "how much inactive windows should be dimmed [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.5, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:dim_special", ++ .description = "how much to dim the rest of the screen by when a special workspace is open. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:dim_around", ++ .description = "how much the dimaround window rule should dim by. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.4, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "decoration:screen_shader", ++ .description = "screen_shader a path to a custom shader to be applied at the end of rendering. See examples/screenShader.frag for an example.", ++ .type = CONFIG_OPTION_STRING_LONG, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ ++ /* ++ * blur: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "blur:enabled", ++ .description = "enable kawase window background blur", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:size", ++ .description = "blur size (distance)", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{8, 0, 100}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:passes", ++ .description = "the amount of passes to perform", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 10}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:ignore_opacity", ++ .description = "make the blur layer ignore the opacity of the window", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:new_optimizations", ++ .description = "whether to enable further optimizations to the blur. Recommended to leave on, as it will massively improve performance.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:xray", ++ .description = "if enabled, floating windows will ignore tiled windows in their blur. Only available if blur_new_optimizations is true. Will reduce overhead on floating " ++ "blur significantly.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:noise", ++ .description = "how much noise to apply. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.0117, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:contrast", ++ .description = "contrast modulation for blur. [0.0 - 2.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.8916, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:brightness", ++ .description = "brightness modulation for blur. [0.0 - 2.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.8172, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:vibrancy", ++ .description = "Increase saturation of blurred colors. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.1696, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:vibrancy_darkness", ++ .description = "How strong the effect of vibrancy is on dark areas . [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:special", ++ .description = "whether to blur behind the special workspace (note: expensive)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:popups", ++ .description = "whether to blur popups (e.g. right-click menus)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "blur:popups_ignorealpha", ++ .description = "works like ignorealpha in layer rules. If pixel opacity is below set value, will not blur. [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, ++ }, ++ ++ /* ++ * animations: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "animations:enabled", ++ .description = "enable animations", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "animations:first_launch_animation", ++ .description = "enable first launch animation", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ ++ /* ++ * input: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "input:kb_model", ++ .description = "Appropriate XKB keymap parameter. See the note below.", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{STRVAL_EMPTY}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:kb_layout", ++ .description = "Appropriate XKB keymap parameter", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{"us"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:kb_variant", ++ .description = "Appropriate XKB keymap parameter", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:kb_options", ++ .description = "Appropriate XKB keymap parameter", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:kb_rules", ++ .description = "Appropriate XKB keymap parameter", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:kb_file", ++ .description = "Appropriate XKB keymap parameter", ++ .type = CONFIG_OPTION_STRING_LONG, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:numlock_by_default", ++ .description = "Engage numlock by default.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:resolve_binds_by_sym", ++ .description = "Determines how keybinds act when multiple layouts are used. If false, keybinds will always act as if the first specified layout is active. If true, " ++ "keybinds specified by symbols are activated when you type the respective symbol with the current layout.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:repeat_rate", ++ .description = "The repeat rate for held-down keys, in repeats per second.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{25, 0, 200}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:repeat_delay", ++ .description = "Delay before a held-down key is repeated, in milliseconds.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{600, 0, 2000}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:sensitivity", ++ .description = "Sets the mouse input sensitivity. Value is clamped to the range -1.0 to 1.0.", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0, -1, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:accel_profile", ++ .description = "Sets the cursor acceleration profile. Can be one of adaptive, flat. Can also be custom, see below. Leave empty to use libinput's default mode for your " ++ "input device. [adaptive/flat/custom]", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:force_no_accel", ++ .description = "Force no cursor acceleration. This bypasses most of your pointer settings to get as raw of a signal as possible. Enabling this is not recommended due to " ++ "potential cursor desynchronization.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:left_handed", ++ .description = "Switches RMB and LMB", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:scroll_points", ++ .description = "Sets the scroll acceleration profile, when accel_profile is set to custom. Has to be in the form . Leave empty to have a flat scroll curve.", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:scroll_method", ++ .description = "Sets the scroll method. Can be one of 2fg (2 fingers), edge, on_button_down, no_scroll. [2fg/edge/on_button_down/no_scroll]", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:scroll_button", ++ .description = "Sets the scroll button. Has to be an int, cannot be a string. Check wev if you have any doubts regarding the ID. 0 means default.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 300}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:scroll_button_lock", ++ .description = "If the scroll button lock is enabled, the button does not need to be held down. Pressing and releasing the button toggles the button lock, which logically " ++ "holds the button down or releases it. While the button is logically held down, motion events are converted to scroll events.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:scroll_factor", ++ .description = "Multiplier added to scroll movement for external mice. Note that there is a separate setting for touchpad scroll_factor.", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:natural_scroll", ++ .description = "Inverts scrolling direction. When enabled, scrolling moves content directly, rather than manipulating a scrollbar.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:follow_mouse", ++ .description = "Specify if and how cursor movement should affect window focus. See the note below. [0/1/2/3]", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 3}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:mouse_refocus", ++ .description = "if disabled, mouse focus won't switch to the hovered window unless the mouse crosses a window boundary when follow_mouse=1.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:float_switch_override_focus", ++ .description = "If enabled (1 or 2), focus will change to the window under the cursor when changing from tiled-to-floating and vice versa. If 2, focus will also follow " ++ "mouse on float-to-float switches.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:special_fallthrough", ++ .description = "if enabled, having only floating windows in the special workspace will not block focusing windows in the regular workspace.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:off_window_axis_events", ++ .description = "Handles axis events around (gaps/border for tiled, dragarea/border for floated) a focused window. 0 ignores axis events 1 sends out-of-bound coordinates 2 " ++ "fakes pointer coordinates to the closest point inside the window 3 warps the cursor to the closest point inside the window", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 3}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:emulate_discrete_scroll", ++ .description = "Emulates discrete scrolling from high resolution scrolling events. 0 disables it, 1 enables handling of non-standard events only, and 2 force enables all " ++ "scroll wheel events to be handled", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 2}, ++ }, ++ ++ /* ++ * input:touchpad: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "input:touchpad:disable_while_typing", ++ .description = "Disable the touchpad while typing.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:natural_scroll", ++ .description = "Inverts scrolling direction. When enabled, scrolling moves content directly, rather than manipulating a scrollbar.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:scroll_factor", ++ .description = "Multiplier applied to the amount of scroll movement.", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:middle_button_emulation", ++ .description = ++ "Sending LMB and RMB simultaneously will be interpreted as a middle click. This disables any touchpad area that would normally send a middle click based on location.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:tap_button_map", ++ .description = "Sets the tap button mapping for touchpad button emulation. Can be one of lrm (default) or lmr (Left, Middle, Right Buttons). [lrm/lmr]", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:clickfinger_behavior", ++ .description = ++ "Button presses with 1, 2, or 3 fingers will be mapped to LMB, RMB, and MMB respectively. This disables interpretation of clicks based on location on the touchpad.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:tap-to-click", ++ .description = "Tapping on the touchpad with 1, 2, or 3 fingers will send LMB, RMB, and MMB respectively.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:drag_lock", ++ .description = "When enabled, lifting the finger off for a short time while dragging will not drop the dragged item.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchpad:tap-and-drag", ++ .description = "Sets the tap and drag mode for the touchpad", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ ++ /* ++ * input:touchdevice: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "input:touchdevice:transform", ++ .description = "Transform the input from touchdevices. The possible transformations are the same as those of the monitors", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 6}, // ##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchdevice:output", ++ .description = "The monitor to bind touch devices. The default is auto-detection. To stop auto-detection, use an empty string or the [[Empty]] value.", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:touchdevice:enabled", ++ .description = "Whether input is enabled for touch devices.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ ++ /* ++ * input:tablet: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "input:tablet:transform", ++ .description = "transform the input from tablets. The possible transformations are the same as those of the monitors", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 6}, // ##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:output", ++ .description = "the monitor to bind tablets. Empty means unbound..", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:region_position", ++ .description = "position of the mapped region in monitor layout.", ++ .type = CONFIG_OPTION_VECTOR, ++ .data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:region_size", ++ .description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.", ++ .type = CONFIG_OPTION_VECTOR, ++ .data = SConfigOptionDescription::SVectorData{{}, {-100, -100}, {4000, 4000}}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:relative_input", ++ .description = "whether the input should be relative", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:left_handed", ++ .description = "if enabled, the tablet will be rotated 180 degrees", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:active_area_size", ++ .description = "size of tablet's active area in mm", ++ .type = CONFIG_OPTION_VECTOR, ++ .data = SConfigOptionDescription::SVectorData{{}, {}, {500, 500}}, ++ }, ++ SConfigOptionDescription{ ++ .value = "input:tablet:active_area_position", ++ .description = "position of the active area in mm", ++ .type = CONFIG_OPTION_VECTOR, ++ .data = SConfigOptionDescription::SVectorData{{}, {}, {500, 500}}, ++ }, ++ ++ /* ##TODO ++ * ++ * PER DEVICE SETTINGS? ++ * ++ * */ ++ ++ /* ++ * gestures: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe", ++ .description = "enable workspace swipe gesture on touchpad", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_fingers", ++ .description = "how many fingers for the touchpad gesture", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{3, 0, 5}, //##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_min_fingers", ++ .description = "if enabled, workspace_swipe_fingers is considered the minimum number of fingers to swipe", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_distance", ++ .description = "in px, the distance of the touchpad gesture", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{300, 0, 2000}, //##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_touch", ++ .description = "enable workspace swiping from the edge of a touchscreen", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_invert", ++ .description = "invert the direction (touchpad only)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_touch_invert", ++ .description = "invert the direction (touchscreen only)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_min_speed_to_force", ++ .description = "minimum speed in px per timepoint to force the change ignoring cancel_ratio. Setting to 0 will disable this mechanic.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{30, 0, 200}, //##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_cancel_ratio", ++ .description = "how much the swipe has to proceed in order to commence it. (0.7 -> if > 0.7 * distance, switch, if less, revert) [0.0 - 1.0]", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{0.5, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_create_new", ++ .description = "whether a swipe right on the last workspace should create a new one.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_direction_lock", ++ .description = "if enabled, switching direction will be locked when you swipe past the direction_lock_threshold (touchpad only).", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_direction_lock_threshold", ++ .description = "in px, the distance to swipe before direction lock activates (touchpad only).", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{10, 0, 200}, //##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_forever", ++ .description = "if enabled, swiping will not clamp at the neighboring workspaces but continue to the further ones.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "gestures:workspace_swipe_use_r", ++ .description = "if enabled, swiping will use the r prefix instead of the m prefix for finding workspaces.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ ++ /* ++ * group: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "group:insert_after_current", ++ .description = "whether new windows in a group spawn after current or at group tail", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:focus_removed_window", ++ .description = "whether Hyprland should focus on the window that has just been moved out of the group", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.border_active", ++ .description = "border color for inactive windows", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0x66ffff00"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.border_inactive", ++ .description = "border color for the active window", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0x66777700"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.border_locked_active", ++ .description = "inactive border color for window that cannot be added to a group (see denywindowfromgroup dispatcher)", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0x66ff5500"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "general:col.border_locked_inactive", ++ .description = "active border color for window that cannot be added to a group", ++ .type = CONFIG_OPTION_GRADIENT, ++ .data = SConfigOptionDescription::SGradientData{"0x66775500"}, ++ }, ++ ++ /* ++ * group:groupbar: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "group:groupbar:enabled", ++ .description = "enables groupbars", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:font_family", ++ .description = "font used to display groupbar titles, use misc:font_family if not specified", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{STRVAL_EMPTY}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:font_size", ++ .description = "font size of groupbar title", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{8, 2, 64}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:gradients", ++ .description = "enables gradients", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:height", ++ .description = "height of the groupbar", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{14, 1, 64}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:stacked", ++ .description = "render the groupbar as a vertical stack", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:priority", ++ .description = "sets the decoration priority for groupbars", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{3, 0, 6}, //##TODO RANGE? ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:render_titles", ++ .description = "whether to render titles in the group bar decoration", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:scrolling", ++ .description = "whether scrolling in the groupbar changes group active window", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:text_color", ++ .description = "controls the group bar text color", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0xffffffff}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:col.active", ++ .description = "active group border color", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0x66ffff00}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:col.inactive", ++ .description = "inactive (out of focus) group border color", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0x66777700}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:col.locked_active", ++ .description = "active locked group border color", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0x66ff5500}, ++ }, ++ SConfigOptionDescription{ ++ .value = "group:groupbar:col.locked_inactive", ++ .description = "controls the group bar text color", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0x66775500}, ++ }, ++ ++ /* ++ * misc: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "misc:disable_hyprland_logo", ++ .description = "disables the random Hyprland logo / anime girl background. :(", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:disable_splash_rendering", ++ .description = "disables the Hyprland splash rendering. (requires a monitor reload to take effect)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:col.splash", ++ .description = "Changes the color of the splash text (requires a monitor reload to take effect).", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0xffffffff}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:font_family", ++ .description = "Set the global default font to render the text including debug fps/notification, config error messages and etc., selected from system fonts.", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{"Sans"}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:splash_font_family", ++ .description = "Changes the font used to render the splash text, selected from system fonts (requires a monitor reload to take effect).", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{STRVAL_EMPTY}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:force_default_wallpaper", ++ .description = "Enforce any of the 3 default wallpapers. Setting this to 0 or 1 disables the anime background. -1 means “random”. [-1/0/1/2]", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{-1, -1, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:vfr", ++ .description = "controls the VFR status of Hyprland. Heavily recommended to leave enabled to conserve resources.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:vrr", ++ .description = " controls the VRR (Adaptive Sync) of your monitors. 0 - off, 1 - on, 2 - fullscreen only [0/1/2]", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:mouse_move_enables_dpms", ++ .description = "If DPMS is set to off, wake up the monitors if the mouse move", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:key_press_enables_dpms", ++ .description = "If DPMS is set to off, wake up the monitors if a key is pressed.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:always_follow_on_dnd", ++ .description = "Will make mouse focus follow the mouse when drag and dropping. Recommended to leave it enabled, especially for people using focus follows mouse at 0.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:layers_hog_keyboard_focus", ++ .description = "If true, will make keyboard-interactive layers keep their focus on mouse move (e.g. wofi, bemenu)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:animate_manual_resizes", ++ .description = "If true, will animate manual window resizes/moves", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:animate_mouse_windowdragging", ++ .description = "If true, will animate windows being dragged by mouse, note that this can cause weird behavior on some curves", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:disable_autoreload", ++ .description = "If true, the config will not reload automatically on save, and instead needs to be reloaded with hyprctl reload. Might save on battery.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:enable_swallow", ++ .description = "Enable window swallowing", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:swallow_regex", ++ .description = ++ "The class regex to be used for windows that should be swallowed (usually, a terminal). To know more about the list of regex which can be used use this cheatsheet.", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:swallow_exception_regex", ++ .description = "The title regex to be used for windows that should not be swallowed by the windows specified in swallow_regex (e.g. wev). The regex is matched against the " ++ "parent (e.g. Kitty) window’s title on the assumption that it changes to whatever process it’s running.", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:focus_on_activate", ++ .description = "Whether Hyprland should focus an app that requests to be focused (an activate request)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:mouse_move_focuses_monitor", ++ .description = "Whether mouse moving into a different monitor should focus it", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:render_ahead_of_time", ++ .description = "[Warning: buggy] starts rendering before your monitor displays a frame in order to lower latency", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:render_ahead_safezone", ++ .description = "how many ms of safezone to add to rendering ahead of time. Recommended 1-2.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 1, 10}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:allow_session_lock_restore", ++ .description = "if true, will allow you to restart a lockscreen app in case it crashes (red screen of death)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:background_color", ++ .description = "change the background color. (requires enabled disable_hyprland_logo)", ++ .type = CONFIG_OPTION_COLOR, ++ .data = SConfigOptionDescription::SColorData{0x111111}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:close_special_on_empty", ++ .description = "close the special workspace if the last window is removed", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:new_window_takes_over_fullscreen", ++ .description = "if there is a fullscreen or maximized window, decide whether a new tiled window opened should replace it, stay behind or disable the fullscreen/maximized " ++ "state. 0 - behind, 1 - takes over, 2 - unfullscreen/unmaxize [0/1/2]", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:exit_window_retains_fullscreen", ++ .description = "if true, closing a fullscreen window makes the next focused window fullscreen", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:initial_workspace_tracking", ++ .description = "if enabled, windows will open on the workspace they were invoked on. 0 - disabled, 1 - single-shot, 2 - persistent (all children too)", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "misc:middle_click_paste", ++ .description = "whether to enable middle-click-paste (aka primary selection)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ ++ /* ++ * binds: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "binds:pass_mouse_when_bound", ++ .description = "if disabled, will not pass the mouse events to apps / dragging windows around if a keybind has been triggered.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:scroll_event_delay", ++ .description = "in ms, how many ms to wait after a scroll event to allow passing another one for the binds.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{300, 0, 2000}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:workspace_back_and_forth", ++ .description = "If enabled, an attempt to switch to the currently focused workspace will instead switch to the previous workspace. Akin to i3’s auto_back_and_forth.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:allow_workspace_cycles", ++ .description = "If enabled, workspaces don’t forget their previous workspace, so cycles can be created by switching to the first workspace in a sequence, then endlessly " ++ "going to the previous workspace.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:workspace_center_on", ++ .description = "Whether switching workspaces should center the cursor on the workspace (0) or on the last active window for that workspace (1)", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:focus_preferred_method", ++ .description = "sets the preferred focus finding method when using focuswindow/movewindow/etc with a direction. 0 - history (recent have priority), 1 - length (longer " ++ "shared edges have priority)", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:ignore_group_lock", ++ .description = "If enabled, dispatchers like moveintogroup, moveoutofgroup and movewindoworgroup will ignore lock per group.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:movefocus_cycles_fullscreen", ++ .description = "If enabled, when on a fullscreen window, movefocus will cycle fullscreen, if not, it will move the focus in a direction.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:disable_keybind_grabbing", ++ .description = "If enabled, apps that request keybinds to be disabled (e.g. VMs) will not be able to do so.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "binds:window_direction_monitor_fallback", ++ .description = "If enabled, moving a window or focus over the edge of a monitor with a direction will move it to the next monitor in that direction.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ ++ /* ++ * xwayland: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "xwayland:use_nearest_neighbor", ++ .description = "uses the nearest neighbor filtering for xwayland apps, making them pixelated rather than blurry", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "xwayland:force_zero_scaling", ++ .description = "forces a scale of 1 on xwayland windows on scaled displays.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ ++ /* ++ * opengl: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "opengl:nvidia_anti_flicker", ++ .description = "reduces flickering on nvidia at the cost of possible frame drops on lower-end GPUs. On non-nvidia, this is ignored.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "opengl:force_introspection", ++ .description = "forces introspection at all times. Introspection is aimed at reducing GPU usage in certain cases, but might cause graphical glitches on nvidia. 0 - " ++ "nothing, 1 - force always on, 2 - force always on if nvidia", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{2, 0, 2}, ++ }, ++ ++ /* ++ * render: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "render:explicit_sync", ++ .description = "Whether to enable explicit sync support. Requires a hyprland restart. 0 - no, 1 - yes, 2 - auto based on the gpu driver", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{2, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "render:explicit_sync_kms", ++ .description = "Whether to enable explicit sync support for the KMS layer. Requires explicit_sync to be enabled. 0 - no, 1 - yes, 2 - auto based on the gpu driver", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{2, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "render:direct_scanout", ++ .description = "Enables direct scanout. Direct scanout attempts to reduce lag when there is only one fullscreen application on a screen (e.g. game). It is also " ++ "recommended to set this to false if the fullscreen application shows graphical glitches.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ ++ /* ++ * cursor: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "cursor:use_nearest_neighbor", ++ .description = "sync xcursor theme with gsettings, it applies cursor-theme and cursor-size on theme load to gsettings making most CSD gtk based clients use same xcursor " ++ "theme and size.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:no_hardware_cursors", ++ .description = "disables hardware cursors", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:no_break_fs_vrr", ++ .description = "disables scheduling new frames on cursor movement for fullscreen apps with VRR enabled to avoid framerate spikes (requires no_hardware_cursors = true)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:min_refresh_rate", ++ .description = "minimum refresh rate for cursor movement when no_break_fs_vrr is active. Set to minimum supported refresh rate or higher", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{24, 10, 500}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:hotspot_padding", ++ .description = "the padding, in logical px, between screen edges and the cursor", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{1, 0, 20}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:inactive_timeout", ++ .description = "in seconds, after how many seconds of cursor’s inactivity to hide it. Set to 0 for never.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 20}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:no_warps", ++ .description = "if true, will not warp the cursor in many cases (focusing, keybinds, etc)", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:persistent_warps", ++ .description = "When a window is refocused, the cursor returns to its last position relative to that window, rather than to the centre.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:warp_on_change_workspace", ++ .description = "If true, move the cursor to the last focused window after changing the workspace.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:default_monitor", ++ .description = "the name of a default monitor for the cursor to be set to on startup (see hyprctl monitors for names)", ++ .type = CONFIG_OPTION_STRING_SHORT, ++ .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:zoom_factor", ++ .description = "the factor to zoom by around the cursor. Like a magnifying glass. Minimum 1.0 (meaning no zoom)", ++ .type = CONFIG_OPTION_FLOAT, ++ .data = SConfigOptionDescription::SFloatData{1, 1, 10}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:zoom_rigid", ++ .description = "whether the zoom should follow the cursor rigidly (cursor is always centered if it can be) or loosely", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:enable_hyprcursor", ++ .description = "whether to enable hyprcursor support", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:hide_on_key_press", ++ .description = "Hides the cursor when you press any key until the mouse is moved.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:hide_on_touch", ++ .description = "Hides the cursor when the last input was a touch input until a mouse input is done.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "cursor:allow_dumb_copy", ++ .description = "Makes HW cursors work on Nvidia, at the cost of a possible hitch whenever the image changes", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ ++ /* ++ * debug: ++ */ ++ ++ SConfigOptionDescription{ ++ .value = "debug:overlay", ++ .description = "print the debug performance overlay. Disable VFR for accurate results.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:damage_blink", ++ .description = "disable logging to a file", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:disable_logs", ++ .description = "disable logging to a file", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:disable_time", ++ .description = "disables time logging", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:damage_tracking", ++ .description = "redraw only the needed bits of the display. Do not change. (default: full - 2) monitor - 1, none - 0", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{2, 0, 2}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:enable_stdout_logs", ++ .description = "enables logging to stdout", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:manual_crash", ++ .description = "set to 1 and then back to 0 to crash Hyprland.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:suppress_errors", ++ .description = "if true, do not display config file parsing errors.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:watchdog_timeout", ++ .description = "sets the timeout in seconds for watchdog to abort processing of a signal of the main thread. Set to 0 to disable.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{5, 0, 20}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:disable_scale_checks", ++ .description = "disables verification of the scale factors. Will result in pixel alignment and rounding errors.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{false}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:error_limit", ++ .description = "limits the number of displayed config file parsing errors.", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{5, 0, 20}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:error_position", ++ .description = "sets the position of the error bar. top - 0, bottom - 1", ++ .type = CONFIG_OPTION_INT, ++ .data = SConfigOptionDescription::SRangeData{0, 0, 1}, ++ }, ++ SConfigOptionDescription{ ++ .value = "debug:colored_stdout_logs", ++ .description = "enables colors in the stdout logs.", ++ .type = CONFIG_OPTION_BOOL, ++ .data = SConfigOptionDescription::SBoolData{true}, ++ }, ++}; +\ No newline at end of file +diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp +index be6433fa..1856bd49 100644 +--- a/src/config/ConfigManager.cpp ++++ b/src/config/ConfigManager.cpp +@@ -28,7 +28,9 @@ + #include + using namespace Hyprutils::String; + +-extern "C" char** environ; ++extern "C" char** environ; ++ ++#include "ConfigDescriptions.hpp" + + static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** data) { + std::string V = VALUE; +@@ -312,8 +314,6 @@ CConfigManager::CConfigManager() { + configPaths.emplace_back(getMainConfigPath()); + m_pConfig = std::make_unique(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); + +- m_pConfig->addConfigValue("general:sensitivity", {1.0f}); +- m_pConfig->addConfigValue("general:apply_sens_to_raw", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); + m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:border_part_of_window", Hyprlang::INT{1}); +@@ -531,7 +531,7 @@ CConfigManager::CConfigManager() { + m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); + m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); +- m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0}); ++ m_pConfig->addConfigValue("cursor:inactive_timeout", {0.f}); + m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0}); +@@ -539,6 +539,7 @@ CConfigManager::CConfigManager() { + m_pConfig->addConfigValue("cursor:zoom_factor", {1.f}); + m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1}); ++ m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); +@@ -821,9 +822,6 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { + if (!isFirstLaunch) + g_pHyprOpenGL->m_bReloadScreenShader = true; + +- if (!isFirstLaunch && *PENABLEEXPLICIT != prevEnabledExplicit) +- g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); +- + // parseError will be displayed next frame + + if (result.error) +@@ -836,6 +834,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { + else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) + g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", + CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); ++ else if (*PENABLEEXPLICIT != prevEnabledExplicit) ++ g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + else + g_pHyprError->destroy(); + +@@ -924,7 +924,10 @@ void CConfigManager::init() { + } + + std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) { +- const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str()); ++ static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); ++ static int prevEnabledExplicit = *PENABLEEXPLICIT; ++ ++ const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str()); + + // invalidate layouts if they changed + if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) { +@@ -932,6 +935,13 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); + } + ++ if (COMMAND.contains("explicit")) { ++ if (*PENABLEEXPLICIT != prevEnabledExplicit) ++ g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); ++ else ++ g_pHyprError->destroy(); ++ } ++ + // Update window border colors + g_pCompositor->updateAllWindowsAnimatedDecorationValues(); + +@@ -2425,7 +2435,7 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin + // } + + const static std::string ruleOnCreatedEmpty = "on-created-empty:"; +- const static int ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); ++ const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); + + auto assignRule = [&](std::string rule) -> std::optional { + size_t delim = std::string::npos; +@@ -2597,3 +2607,60 @@ std::optional CConfigManager::handlePlugin(const std::string& comma + + return {}; + } ++ ++const std::vector& CConfigManager::getAllDescriptions() { ++ return CONFIG_OPTIONS; ++} ++ ++std::string SConfigOptionDescription::jsonify() const { ++ auto parseData = [this]() -> std::string { ++ return std::visit( ++ [](auto&& val) { ++ using T = std::decay_t; ++ if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": "{}")#", val.value); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": {}, ++ "min": {}, ++ "max": {})#", ++ val.value, val.min, val.max); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": {}, ++ "min": {}, ++ "max": {})#", ++ val.value, val.min, val.max); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": {})#", val.color.getAsHex()); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": {})#", val.value); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": {})#", val.choices); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "x": {}, ++ "y": {}, ++ "min_x": {}, ++ "min_y": {}, ++ "max_x": {}, ++ "max_y": {})#", ++ val.vec.x, val.vec.y, val.min.x, val.min.y, val.max.x, val.max.y); ++ } else if constexpr (std::is_same_v) { ++ return std::format(R"#( "value": "{}")#", val.gradient); ++ } ++ return std::string{""}; ++ }, ++ data); ++ }; ++ ++ std::string json = std::format(R"#({{ ++ "value": "{}", ++ "description": "{}", ++ "type": {}, ++ "flags": {}, ++ "data": {{ ++ {} ++ }} ++}})#", ++ value, description, (uint16_t)type, (uint32_t)flags, parseData()); ++ ++ return json; ++} +diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp +index 75dea9ef..4241031b 100644 +--- a/src/config/ConfigManager.hpp ++++ b/src/config/ConfigManager.hpp +@@ -33,7 +33,7 @@ struct SWorkspaceRule { + std::string monitor = ""; + std::string workspaceString = ""; + std::string workspaceName = ""; +- int workspaceId = -1; ++ WORKSPACEID workspaceId = -1; + bool isDefault = false; + bool isPersistent = false; + std::optional gapsIn; +@@ -83,6 +83,70 @@ struct SExecRequestedRule { + uint64_t iPid = 0; + }; + ++enum eConfigOptionType : uint16_t { ++ CONFIG_OPTION_BOOL = 0, ++ CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/ ++ CONFIG_OPTION_FLOAT = 2, ++ CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */ ++ CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */ ++ CONFIG_OPTION_COLOR = 5, ++ CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */ ++ CONFIG_OPTION_GRADIENT = 7, ++ CONFIG_OPTION_VECTOR = 8, ++}; ++ ++enum eConfigOptionFlags : uint32_t { ++ CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0), ++}; ++ ++struct SConfigOptionDescription { ++ ++ struct SBoolData { ++ bool value = false; ++ }; ++ ++ struct SRangeData { ++ int value = 0, min = 0, max = 2; ++ }; ++ ++ struct SFloatData { ++ float value = 0, min = 0, max = 100; ++ }; ++ ++ struct SStringData { ++ std::string value; ++ }; ++ ++ struct SColorData { ++ CColor color; ++ }; ++ ++ struct SChoiceData { ++ int firstIndex = 0; ++ std::string choices; // comma-separated ++ }; ++ ++ struct SGradientData { ++ std::string gradient; ++ }; ++ ++ struct SVectorData { ++ Vector2D vec, min, max; ++ }; ++ ++ std::string value; // e.g. general:gaps_in ++ std::string description; ++ std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device ++ bool specialKey = false; ++ eConfigOptionType type = CONFIG_OPTION_BOOL; ++ uint32_t flags = 0; // eConfigOptionFlags ++ ++ std::string jsonify() const; ++ ++ // ++ std::variant data; ++}; ++ + class CConfigManager { + public: + CConfigManager(); +@@ -115,6 +179,8 @@ class CConfigManager { + std::vector getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); + std::vector getMatchingRules(PHLLS); + ++ const std::vector& getAllDescriptions(); ++ + std::unordered_map m_mAdditionalReservedAreas; + + std::unordered_map getAnimationConfig(); +diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp +index d91a1cec..78c8504a 100644 +--- a/src/debug/HyprCtl.cpp ++++ b/src/debug/HyprCtl.cpp +@@ -71,7 +71,7 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor + + std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m, eHyprCtlOutputFormat format) { + std::string result; +- if (!m->output || m->ID == -1ull) ++ if (!m->output || m->ID == -1) + return ""; + + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { +@@ -155,19 +155,19 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { + result += "]"; + } else { + for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { +- if (!m->output || m->ID == -1ull) ++ if (!m->output || m->ID == -1) + continue; + +- result += +- std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" +- "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" +- "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", +- m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, +- m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), +- m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, +- (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, +- (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), +- m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); ++ result += std::format( ++ "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" ++ "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" ++ "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: A {} H {}\n\tavailableModes: {}\n\n", ++ m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, ++ m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), ++ m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, ++ (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), ++ (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), m->tearingState.activelyTearing, !m->m_bEnabled, ++ formatToString(m->output->state->state().drmFormat), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + } + } + +@@ -1561,6 +1561,21 @@ std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) { + return lockedStr; + } + ++std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) { ++ std::string json = "{"; ++ const auto& DESCS = g_pConfigManager->getAllDescriptions(); ++ ++ for (const auto& d : DESCS) { ++ json += d.jsonify() + ",\n"; ++ } ++ ++ json.pop_back(); ++ json.pop_back(); ++ ++ json += "}\n"; ++ return json; ++} ++ + CHyprCtl::CHyprCtl() { + registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest}); + registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest}); +@@ -1581,6 +1596,7 @@ CHyprCtl::CHyprCtl() { + registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest}); + registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest}); + registerCommand(SHyprCtlCommand{"locked", true, getIsLocked}); ++ registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions}); + + registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest}); + registerCommand(SHyprCtlCommand{"reload", false, reloadRequest}); +diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp +index 889be8ea..fbd8cd71 100644 +--- a/src/debug/HyprDebugOverlay.cpp ++++ b/src/debug/HyprDebugOverlay.cpp +@@ -7,8 +7,8 @@ CHyprDebugOverlay::CHyprDebugOverlay() { + m_pTexture = makeShared(); + } + +-void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) { +- m_dLastRenderTimes.push_back(µs / 1000.f); ++void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { ++ m_dLastRenderTimes.push_back(durationUs / 1000.f); + + if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate) + m_dLastRenderTimes.pop_front(); +@@ -17,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) { + m_pMonitor = pMonitor; + } + +-void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) { +- m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f); ++void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { ++ m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f); + + if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate) + m_dLastRenderTimesNoOverlay.pop_front(); +@@ -188,12 +188,12 @@ int CHyprMonitorDebugOverlay::draw(int offset) { + return posY - offset; + } + +-void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) { +- m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs); ++void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { ++ m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs); + } + +-void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) { +- m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs); ++void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { ++ m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs); + } + + void CHyprDebugOverlay::frameData(CMonitor* pMonitor) { +diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp +index a6063ee9..e7742b35 100644 +--- a/src/debug/HyprDebugOverlay.hpp ++++ b/src/debug/HyprDebugOverlay.hpp +@@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay { + public: + int draw(int offset); + +- void renderData(CMonitor* pMonitor, float µs); +- void renderDataNoOverlay(CMonitor* pMonitor, float µs); ++ void renderData(CMonitor* pMonitor, float durationUs); ++ void renderDataNoOverlay(CMonitor* pMonitor, float durationUs); + void frameData(CMonitor* pMonitor); + + private: +@@ -33,8 +33,8 @@ class CHyprDebugOverlay { + public: + CHyprDebugOverlay(); + void draw(); +- void renderData(CMonitor*, float µs); +- void renderDataNoOverlay(CMonitor*, float µs); ++ void renderData(CMonitor*, float durationUs); ++ void renderDataNoOverlay(CMonitor*, float durationUs); + void frameData(CMonitor*); + + private: +diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp +index 0def77c0..a4c5b08e 100644 +--- a/src/debug/Log.cpp ++++ b/src/debug/Log.cpp +@@ -5,10 +5,13 @@ + + #include + #include ++#include + + void Debug::init(const std::string& IS) { + logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log"); + logOfs.open(logFile, std::ios::out | std::ios::app); ++ auto handle = logOfs.native_handle(); ++ fcntl(handle, F_SETFD, FD_CLOEXEC); + } + + void Debug::close() { +diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp +index 8fd448ef..c352fa74 100644 +--- a/src/desktop/LayerSurface.cpp ++++ b/src/desktop/LayerSurface.cpp +@@ -432,8 +432,8 @@ void CLayerSurface::startAnimation(bool in, bool instant) { + PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, + }; + +- float closest = std::numeric_limits::max(); +- int leader = force; ++ float closest = std::numeric_limits::max(); ++ size_t leader = force; + if (leader == -1) { + for (size_t i = 0; i < 4; ++i) { + float dist = MIDDLE.distance(edgePoints[i]); +diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp +index 056f66a8..84935b34 100644 +--- a/src/desktop/LayerSurface.hpp ++++ b/src/desktop/LayerSurface.hpp +@@ -42,7 +42,7 @@ class CLayerSurface { + bool mapped = false; + uint32_t layer = 0; + +- int monitorID = -1; ++ MONITORID monitorID = -1; + + bool fadingOut = false; + bool readyToDelete = false; +@@ -51,7 +51,7 @@ class CLayerSurface { + + bool forceBlur = false; + bool forceBlurPopups = false; +- int xray = -1; ++ int64_t xray = -1; + bool ignoreAlpha = false; + float ignoreAlphaValue = 0.f; + bool dimAround = false; +diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp +index 93c208cf..dcdcb573 100644 +--- a/src/desktop/Window.cpp ++++ b/src/desktop/Window.cpp +@@ -1243,7 +1243,7 @@ bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) { + return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE; + } + +-int CWindow::workspaceID() { ++WORKSPACEID CWindow::workspaceID() { + return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace; + } + +diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp +index 11bf662a..2e5b54b1 100644 +--- a/src/desktop/Window.hpp ++++ b/src/desktop/Window.hpp +@@ -270,7 +270,7 @@ class CWindow { + bool m_bDraggingTiled = false; // for dragging around tiled windows + bool m_bWasMaximized = false; + sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; +- uint64_t m_iMonitorID = -1; ++ MONITORID m_iMonitorID = -1; + std::string m_szTitle = ""; + std::string m_szClass = ""; + std::string m_szInitialTitle = ""; +@@ -358,8 +358,8 @@ class CWindow { + bool m_bStayFocused = false; + + // for toplevel monitor events +- uint64_t m_iLastToplevelMonitorID = -1; +- uint64_t m_iLastSurfaceMonitorID = -1; ++ MONITORID m_iLastToplevelMonitorID = -1; ++ MONITORID m_iLastSurfaceMonitorID = -1; + + // for idle inhibiting windows + eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE; +@@ -421,7 +421,7 @@ class CWindow { + bool canBeTorn(); + void setSuspended(bool suspend); + bool visibleOnMonitor(CMonitor* pMonitor); +- int workspaceID(); ++ WORKSPACEID workspaceID(); + bool onSpecialWorkspace(); + void activate(bool force = false); + int surfacesCount(); +@@ -490,9 +490,9 @@ class CWindow { + + private: + // For hidden windows and stuff +- bool m_bHidden = false; +- bool m_bSuspended = false; +- int m_iLastWorkspace = WORKSPACE_INVALID; ++ bool m_bHidden = false; ++ bool m_bSuspended = false; ++ WORKSPACEID m_iLastWorkspace = WORKSPACE_INVALID; + }; + + inline bool valid(PHLWINDOW w) { +diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp +index a08f1804..d9ac7927 100644 +--- a/src/desktop/Workspace.cpp ++++ b/src/desktop/Workspace.cpp +@@ -5,13 +5,13 @@ + #include + using namespace Hyprutils::String; + +-PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) { ++PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) { + PHLWORKSPACE workspace = makeShared(id, monitorID, name, special, isEmtpy); + workspace->init(workspace); + return workspace; + } + +-CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) { ++CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) { + m_iMonitorID = monitorID; + m_iID = id; + m_szName = name; +@@ -190,7 +190,7 @@ void CWorkspace::setActive(bool on) { + ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 + } + +-void CWorkspace::moveToMonitor(const int& id) { ++void CWorkspace::moveToMonitor(const MONITORID& id) { + ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 + } + +@@ -275,7 +275,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { + i = std::min(NEXTSPACE, std::string::npos - 1); + + if (cur == 'r') { +- int from = 0, to = 0; ++ WORKSPACEID from = 0, to = 0; + if (!prop.starts_with("r[") || !prop.ends_with("]")) { + Debug::log(LOG, "Invalid selector {}", selector); + return false; +@@ -365,7 +365,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { + } + + if (cur == 'w') { +- int from = 0, to = 0; ++ WORKSPACEID from = 0, to = 0; + if (!prop.starts_with("w[") || !prop.ends_with("]")) { + Debug::log(LOG, "Invalid selector {}", selector); + return false; +@@ -446,7 +446,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { + return false; + } + +- int count; ++ WORKSPACEID count; + if (wantsCountGroup) + count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); +@@ -506,7 +506,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { + void CWorkspace::markInert() { + m_bInert = true; + m_iID = WORKSPACE_INVALID; +- m_iMonitorID = -1; ++ m_iMonitorID = MONITOR_INVALID; + m_bVisible = false; + } + +diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp +index 3e9ac8a8..9cacb0cc 100644 +--- a/src/desktop/Workspace.hpp ++++ b/src/desktop/Workspace.hpp +@@ -17,16 +17,16 @@ class CWindow; + + class CWorkspace { + public: +- static PHLWORKSPACE create(int id, int monitorID, std::string name, bool special = false, bool isEmtpy = true); ++ static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmtpy = true); + // use create() don't use this +- CWorkspace(int id, int monitorID, std::string name, bool special = false, bool isEmpty = true); ++ CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); + ~CWorkspace(); + + // Workspaces ID-based have IDs > 0 + // and workspaces name-based have IDs starting with -1337 +- int m_iID = -1; ++ WORKSPACEID m_iID = WORKSPACE_INVALID; + std::string m_szName = ""; +- uint64_t m_iMonitorID = -1; ++ MONITORID m_iMonitorID = MONITOR_INVALID; + // Previous workspace ID and name is stored during a workspace change, allowing travel + // to the previous workspace. + SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; +@@ -67,7 +67,7 @@ class CWorkspace { + void startAnim(bool in, bool left, bool instant = false); + void setActive(bool on); + +- void moveToMonitor(const int&); ++ void moveToMonitor(const MONITORID&); + + PHLWINDOW getLastFocusedWindow(); + void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); +diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp +index 5d29a3b7..2eb7038f 100644 +--- a/src/events/Windows.cpp ++++ b/src/events/Windows.cpp +@@ -148,7 +148,7 @@ void Events::listener_mapWindow(void* owner, void* data) { + PWINDOW->m_iMonitorID = PMONITOR->ID; + } else { + if (isNumber(MONITORSTR)) { +- const long int MONITOR = std::stoi(MONITORSTR); ++ const MONITORID MONITOR = std::stoi(MONITORSTR); + if (!g_pCompositor->getMonitorFromID(MONITOR)) + PWINDOW->m_iMonitorID = 0; + else +diff --git a/src/helpers/Color.cpp b/src/helpers/Color.cpp +index 67526dc7..f9a207bb 100644 +--- a/src/helpers/Color.cpp ++++ b/src/helpers/Color.cpp +@@ -21,6 +21,6 @@ CColor::CColor(uint64_t hex) { + this->a = ALPHA(hex); + } + +-uint32_t CColor::getAsHex() { ++uint32_t CColor::getAsHex() const { + return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1; + } +\ No newline at end of file +diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp +index 7ec55b0d..8abfe748 100644 +--- a/src/helpers/Color.hpp ++++ b/src/helpers/Color.hpp +@@ -10,7 +10,7 @@ class CColor { + + float r = 0, g = 0, b = 0, a = 1.f; + +- uint32_t getAsHex(); ++ uint32_t getAsHex() const; + + CColor operator-(const CColor& c2) const { + return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a); +diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp +index 53c0dc13..86f24e3a 100644 +--- a/src/helpers/MiscFunctions.cpp ++++ b/src/helpers/MiscFunctions.cpp +@@ -249,7 +249,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + return {WORKSPACE_INVALID}; + } + +- std::set invalidWSes; ++ std::set invalidWSes; + if (same_mon) { + for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) { + const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor); +@@ -258,8 +258,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + } + } + +- int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; +- while (++id < INT_MAX) { ++ WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; ++ while (++id < LONG_MAX) { + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); + if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { + result.id = id; +@@ -296,9 +296,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + + result.id = (int)PLUSMINUSRESULT.value(); + +- int remains = (int)result.id; ++ WORKSPACEID remains = result.id; + +- std::set invalidWSes; ++ std::set invalidWSes; + + // Collect all the workspaces we can't jump to. + for (auto& ws : g_pCompositor->m_vWorkspaces) { +@@ -318,7 +318,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + } + + // Prepare all named workspaces in case when we need them +- std::vector namedWSes; ++ std::vector namedWSes; + for (auto& ws : g_pCompositor->m_vWorkspaces) { + if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0) + continue; +@@ -347,18 +347,18 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + } else { + + // Just take a blind guess at where we'll probably end up +- int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; +- int predictedWSID = activeWSID + remains; +- int remainingWSes = 0; +- char walkDir = in[1]; ++ WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; ++ WORKSPACEID predictedWSID = activeWSID + remains; ++ int remainingWSes = 0; ++ char walkDir = in[1]; + + // sanitize. 0 means invalid oob in - +- predictedWSID = std::max(predictedWSID, 0); ++ predictedWSID = std::max(predictedWSID, 0L); + + // Count how many invalidWSes are in between (how bad the prediction was) +- int beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID; +- int endID = in[1] == '+' ? predictedWSID : activeWSID; +- auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= ++ WORKSPACEID beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID; ++ WORKSPACEID endID = in[1] == '+' ? predictedWSID : activeWSID; ++ auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= + for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { + remainingWSes++; + } +@@ -367,7 +367,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + if (activeWSID < 0) { + // Behaviour similar to 'm' + // Find current +- int currentItem = -1; ++ size_t currentItem = -1; + for (size_t i = 0; i < namedWSes.size(); i++) { + if (namedWSes[i] == activeWSID) { + currentItem = i; +@@ -376,14 +376,14 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + } + + currentItem += remains; +- currentItem = std::max(currentItem, 0); +- if (currentItem >= (int)namedWSes.size()) { ++ currentItem = std::max(currentItem, 0UL); ++ if (currentItem >= namedWSes.size()) { + // At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0 +- int diff = currentItem - (namedWSes.size() - 1); +- predictedWSID = diff; +- int beginID = 1; +- int endID = predictedWSID; +- auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= ++ size_t diff = currentItem - (namedWSes.size() - 1); ++ predictedWSID = diff; ++ WORKSPACEID beginID = 1; ++ WORKSPACEID endID = predictedWSID; ++ auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= + for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { + remainingWSes++; + } +@@ -397,10 +397,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + + // Go in the search direction for remainingWSes + // The performance impact is directly proportional to the number of open and bound workspaces +- int finalWSID = predictedWSID; ++ WORKSPACEID finalWSID = predictedWSID; + if (walkDir == '-') { +- int beginID = finalWSID; +- int curID = finalWSID; ++ WORKSPACEID beginID = finalWSID; ++ WORKSPACEID curID = finalWSID; + while (--curID > 0 && remainingWSes > 0) { + if (!invalidWSes.contains(curID)) { + remainingWSes--; +@@ -411,9 +411,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + if (namedWSes.size()) { + // Go to the named workspaces + // Need remainingWSes more +- int namedWSIdx = namedWSes.size() - remainingWSes; ++ auto namedWSIdx = namedWSes.size() - remainingWSes; + // Sanitze +- namedWSIdx = std::clamp(namedWSIdx, 0, (int)namedWSes.size() - 1); ++ namedWSIdx = std::clamp(namedWSIdx, 0UL, namedWSes.size() - 1); + finalWSID = namedWSes[namedWSIdx]; + } else { + // Couldn't find valid workspace in negative direction, search last first one back up positive direction +@@ -425,7 +425,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + } + } + if (walkDir == '+') { +- int curID = finalWSID; ++ WORKSPACEID curID = finalWSID; + while (++curID < INT32_MAX && remainingWSes > 0) { + if (!invalidWSes.contains(curID)) { + remainingWSes--; +@@ -460,9 +460,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + result.id = (int)PLUSMINUSRESULT.value(); + + // result now has +/- what we should move on mon +- int remains = (int)result.id; ++ int remains = (int)result.id; + +- std::vector validWSes; ++ std::vector validWSes; + for (auto& ws : g_pCompositor->m_vWorkspaces) { + if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors)) + continue; +@@ -472,7 +472,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + + std::sort(validWSes.begin(), validWSes.end()); + +- int currentItem = -1; ++ ssize_t currentItem = -1; + + if (absolute) { + // 1-index +@@ -481,7 +481,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + // clamp + if (currentItem < 0) { + currentItem = 0; +- } else if (currentItem >= (int)validWSes.size()) { ++ } else if (currentItem >= (ssize_t)validWSes.size()) { + currentItem = validWSes.size() - 1; + } + } else { +@@ -489,8 +489,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size(); + + // get the current item +- int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; +- for (size_t i = 0; i < validWSes.size(); i++) { ++ WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; ++ for (ssize_t i = 0; i < (ssize_t)validWSes.size(); i++) { + if (validWSes[i] == activeWSID) { + currentItem = i; + break; +@@ -501,7 +501,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + currentItem += remains; + + // sanitize +- if (currentItem >= (int)validWSes.size()) { ++ if (currentItem >= (ssize_t)validWSes.size()) { + currentItem = currentItem % validWSes.size(); + } else if (currentItem < 0) { + currentItem = validWSes.size() + currentItem; +@@ -547,9 +547,9 @@ std::optional cleanCmdForWorkspace(const std::string& inWorkspaceNa + const std::string workspaceRule = "workspace " + inWorkspaceName; + + if (cmd[0] == '[') { +- const int closingBracketIdx = cmd.find_last_of(']'); +- auto tmpRules = cmd.substr(1, closingBracketIdx - 1); +- cmd = cmd.substr(closingBracketIdx + 1); ++ const auto closingBracketIdx = cmd.find_last_of(']'); ++ auto tmpRules = cmd.substr(1, closingBracketIdx - 1); ++ cmd = cmd.substr(closingBracketIdx + 1); + + auto rulesList = CVarList(tmpRules, 0, ';'); + +@@ -785,13 +785,13 @@ std::vector getBacktrace() { + + #ifdef HAS_EXECINFO + void* bt[1024]; +- size_t btSize; ++ int btSize; + char** btSymbols; + + btSize = backtrace(bt, 1024); + btSymbols = backtrace_symbols(bt, btSize); + +- for (size_t i = 0; i < btSize; ++i) { ++ for (auto i = 0; i < btSize; ++i) { + callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}}); + } + #else +diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp +index 49e3bced..8b2ea0d1 100644 +--- a/src/helpers/MiscFunctions.hpp ++++ b/src/helpers/MiscFunctions.hpp +@@ -6,6 +6,8 @@ + #include "math/Math.hpp" + #include + #include ++#include "../SharedDefs.hpp" ++#include "../macros.hpp" + + struct SCallstackFrameInfo { + void* adr = nullptr; +@@ -13,7 +15,7 @@ struct SCallstackFrameInfo { + }; + + struct SWorkspaceIDName { +- int id = -1; ++ WORKSPACEID id = WORKSPACE_INVALID; + std::string name; + }; + +diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp +index 8f23c462..9542d2c4 100644 +--- a/src/helpers/Monitor.cpp ++++ b/src/helpers/Monitor.cpp +@@ -389,8 +389,8 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const { + } + } + +-int CMonitor::findAvailableDefaultWS() { +- for (size_t i = 1; i < INT32_MAX; ++i) { ++WORKSPACEID CMonitor::findAvailableDefaultWS() { ++ for (WORKSPACEID i = 1; i < LONG_MAX; ++i) { + if (g_pCompositor->getWorkspaceByID(i)) + continue; + +@@ -400,7 +400,7 @@ int CMonitor::findAvailableDefaultWS() { + return i; + } + +- return INT32_MAX; // shouldn't be reachable ++ return LONG_MAX; // shouldn't be reachable + } + + void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { +@@ -638,7 +638,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo + g_pCompositor->updateFullscreenFadeOnWorkspace(activeSpecialWorkspace); + } + +-void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) { ++void CMonitor::changeWorkspace(const WORKSPACEID& id, bool internal, bool noMouseMove, bool noFocus) { + changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus); + } + +@@ -745,7 +745,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { + g_pCompositor->updateSuspendedStates(); + } + +-void CMonitor::setSpecialWorkspace(const int& id) { ++void CMonitor::setSpecialWorkspace(const WORKSPACEID& id) { + setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id)); + } + +@@ -766,11 +766,11 @@ void CMonitor::updateMatrix() { + } + } + +-int64_t CMonitor::activeWorkspaceID() { ++WORKSPACEID CMonitor::activeWorkspaceID() { + return activeWorkspace ? activeWorkspace->m_iID : 0; + } + +-int64_t CMonitor::activeSpecialWorkspaceID() { ++WORKSPACEID CMonitor::activeSpecialWorkspaceID() { + return activeSpecialWorkspace ? activeSpecialWorkspace->m_iID : 0; + } + +@@ -946,7 +946,7 @@ bool CMonitorState::updateSwapchain() { + Debug::log(WARN, "updateSwapchain: No mode?"); + return true; + } +- options.format = STATE.drmFormat; ++ options.format = m_pOwner->drmFormat; + options.scanout = true; + options.length = 2; + options.size = MODE->pixelSize; +diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp +index fbe26f67..dcfcb63b 100644 +--- a/src/helpers/Monitor.hpp ++++ b/src/helpers/Monitor.hpp +@@ -70,7 +70,7 @@ class CMonitor { + + bool primary = false; + +- uint64_t ID = -1; ++ MONITORID ID = MONITOR_INVALID; + PHLWORKSPACE activeWorkspace = nullptr; + PHLWORKSPACE activeSpecialWorkspace = nullptr; + float setScale = 1; // scale set by cfg +@@ -100,6 +100,7 @@ class CMonitor { + std::optional forceSize; + SP currentMode; + SP cursorSwapchain; ++ uint32_t drmFormat = DRM_FORMAT_INVALID; + + bool dpmsStatus = true; + bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. +@@ -155,31 +156,31 @@ class CMonitor { + std::array, 4> m_aLayerSurfaceLayers; + + // methods +- void onConnect(bool noRule); +- void onDisconnect(bool destroy = false); +- void addDamage(const pixman_region32_t* rg); +- void addDamage(const CRegion* rg); +- void addDamage(const CBox* box); +- bool shouldSkipScheduleFrameOnMouseEvent(); +- void setMirror(const std::string&); +- bool isMirror(); +- bool matchesStaticSelector(const std::string& selector) const; +- float getDefaultScale(); +- void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); +- void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); +- void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace); +- void setSpecialWorkspace(const int& id); +- void moveTo(const Vector2D& pos); +- Vector2D middle(); +- void updateMatrix(); +- int64_t activeWorkspaceID(); +- int64_t activeSpecialWorkspaceID(); +- CBox logicalBox(); +- void scheduleDone(); +- bool attemptDirectScanout(); +- +- bool m_bEnabled = false; +- bool m_bRenderingInitPassed = false; ++ void onConnect(bool noRule); ++ void onDisconnect(bool destroy = false); ++ void addDamage(const pixman_region32_t* rg); ++ void addDamage(const CRegion* rg); ++ void addDamage(const CBox* box); ++ bool shouldSkipScheduleFrameOnMouseEvent(); ++ void setMirror(const std::string&); ++ bool isMirror(); ++ bool matchesStaticSelector(const std::string& selector) const; ++ float getDefaultScale(); ++ void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); ++ void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); ++ void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace); ++ void setSpecialWorkspace(const WORKSPACEID& id); ++ void moveTo(const Vector2D& pos); ++ Vector2D middle(); ++ void updateMatrix(); ++ WORKSPACEID activeWorkspaceID(); ++ WORKSPACEID activeSpecialWorkspaceID(); ++ CBox logicalBox(); ++ void scheduleDone(); ++ bool attemptDirectScanout(); ++ ++ bool m_bEnabled = false; ++ bool m_bRenderingInitPassed = false; + + // For the list lookup + +@@ -189,7 +190,7 @@ class CMonitor { + + private: + void setupDefaultWS(const SMonitorRule&); +- int findAvailableDefaultWS(); ++ WORKSPACEID findAvailableDefaultWS(); + + wl_event_source* doneSource = nullptr; + +diff --git a/src/helpers/SdDaemon.cpp b/src/helpers/SdDaemon.cpp +index 25e0ca3b..48c23e6b 100644 +--- a/src/helpers/SdDaemon.cpp ++++ b/src/helpers/SdDaemon.cpp +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + namespace Systemd { + int SdBooted(void) { +diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp +index ec530df4..7b1726df 100644 +--- a/src/helpers/Timer.cpp ++++ b/src/helpers/Timer.cpp +@@ -8,7 +8,7 @@ std::chrono::steady_clock::duration CTimer::getDuration() { + return std::chrono::steady_clock::now() - m_tpLastReset; + } + +-int CTimer::getMillis() { ++long CTimer::getMillis() { + return std::chrono::duration_cast(getDuration()).count(); + } + +diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp +index a6d1aeed..827e7625 100644 +--- a/src/helpers/Timer.hpp ++++ b/src/helpers/Timer.hpp +@@ -6,7 +6,7 @@ class CTimer { + public: + void reset(); + float getSeconds(); +- int getMillis(); ++ long getMillis(); + const std::chrono::steady_clock::time_point& chrono() const; + + private: +diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp +index b9f654da..c7ff648b 100644 +--- a/src/helpers/Watchdog.cpp ++++ b/src/helpers/Watchdog.cpp +@@ -18,15 +18,14 @@ CWatchdog::CWatchdog() { + m_pWatchdog = std::make_unique([this] { + static auto PTIMEOUT = CConfigValue("debug:watchdog_timeout"); + +- while (1337) { +- std::unique_lock lk(m_mWatchdogMutex); ++ m_bWatchdogInitialized = true; ++ while (!m_bExitThread) { ++ std::unique_lock lk(m_mWatchdogMutex); + + if (!m_bWillWatch) +- m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; }); +- else { +- if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false) +- pthread_kill(m_iMainThreadPID, SIGUSR1); +- } ++ m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified || m_bExitThread; }); ++ else if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified || m_bExitThread; }) == false) ++ pthread_kill(m_iMainThreadPID, SIGUSR1); + + if (m_bExitThread) + break; +diff --git a/src/helpers/Watchdog.hpp b/src/helpers/Watchdog.hpp +index 7bb499d6..b16cb518 100644 +--- a/src/helpers/Watchdog.hpp ++++ b/src/helpers/Watchdog.hpp +@@ -11,21 +11,23 @@ class CWatchdog { + CWatchdog(); + ~CWatchdog(); + +- void startWatching(); +- void endWatching(); ++ void startWatching(); ++ void endWatching(); ++ ++ std::atomic m_bWatchdogInitialized{false}; + + private: + std::chrono::high_resolution_clock::time_point m_tTriggered; + + pthread_t m_iMainThreadPID = 0; + +- bool m_bWatching = false; +- bool m_bWillWatch = false; ++ std::atomic m_bWatching = false; ++ std::atomic m_bWillWatch = false; + + std::unique_ptr m_pWatchdog; + std::mutex m_mWatchdogMutex; +- bool m_bNotified = false; +- bool m_bExitThread = false; ++ std::atomic m_bNotified = false; ++ std::atomic m_bExitThread = false; + std::condition_variable m_cvWatchdogCondition; + }; + +diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp +index f287056f..20085ff7 100644 +--- a/src/layout/DwindleLayout.cpp ++++ b/src/layout/DwindleLayout.cpp +@@ -47,7 +47,7 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque* pD + } + } + +-int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) { ++int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) { + int no = 0; + for (auto& n : m_lDwindleNodesData) { + if (n.workspaceID == id && n.valid) +@@ -56,7 +56,7 @@ int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) { + return no; + } + +-SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) { ++SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) { + for (auto& n : m_lDwindleNodesData) { + if (n.workspaceID == id && validMapped(n.pWindow)) + return &n; +@@ -64,7 +64,7 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) { + return nullptr; + } + +-SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) { ++SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) { + SDwindleNodeData* res = nullptr; + double distClosest = -1; + for (auto& n : m_lDwindleNodesData) { +@@ -88,7 +88,7 @@ SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) { + return nullptr; + } + +-SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) { ++SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) { + for (auto& n : m_lDwindleNodesData) { + if (!n.pParent && n.workspaceID == id) + return &n; +@@ -246,6 +246,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for + + g_pHyprRenderer->damageWindow(PWINDOW); + } ++ ++ PWINDOW->updateWindowDecos(); + } + + void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection direction) { +@@ -535,7 +537,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { + m_lDwindleNodesData.remove(*PNODE); + } + +-void CHyprDwindleLayout::recalculateMonitor(const int& monid) { ++void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); + + if (!PMONITOR || !PMONITOR->activeWorkspace) +@@ -872,7 +874,7 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, + return; + + const auto PNODE = getNodeFromWindow(pWindow); +- const int originalWorkspaceID = pWindow->workspaceID(); ++ const auto originalWorkspaceID = pWindow->workspaceID(); + const Vector2D originalPos = pWindow->middle(); + + if (!PNODE) +diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp +index f638f6a2..bbd511c2 100644 +--- a/src/layout/DwindleLayout.hpp ++++ b/src/layout/DwindleLayout.hpp +@@ -24,7 +24,7 @@ struct SDwindleNodeData { + + CBox box = {0}; + +- int workspaceID = -1; ++ WORKSPACEID workspaceID = WORKSPACE_INVALID; + + float splitRatio = 1.f; + +@@ -48,7 +48,7 @@ class CHyprDwindleLayout : public IHyprLayout { + virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); + virtual void onWindowRemovedTiling(PHLWINDOW); + virtual bool isWindowTiled(PHLWINDOW); +- virtual void recalculateMonitor(const int&); ++ virtual void recalculateMonitor(const MONITORID&); + virtual void recalculateWindow(PHLWINDOW); + virtual void onBeginDragWindow(); + virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); +@@ -77,13 +77,13 @@ class CHyprDwindleLayout : public IHyprLayout { + + std::optional m_vOverrideFocalPoint; // for onWindowCreatedTiling. + +- int getNodesOnWorkspace(const int&); ++ int getNodesOnWorkspace(const WORKSPACEID&); + void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); + void calculateWorkspace(const PHLWORKSPACE& pWorkspace); + SDwindleNodeData* getNodeFromWindow(PHLWINDOW); +- SDwindleNodeData* getFirstNodeOnWorkspace(const int&); +- SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&); +- SDwindleNodeData* getMasterNodeOnWorkspace(const int&); ++ SDwindleNodeData* getFirstNodeOnWorkspace(const WORKSPACEID&); ++ SDwindleNodeData* getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&); ++ SDwindleNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); + + void toggleSplit(PHLWINDOW); + void swapSplit(PHLWINDOW); +diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp +index 4b1b59e3..7e0d5704 100644 +--- a/src/layout/IHyprLayout.hpp ++++ b/src/layout/IHyprLayout.hpp +@@ -63,7 +63,7 @@ class IHyprLayout { + Called when the monitor requires a layout recalculation + this usually means reserved area changes + */ +- virtual void recalculateMonitor(const int&) = 0; ++ virtual void recalculateMonitor(const MONITORID&) = 0; + + /* + Called when the compositor requests a window +diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp +index be00168f..e0b48e98 100644 +--- a/src/layout/MasterLayout.cpp ++++ b/src/layout/MasterLayout.cpp +@@ -14,7 +14,7 @@ SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) { + return nullptr; + } + +-int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) { ++int CHyprMasterLayout::getNodesOnWorkspace(const WORKSPACEID& ws) { + int no = 0; + for (auto& n : m_lMasterNodesData) { + if (n.workspaceID == ws) +@@ -24,7 +24,7 @@ int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) { + return no; + } + +-int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) { ++int CHyprMasterLayout::getMastersOnWorkspace(const WORKSPACEID& ws) { + int no = 0; + for (auto& n : m_lMasterNodesData) { + if (n.workspaceID == ws && n.isMaster) +@@ -34,7 +34,7 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) { + return no; + } + +-SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { ++SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const WORKSPACEID& ws) { + for (auto& n : m_lMasterWorkspacesData) { + if (n.workspaceID == ws) + return &n; +@@ -63,7 +63,7 @@ std::string CHyprMasterLayout::getLayoutName() { + return "Master"; + } + +-SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) { ++SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const WORKSPACEID& ws) { + for (auto& n : m_lMasterNodesData) { + if (n.isMaster && n.workspaceID == ws) + return &n; +@@ -304,7 +304,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { + recalculateMonitor(pWindow->m_iMonitorID); + } + +-void CHyprMasterLayout::recalculateMonitor(const int& monid) { ++void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); + + if (!PMONITOR || !PMONITOR->activeWorkspace) +@@ -732,6 +732,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { + + g_pHyprRenderer->damageWindow(PWINDOW); + } ++ ++ PWINDOW->updateWindowDecos(); + } + + bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) { +diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp +index fdb916e5..b72be74f 100644 +--- a/src/layout/MasterLayout.hpp ++++ b/src/layout/MasterLayout.hpp +@@ -30,7 +30,7 @@ struct SMasterNodeData { + + float percSize = 1.f; // size multiplier for resizing children + +- int workspaceID = -1; ++ WORKSPACEID workspaceID = WORKSPACE_INVALID; + + bool ignoreFullscreenChecks = false; + +@@ -41,7 +41,7 @@ struct SMasterNodeData { + }; + + struct SMasterWorkspaceData { +- int workspaceID = -1; ++ WORKSPACEID workspaceID = WORKSPACE_INVALID; + eOrientation orientation = ORIENTATION_LEFT; + + // +@@ -55,7 +55,7 @@ class CHyprMasterLayout : public IHyprLayout { + virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); + virtual void onWindowRemovedTiling(PHLWINDOW); + virtual bool isWindowTiled(PHLWINDOW); +- virtual void recalculateMonitor(const int&); ++ virtual void recalculateMonitor(const MONITORID&); + virtual void recalculateWindow(PHLWINDOW); + virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); + virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE); +@@ -81,14 +81,14 @@ class CHyprMasterLayout : public IHyprLayout { + void buildOrientationCycleVectorFromEOperation(std::vector& cycle); + void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next); + eOrientation getDynamicOrientation(PHLWORKSPACE); +- int getNodesOnWorkspace(const int&); ++ int getNodesOnWorkspace(const WORKSPACEID&); + void applyNodeDataToWindow(SMasterNodeData*); + SMasterNodeData* getNodeFromWindow(PHLWINDOW); +- SMasterNodeData* getMasterNodeOnWorkspace(const int&); +- SMasterWorkspaceData* getMasterWorkspaceData(const int&); ++ SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); ++ SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&); + void calculateWorkspace(PHLWORKSPACE); + PHLWINDOW getNextWindow(PHLWINDOW, bool); +- int getMastersOnWorkspace(const int&); ++ int getMastersOnWorkspace(const WORKSPACEID&); + + friend struct SMasterNodeData; + friend struct SMasterWorkspaceData; +diff --git a/src/macros.hpp b/src/macros.hpp +index b2adb036..44014085 100644 +--- a/src/macros.hpp ++++ b/src/macros.hpp +@@ -27,6 +27,8 @@ + #define WORKSPACE_INVALID -1L + #define WORKSPACE_NOT_CHANGED -101 + ++#define MONITOR_INVALID -1L ++ + #define LISTENER(name) \ + void listener_##name(wl_listener*, void*); \ + inline wl_listener listen_##name = {.notify = listener_##name} +diff --git a/src/main.cpp b/src/main.cpp +index e85b0a22..820a248c 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -36,7 +36,6 @@ int main(int argc, char** argv) { + setenv("XDG_BACKEND", "wayland", 1); + setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1); + setenv("MOZ_ENABLE_WAYLAND", "1", 1); +- setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1); + + // parse some args + std::string configPath; +diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp +index 3f3a25f6..1c047f85 100644 +--- a/src/managers/CursorManager.cpp ++++ b/src/managers/CursorManager.cpp +@@ -102,7 +102,7 @@ CCursorManager::CCursorManager() { + + // since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config + // and then later is disabled. +- m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); ++ m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize, m_fCursorScale); + + m_pAnimationTimer = makeShared(std::nullopt, cursorAnimTimer, this); + g_pEventLoopManager->addTimer(m_pAnimationTimer); +@@ -163,7 +163,7 @@ void CCursorManager::setCursorFromName(const std::string& name) { + auto setXCursor = [this](auto const& name) { + float scale = std::ceil(m_fCursorScale); + +- auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); ++ auto xcursor = m_pXcursor->getShape(name, m_iSize, m_fCursorScale); + auto& icon = xcursor->images.front(); + auto buf = makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); + setCursorBuffer(buf, icon.hotspot / scale, scale); +@@ -277,7 +277,7 @@ 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 { +- auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale)); ++ auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize, 1); + auto& icon = xcursor->images.front(); + + g_pXWayland->setCursor((uint8_t*)icon.pixels.data(), icon.size.x * 4, icon.size, icon.hotspot); +@@ -329,12 +329,16 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { + m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); + if (!m_pHyprcursor->valid()) { + Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); +- m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); ++ m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale); + } + } else +- m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); ++ m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale); + + updateTheme(); + + return true; +-} +\ No newline at end of file ++} ++ ++void CCursorManager::syncGsettings() { ++ m_pXcursor->syncGsettings(); ++} +diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp +index ceb4816b..796ab10e 100644 +--- a/src/managers/CursorManager.hpp ++++ b/src/managers/CursorManager.hpp +@@ -53,6 +53,7 @@ class CCursorManager { + void updateTheme(); + SCursorImageData dataFor(const std::string& name); // for xwayland + void setXWaylandCursor(); ++ void syncGsettings(); + + void tickAnimatedCursor(); + +@@ -75,4 +76,4 @@ class CCursorManager { + Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; + }; + +-inline std::unique_ptr g_pCursorManager; +\ No newline at end of file ++inline std::unique_ptr g_pCursorManager; +diff --git a/src/managers/EventManager.cpp b/src/managers/EventManager.cpp +index 75c98e2a..079a6b68 100644 +--- a/src/managers/EventManager.cpp ++++ b/src/managers/EventManager.cpp +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + CEventManager::CEventManager() { + m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); +diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp +index c7b93730..38593497 100644 +--- a/src/managers/KeybindManager.cpp ++++ b/src/managers/KeybindManager.cpp +@@ -180,6 +180,9 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { + } + + uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) { ++ if (keycode == 0) ++ return 0; ++ + switch (keycode - 8) { + case KEY_LEFTMETA: return HL_MODIFIER_META; + case KEY_RIGHTMETA: return HL_MODIFIER_META; +@@ -1163,6 +1166,8 @@ void CKeybindManager::fullscreenStateActive(std::string args) { + if (!PWINDOW) + return; + ++ PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); ++ + int internalMode, clientMode; + try { + internalMode = std::stoi(ARGS[0]); +@@ -1174,26 +1179,16 @@ void CKeybindManager::fullscreenStateActive(std::string args) { + const sFullscreenState STATE = sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal), + .client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)}; + +- if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) { ++ if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE}); +- PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); +- return; +- } +- +- if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) { +- g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.client, .client = PWINDOW->m_sFullscreenState.client}); +- PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); +- return; +- } +- +- if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) { +- g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = PWINDOW->m_sFullscreenState.internal}); +- PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); +- return; +- } ++ else if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) ++ g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client}); ++ else if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) ++ g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE}); ++ else ++ g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); + +- PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); +- g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); ++ PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(PWINDOW->m_sFullscreenState.internal == PWINDOW->m_sFullscreenState.client, PRIORITY_SET_PROP); + } + + void CKeybindManager::moveActiveToWorkspace(std::string args) { +@@ -1738,7 +1733,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { + return; + } + +- const int WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; ++ const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; + + if (WORKSPACEID == WORKSPACE_INVALID) { + Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); +@@ -1756,7 +1751,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { + } + + void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { +- int workspaceID = getWorkspaceIDNameFromString(args).id; ++ auto workspaceID = getWorkspaceIDNameFromString(args).id; + if (workspaceID == WORKSPACE_INVALID) { + Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); + return; +@@ -1816,7 +1811,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { + + bool requestedWorkspaceIsAlreadyOpen = false; + const auto PMONITOR = g_pCompositor->m_pLastMonitor; +- int specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); ++ auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); + + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->activeSpecialWorkspaceID() == workspaceID) { +diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp +index 3ba34c11..72ff5ae7 100644 +--- a/src/managers/PointerManager.cpp ++++ b/src/managers/PointerManager.cpp +@@ -11,13 +11,21 @@ + #include + + CPointerManager::CPointerManager() { +- hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { +- auto PMONITOR = std::any_cast>(data); ++ hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { ++ auto PMONITOR = std::any_cast(data)->self.lock(); + + onMonitorLayoutChange(); + +- PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); +- PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); ++ PMONITOR->events.modeChanged.registerStaticListener( ++ [this, PMONITOR](void* owner, std::any data) { ++ g_pEventLoopManager->doLater([this, PMONITOR]() { ++ onMonitorLayoutChange(); ++ checkDefaultCursorWarp(PMONITOR, PMONITOR->output->name); ++ }); ++ }, ++ nullptr); ++ PMONITOR->events.disconnect.registerStaticListener( ++ [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.destroy.registerStaticListener( + [this](void* owner, std::any data) { + if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) +@@ -35,6 +43,38 @@ CPointerManager::CPointerManager() { + }); + } + ++void CPointerManager::checkDefaultCursorWarp(SP monitor, std::string monitorName) { ++ static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); ++ static bool cursorDefaultDone = false; ++ static bool firstLaunch = true; ++ ++ const auto POS = monitor->middle(); ++ ++ // by default, cursor should be set to first monitor detected ++ // this is needed as a default if the monitor given in config above doesn't exist ++ if (firstLaunch) { ++ firstLaunch = false; ++ g_pCompositor->warpCursorTo(POS, true); ++ g_pInputManager->refocus(); ++ return; ++ } ++ ++ if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) { ++ if (*PCURSORMONITOR == monitorName) { ++ cursorDefaultDone = true; ++ g_pCompositor->warpCursorTo(POS, true); ++ g_pInputManager->refocus(); ++ return; ++ } ++ } ++ ++ // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. ++ if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { ++ g_pCompositor->warpCursorTo(POS, true); ++ g_pInputManager->refocus(); ++ } ++} ++ + void CPointerManager::lockSoftwareAll() { + for (auto& state : monitorStates) + state->softwareLocks++; +diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp +index 4a4c4f61..082855b5 100644 +--- a/src/managers/PointerManager.hpp ++++ b/src/managers/PointerManager.hpp +@@ -26,6 +26,7 @@ class CPointerManager { + public: + CPointerManager(); + ++ void checkDefaultCursorWarp(SP monitor, std::string monitorName); + void attachPointer(SP pointer); + void attachTouch(SP touch); + void attachTablet(SP tablet); +diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp +index f2a7ab53..6f000f9f 100644 +--- a/src/managers/XCursorManager.cpp ++++ b/src/managers/XCursorManager.cpp +@@ -1,7 +1,11 @@ + #include + #include + #include ++#include ++#include ++#include "config/ConfigValue.hpp" + #include "helpers/CursorShapes.hpp" ++#include "../managers/CursorManager.hpp" + #include "debug/Log.hpp" + #include "XCursorManager.hpp" + +@@ -96,12 +100,13 @@ CXCursorManager::CXCursorManager() { + defaultCursor = hyprCursor; + } + +-void CXCursorManager::loadTheme(std::string const& name, int size) { +- if (lastLoadSize == size && themeName == name) ++void CXCursorManager::loadTheme(std::string const& name, int size, float scale) { ++ if (lastLoadSize == (size * std::ceil(scale)) && themeName == name && lastLoadScale == scale) + return; + +- lastLoadSize = size; +- themeName = name.empty() ? "default" : name; ++ lastLoadSize = size * std::ceil(scale); ++ lastLoadScale = scale; ++ themeName = name.empty() ? "default" : name; + defaultCursor.reset(); + cursors.clear(); + +@@ -146,12 +151,16 @@ void CXCursorManager::loadTheme(std::string const& name, int size) { + + cursors.emplace_back(cursor); + } ++ ++ static auto SYNCGSETTINGS = CConfigValue("cursor:sync_gsettings_theme"); ++ if (*SYNCGSETTINGS) ++ syncGsettings(); + } + +-SP CXCursorManager::getShape(std::string const& shape, int size) { ++SP CXCursorManager::getShape(std::string const& shape, int size, float scale) { + // monitor scaling changed etc, so reload theme with new size. +- if (size != lastLoadSize) +- loadTheme(themeName, size); ++ if ((size * std::ceil(scale)) != lastLoadSize || scale != lastLoadScale) ++ loadTheme(themeName, size, scale); + + // try to get an icon we know if we have one + for (auto const& c : cursors) { +@@ -503,8 +512,11 @@ std::vector> CXCursorManager::loadAllFromDir(std::string const& pa + + if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) { + for (const auto& entry : std::filesystem::directory_iterator(path)) { +- if (!entry.is_regular_file() && !entry.is_symlink()) ++ std::error_code e1, e2; ++ if ((!entry.is_regular_file(e1) && !entry.is_symlink(e2)) || e1 || e2) { ++ Debug::log(WARN, "XCursor failed to load shape {}: {}", entry.path().stem().string(), e1 ? e1.message() : e2.message()); + continue; ++ } + + auto const& full = entry.path().string(); + using PcloseType = int (*)(FILE*); +@@ -542,3 +554,56 @@ std::vector> CXCursorManager::loadAllFromDir(std::string const& pa + + return newCursors; + } ++ ++void CXCursorManager::syncGsettings() { ++ auto checkParamExists = [](std::string const& paramName, std::string const& category) { ++ auto* gSettingsSchemaSource = g_settings_schema_source_get_default(); ++ ++ if (!gSettingsSchemaSource) { ++ Debug::log(WARN, "GSettings default schema source does not exist, cant sync GSettings"); ++ return false; ++ } ++ ++ auto* gSettingsSchema = g_settings_schema_source_lookup(gSettingsSchemaSource, category.c_str(), true); ++ bool hasParam = false; ++ ++ if (gSettingsSchema != NULL) { ++ hasParam = gSettingsSchema && g_settings_schema_has_key(gSettingsSchema, paramName.c_str()); ++ g_settings_schema_unref(gSettingsSchema); ++ } ++ ++ return hasParam; ++ }; ++ ++ using SettingValue = std::variant; ++ auto setValue = [&checkParamExists](std::string const& paramName, const SettingValue& paramValue, std::string const& category) { ++ if (!checkParamExists(paramName, category)) { ++ Debug::log(WARN, "GSettings parameter doesnt exist {} in {}", paramName, category); ++ return; ++ } ++ ++ auto* gsettings = g_settings_new(category.c_str()); ++ ++ if (!gsettings) { ++ Debug::log(WARN, "GSettings failed to allocate new settings with category {}", category); ++ return; ++ } ++ ++ std::visit( ++ [&](auto&& value) { ++ using T = std::decay_t; ++ if constexpr (std::is_same_v) ++ g_settings_set_string(gsettings, paramName.c_str(), value.c_str()); ++ else if constexpr (std::is_same_v) ++ g_settings_set_int(gsettings, paramName.c_str(), value); ++ }, ++ paramValue); ++ ++ g_settings_sync(); ++ g_object_unref(gsettings); ++ }; ++ ++ int unscaledSize = lastLoadSize / std::ceil(lastLoadScale); ++ setValue("cursor-theme", themeName, "org.gnome.desktop.interface"); ++ setValue("cursor-size", unscaledSize, "org.gnome.desktop.interface"); ++} +diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp +index 20637055..1f3c24db 100644 +--- a/src/managers/XCursorManager.hpp ++++ b/src/managers/XCursorManager.hpp +@@ -29,8 +29,9 @@ class CXCursorManager { + CXCursorManager(); + ~CXCursorManager() = default; + +- void loadTheme(const std::string& name, int size); +- SP getShape(std::string const& shape, int size); ++ void loadTheme(const std::string& name, int size, float scale); ++ SP getShape(std::string const& shape, int size, float scale); ++ void syncGsettings(); + + private: + SP createCursor(std::string const& shape, XcursorImages* xImages); +@@ -39,9 +40,10 @@ class CXCursorManager { + std::vector> loadStandardCursors(std::string const& name, int size); + std::vector> loadAllFromDir(std::string const& path, int size); + +- int lastLoadSize = 0; +- std::string themeName = ""; ++ int lastLoadSize = 0; ++ float lastLoadScale = 0; ++ std::string themeName = ""; + SP defaultCursor; + SP hyprCursor; + std::vector> cursors; +-}; +\ No newline at end of file ++}; +diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp +index c2c088f8..d1b85cf2 100644 +--- a/src/managers/eventLoop/EventLoopManager.cpp ++++ b/src/managers/eventLoop/EventLoopManager.cpp +@@ -48,7 +48,6 @@ void CEventLoopManager::enterLoop() { + aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + for (auto& fd : aqPollFDs) { + m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); +- fd->onSignal(); // dispatch outstanding + } + + wl_display_run(m_sWayland.display); +@@ -76,8 +75,8 @@ void CEventLoopManager::removeTimer(SP timer) { + } + + static void timespecAddNs(timespec* pTimespec, int64_t delta) { +- int delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC; +- int delta_s_high = delta / TIMESPEC_NSEC_PER_SEC; ++ auto delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC; ++ auto delta_s_high = delta / TIMESPEC_NSEC_PER_SEC; + + pTimespec->tv_sec += delta_s_high; + +diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp +index c502cb0d..e5f921a2 100644 +--- a/src/managers/input/InputManager.cpp ++++ b/src/managers/input/InputManager.cpp +@@ -82,18 +82,13 @@ CInputManager::~CInputManager() { + } + + void CInputManager::onMouseMoved(IPointer::SMotionEvent e) { +- static auto PSENS = CConfigValue("general:sensitivity"); +- static auto PNOACCEL = CConfigValue("input:force_no_accel"); +- static auto PSENSTORAW = CConfigValue("general:apply_sens_to_raw"); ++ static auto PNOACCEL = CConfigValue("input:force_no_accel"); + + const auto DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta; + +- if (*PSENSTORAW == 1) +- PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA * *PSENS, e.unaccel * *PSENS); +- else +- PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel); ++ PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel); + +- g_pPointerManager->move(DELTA * *PSENS); ++ g_pPointerManager->move(DELTA); + + mouseMoveUnified(e.timeMs); + +@@ -1112,8 +1107,9 @@ void CInputManager::setPointerConfigs() { + libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + + if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop) +- if (g_pConfigManager->getDeviceInt(devname, "tap-to-click", "input:touchpad:tap-to-click") == 1) +- libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED); ++ libinput_device_config_tap_set_enabled(LIBINPUTDEV, ++ g_pConfigManager->getDeviceInt(devname, "tap-to-click", "input:touchpad:tap-to-click") == 1 ? LIBINPUT_CONFIG_TAP_ENABLED : ++ LIBINPUT_CONFIG_TAP_DISABLED); + + if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) { + +diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp +index f6e5c8be..f8e4b962 100644 +--- a/src/managers/input/InputMethodPopup.hpp ++++ b/src/managers/input/InputMethodPopup.hpp +@@ -33,7 +33,7 @@ class CInputPopup { + WP popup; + SP surface; + CBox lastBoxLocal; +- uint64_t lastMonitor = -1; ++ MONITORID lastMonitor = MONITOR_INVALID; + + struct { + CHyprSignalListener map; +diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp +index c0e6c4f0..6ee690cd 100644 +--- a/src/managers/input/Swipe.cpp ++++ b/src/managers/input/Swipe.cpp +@@ -77,7 +77,7 @@ void CInputManager::endWorkspaceSwipe() { + // left of where we started. Instead, it's one more than the greatest + // workspace ID that currently exists. + if (workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID && *PSWIPENEW) { +- int maxWorkspace = 0; ++ WORKSPACEID maxWorkspace = 0; + for (const auto& ws : g_pCompositor->m_vWorkspaces) { + maxWorkspace = std::max(maxWorkspace, ws->m_iID); + } +diff --git a/src/meson.build b/src/meson.build +index 098d8298..475ecc24 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -28,6 +28,7 @@ executable('Hyprland', src, + xcb_xfixes_dep, + backtrace_dep, + epoll_dep, ++ gio_dep, + udis86, + + dependency('pixman-1'), +diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp +index 38b8c800..13597fa9 100644 +--- a/src/protocols/AlphaModifier.cpp ++++ b/src/protocols/AlphaModifier.cpp +@@ -4,8 +4,6 @@ + #include "../render/Renderer.hpp" + #include "core/Compositor.hpp" + +-#define LOGM PROTO::alphaModifier->protoLog +- + CAlphaModifier::CAlphaModifier(SP resource_, SP surface_) : resource(resource_), pSurface(surface_) { + if (!resource->resource()) + return; +diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp +index 812afe53..233a5df9 100644 +--- a/src/protocols/CursorShape.cpp ++++ b/src/protocols/CursorShape.cpp +@@ -2,8 +2,6 @@ + #include + #include "../helpers/CursorShapes.hpp" + +-#define LOGM PROTO::cursorShape->protoLog +- + CCursorShapeProtocol::CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; + } +diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp +index 9f5b6312..bc0945f1 100644 +--- a/src/protocols/DRMLease.cpp ++++ b/src/protocols/DRMLease.cpp +@@ -1,10 +1,9 @@ + #include "DRMLease.hpp" + #include "../Compositor.hpp" ++#include "managers/eventLoop/EventLoopManager.hpp" + #include + #include + +-#define LOGM PROTO::lease->protoLog +- + CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP request) : resource(resource_) { + if (!good()) + return; +@@ -247,10 +246,8 @@ CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, + break; + } + +- if (!primaryDevice || primaryDevice->success) { +- PROTO::lease.reset(); +- return; +- } ++ if (!primaryDevice || !primaryDevice->success) ++ g_pEventLoopManager->doLater([]() { PROTO::lease.reset(); }); + } + + void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { +diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp +index 9a48b99a..4993f1a4 100644 +--- a/src/protocols/DRMSyncobj.cpp ++++ b/src/protocols/DRMSyncobj.cpp +@@ -7,8 +7,6 @@ + + #include + +-#define LOGM PROTO::sync->protoLog +- + CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp +index c039d3b4..ad6ee89a 100644 +--- a/src/protocols/DataDeviceWlr.cpp ++++ b/src/protocols/DataDeviceWlr.cpp +@@ -3,8 +3,6 @@ + #include "../managers/SeatManager.hpp" + #include "core/Seat.hpp" + +-#define LOGM PROTO::dataWlr->protoLog +- + CWLRDataOffer::CWLRDataOffer(SP resource_, SP source_) : source(source_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp +index 40f9af44..2d6b2ee2 100644 +--- a/src/protocols/FocusGrab.cpp ++++ b/src/protocols/FocusGrab.cpp +@@ -8,8 +8,6 @@ + #include + #include + +-#define LOGM PROTO::focusGrab->protoLog +- + CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, SP surface) { + listeners.destroy = surface->events.destroy.registerListener([=](std::any d) { grab->eraseSurface(surface); }); + } +diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp +index f7b3886f..59888ce2 100644 +--- a/src/protocols/ForeignToplevel.cpp ++++ b/src/protocols/ForeignToplevel.cpp +@@ -1,8 +1,6 @@ + #include "ForeignToplevel.hpp" + #include "../Compositor.hpp" + +-#define LOGM PROTO::foreignToplevel->protoLog +- + CForeignToplevelHandle::CForeignToplevelHandle(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { + if (!resource_->resource()) + return; +diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp +index 295834ea..bd597a91 100644 +--- a/src/protocols/ForeignToplevelWlr.cpp ++++ b/src/protocols/ForeignToplevelWlr.cpp +@@ -4,8 +4,6 @@ + #include "protocols/core/Output.hpp" + #include "render/Renderer.hpp" + +-#define LOGM PROTO::foreignToplevelWlr->protoLog +- + CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { + if (!resource_->resource()) + return; +@@ -119,7 +117,7 @@ wl_resource* CForeignToplevelHandleWlr::res() { + } + + void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) { +- if (lastMonitorID == (int64_t)pMonitor->ID) ++ if (lastMonitorID == pMonitor->ID) + return; + + const auto CLIENT = resource->client(); +diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp +index e3b6f3f3..99f63b47 100644 +--- a/src/protocols/ForeignToplevelWlr.hpp ++++ b/src/protocols/ForeignToplevelWlr.hpp +@@ -20,7 +20,7 @@ class CForeignToplevelHandleWlr { + SP resource; + PHLWINDOWREF pWindow; + bool closed = false; +- int64_t lastMonitorID = -1; ++ MONITORID lastMonitorID = MONITOR_INVALID; + + void sendMonitor(CMonitor* pMonitor); + void sendState(); +diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp +index 5bf56c5a..d39fa67c 100644 +--- a/src/protocols/FractionalScale.cpp ++++ b/src/protocols/FractionalScale.cpp +@@ -2,8 +2,6 @@ + #include + #include "core/Compositor.hpp" + +-#define LOGM PROTO::fractional->protoLog +- + CFractionalScaleProtocol::CFractionalScaleProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; + } +diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp +index 494d9862..c902d00e 100644 +--- a/src/protocols/GammaControl.cpp ++++ b/src/protocols/GammaControl.cpp +@@ -5,8 +5,6 @@ + #include "../Compositor.hpp" + #include "../protocols/core/Output.hpp" + +-#define LOGM PROTO::gamma->protoLog +- + CGammaControl::CGammaControl(SP resource_, wl_resource* output) : resource(resource_) { + if (!resource_->resource()) + return; +@@ -109,7 +107,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out + } + + CGammaControl::~CGammaControl() { +- if (!gammaTableSet || !pMonitor) ++ if (!gammaTableSet || !pMonitor || !pMonitor->output) + return; + + // reset the LUT if the client dies for whatever reason and doesn't unset the gamma +diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp +index 860004c9..92bfbae4 100644 +--- a/src/protocols/GlobalShortcuts.cpp ++++ b/src/protocols/GlobalShortcuts.cpp +@@ -1,8 +1,6 @@ + #include "GlobalShortcuts.hpp" + #include "../Compositor.hpp" + +-#define LOGM PROTO::globalShortcuts->protoLog +- + CShortcutClient::CShortcutClient(SP resource_) : resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp +index 2ec7d2a1..8d915ac6 100644 +--- a/src/protocols/IdleNotify.cpp ++++ b/src/protocols/IdleNotify.cpp +@@ -1,8 +1,6 @@ + #include "IdleNotify.hpp" + #include "../managers/eventLoop/EventLoopManager.hpp" + +-#define LOGM PROTO::idle->protoLog +- + static int onTimer(SP self, void* data) { + + const auto NOTIF = (CExtIdleNotification*)data; +diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp +index fd306f09..a0820e0b 100644 +--- a/src/protocols/InputMethodV2.cpp ++++ b/src/protocols/InputMethodV2.cpp +@@ -6,8 +6,6 @@ + #include "core/Compositor.hpp" + #include + +-#define LOGM PROTO::ime->protoLog +- + CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SP resource_, SP owner_) : resource(resource_), owner(owner_) { + if (!resource->resource()) + return; +diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp +index 17d3b22a..c02d23f3 100644 +--- a/src/protocols/LayerShell.cpp ++++ b/src/protocols/LayerShell.cpp +@@ -4,8 +4,6 @@ + #include "core/Compositor.hpp" + #include "core/Output.hpp" + +-#define LOGM PROTO::layerShell->protoLog +- + void CLayerShellResource::SState::reset() { + anchor = 0; + exclusive = 0; +diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp +index 0fbf832e..32625792 100644 +--- a/src/protocols/LinuxDMABUF.cpp ++++ b/src/protocols/LinuxDMABUF.cpp +@@ -14,8 +14,6 @@ + #include "../render/OpenGL.hpp" + #include "../Compositor.hpp" + +-#define LOGM PROTO::linuxDma->protoLog +- + static std::optional devIDFromFD(int fd) { + struct stat stat; + if (fstat(fd, &stat) != 0) +@@ -425,7 +423,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const + auto dev = devIDFromFD(rendererFD); + + if (!dev.has_value()) { +- protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); ++ LOGM(ERR, "failed to get drm dev, disabling linux dmabuf"); + removeGlobal(); + return; + } +@@ -477,7 +475,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const + + drmDevice* device = nullptr; + if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) { +- protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); ++ LOGM(ERR, "failed to get drm dev, disabling linux dmabuf"); + removeGlobal(); + return; + } +@@ -487,14 +485,13 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const + mainDeviceFD = open(name, O_RDWR | O_CLOEXEC); + drmFreeDevice(&device); + if (mainDeviceFD < 0) { +- protoLog(ERR, "failed to open drm dev, disabling linux dmabuf"); ++ LOGM(ERR, "failed to open drm dev, disabling linux dmabuf"); + removeGlobal(); + return; + } + } else { +- protoLog(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); ++ LOGM(ERR, "DRM device {} has no render node, disabling linux dmabuf checks", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); + drmFreeDevice(&device); +- removeGlobal(); + } + }); + } +diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp +index ed412555..9fcd5f9b 100644 +--- a/src/protocols/MesaDRM.cpp ++++ b/src/protocols/MesaDRM.cpp +@@ -4,8 +4,6 @@ + #include "../Compositor.hpp" + #include "types/WLBuffer.hpp" + +-#define LOGM PROTO::mesaDRM->protoLog +- + CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) { + LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes); + for (int i = 0; i < attrs_.planes; ++i) { +@@ -115,7 +113,7 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co + drmDevice* dev = nullptr; + int drmFD = g_pCompositor->m_iDRMFD; + if (drmGetDevice2(drmFD, 0, &dev) != 0) { +- protoLog(ERR, "Failed to get device, disabling MesaDRM"); ++ LOGM(ERR, "Failed to get device, disabling MesaDRM"); + removeGlobal(); + return; + } +@@ -126,13 +124,13 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co + ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY)); + + if (!dev->nodes[DRM_NODE_PRIMARY]) { +- protoLog(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); ++ LOGM(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); + drmFreeDevice(&dev); + removeGlobal(); + return; + } + +- protoLog(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); ++ LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); + nodeName = dev->nodes[DRM_NODE_PRIMARY]; + } + drmFreeDevice(&dev); +diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp +index 66f4c5f0..cfe388fa 100644 +--- a/src/protocols/OutputManagement.cpp ++++ b/src/protocols/OutputManagement.cpp +@@ -4,8 +4,6 @@ + + using namespace Aquamarine; + +-#define LOGM PROTO::outputManagement->protoLog +- + COutputManager::COutputManager(SP resource_) : resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp +index 597b9871..0c324bf0 100644 +--- a/src/protocols/OutputPower.cpp ++++ b/src/protocols/OutputPower.cpp +@@ -2,8 +2,6 @@ + #include "../Compositor.hpp" + #include "core/Output.hpp" + +-#define LOGM PROTO::outputPower->protoLog +- + COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { + if (!resource->resource()) + return; +diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp +index fd15242d..0f2dd991 100644 +--- a/src/protocols/PointerConstraints.cpp ++++ b/src/protocols/PointerConstraints.cpp +@@ -5,8 +5,6 @@ + #include "../managers/SeatManager.hpp" + #include "core/Compositor.hpp" + +-#define LOGM PROTO::constraints->protoLog +- + CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : + resourceL(resource_), locked(true), lifetime(lifetime_) { + if (!resource_->resource()) +diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp +index 86510779..c83e3887 100644 +--- a/src/protocols/PointerGestures.cpp ++++ b/src/protocols/PointerGestures.cpp +@@ -4,8 +4,6 @@ + #include "core/Seat.hpp" + #include "core/Compositor.hpp" + +-#define LOGM PROTO::pointerGestures->protoLog +- + CPointerGestureSwipe::CPointerGestureSwipe(SP resource_) : resource(resource_) { + if (!resource->resource()) + return; +diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp +index a2fc270c..335cf557 100644 +--- a/src/protocols/PresentationTime.cpp ++++ b/src/protocols/PresentationTime.cpp +@@ -6,8 +6,6 @@ + #include "core/Output.hpp" + #include + +-#define LOGM PROTO::presentation->protoLog +- + CQueuedPresentationData::CQueuedPresentationData(SP surf) : surface(surf) { + ; + } +diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp +index 78eb8d63..4fede706 100644 +--- a/src/protocols/PrimarySelection.cpp ++++ b/src/protocols/PrimarySelection.cpp +@@ -4,8 +4,6 @@ + #include "core/Seat.hpp" + #include "../config/ConfigValue.hpp" + +-#define LOGM PROTO::primarySelection->protoLog +- + CPrimarySelectionOffer::CPrimarySelectionOffer(SP resource_, SP source_) : source(source_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp +index a8afba84..f246f6dd 100644 +--- a/src/protocols/Screencopy.cpp ++++ b/src/protocols/Screencopy.cpp +@@ -9,8 +9,6 @@ + + #include + +-#define LOGM PROTO::screencopy->protoLog +- + CScreencopyFrame::~CScreencopyFrame() { + if (buffer && buffer->locked()) + buffer->unlock(); +diff --git a/src/protocols/ServerDecorationKDE.cpp b/src/protocols/ServerDecorationKDE.cpp +index 42da52a9..c7b98a9c 100644 +--- a/src/protocols/ServerDecorationKDE.cpp ++++ b/src/protocols/ServerDecorationKDE.cpp +@@ -1,8 +1,6 @@ + #include "ServerDecorationKDE.hpp" + #include "core/Compositor.hpp" + +-#define LOGM PROTO::serverDecorationKDE->protoLog +- + CServerDecorationKDE::CServerDecorationKDE(SP resource_, SP surf) : resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp +index df97413c..7b0d8b3b 100644 +--- a/src/protocols/SessionLock.cpp ++++ b/src/protocols/SessionLock.cpp +@@ -5,8 +5,6 @@ + #include "core/Compositor.hpp" + #include "core/Output.hpp" + +-#define LOGM PROTO::sessionLock->protoLog +- + CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_) : + resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { + if (!resource->resource()) +diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp +index 1a0433e6..e4424ed7 100644 +--- a/src/protocols/ShortcutsInhibit.cpp ++++ b/src/protocols/ShortcutsInhibit.cpp +@@ -3,8 +3,6 @@ + #include "../Compositor.hpp" + #include "core/Compositor.hpp" + +-#define LOGM PROTO::shortcutsInhibit->protoLog +- + CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP resource_, SP surf) : resource(resource_), pSurface(surf) { + if (!resource->resource()) + return; +diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp +index 72c7cfde..b974152e 100644 +--- a/src/protocols/Tablet.cpp ++++ b/src/protocols/Tablet.cpp +@@ -7,8 +7,6 @@ + #include + #include + +-#define LOGM PROTO::tablet->protoLog +- + CTabletPadStripV2Resource::CTabletPadStripV2Resource(SP resource_, uint32_t id_) : id(id_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp +index 78e910cb..f25f5aca 100644 +--- a/src/protocols/TextInputV1.cpp ++++ b/src/protocols/TextInputV1.cpp +@@ -3,8 +3,6 @@ + #include "../Compositor.hpp" + #include "core/Compositor.hpp" + +-#define LOGM PROTO::textInputV1->protoLog +- + CTextInputV1::~CTextInputV1() { + events.destroy.emit(); + } +diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp +index 1302a57f..99d799f3 100644 +--- a/src/protocols/TextInputV3.cpp ++++ b/src/protocols/TextInputV3.cpp +@@ -2,8 +2,6 @@ + #include + #include "core/Compositor.hpp" + +-#define LOGM PROTO::textInputV3->protoLog +- + void CTextInputV3::SState::reset() { + cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD; + surrounding.updated = false; +diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp +index fb3fde2b..05e991d6 100644 +--- a/src/protocols/ToplevelExport.cpp ++++ b/src/protocols/ToplevelExport.cpp +@@ -8,8 +8,6 @@ + + #include + +-#define LOGM PROTO::toplevelExport->protoLog +- + CToplevelExportClient::CToplevelExportClient(SP resource_) : resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp +index 78f3039f..58cb851d 100644 +--- a/src/protocols/Viewporter.cpp ++++ b/src/protocols/Viewporter.cpp +@@ -2,8 +2,6 @@ + #include "core/Compositor.hpp" + #include + +-#define LOGM PROTO::viewport->protoLog +- + CViewportResource::CViewportResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp +index 2642ec11..27a4f248 100644 +--- a/src/protocols/VirtualKeyboard.cpp ++++ b/src/protocols/VirtualKeyboard.cpp +@@ -2,8 +2,6 @@ + #include + #include "../devices/IKeyboard.hpp" + +-#define LOGM PROTO::virtualKeyboard->protoLog +- + CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp +index 8626241a..eb92a640 100644 +--- a/src/protocols/VirtualPointer.cpp ++++ b/src/protocols/VirtualPointer.cpp +@@ -1,8 +1,6 @@ + #include "VirtualPointer.hpp" + #include "core/Output.hpp" + +-#define LOGM PROTO::virtualPointer->protoLog +- + CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, WP boundOutput_) : boundOutput(boundOutput_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp +index 954f160d..0782d323 100644 +--- a/src/protocols/WaylandProtocol.cpp ++++ b/src/protocols/WaylandProtocol.cpp +@@ -21,7 +21,7 @@ IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, co + m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, iface, ver, this, &bindManagerInternal); + + if (!m_pGlobal) { +- protoLog(ERR, "could not create a global"); ++ LOGM(ERR, "could not create a global [{}]", m_szName); + return; + } + +@@ -30,7 +30,7 @@ IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, co + m_liDisplayDestroy.parent = this; + wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy.listener); + +- protoLog(LOG, "Registered global"); ++ LOGM(LOG, "Registered global [{}]", m_szName); + } + + IWaylandProtocol::~IWaylandProtocol() { +diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp +index 4d4e7925..0fa8daab 100644 +--- a/src/protocols/WaylandProtocol.hpp ++++ b/src/protocols/WaylandProtocol.hpp +@@ -11,6 +11,35 @@ + + #define PROTO NProtocols + ++#define EXTRACT_CLASS_NAME() \ ++ []() constexpr -> std::string_view { \ ++ constexpr std::string_view prettyFunction = __PRETTY_FUNCTION__; \ ++ constexpr size_t colons = prettyFunction.find("::"); \ ++ if (colons != std::string_view::npos) { \ ++ constexpr size_t begin = prettyFunction.substr(0, colons).rfind(' ') + 1; \ ++ constexpr size_t end = colons - begin; \ ++ return prettyFunction.substr(begin, end); \ ++ } else { \ ++ return "Global"; \ ++ } \ ++ }() ++ ++#define LOGM(level, ...) \ ++ do { \ ++ std::ostringstream oss; \ ++ if (level == WARN || level == ERR || level == CRIT) { \ ++ oss << "[" << __FILE__ << ":" << __LINE__ << "] "; \ ++ } else if (level == LOG || level == INFO || level == TRACE) { \ ++ oss << "[" << EXTRACT_CLASS_NAME() << "] "; \ ++ } \ ++ if constexpr (std::is_same_v) { \ ++ oss << __VA_ARGS__; \ ++ Debug::log(level, oss.str()); \ ++ } else { \ ++ Debug::log(level, std::format("{}{}", oss.str(), std::format(__VA_ARGS__))); \ ++ } \ ++ } while (0) ++ + class IWaylandProtocol; + struct IWaylandProtocolDestroyWrapper { + wl_listener listener; +@@ -22,15 +51,10 @@ class IWaylandProtocol { + IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name); + virtual ~IWaylandProtocol(); + +- virtual void onDisplayDestroy(); +- virtual void removeGlobal(); +- +- virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0; ++ virtual void onDisplayDestroy(); ++ virtual void removeGlobal(); + +- template +- void protoLog(LogLevel level, std::format_string fmt, Args&&... args) { +- Debug::log(level, std::format("[{}] ", m_szName) + std::vformat(fmt.get(), std::make_format_args(args...))); +- }; ++ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0; + + IWaylandProtocolDestroyWrapper m_liDisplayDestroy; + +diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp +index 40f33f02..4a6c7bfe 100644 +--- a/src/protocols/XDGActivation.cpp ++++ b/src/protocols/XDGActivation.cpp +@@ -4,8 +4,6 @@ + #include "core/Compositor.hpp" + #include + +-#define LOGM PROTO::activation->protoLog +- + CXDGActivationToken::CXDGActivationToken(SP resource_) : resource(resource_) { + if (!resource_->resource()) + return; +diff --git a/src/protocols/XDGDecoration.cpp b/src/protocols/XDGDecoration.cpp +index 021a1141..07b1694c 100644 +--- a/src/protocols/XDGDecoration.cpp ++++ b/src/protocols/XDGDecoration.cpp +@@ -1,8 +1,6 @@ + #include "XDGDecoration.hpp" + #include + +-#define LOGM PROTO::xdgDecoration->protoLog +- + CXDGDecoration::CXDGDecoration(SP resource_, wl_resource* toplevel) : resource(resource_), pToplevelResource(toplevel) { + if (!resource->resource()) + return; +diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp +index 073aa502..9c2c353c 100644 +--- a/src/protocols/XDGOutput.cpp ++++ b/src/protocols/XDGOutput.cpp +@@ -12,8 +12,6 @@ + + // + +-#define LOGM PROTO::xdgOutput->protoLog +- + void CXDGOutputProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_vManagerResources, [&](const auto& other) { return other->resource() == res; }); + } +diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp +index aea23329..eaf5c333 100644 +--- a/src/protocols/XDGShell.cpp ++++ b/src/protocols/XDGShell.cpp +@@ -6,8 +6,6 @@ + #include "core/Compositor.hpp" + #include + +-#define LOGM PROTO::xdgShell->protoLog +- + void SXDGPositionerState::setAnchor(xdgPositionerAnchor edges) { + anchor.setTop(edges == XDG_POSITIONER_ANCHOR_TOP || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_RIGHT); + anchor.setLeft(edges == XDG_POSITIONER_ANCHOR_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT); +diff --git a/src/protocols/XWaylandShell.cpp b/src/protocols/XWaylandShell.cpp +index 6cc5256f..d6c3b1a8 100644 +--- a/src/protocols/XWaylandShell.cpp ++++ b/src/protocols/XWaylandShell.cpp +@@ -2,8 +2,6 @@ + #include "core/Compositor.hpp" + #include + +-#define LOGM PROTO::xwaylandShell->protoLog +- + CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp +index a767dd52..8b6f46b1 100644 +--- a/src/protocols/core/Compositor.cpp ++++ b/src/protocols/core/Compositor.cpp +@@ -13,8 +13,6 @@ + #include "../../render/Renderer.hpp" + #include + +-#define LOGM PROTO::compositor->protoLog +- + class CDefaultSurfaceRole : public ISurfaceRole { + public: + virtual eSurfaceRole role() { +diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp +index fe3905d0..4ed28f24 100644 +--- a/src/protocols/core/DataDevice.cpp ++++ b/src/protocols/core/DataDevice.cpp +@@ -6,8 +6,6 @@ + #include "Seat.hpp" + #include "Compositor.hpp" + +-#define LOGM PROTO::data->protoLog +- + CWLDataOfferResource::CWLDataOfferResource(SP resource_, SP source_) : source(source_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp +index bb6a9d4d..a111c12c 100644 +--- a/src/protocols/core/Seat.cpp ++++ b/src/protocols/core/Seat.cpp +@@ -9,8 +9,6 @@ + + #include + +-#define LOGM PROTO::seat->protoLog +- + CWLTouchResource::CWLTouchResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { + if (!good()) + return; +diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp +index 75c2134a..9996a607 100644 +--- a/src/protocols/core/Shm.cpp ++++ b/src/protocols/core/Shm.cpp +@@ -7,8 +7,6 @@ + #include "../../Compositor.hpp" + #include "../../helpers/Format.hpp" + +-#define LOGM PROTO::shm->protoLog +- + CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) { + if (!pool_->pool->data) + return; +@@ -65,7 +63,7 @@ Aquamarine::SSHMAttrs CWLSHMBuffer::shm() { + } + + std::tuple CWLSHMBuffer::beginDataPtr(uint32_t flags) { +- return {(uint8_t*)pool->data + offset, fmt, size.x * size.y * 4}; ++ return {(uint8_t*)pool->data + offset, fmt, stride * size.y}; + } + + void CWLSHMBuffer::endDataPtr() { +diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp +index 2a7c06dc..e0679eff 100644 +--- a/src/protocols/core/Subcompositor.cpp ++++ b/src/protocols/core/Subcompositor.cpp +@@ -2,8 +2,6 @@ + #include "Compositor.hpp" + #include + +-#define LOGM PROTO::subcompositor->protoLog +- + CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SP surface_, SP parent_) : + surface(surface_), parent(parent_), resource(resource_) { + if (!good()) +diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp +index 67629e23..c48ff6f3 100644 +--- a/src/render/Framebuffer.cpp ++++ b/src/render/Framebuffer.cpp +@@ -12,9 +12,10 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { + uint32_t glFormat = FormatUtils::drmFormatToGL(drmFormat); + uint32_t glType = FormatUtils::glFormatToType(glFormat); + +- if (m_iFb == (uint32_t)-1) { ++ if (!m_iFbAllocated) { + firstAlloc = true; + glGenFramebuffers(1, &m_iFb); ++ m_iFbAllocated = true; + } + + if (m_cTex->m_iTexID == 0) { +@@ -88,12 +89,12 @@ void CFramebuffer::bind() { + } + + void CFramebuffer::release() { +- if (m_iFb != (uint32_t)-1 && m_iFb) ++ if (m_iFbAllocated) + glDeleteFramebuffers(1, &m_iFb); + + m_cTex->destroyTexture(); +- m_iFb = -1; +- m_vSize = Vector2D(); ++ m_iFbAllocated = false; ++ m_vSize = Vector2D(); + } + + CFramebuffer::~CFramebuffer() { +@@ -101,5 +102,5 @@ CFramebuffer::~CFramebuffer() { + } + + bool CFramebuffer::isAllocated() { +- return m_iFb != (GLuint)-1; ++ return m_iFbAllocated; + } +\ No newline at end of file +diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp +index a46a4859..ca7f9e8a 100644 +--- a/src/render/Framebuffer.hpp ++++ b/src/render/Framebuffer.hpp +@@ -18,7 +18,8 @@ class CFramebuffer { + Vector2D m_vSize; + + SP m_cTex; +- GLuint m_iFb = -1; ++ GLuint m_iFb; ++ bool m_iFbAllocated{false}; + + SP m_pStencilTex; + }; +\ No newline at end of file +diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp +index c355f4f9..63cc2203 100644 +--- a/src/render/OpenGL.cpp ++++ b/src/render/OpenGL.cpp +@@ -1247,14 +1247,14 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round + + glEnable(GL_STENCIL_TEST); + +- glStencilFunc(GL_ALWAYS, 1, -1); ++ glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + renderRect(box, CColor(0, 0, 0, 0), round); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + +- glStencilFunc(GL_EQUAL, 1, -1); ++ glStencilFunc(GL_EQUAL, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + scissor(box); +@@ -1269,7 +1269,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glDisable(GL_STENCIL_TEST); +- glStencilMask(-1); ++ glStencilMask(0xFF); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + scissor((CBox*)nullptr); + +@@ -1802,12 +1802,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o + CRegion tempDamage{damage}; + + // and draw +- for (int i = 1; i <= *PBLURPASSES; ++i) { ++ for (auto i = 1; i <= *PBLURPASSES; ++i) { + tempDamage = damage.copy().scale(1.f / (1 << i)); + drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down + } + +- for (int i = *PBLURPASSES - 1; i >= 0; --i) { ++ for (auto i = *PBLURPASSES - 1; i >= 0; --i) { + tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big + drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up + } +@@ -2091,7 +2091,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float + + glEnable(GL_STENCIL_TEST); + +- glStencilFunc(GL_ALWAYS, 1, -1); ++ glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); +@@ -2101,7 +2101,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float + renderTexture(tex, pBox, a, round, true, true); // discard opaque + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + +- glStencilFunc(GL_EQUAL, 1, -1); ++ glStencilFunc(GL_EQUAL, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + // stencil done. Render everything. +@@ -2124,7 +2124,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float + glDisable(GL_STENCIL_TEST); + renderTextureInternalWithDamage(tex, pBox, a, &texDamage, round, false, false, true, true); + +- glStencilMask(-1); ++ glStencilMask(0xFF); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + scissor((CBox*)nullptr); + } +@@ -2690,7 +2690,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { + // check if wallpapers exist + std::error_code err; + if (!std::filesystem::exists(texPath, err)) { +- Debug::log(ERR, "createBGTextureForMonitor: failed, file doesn't exist or access denied, ec: {}", err.message()); ++ Debug::log(ERR, "createBGTextureForMonitor: failed, file \"{}\" doesn't exist or access denied, ec: {}", texPath, err.message()); + return; // the texture will be empty, oh well. We'll clear with a solid color anyways. + } + +diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp +index 58ed88d6..c4425ce9 100644 +--- a/src/render/Renderbuffer.cpp ++++ b/src/render/Renderbuffer.cpp +@@ -35,7 +35,8 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glGenFramebuffers(1, &m_sFramebuffer.m_iFb); +- m_sFramebuffer.m_vSize = buffer->size; ++ m_sFramebuffer.m_iFbAllocated = true; ++ m_sFramebuffer.m_vSize = buffer->size; + m_sFramebuffer.bind(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); + +diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp +index 7b29eb77..b363c287 100644 +--- a/src/render/Renderer.cpp ++++ b/src/render/Renderer.cpp +@@ -1207,6 +1207,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { + } else if (!pMonitor->lastScanout.expired()) { + Debug::log(LOG, "Left a direct scanout."); + pMonitor->lastScanout.reset(); ++ ++ // reset DRM format, make sure it's the one we want. ++ pMonitor->output->state->setFormat(pMonitor->drmFormat); + } + } + +@@ -1395,15 +1398,15 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { + + pMonitor->pendingFrame = false; + +- const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; +- g_pDebugOverlay->renderData(pMonitor, µs); ++ const float durationUs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; ++ g_pDebugOverlay->renderData(pMonitor, durationUs); + + if (*PDEBUGOVERLAY == 1) { + if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { +- const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; +- g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); ++ const float noOverlayUs = durationUs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; ++ g_pDebugOverlay->renderDataNoOverlay(pMonitor, noOverlayUs); + } else { +- g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs); ++ g_pDebugOverlay->renderDataNoOverlay(pMonitor, durationUs); + } + } + } +@@ -1658,7 +1661,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgetMonitorFromID(monitor); + + if (!PMONITOR) +@@ -2155,6 +2158,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR + + for (auto& fmt : formats[(int)!RULE->enable10bit]) { + pMonitor->output->state->setFormat(fmt.second); ++ pMonitor->drmFormat = fmt.second; + + if (!pMonitor->state.test()) { + Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); +@@ -2299,7 +2303,7 @@ void CHyprRenderer::setCursorFromName(const std::string& name, bool force) { + } + + void CHyprRenderer::ensureCursorRenderingMode() { +- static auto PCURSORTIMEOUT = CConfigValue("cursor:inactive_timeout"); ++ static auto PCURSORTIMEOUT = CConfigValue("cursor:inactive_timeout"); + static auto PHIDEONTOUCH = CConfigValue("cursor:hide_on_touch"); + static auto PHIDEONKEY = CConfigValue("cursor:hide_on_key_press"); + +diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp +index 84501821..0b16efea 100644 +--- a/src/render/Renderer.hpp ++++ b/src/render/Renderer.hpp +@@ -49,7 +49,7 @@ class CHyprRenderer { + ~CHyprRenderer(); + + void renderMonitor(CMonitor* pMonitor); +- void arrangeLayersForMonitor(const int&); ++ void arrangeLayersForMonitor(const MONITORID&); + void damageSurface(SP, double, double, double scale = 1.0); + void damageWindow(PHLWINDOW, bool forceFull = false); + void damageBox(CBox*, bool skipFrameSchedule = false); +diff --git a/src/signal-safe.cpp b/src/signal-safe.cpp +index 05ca9c65..44d23f9b 100644 +--- a/src/signal-safe.cpp ++++ b/src/signal-safe.cpp +@@ -10,7 +10,7 @@ + extern char** environ; + + char const* sig_getenv(char const* name) { +- int len = strlen(name); ++ size_t len = strlen(name); + for (char** var = environ; *var != NULL; var++) { + if (strncmp(*var, name, len) == 0 && (*var)[len] == '=') { + return (*var) + len + 1; +diff --git a/src/signal-safe.hpp b/src/signal-safe.hpp +index 3a38f043..ef643097 100644 +--- a/src/signal-safe.hpp ++++ b/src/signal-safe.hpp +@@ -139,7 +139,7 @@ class BufFileWriter { + abort(); + } else { + close(pipefd[1]); +- int len; ++ long len; + char readbuf[256]; + while ((len = read(pipefd[0], readbuf, 256)) > 0) { + write(readbuf, len); +@@ -155,7 +155,7 @@ class BufFileWriter { + void flush() { + size_t i = 0; + while (i < m_writeBufPos) { +- int written = ::write(m_fd, m_writeBuf + i, m_writeBufPos - i); ++ auto written = ::write(m_fd, m_writeBuf + i, m_writeBufPos - i); + if (written <= 0) { + return; + } +diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp +index cec582f6..200bec70 100644 +--- a/src/xwayland/Server.cpp ++++ b/src/xwayland/Server.cpp +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + // TODO: cleanup + static bool set_cloexec(int fd, bool cloexec) { diff --git a/hosts/callisto/configuration.nix b/hosts/callisto/configuration.nix index 7968a47..436419d 100755 --- a/hosts/callisto/configuration.nix +++ b/hosts/callisto/configuration.nix @@ -45,26 +45,7 @@ oldAttrs.patches or [] ++ [ - ./0001-linux-dmabuf-allow-on-split-node-systems.patch - ./0002-renderer-pass-custom-modelines-to-aq.patch - ./0003-compositor-update-suspendstate-on-window-move-7396.patch - ./0004-screencopy-nuke-unused-stuff.patch - ./0005-protocol-fix-logm-template-checks.patch - ./0006-screencopy-fix-10b-format-r-b-flip.patch - ./0007-flake-update-aquamarine.patch - ./0008-hyprpm-hyprctl-update-shell-completions.patch - ./0009-config-add-missing-header-for-libc-after-92744b5b9aa.patch - ./0010-examples-more-systemd-examples-7409.patch - ./0011-monitors-avoid-crash-on-wayland-output-removal.patch - ./0012-monitor-avoid-dangling-references-to-old-monitors-be.patch - ./0013-example-config-fix-typo-in-default-config-7446.patch - ./0014-core-add-option-to-control-which-window-to-focus-on-.patch - ./0015-output-dont-cast-enum-out-of-range-7448.patch - ./0016-animations-add-workspace-in-out-configs.patch - ./0017-Nix-include-xcursor-regardless-of-xwayland.patch - ./0018-Fix-static-asan-patch.patch - ./0019-Fix-Makefile-too.patch - ./0020-layersurface-dont-rollover-on-size_t-7451.patch + ./asahi-fix.patch ]; }); })