From 7fd01a1f16c5b62a767ba1c4e2f0787d1545f946 Mon Sep 17 00:00:00 2001 From: Alessio Molinari Date: Sun, 17 Nov 2024 12:29:14 +0000 Subject: [PATCH 1/2] feat: listen to new monitor events --- include/VirtualDeskManager.hpp | 2 +- src/VirtualDeskManager.cpp | 8 +-- src/main.cpp | 97 ++++++++++++++++++++-------------- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/include/VirtualDeskManager.hpp b/include/VirtualDeskManager.hpp index 3066ab0..172d01d 100644 --- a/include/VirtualDeskManager.hpp +++ b/include/VirtualDeskManager.hpp @@ -30,12 +30,12 @@ class VirtualDeskManager { int prevDeskId(bool backwardCycle); int nextDeskId(bool cycle); int getDeskIdFromName(const std::string& name, bool createIfNotFound = true); + CSharedPointer getFocusedMonitor(); private: int m_activeDeskKey = 1; bool confLoaded = false; void cycleWorkspaces(); - CSharedPointer getCurrentMonitor(); std::shared_ptr getOrCreateVdesk(int vdeskId); }; #endif diff --git a/src/VirtualDeskManager.cpp b/src/VirtualDeskManager.cpp index 391a125..fee9b26 100644 --- a/src/VirtualDeskManager.cpp +++ b/src/VirtualDeskManager.cpp @@ -57,7 +57,7 @@ void VirtualDeskManager::applyCurrentVDesk() { } if (isVerbose()) printLog("applying vdesk" + activeVdesk()->name); - auto currentMonitor = getCurrentMonitor(); + auto currentMonitor = getFocusedMonitor(); auto layout = activeVdesk()->activeLayout(conf); PHLWORKSPACE focusedWorkspace = nullptr; for (const auto& [lmon, workspaceId] : layout) { @@ -177,7 +177,7 @@ void VirtualDeskManager::cycleWorkspaces() { if (!**PCYCLEWORKSPACES) return; - auto n_monitors = g_pCompositor->m_vMonitors.size(); + auto n_monitors = g_pCompositor->m_vMonitors.size(); CSharedPointer currentMonitor = g_pCompositor->m_pLastMonitor.lock(); // TODO: implement for more than two monitors as well. @@ -280,7 +280,7 @@ void VirtualDeskManager::invalidateAllLayouts() { } } -CSharedPointer VirtualDeskManager::getCurrentMonitor() { +CSharedPointer VirtualDeskManager::getFocusedMonitor() { CWeakPointer currentMonitor = g_pCompositor->m_pLastMonitor; // This can happen when we receive the "on disconnect" signal // let's just take first monitor we can find @@ -292,4 +292,4 @@ CSharedPointer VirtualDeskManager::getCurrentMonitor() { return nullptr; } return currentMonitor.lock(); -} \ No newline at end of file +} diff --git a/src/main.cpp b/src/main.cpp index ea8fff6..c7d21c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,21 +16,20 @@ using namespace Hyprutils::Memory; -static CSharedPointer onWorkspaceChangeHook = nullptr; -static CSharedPointer onWindowOpenHook = nullptr; -static CSharedPointer onConfigReloadedHook = nullptr; - -inline CFunctionHook* g_pMonitorConnectHook = nullptr; -inline CFunctionHook* g_pMonitorDisconnectHook = nullptr; -typedef void (*origMonitorConnect)(void*, bool); -typedef void (*origMonitorDisconnect)(void*, bool); - -std::unique_ptr manager = std::make_unique(); -std::vector stickyRules; -bool notifiedInit = false; -bool monitorLayoutChanging = false; - -void parseNamesConf(std::string& conf) { +static CSharedPointer onWorkspaceChangeHook = nullptr; +static CSharedPointer onWindowOpenHook = nullptr; +static CSharedPointer onConfigReloadedHook = nullptr; +static CSharedPointer onPreMonitorAddedHook = nullptr; +static CSharedPointer onMonitorAddedHook = nullptr; +static CSharedPointer onPreMonitorRemovedHook = nullptr; +static CSharedPointer onMonitorRemovedHook = nullptr; + +std::unique_ptr manager = std::make_unique(); +std::vector stickyRules; +bool notifiedInit = false; +bool monitorLayoutChanging = false; + +void parseNamesConf(std::string& conf) { size_t pos; size_t delim; std::string rule; @@ -275,34 +274,46 @@ void resetVDeskDispatch(std::string arg) { void onWorkspaceChange(void*, SCallbackInfo&, std::any val) { if (monitorLayoutChanging) return; - auto workspace = std::any_cast(val); - WORKSPACEID workspaceID = std::any_cast(val)->m_iID; + auto workspace = std::any_cast(val); + WORKSPACEID workspaceID = std::any_cast(val)->m_iID; - auto monitor = workspace->m_pMonitor.lock(); + auto monitor = workspace->m_pMonitor.lock(); if (!monitor || !monitor->m_bEnabled) return; manager->activeVdesk()->changeWorkspaceOnMonitor(workspaceID, monitor); - if (isVerbose()) - printLog("workspace changed: workspace id " + std::to_string(workspaceID) + "; on monitor " + std::to_string(monitor->ID)); + if (isVerbose()) { + auto vdesk = manager->activeVdesk(); + printLog("workspace changed on vdesk " + std::to_string(vdesk->id) + ": workspace id " + std::to_string(workspaceID) + "; on monitor " + std::to_string(monitor->ID)); + } } void onWindowOpen(void*, SCallbackInfo&, std::any val) { auto window = std::any_cast(val); - int vdesk = StickyApps::matchRuleOnWindow(stickyRules, manager, window); + int vdesk = StickyApps::matchRuleOnWindow(stickyRules, manager, window); if (vdesk > 0) manager->changeActiveDesk(vdesk, true); } -void hookMonitorDisconnect(void* thisptr, bool destroy) { +void onPreMonitorRemoved(void*, SCallbackInfo&, std::any val) { + CSharedPointer monitor = std::any_cast>(val); + if (monitor->szName == std::string("HEADLESS-1")) { + return; + } + if (isVerbose()) + printLog("Monitor PRE disconnect called with disabled monitor " + monitor->szName); monitorLayoutChanging = true; - (*(origMonitorDisconnect)g_pMonitorDisconnectHook->m_pOriginal)(thisptr, destroy); - monitorLayoutChanging = false; +} - CSharedPointer monitor = CSharedPointer(static_cast(thisptr)); +void onMonitorRemoved(void*, SCallbackInfo&, std::any val) { + CSharedPointer monitor = std::any_cast>(val); + if (monitor->szName == std::string("HEADLESS-1")) { + return; + } if (isVerbose()) printLog("Monitor disconnect called with disabled monitor " + monitor->szName); if (!currentlyEnabledMonitors(monitor).empty()) { + monitorLayoutChanging = false; manager->invalidateAllLayouts(); manager->deleteInvalidMonitorsOnAllVdesks(monitor); manager->applyCurrentVDesk(); @@ -310,15 +321,24 @@ void hookMonitorDisconnect(void* thisptr, bool destroy) { } } -void hookMonitorConnect(void* thisptr, bool noRule) { +void onPreMonitorAdded(void*, SCallbackInfo&, std::any val) { + CSharedPointer monitor = std::any_cast>(val); + if (monitor->szName == std::string("HEADLESS-1")) { + return; + } + if (isVerbose()) + printLog("Monitor PRE connect called with monitor " + monitor->szName); monitorLayoutChanging = true; - (*(origMonitorConnect)g_pMonitorConnectHook->m_pOriginal)(thisptr, noRule); - monitorLayoutChanging = false; +} - CSharedPointer monitor = CSharedPointer(static_cast(thisptr)); +void onMonitorAdded(void*, SCallbackInfo&, std::any val) { + CSharedPointer monitor = std::any_cast>(val); if (monitor->szName == std::string("HEADLESS-1")) { return; } + if (isVerbose()) + printLog("Monitor connect called with monitor " + monitor->szName); + monitorLayoutChanging = false; manager->invalidateAllLayouts(); manager->deleteInvalidMonitorsOnAllVdesks(); manager->applyCurrentVDesk(); @@ -402,18 +422,13 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { // Keywords HyprlandAPI::addConfigKeyword(PHANDLE, STICKY_RULES_KEYW, parseStickyRule, Hyprlang::SHandlerOptions{}); - onWorkspaceChangeHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "workspace", onWorkspaceChange); - onWindowOpenHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", onWindowOpen); - onConfigReloadedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "configReloaded", onConfigReloaded); - - // Function hooks - static const auto METHODS_CONNECT = HyprlandAPI::findFunctionsByName(PHANDLE, "onConnect"); - g_pMonitorConnectHook = HyprlandAPI::createFunctionHook(handle, METHODS_CONNECT[0].address, (void*)&hookMonitorConnect); - g_pMonitorConnectHook->hook(); - - static const auto METHODS_DISCONNECT = HyprlandAPI::findFunctionsByName(PHANDLE, "onDisconnect"); - g_pMonitorDisconnectHook = HyprlandAPI::createFunctionHook(handle, METHODS_DISCONNECT[0].address, (void*)&hookMonitorDisconnect); - g_pMonitorDisconnectHook->hook(); + onWorkspaceChangeHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "workspace", onWorkspaceChange); + onWindowOpenHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", onWindowOpen); + onConfigReloadedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "configReloaded", onConfigReloaded); + onPreMonitorAddedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "preMonitorAdded", onPreMonitorAdded); + onPreMonitorRemovedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "preMonitorRemoved", onPreMonitorRemoved); + onMonitorAddedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "monitorAdded", onMonitorAdded); + onMonitorRemovedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "monitorRemoved", onMonitorRemoved); registerHyprctlCommands(); From bc038f2683107e8fca2ed328f80e5aecb4280b0d Mon Sep 17 00:00:00 2001 From: Alessio Molinari Date: Mon, 18 Nov 2024 09:18:29 +0100 Subject: [PATCH 2/2] refactor: move internal getter to private again --- include/VirtualDeskManager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/VirtualDeskManager.hpp b/include/VirtualDeskManager.hpp index 172d01d..0bd78fc 100644 --- a/include/VirtualDeskManager.hpp +++ b/include/VirtualDeskManager.hpp @@ -30,12 +30,12 @@ class VirtualDeskManager { int prevDeskId(bool backwardCycle); int nextDeskId(bool cycle); int getDeskIdFromName(const std::string& name, bool createIfNotFound = true); - CSharedPointer getFocusedMonitor(); private: int m_activeDeskKey = 1; bool confLoaded = false; void cycleWorkspaces(); std::shared_ptr getOrCreateVdesk(int vdeskId); + CSharedPointer getFocusedMonitor(); }; #endif