aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-02-14 23:08:03 +0000
committerGitHub <[email protected]>2024-02-14 23:08:03 +0000
commit3a6451b6026a5f38987e61ee07b442910b5432f5 (patch)
tree20cd2a725aac2d600c6a7b1b1cf29d3c622e22f3
parent7af2e270fda4f20e3b4687ec07cbc149bb220930 (diff)
parent9c3f3b00183c9bcca528d1c74fa29eed0bd747fa (diff)
downloadHyprland-3a6451b6026a5f38987e61ee07b442910b5432f5.tar.gz
Hyprland-3a6451b6026a5f38987e61ee07b442910b5432f5.zip
Merge branch 'main' into hyprlang-migration
-rw-r--r--assets/wall1.pngbin5690948 -> 6144371 bytes
-rw-r--r--example/hyprland.conf2
-rw-r--r--flake.lock12
-rw-r--r--hyprctl/main.cpp47
-rw-r--r--nix/overlays.nix6
-rw-r--r--src/Compositor.cpp30
-rw-r--r--src/Window.hpp19
-rw-r--r--src/config/ConfigManager.cpp10
-rw-r--r--src/config/defaultConfig.hpp4
-rw-r--r--src/debug/HyprCtl.cpp15
-rw-r--r--src/debug/HyprNotificationOverlay.cpp4
-rw-r--r--src/debug/HyprNotificationOverlay.hpp1
-rw-r--r--src/events/Monitors.cpp16
-rw-r--r--src/events/Windows.cpp44
-rw-r--r--src/helpers/Monitor.hpp55
-rw-r--r--src/layout/DwindleLayout.cpp31
-rw-r--r--src/layout/DwindleLayout.hpp1
-rw-r--r--src/layout/IHyprLayout.cpp4
-rw-r--r--src/managers/KeybindManager.cpp16
-rw-r--r--src/managers/KeybindManager.hpp1
-rw-r--r--src/managers/input/InputManager.cpp15
-rw-r--r--src/render/Renderer.cpp125
22 files changed, 261 insertions, 197 deletions
diff --git a/assets/wall1.png b/assets/wall1.png
index ad2b5678..53e4c90d 100644
--- a/assets/wall1.png
+++ b/assets/wall1.png
Binary files differ
diff --git a/example/hyprland.conf b/example/hyprland.conf
index 5d5441e9..75ff0abe 100644
--- a/example/hyprland.conf
+++ b/example/hyprland.conf
@@ -126,7 +126,7 @@ device:epic-mouse-v1 {
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
-windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
+windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
diff --git a/flake.lock b/flake.lock
index b94fee70..3029b49e 100644
--- a/flake.lock
+++ b/flake.lock
@@ -66,11 +66,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1706191920,
- "narHash": "sha256-eLihrZAPZX0R6RyM5fYAWeKVNuQPYjAkCUBr+JNvtdE=",
+ "lastModified": 1707546158,
+ "narHash": "sha256-nYYJTpzfPMDxI8mzhQsYjIUX+grorqjKEU9Np6Xwy/0=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "ae5c332cbb5827f6b1f02572496b141021de335f",
+ "rev": "d934204a0f8d9198e1e4515dd6fec76a139c87f0",
"type": "github"
},
"original": {
@@ -138,11 +138,11 @@
]
},
"locked": {
- "lastModified": 1706145785,
- "narHash": "sha256-j9MP4fv2U/vdRKAXXc2gyMTmYwVnHP6kHx1/y6jprrU=",
+ "lastModified": 1706521509,
+ "narHash": "sha256-AInZ50acOJ3wzUwGzNr1TmxGTMx+8j6oSTzz4E7Vbp8=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
- "rev": "5a592647587cd20b9692a347df6939b6d371b3bb",
+ "rev": "c06fd88b3da492b8f9067be021b9184f7012b5a8",
"type": "github"
},
"original": {
diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp
index 281a74ac..b1d89a8a 100644
--- a/hyprctl/main.cpp
+++ b/hyprctl/main.cpp
@@ -371,44 +371,8 @@ int main(int argc, char** argv) {
if (fullRequest.contains("/--batch"))
batchRequest(fullRequest);
- else if (fullRequest.contains("/monitors"))
- request(fullRequest);
- else if (fullRequest.contains("/clients"))
- request(fullRequest);
- else if (fullRequest.contains("/workspaces"))
- request(fullRequest);
- else if (fullRequest.contains("/activeworkspace"))
- request(fullRequest);
- else if (fullRequest.contains("/workspacerules"))
- request(fullRequest);
- else if (fullRequest.contains("/activewindow"))
- request(fullRequest);
- else if (fullRequest.contains("/layers"))
- request(fullRequest);
- else if (fullRequest.contains("/version"))
- request(fullRequest);
- else if (fullRequest.contains("/kill"))
- request(fullRequest);
- else if (fullRequest.contains("/systeminfo"))
- request(fullRequest);
- else if (fullRequest.contains("/splash"))
- request(fullRequest);
- else if (fullRequest.contains("/devices"))
- request(fullRequest);
- else if (fullRequest.contains("/reload"))
- request(fullRequest);
- else if (fullRequest.contains("/getoption"))
- request(fullRequest);
- else if (fullRequest.contains("/binds"))
- request(fullRequest);
- else if (fullRequest.contains("/cursorpos"))
- request(fullRequest);
- else if (fullRequest.contains("/animations"))
- request(fullRequest);
- else if (fullRequest.contains("/globalshortcuts"))
- request(fullRequest);
- else if (fullRequest.contains("/rollinglog"))
- request(fullRequest);
+ else if (fullRequest.contains("/hyprpaper"))
+ requestHyprpaper(fullRequest);
else if (fullRequest.contains("/switchxkblayout"))
request(fullRequest, 2);
else if (fullRequest.contains("/seterror"))
@@ -429,15 +393,10 @@ int main(int argc, char** argv) {
request(fullRequest, 2);
else if (fullRequest.contains("/decorations"))
request(fullRequest, 1);
- else if (fullRequest.contains("/hyprpaper"))
- requestHyprpaper(fullRequest);
- else if (fullRequest.contains("/layouts"))
- request(fullRequest);
else if (fullRequest.contains("/--help"))
printf("%s", USAGE.c_str());
else {
- printf("%s\n", USAGE.c_str());
- return 1;
+ request(fullRequest);
}
printf("\n");
diff --git a/nix/overlays.nix b/nix/overlays.nix
index 3eedd84c..0a84d93e 100644
--- a/nix/overlays.nix
+++ b/nix/overlays.nix
@@ -32,9 +32,9 @@ in {
hyprland = final.callPackage ./default.nix {
stdenv = final.gcc13Stdenv;
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
- wlroots = prev.wlroots-hyprland;
commit = self.rev or "";
- inherit (final) udis86 hyprland-protocols;
+ wlroots = final.wlroots-hyprland; # explicit override until decided on breaking change of the name
+ udis86 = final.udis86-hyprland; # explicit override until decided on breaking change of the name
inherit date;
};
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
@@ -62,7 +62,7 @@ in {
];
udis86 = final: prev: {
- udis86 = final.callPackage ./udis86.nix {};
+ udis86-hyprland = final.callPackage ./udis86.nix {};
};
# Patched version of wlroots for Hyprland.
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 82bc6209..a3ce5609 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -710,7 +710,8 @@ CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t propert
for (auto& w : m_vWindows | std::views::reverse) {
const auto BB = w->getWindowBoxUnified(properties);
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
- if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
+ if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
+ w.get() != pIgnoreWindow) {
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
return w.get();
@@ -732,7 +733,8 @@ CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t propert
const auto BB = w->getWindowBoxUnified(properties);
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
- if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
+ if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
+ w.get() != pIgnoreWindow) {
// OR windows should add focus to parent
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
continue;
@@ -770,8 +772,8 @@ CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t propert
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
continue;
- if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
- w.get() != pIgnoreWindow) {
+ if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
+ !w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow) {
if (w->hasPopupAt(pos))
return w.get();
}
@@ -782,8 +784,8 @@ CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t propert
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->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
- w.get() != pIgnoreWindow)
+ if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
+ !w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow)
return w.get();
}
@@ -928,7 +930,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
return;
}
- if (pWindow->m_bNoFocus) {
+ if (pWindow->m_sAdditionalConfigData.noFocus) {
Debug::log(LOG, "Ignoring focus to nofocus window!");
return;
}
@@ -1646,7 +1648,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
- if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
+ if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
return w.get();
}
@@ -1654,7 +1656,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
- if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
+ if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
return w.get();
}
@@ -1675,7 +1677,7 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
- if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
+ if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
return w.get();
}
@@ -1683,7 +1685,7 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
- if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
+ if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
return w.get();
}
@@ -2028,7 +2030,11 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
updateFullscreenFadeOnWorkspace(PWORKSPACEB);
updateFullscreenFadeOnWorkspace(PWORKSPACEA);
- g_pInputManager->sendMotionEventsToFocused();
+ if (pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID || pMonitorB->ID == g_pCompositor->m_pLastMonitor->ID) {
+ const auto LASTWIN = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow();
+ g_pCompositor->focusWindow(LASTWIN ? LASTWIN :
+ (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)));
+ }
// event
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName});
diff --git a/src/Window.hpp b/src/Window.hpp
index b0689b61..38eb857c 100644
--- a/src/Window.hpp
+++ b/src/Window.hpp
@@ -37,7 +37,15 @@ enum eGetWindowProperties {
FULL_EXTENTS = 1 << 2,
FLOATING_ONLY = 1 << 3,
ALLOW_FLOATING = 1 << 4,
- USE_PROP_TILED = 1 << 5
+ USE_PROP_TILED = 1 << 5,
+};
+
+enum eSuppressEvents {
+ SUPPRESS_NONE = 0,
+ SUPPRESS_FULLSCREEN = 1 << 0,
+ SUPPRESS_MAXIMIZE = 1 << 1,
+ SUPPRESS_ACTIVATE = 1 << 2,
+ SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3,
};
class IWindowTransformer;
@@ -143,6 +151,7 @@ struct SWindowAdditionalConfigData {
CWindowOverridableVar<bool> forceNoBorder = false;
CWindowOverridableVar<bool> forceNoShadow = false;
CWindowOverridableVar<bool> forceNoDim = false;
+ CWindowOverridableVar<bool> noFocus = false;
CWindowOverridableVar<bool> windowDanceCompat = false;
CWindowOverridableVar<bool> noMaxSize = false;
CWindowOverridableVar<bool> dimAround = false;
@@ -260,13 +269,13 @@ class CWindow {
//
// For nofocus
- bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
// Fullscreen and Maximize
- bool m_bWantsInitialFullscreen = false;
- bool m_bNoFullscreenRequest = false;
- bool m_bNoMaximizeRequest = false;
+ bool m_bWantsInitialFullscreen = false;
+
+ // bitfield eSuppressEvents
+ uint64_t m_eSuppressedEvents = SUPPRESS_NONE;
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index da479ac6..7888df36 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -1812,11 +1812,11 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma
bool windowRuleValid(const std::string& RULE) {
return RULE == "float" || RULE == "tile" || RULE.starts_with("opacity") || RULE.starts_with("move") || RULE.starts_with("size") || RULE.starts_with("minsize") ||
RULE.starts_with("maxsize") || RULE.starts_with("pseudo") || RULE.starts_with("monitor") || RULE.starts_with("idleinhibit") || RULE == "nofocus" || RULE == "noblur" ||
- RULE == "noshadow" || RULE == "nodim" || RULE == "noborder" || RULE == "opaque" || RULE == "forceinput" || RULE == "fullscreen" || RULE == "nofullscreenrequest" ||
- RULE == "nomaximizerequest" || RULE == "fakefullscreen" || RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" ||
- RULE == "maximize" || RULE == "keepaspectratio" || RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") ||
- RULE.starts_with("bordercolor") || RULE == "forcergbx" || RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") ||
- RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor";
+ RULE == "noshadow" || RULE == "nodim" || RULE == "noborder" || RULE == "opaque" || RULE == "forceinput" || RULE == "fullscreen" || RULE == "fakefullscreen" ||
+ RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" || RULE == "maximize" || RULE == "keepaspectratio" ||
+ RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") || RULE.starts_with("bordercolor") || RULE == "forcergbx" ||
+ RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") || RULE.starts_with("center") ||
+ RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor" || RULE.starts_with("suppressevent");
}
bool layerRuleValid(const std::string& RULE) {
diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp
index ac889241..95e98e4f 100644
--- a/src/config/defaultConfig.hpp
+++ b/src/config/defaultConfig.hpp
@@ -51,7 +51,7 @@ input {
natural_scroll = no
}
- sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
+ sensitivity = 0 # -1.0 to 1.0, 0 means no modification.
}
general {
@@ -133,7 +133,7 @@ device:epic-mouse-v1 {
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
-windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
+windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp
index 56dfd283..f2584ad0 100644
--- a/src/debug/HyprCtl.cpp
+++ b/src/debug/HyprCtl.cpp
@@ -965,7 +965,7 @@ std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
nextItem();
- while (curitem != "") {
+ while (curitem != "" || request != "") {
reply += g_pHyprCtl->getReply(curitem);
nextItem();
@@ -1087,7 +1087,8 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
if (vars.size() < 4)
return "not enough args";
- const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
+ const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
+ const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
if (!PWINDOW)
return "window not found";
@@ -1095,6 +1096,8 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
const auto PROP = vars[2];
const auto VAL = vars[3];
+ auto noFocus = PWINDOW->m_sAdditionalConfigData.noFocus;
+
bool lock = false;
if (vars.size() > 4) {
@@ -1124,6 +1127,8 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forcenodim") {
PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock);
+ } else if (PROP == "nofocus") {
+ PWINDOW->m_sAdditionalConfigData.noFocus.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "windowdancecompat") {
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "nomaxsize") {
@@ -1159,6 +1164,12 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
+ if (!(PWINDOW->m_sAdditionalConfigData.noFocus.toUnderlying() == noFocus.toUnderlying())) {
+ g_pCompositor->focusWindow(nullptr);
+ g_pCompositor->focusWindow(PWINDOW);
+ g_pCompositor->focusWindow(PLASTWINDOW);
+ }
+
for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp
index 12f7a575..2968134b 100644
--- a/src/debug/HyprNotificationOverlay.cpp
+++ b/src/debug/HyprNotificationOverlay.cpp
@@ -226,4 +226,8 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
+}
+
+bool CHyprNotificationOverlay::hasAny() {
+ return !m_dNotifications.empty();
} \ No newline at end of file
diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp
index 84e61f80..7a883f15 100644
--- a/src/debug/HyprNotificationOverlay.hpp
+++ b/src/debug/HyprNotificationOverlay.hpp
@@ -41,6 +41,7 @@ class CHyprNotificationOverlay {
void draw(CMonitor* pMonitor);
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
+ bool hasAny();
private:
CBox drawNotifications(CMonitor* pMonitor);
diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp
index 14d617fe..01ea24f8 100644
--- a/src/events/Monitors.cpp
+++ b/src/events/Monitors.cpp
@@ -209,10 +209,20 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
}
void Events::listener_monitorStateRequest(void* owner, void* data) {
- //const auto PMONITOR = (CMonitor*)owner;
- //const auto E = (wlr_output_event_request_state*)data;
+ const auto PMONITOR = (CMonitor*)owner;
+ const auto E = (wlr_output_event_request_state*)data;
+
+ if (!PMONITOR->createdByUser)
+ return;
+
+ const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
+
+ PMONITOR->forceSize = SIZE;
+
+ SMonitorRule rule = PMONITOR->activeMonitorRule;
+ rule.resolution = SIZE;
- // TODO: maybe don't ignore?
+ g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
}
void Events::listener_monitorDamage(void* owner, void* data) {
diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp
index f78bf199..b5072295 100644
--- a/src/events/Windows.cpp
+++ b/src/events/Windows.cpp
@@ -173,13 +173,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
} else if (r.szRule.starts_with("pseudo")) {
PWINDOW->m_bIsPseudotiled = true;
} else if (r.szRule.starts_with("nofocus")) {
- PWINDOW->m_bNoFocus = true;
+ PWINDOW->m_sAdditionalConfigData.noFocus = true;
} else if (r.szRule.starts_with("noinitialfocus")) {
PWINDOW->m_bNoInitialFocus = true;
- } else if (r.szRule.starts_with("nofullscreenrequest")) {
- PWINDOW->m_bNoFullscreenRequest = true;
- } else if (r.szRule.starts_with("nomaximizerequest")) {
- PWINDOW->m_bNoMaximizeRequest = true;
+ } else if (r.szRule.starts_with("suppressevent")) {
+ CVarList vars(r.szRule, 0, 's', true);
+ for (size_t i = 1; i < vars.size(); ++i) {
+ if (vars[i] == "fullscreen")
+ PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN;
+ else if (vars[i] == "maximize")
+ PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE;
+ else if (vars[i] == "activate")
+ PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE;
+ else if (vars[i] == "activatefocus")
+ PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
+ else
+ Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
+ }
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
overridingNoFullscreen = true;
@@ -443,9 +453,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow;
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
- PWINDOW->m_bNoFocus = false;
- PWINDOW->m_bNoInitialFocus = false;
- PWINDOW->m_bX11ShouldntFocus = false;
+ PWINDOW->m_sAdditionalConfigData.noFocus = false;
+ PWINDOW->m_bNoInitialFocus = false;
+ PWINDOW->m_bX11ShouldntFocus = false;
}
// check LS focus grab
@@ -464,7 +474,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
requestsFullscreen = true;
}
- if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus &&
+ if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus &&
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
g_pCompositor->focusWindow(PWINDOW);
@@ -504,8 +514,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
"XWayland Window Late");
}
- if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) ||
- requestsFakeFullscreen) {
+ if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) ||
+ (requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
@@ -905,7 +915,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
return;
}
- if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest)
+ if (PWINDOW->isHidden() || (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
return;
bool requestedFullState = false;
@@ -968,7 +978,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
- if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow)
+ if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
return;
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
@@ -976,7 +986,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
PWINDOW->m_bIsUrgent = true;
- if (!**PFOCUSONACTIVATE)
+ if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
return;
if (PWINDOW->m_bIsFloating)
@@ -1004,13 +1014,13 @@ void Events::listener_activateX11(void* owner, void* data) {
return;
}
- if (PWINDOW == g_pCompositor->m_pLastWindow)
+ if (PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
return;
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
EMIT_HOOK_EVENT("urgent", PWINDOW);
- if (!**PFOCUSONACTIVATE)
+ if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
return;
if (PWINDOW->m_bIsFloating)
@@ -1206,7 +1216,7 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
void Events::listener_requestMaximize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
- if (PWINDOW->m_bNoMaximizeRequest)
+ if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)
return;
Debug::log(LOG, "Maximize request for {}", PWINDOW);
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index d5aba751..c5eb70a0 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -73,33 +73,34 @@ class CMonitor {
CMonitorState state;
// WLR stuff
- wlr_damage_ring damage;
- wlr_output* output = nullptr;
- float refreshRate = 60;
- int framesToSkip = 0;
- int forceFullFrames = 0;
- bool noFrameSchedule = false;
- bool scheduledRecalc = false;
- wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
- bool gammaChanged = false;
- float xwaylandScale = 1.f;
- std::array<float, 9> projMatrix = {0};
-
- 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.
- bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
- bool createdByUser = false;
- uint32_t drmFormat = DRM_FORMAT_INVALID;
- bool isUnsafeFallback = false;
-
- bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
- bool renderingActive = false;
-
- wl_event_source* renderTimer = nullptr; // for RAT
- bool RATScheduled = false;
- CTimer lastPresentationTimer;
-
- SMonitorRule activeMonitorRule;
+ wlr_damage_ring damage;
+ wlr_output* output = nullptr;
+ float refreshRate = 60;
+ int framesToSkip = 0;
+ int forceFullFrames = 0;
+ bool noFrameSchedule = false;
+ bool scheduledRecalc = false;
+ wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ bool gammaChanged = false;
+ float xwaylandScale = 1.f;
+ std::array<float, 9> projMatrix = {0};
+ std::optional<Vector2D> forceSize;
+
+ 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.
+ bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
+ bool createdByUser = false;
+ uint32_t drmFormat = DRM_FORMAT_INVALID;
+ bool isUnsafeFallback = false;
+
+ bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
+ bool renderingActive = false;
+
+ wl_event_source* renderTimer = nullptr; // for RAT
+ bool RATScheduled = false;
+ CTimer lastPresentationTimer;
+
+ SMonitorRule activeMonitorRule;
// mirroring
CMonitor* pMirrorOf = nullptr;
diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp
index 9e168df4..5bdf8748 100644
--- a/src/layout/DwindleLayout.cpp
+++ b/src/layout/DwindleLayout.cpp
@@ -225,10 +225,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} else {
- PWINDOW->m_vRealSize = calcSize;
- PWINDOW->m_vRealPosition = calcPos;
+ CBox wb = {calcPos, calcSize};
+ wb.round(); // avoid rounding mess
- g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
+ PWINDOW->m_vRealSize = wb.size();
+ PWINDOW->m_vRealPosition = wb.pos();
+
+ g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
}
if (force) {
@@ -644,8 +647,10 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
else
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
- PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w);
- PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h);
+ CBox wbox = PNODE->box;
+ wbox.round();
+
+ PWINDOW->m_vPseudoSize = {std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, wbox.w), std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, wbox.h)};
PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize;
PNODE->recalcSizePosRecursive(**PANIMATE == 0);
@@ -990,6 +995,8 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
const auto ARGS = CVarList(message, 0, ' ');
if (ARGS[0] == "togglesplit") {
toggleSplit(header.pWindow);
+ } else if (ARGS[0] == "swapsplit") {
+ swapSplit(header.pWindow);
} else if (ARGS[0] == "preselect") {
std::string direction = ARGS[1];
@@ -1043,6 +1050,20 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
PNODE->pParent->recalcSizePosRecursive();
}
+void CHyprDwindleLayout::swapSplit(CWindow* pWindow) {
+ const auto PNODE = getNodeFromWindow(pWindow);
+
+ if (!PNODE || !PNODE->pParent)
+ return;
+
+ if (pWindow->m_bIsFullscreen)
+ return;
+
+ std::swap(PNODE->pParent->children[0], PNODE->pParent->children[1]);
+
+ PNODE->pParent->recalcSizePosRecursive();
+}
+
void CHyprDwindleLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
const auto PNODE = getNodeFromWindow(from);
diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp
index 780dd121..f5501b28 100644
--- a/src/layout/DwindleLayout.hpp
+++ b/src/layout/DwindleLayout.hpp
@@ -83,6 +83,7 @@ class CHyprDwindleLayout : public IHyprLayout {
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
void toggleSplit(CWindow*);
+ void swapSplit(CWindow*);
eDirection overrideDirection = DIRECTION_DEFAULT;
diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp
index 34499ca5..49e20435 100644
--- a/src/layout/IHyprLayout.cpp
+++ b/src/layout/IHyprLayout.cpp
@@ -530,7 +530,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// find whether there is a floating window below this one
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
- !w->m_bNoFocus && w.get() != pWindow) {
+ !w->m_sAdditionalConfigData.noFocus && w.get() != pWindow) {
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
w->m_vPosition.y + w->m_vSize.y)) {
return w.get();
@@ -550,7 +550,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// if not, floating window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
- !w->m_bNoFocus && w.get() != pWindow)
+ !w->m_sAdditionalConfigData.noFocus && w.get() != pWindow)
return w.get();
}
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp
index 2d8bd1e8..3afe7949 100644
--- a/src/managers/KeybindManager.cpp
+++ b/src/managers/KeybindManager.cpp
@@ -39,6 +39,7 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["changegroupactive"] = changeGroupActive;
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
m_mDispatchers["togglesplit"] = toggleSplit;
+ m_mDispatchers["swapsplit"] = swapSplit;
m_mDispatchers["splitratio"] = alterSplitRatio;
m_mDispatchers["focusmonitor"] = focusMonitor;
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
@@ -1293,6 +1294,21 @@ void CKeybindManager::toggleSplit(std::string args) {
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "togglesplit");
}
+void CKeybindManager::swapSplit(std::string args) {
+ SLayoutMessageHeader header;
+ header.pWindow = g_pCompositor->m_pLastWindow;
+
+ if (!header.pWindow)
+ return;
+
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(header.pWindow->m_iWorkspaceID);
+
+ if (PWORKSPACE->m_bHasFullscreenWindow)
+ return;
+
+ g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "swapsplit");
+}
+
void CKeybindManager::alterSplitRatio(std::string args) {
std::optional<float> splitResult;
bool exact = false;
diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp
index 7ca43ec1..7022593a 100644
--- a/src/managers/KeybindManager.hpp
+++ b/src/managers/KeybindManager.hpp
@@ -127,6 +127,7 @@ class CKeybindManager {
static void alterSplitRatio(std::string);
static void focusMonitor(std::string);
static void toggleSplit(std::string);
+ static void swapSplit(std::string);
static void moveCursorToCorner(std::string);
static void moveCursor(std::string);
static void workspaceOpt(std::string);
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index 079c0336..155be729 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -487,10 +487,15 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
return;
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
- m_sCursorSurfaceInfo.wlSurface.unassign();
+
+ if (e->surface != m_sCursorSurfaceInfo.wlSurface.wlr()) {
+ m_sCursorSurfaceInfo.wlSurface.unassign();
+
+ if (e->surface)
+ m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
+ }
if (e->surface) {
- m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
m_sCursorSurfaceInfo.hidden = false;
} else {
@@ -645,9 +650,11 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
}
// notify app if we didnt handle it
- if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) {
+ if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus))
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
- }
+
+ if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor && PMON)
+ g_pCompositor->setActiveMonitor(PMON);
}
void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index dfd8d9f8..74189622 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1231,20 +1231,20 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
TRACY_GPU_COLLECT;
- // calc frame damage
- CRegion frameDamage{};
+ if (!pMonitor->mirrors.empty()) {
+ CRegion frameDamage{};
- const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform);
- wlr_region_transform(frameDamage.pixman(), pMonitor->lastFrameDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
+ const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform);
+ wlr_region_transform(frameDamage.pixman(), pMonitor->lastFrameDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
- if (**PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || **PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
- frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
+ if (**PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || **PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
+ frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
- if (**PDAMAGEBLINK)
- frameDamage.add(damage);
+ if (**PDAMAGEBLINK)
+ frameDamage.add(damage);
- if (!pMonitor->mirrors.empty())
g_pHyprRenderer->damageMirrorsWith(pMonitor, frameDamage);
+ }
pMonitor->renderingActive = false;
@@ -1735,8 +1735,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->activeMonitorRule = *pMonitorRule;
+ if (pMonitor->forceSize.has_value())
+ pMonitor->activeMonitorRule.resolution = pMonitor->forceSize.value();
+
+ const auto RULE = &pMonitor->activeMonitorRule;
+
// if it's disabled, disable and ignore
- if (pMonitorRule->disabled) {
+ if (RULE->disabled) {
if (pMonitor->m_bEnabled)
pMonitor->onDisconnect();
@@ -1755,12 +1760,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
// Check if the rule isn't already applied
// TODO: clean this up lol
- if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) &&
- DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->setScale == pMonitorRule->scale &&
- ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) ||
- pMonitorRule->offset == Vector2D(-INT32_MAX, -INT32_MAX)) &&
- pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit &&
- !memcmp(&pMonitor->customDrmMode, &pMonitorRule->drmMode, sizeof(pMonitor->customDrmMode))) {
+ if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, RULE->resolution.y, 1) &&
+ DELTALESSTHAN(pMonitor->refreshRate, RULE->refreshRate, 1) && pMonitor->setScale == RULE->scale &&
+ ((DELTALESSTHAN(pMonitor->vecPosition.x, RULE->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, RULE->offset.y, 1)) ||
+ RULE->offset == Vector2D(-INT32_MAX, -INT32_MAX)) &&
+ pMonitor->transform == RULE->transform && RULE->enable10bit == pMonitor->enabled10bit &&
+ !memcmp(&pMonitor->customDrmMode, &RULE->drmMode, sizeof(pMonitor->customDrmMode))) {
Debug::log(LOG, "Not applying a new rule to {} because it's already applied!", pMonitor->szName);
return true;
@@ -1773,8 +1778,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->customDrmMode = {};
bool autoScale = false;
- if (pMonitorRule->scale > 0.1) {
- pMonitor->scale = pMonitorRule->scale;
+ if (RULE->scale > 0.1) {
+ pMonitor->scale = RULE->scale;
} else {
autoScale = true;
const auto DEFAULTSCALE = pMonitor->getDefaultScale();
@@ -1784,21 +1789,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
pMonitor->setScale = pMonitor->scale;
- wlr_output_state_set_transform(pMonitor->state.wlr(), pMonitorRule->transform);
- pMonitor->transform = pMonitorRule->transform;
+ wlr_output_state_set_transform(pMonitor->state.wlr(), RULE->transform);
+ pMonitor->transform = RULE->transform;
- const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : pMonitorRule->refreshRate * 1000;
+ const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : RULE->refreshRate * 1000;
// loop over modes and choose an appropriate one.
- if (pMonitorRule->resolution != Vector2D() && pMonitorRule->resolution != Vector2D(-1, -1) && pMonitorRule->resolution != Vector2D(-1, -2)) {
- if (!wl_list_empty(&pMonitor->output->modes) && pMonitorRule->drmMode.type != DRM_MODE_TYPE_USERDEF) {
+ if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) {
+ if (!wl_list_empty(&pMonitor->output->modes) && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) {
wlr_output_mode* mode;
bool found = false;
wl_list_for_each(mode, &pMonitor->output->modes, link) {
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
- if (DELTALESSTHAN(mode->width, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(mode->height, pMonitorRule->resolution.y, 1) &&
- DELTALESSTHAN(mode->refresh / 1000.f, pMonitorRule->refreshRate, 1)) {
+ if (DELTALESSTHAN(mode->width, RULE->resolution.x, 1) && DELTALESSTHAN(mode->height, RULE->resolution.y, 1) &&
+ DELTALESSTHAN(mode->refresh / 1000.f, RULE->refreshRate, 1)) {
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
@@ -1806,8 +1811,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
continue;
}
- Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh);
+ Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
found = true;
@@ -1819,9 +1824,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!found) {
- wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
- pMonitor->vecSize = pMonitorRule->resolution;
- pMonitor->refreshRate = pMonitorRule->refreshRate;
+ wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
+ pMonitor->vecSize = RULE->resolution;
+ pMonitor->refreshRate = RULE->refreshRate;
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
@@ -1829,47 +1834,47 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate);
+ Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution,
+ (float)RULE->refreshRate);
return true;
}
// Preferred is valid
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
- Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
- pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
} else {
- Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", pMonitorRule->resolution, (float)pMonitorRule->refreshRate);
+ Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
}
}
} else {
// custom resolution
bool fail = false;
- if (pMonitorRule->drmMode.type == DRM_MODE_TYPE_USERDEF) {
+ if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) {
if (!wlr_output_is_drm(pMonitor->output)) {
Debug::log(ERR, "Tried to set custom modeline on non-DRM output");
fail = true;
} else {
- auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &pMonitorRule->drmMode);
+ auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode);
if (mode) {
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
- pMonitor->customDrmMode = pMonitorRule->drmMode;
+ pMonitor->customDrmMode = RULE->drmMode;
} else {
Debug::log(ERR, "wlr_drm_connector_add_mode failed");
fail = true;
}
}
} else {
- wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
+ wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
}
- pMonitor->vecSize = pMonitorRule->resolution;
- pMonitor->refreshRate = pMonitorRule->refreshRate;
+ pMonitor->vecSize = RULE->resolution;
+ pMonitor->refreshRate = RULE->refreshRate;
if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
@@ -1877,25 +1882,25 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate);
+ Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate);
return true;
}
// Preferred is valid
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
- Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
- pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
pMonitor->customDrmMode = {};
} else {
- Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", pMonitorRule->resolution, (float)pMonitorRule->refreshRate);
+ Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
}
}
- } else if (pMonitorRule->resolution != Vector2D()) {
+ } else if (RULE->resolution != Vector2D()) {
if (!wl_list_empty(&pMonitor->output->modes)) {
wlr_output_mode* mode;
float currentWidth = 0;
@@ -1904,7 +1909,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
bool success = false;
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
- if (pMonitorRule->resolution == Vector2D(-1, -1)) {
+ if (RULE->resolution == Vector2D(-1, -1)) {
wl_list_for_each(mode, &pMonitor->output->modes, link) {
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
@@ -1932,22 +1937,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!success) {
- Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
+ Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate);
+ Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate);
return true;
}
// Preferred is valid
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
- Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
- pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
@@ -1976,8 +1980,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
continue;
}
- Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh);
+ Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
pMonitor->refreshRate = mode->refresh / 1000.f;
pMonitor->vecSize = Vector2D(mode->width, mode->height);
@@ -2075,14 +2079,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
bool set10bit = false;
pMonitor->drmFormat = DRM_FORMAT_INVALID;
- for (auto& fmt : formats[(int)!pMonitorRule->enable10bit]) {
+ for (auto& fmt : formats[(int)!RULE->enable10bit]) {
wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second);
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
} else {
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
- if (pMonitorRule->enable10bit && fmt.first.contains("101010"))
+ if (RULE->enable10bit && fmt.first.contains("101010"))
set10bit = true;
pMonitor->drmFormat = fmt.second;
@@ -2146,7 +2150,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY, bool force) {
m_bCursorHasSurface = surf;
- if ((surf == m_sLastCursorData.surf || m_bCursorHidden) && !force)
+ if ((surf == m_sLastCursorData.surf || m_bCursorHidden) && hotspotX == m_sLastCursorData.hotspotX && hotspotY == m_sLastCursorData.hotspotY && !force)
return;
m_sLastCursorData.name = "";
@@ -2356,6 +2360,9 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) {
void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) {
pMonitor->solitaryClient = nullptr; // reset it, if we find one it will be set.
+ if (g_pHyprNotificationOverlay->hasAny())
+ return;
+
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace);
if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID ||