mirror of
https://github.com/levnikmyskin/hyprland-virtual-desktops.git
synced 2024-10-04 06:17:11 +03:00
Merge pull request #19 from levnikmyskin/feat/vdesk_pinned_clients
Implement new stickyrule feature
This commit is contained in:
commit
3dca522d78
29
README.md
29
README.md
@ -9,6 +9,9 @@
|
||||
- [It's just workspaces, really](#its-just-workspaces-really)
|
||||
- [Hyprctl dispatchers](#hyprctl-dispatchers)
|
||||
- [Mix with Hyprland native workspaces](#mix-with-hyprland-native-workspaces)
|
||||
- [Hyprland keywords](#hyprland-keywords)
|
||||
- [Syntax](#syntax)
|
||||
- [Examples](#examples)
|
||||
- [Configuration values](#configuration-values)
|
||||
- [Example config](#example-config)
|
||||
- [Layouts](#layouts)
|
||||
@ -103,6 +106,29 @@ to the same vdesk given the same number of monitors, unless you focus (e.g. with
|
||||
|
||||
The vdesk a workspace will end up to is easily computed by doing `ceil(workspace_id / n_monitors)`. You know where I'm going with this one...you can easily script it.
|
||||
|
||||
### Hyprland keywords
|
||||
Since version 2.2, this plugin exposes one keyword: `stickyrule`.
|
||||
A sticky rule is composed of a window identifier and a vdesk identifier.
|
||||
A window matched by a sticky rule will be moved to the matched vdesk:
|
||||
1. When the window is created (similar to [Hyprland's `workspace` windowrule](https://wiki.hyprland.org/Configuring/Window-Rules/#window-rules-v2), but with virtual desks);
|
||||
2. Every time a monitor is connected/disconnected.
|
||||
|
||||
**BE CAREFUL**:
|
||||
1. **NOT** to mix this with Hyprland's `workspace` windowrule (it wouldn't make sense right?);
|
||||
2. This is not a plugin config, but an Hyprland keyword. Place it in the top level of Hyprland's config (i.e., where you'd put windowrules too).
|
||||
|
||||
#### Syntax
|
||||
```bash
|
||||
stickyrule = window,vdesk
|
||||
```
|
||||
- `window` identifier has the same syntax as [Hyprland's windowrule window](https://wiki.hyprland.org/Configuring/Window-Rules/#window-rules-v2) identifier;
|
||||
- `vdesk` identifier has the same syntax specified above.
|
||||
|
||||
#### Examples
|
||||
`stickyrule = class:^(kittysticky)$,3`
|
||||
`stickyrule = title:thunderbird,mail`
|
||||
|
||||
|
||||
|
||||
### Configuration values
|
||||
|
||||
@ -122,6 +148,9 @@ This plugin exposes a few configuration options, under the `plugin:virtual-deskt
|
||||
|
||||
#### Example config
|
||||
```ini
|
||||
stickyrule = class:^(kittysticky)$,3
|
||||
stickyrule = title:thunderbird,mail
|
||||
|
||||
plugin {
|
||||
virtual-desktops {
|
||||
names = 1:coding, 2:internet, 3:mail and chats
|
||||
|
@ -39,6 +39,7 @@ class VirtualDesk {
|
||||
void deleteInvalidMonitorsOnActiveLayout();
|
||||
void deleteInvalidMonitorOnAllLayouts(const CMonitor*);
|
||||
static std::shared_ptr<CMonitor> firstAvailableMonitor(const std::vector<std::shared_ptr<CMonitor>>&);
|
||||
bool isWorkspaceOnActiveLayout(int workspaceId);
|
||||
|
||||
private:
|
||||
int m_activeLayout_idx;
|
||||
|
@ -29,12 +29,13 @@ class VirtualDeskManager {
|
||||
void deleteInvalidMonitorsOnAllVdesks();
|
||||
int prevDeskId(bool backwardCycle);
|
||||
int nextDeskId(bool cycle);
|
||||
int getDeskIdFromName(const std::string& name, bool createIfNotFound = true);
|
||||
|
||||
private:
|
||||
int m_activeDeskKey = 1;
|
||||
bool confLoaded = false;
|
||||
void cycleWorkspaces();
|
||||
int getDeskIdFromName(const std::string& name, bool createIfNotFound = true);
|
||||
CMonitor* getCurrentMonitor();
|
||||
int m_activeDeskKey = 1;
|
||||
bool confLoaded = false;
|
||||
void cycleWorkspaces();
|
||||
CMonitor* getCurrentMonitor();
|
||||
std::shared_ptr<VirtualDesk> getOrCreateVdesk(int vdeskId);
|
||||
};
|
||||
#endif
|
||||
|
33
include/sticky_apps.hpp
Normal file
33
include/sticky_apps.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef STICKYAPPS_H
|
||||
#define STICKYAPPS_H
|
||||
#include <string>
|
||||
#include <VirtualDeskManager.hpp>
|
||||
|
||||
const std::string TITLE = "title";
|
||||
const std::string INITIAL_TITLE = "initialTitle";
|
||||
const std::string CLASS = "class";
|
||||
const std::string INITIAL_CLASS = "initialClass";
|
||||
|
||||
namespace StickyApps {
|
||||
struct SStickyRule {
|
||||
int vdesk;
|
||||
std::string property;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
bool parseRule(const std::string&, SStickyRule&, std::unique_ptr<VirtualDeskManager>&);
|
||||
|
||||
bool parseWindowRule(const std::string&, SStickyRule&);
|
||||
|
||||
void matchRules(const std::vector<SStickyRule>&, std::unique_ptr<VirtualDeskManager>&);
|
||||
|
||||
int matchRuleOnWindow(const std::vector<SStickyRule>&, std::unique_ptr<VirtualDeskManager>&, CWindow*);
|
||||
|
||||
const std::string extractProperty(const SStickyRule&, std::unique_ptr<CWindow>&);
|
||||
const std::string extractProperty(const SStickyRule&, CWindow*);
|
||||
|
||||
bool ruleMatch(const std::string&, const std::string&);
|
||||
}
|
||||
#endif
|
@ -13,7 +13,10 @@ const std::string CYCLEWORKSPACES_CONF = "plugin:virtual-desktops:cycleworkspa
|
||||
const std::string REMEMBER_LAYOUT_CONF = "plugin:virtual-desktops:rememberlayout";
|
||||
const std::string NOTIFY_INIT = "plugin:virtual-desktops:notifyinit";
|
||||
const std::string VERBOSE_LOGS = "plugin:virtual-desktops:verbose_logging";
|
||||
const std::string VDESK_DISPATCH_STR = "vdesk";
|
||||
|
||||
const std::string STICKY_RULES_KEYW = "stickyrule";
|
||||
|
||||
const std::string VDESK_DISPATCH_STR = "vdesk";
|
||||
|
||||
const std::string MOVETODESK_DISPATCH_STR = "movetodesk";
|
||||
const std::string MOVETOLASTDESK_DISPATCH_STR = "movetolastdesk";
|
||||
@ -52,5 +55,9 @@ std::string parseMoveDispatch(std::string& arg);
|
||||
bool extractBool(std::string& arg);
|
||||
std::vector<std::shared_ptr<CMonitor>> currentlyEnabledMonitors(const CMonitor* exclude = nullptr);
|
||||
|
||||
std::string ltrim(const std::string& s);
|
||||
std::string rtrim(const std::string& s);
|
||||
std::string trim(const std::string& s);
|
||||
|
||||
bool isVerbose();
|
||||
#endif
|
||||
|
@ -130,6 +130,14 @@ std::shared_ptr<CMonitor> VirtualDesk::firstAvailableMonitor(const std::vector<s
|
||||
return newMonitor;
|
||||
}
|
||||
|
||||
bool VirtualDesk::isWorkspaceOnActiveLayout(int workspaceId) {
|
||||
for (auto [_, wid] : layouts[m_activeLayout_idx]) {
|
||||
if (workspaceId == wid)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VirtualDesk::checkAndAdaptLayout(Layout* layout, const CMonitor* exclude) {
|
||||
auto enabledMons = currentlyEnabledMonitors(exclude);
|
||||
if (enabledMons.size() == 0)
|
||||
|
@ -4,9 +4,8 @@
|
||||
#include <ranges>
|
||||
|
||||
VirtualDeskManager::VirtualDeskManager() {
|
||||
this->conf = RememberLayoutConf::size;
|
||||
vdeskNamesMap[1] = "1";
|
||||
vdesksMap[1] = std::make_shared<VirtualDesk>();
|
||||
this->conf = RememberLayoutConf::size;
|
||||
getOrCreateVdesk(1);
|
||||
}
|
||||
|
||||
const std::shared_ptr<VirtualDesk>& VirtualDeskManager::activeVdesk() {
|
||||
@ -28,13 +27,7 @@ void VirtualDeskManager::changeActiveDesk(int vdeskId, bool apply) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vdesksMap.contains(vdeskId)) {
|
||||
if (isVerbose())
|
||||
printLog("creating new vdesk with id " + std::to_string(vdeskId));
|
||||
if (!vdeskNamesMap.contains(vdeskId))
|
||||
vdeskNamesMap[vdeskId] = std::to_string(vdeskId);
|
||||
vdesksMap[vdeskId] = std::make_shared<VirtualDesk>(vdeskId, vdeskNamesMap[vdeskId]);
|
||||
}
|
||||
getOrCreateVdesk(vdeskId);
|
||||
lastDesk = activeVdesk()->id;
|
||||
m_activeDeskKey = vdeskId;
|
||||
if (apply)
|
||||
@ -64,9 +57,9 @@ void VirtualDeskManager::applyCurrentVDesk() {
|
||||
}
|
||||
if (isVerbose())
|
||||
printLog("applying vdesk" + activeVdesk()->name);
|
||||
auto currentMonitor = getCurrentMonitor();
|
||||
auto layout = activeVdesk()->activeLayout(conf);
|
||||
CWorkspace* focusedWorkspace;
|
||||
auto currentMonitor = getCurrentMonitor();
|
||||
auto layout = activeVdesk()->activeLayout(conf);
|
||||
CWorkspace* focusedWorkspace = nullptr;
|
||||
for (auto [lmon, workspaceId] : layout) {
|
||||
CMonitor* mon = g_pCompositor->getMonitorFromID(lmon->ID);
|
||||
if (!lmon || !lmon->m_bEnabled) {
|
||||
@ -95,7 +88,7 @@ void VirtualDeskManager::applyCurrentVDesk() {
|
||||
}
|
||||
mon->changeWorkspace(workspace, false);
|
||||
}
|
||||
if (currentMonitor)
|
||||
if (currentMonitor && focusedWorkspace)
|
||||
currentMonitor->changeWorkspace(focusedWorkspace, false);
|
||||
}
|
||||
|
||||
@ -118,10 +111,8 @@ int VirtualDeskManager::moveToDesk(std::string& arg, int vdeskId) {
|
||||
|
||||
if (isVerbose())
|
||||
printLog("creating new vdesk with id " + std::to_string(vdeskId));
|
||||
if (!vdeskNamesMap.contains(vdeskId))
|
||||
vdeskNamesMap[vdeskId] = std::to_string(vdeskId);
|
||||
|
||||
auto vdesk = vdesksMap[vdeskId] = std::make_shared<VirtualDesk>(vdeskId, vdeskNamesMap[vdeskId]);
|
||||
auto vdesk = getOrCreateVdesk(vdeskId);
|
||||
|
||||
auto* window = g_pCompositor->getWindowByRegex(arg);
|
||||
if (!window) {
|
||||
@ -164,8 +155,8 @@ int VirtualDeskManager::getDeskIdFromName(const std::string& name, bool createIf
|
||||
max_key = key;
|
||||
}
|
||||
if (!found && createIfNotFound) {
|
||||
vdesk = max_key + 1;
|
||||
vdeskNamesMap[vdesk] = name;
|
||||
vdesk = max_key + 1;
|
||||
getOrCreateVdesk(vdesk);
|
||||
}
|
||||
return vdesk;
|
||||
}
|
||||
@ -271,6 +262,18 @@ int VirtualDeskManager::nextDeskId(bool cycle) {
|
||||
return nextId;
|
||||
}
|
||||
|
||||
std::shared_ptr<VirtualDesk> VirtualDeskManager::getOrCreateVdesk(int vdeskId) {
|
||||
if (!vdeskNamesMap.contains(vdeskId))
|
||||
vdeskNamesMap[vdeskId] = std::to_string(vdeskId);
|
||||
if (!vdesksMap.contains(vdeskId)) {
|
||||
if (isVerbose())
|
||||
printLog("creating new vdesk with id " + std::to_string(vdeskId));
|
||||
auto vdesk = vdesksMap[vdeskId] = std::make_shared<VirtualDesk>(vdeskId, vdeskNamesMap[vdeskId]);
|
||||
return vdesk;
|
||||
}
|
||||
return vdesksMap[vdeskId];
|
||||
}
|
||||
|
||||
void VirtualDeskManager::invalidateAllLayouts() {
|
||||
for (const auto& [_, vdesk] : vdesksMap) {
|
||||
vdesk->invalidateActiveLayout();
|
||||
@ -281,9 +284,9 @@ CMonitor* VirtualDeskManager::getCurrentMonitor() {
|
||||
CMonitor* currentMonitor = g_pCompositor->m_pLastMonitor;
|
||||
// This can happen when we receive the "on disconnect" signal
|
||||
// let's just take first monitor we can find
|
||||
if (currentMonitor && !currentMonitor->m_bEnabled) {
|
||||
if (currentMonitor && (!currentMonitor->m_bEnabled || !currentMonitor->output)) {
|
||||
for (std::shared_ptr<CMonitor> mon : g_pCompositor->m_vMonitors) {
|
||||
if (mon->m_bEnabled)
|
||||
if (mon->m_bEnabled && mon->output)
|
||||
return mon.get();
|
||||
}
|
||||
return nullptr;
|
||||
|
48
src/main.cpp
48
src/main.cpp
@ -9,23 +9,25 @@
|
||||
#include "globals.hpp"
|
||||
#include "VirtualDeskManager.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "sticky_apps.hpp"
|
||||
|
||||
#include <any>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
static HOOK_CALLBACK_FN* onWorkspaceChangeHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onConfigReloadedHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onMonitorDisconnectHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onMonitorAddedHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onRenderHook = nullptr;
|
||||
std::unique_ptr<VirtualDeskManager> manager = std::make_unique<VirtualDeskManager>();
|
||||
bool notifiedInit = false;
|
||||
bool needsReloading = false;
|
||||
bool monitorLayoutChanging = false;
|
||||
static HOOK_CALLBACK_FN* onWorkspaceChangeHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onWindowOpenHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onConfigReloadedHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onMonitorDisconnectHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onMonitorAddedHook = nullptr;
|
||||
static HOOK_CALLBACK_FN* onRenderHook = nullptr;
|
||||
std::unique_ptr<VirtualDeskManager> manager = std::make_unique<VirtualDeskManager>();
|
||||
std::vector<StickyApps::SStickyRule> stickyRules;
|
||||
bool notifiedInit = false;
|
||||
bool needsReloading = false;
|
||||
bool monitorLayoutChanging = false;
|
||||
|
||||
inline CFunctionHook* g_pMonitorDestroy = nullptr;
|
||||
typedef void (*origMonitorDestroy)(void*, void*);
|
||||
|
||||
inline CFunctionHook* g_pMonitorAdded = nullptr;
|
||||
@ -58,6 +60,19 @@ void parseNamesConf(std::string& conf) {
|
||||
}
|
||||
}
|
||||
|
||||
Hyprlang::CParseResult parseStickyRule(const char* command, const char* value) {
|
||||
Hyprlang::CParseResult result;
|
||||
StickyApps::SStickyRule rule;
|
||||
std::string value_str = value;
|
||||
if (!StickyApps::parseRule(value_str, rule, manager)) {
|
||||
std::string err = std::format("Error in your sticky rule: {}", value);
|
||||
result.setError(err.c_str());
|
||||
} else {
|
||||
stickyRules.push_back(rule);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void virtualDeskDispatch(std::string arg) {
|
||||
manager->changeActiveDesk(arg, true);
|
||||
}
|
||||
@ -169,6 +184,7 @@ void resetVDeskDispatch(std::string arg) {
|
||||
manager->resetVdesk(arg);
|
||||
}
|
||||
manager->applyCurrentVDesk();
|
||||
StickyApps::matchRules(stickyRules, manager);
|
||||
}
|
||||
|
||||
void onWorkspaceChange(void*, SCallbackInfo&, std::any val) {
|
||||
@ -186,6 +202,13 @@ void onWorkspaceChange(void*, SCallbackInfo&, std::any val) {
|
||||
printLog("workspace changed: workspace id " + std::to_string(workspaceID) + "; on monitor " + std::to_string(workspace->m_iMonitorID));
|
||||
}
|
||||
|
||||
void onWindowOpen(void*, SCallbackInfo&, std::any val) {
|
||||
CWindow* window = std::any_cast<CWindow*>(val);
|
||||
int vdesk = StickyApps::matchRuleOnWindow(stickyRules, manager, window);
|
||||
if (vdesk > 0)
|
||||
manager->changeActiveDesk(vdesk, true);
|
||||
}
|
||||
|
||||
void onMonitorDisconnect(void*, SCallbackInfo&, std::any val) {
|
||||
CMonitor* monitor = std::any_cast<CMonitor*>(val);
|
||||
if (isVerbose())
|
||||
@ -213,6 +236,7 @@ void onRender(void*, SCallbackInfo&, std::any val) {
|
||||
if (needsReloading) {
|
||||
printLog("on render called and needs reloading");
|
||||
manager->applyCurrentVDesk();
|
||||
StickyApps::matchRules(stickyRules, manager);
|
||||
needsReloading = false;
|
||||
}
|
||||
}
|
||||
@ -267,7 +291,11 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||
HyprlandAPI::addConfigValue(PHANDLE, NOTIFY_INIT, Hyprlang::INT{1});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, VERBOSE_LOGS, Hyprlang::INT{0});
|
||||
|
||||
// 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);
|
||||
onMonitorDisconnectHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "monitorRemoved", onMonitorDisconnect);
|
||||
onMonitorAddedHook = HyprlandAPI::registerCallbackDynamic(PHANDLE, "monitorAdded", onMonitorAdded);
|
||||
|
98
src/sticky_apps.cpp
Normal file
98
src/sticky_apps.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "sticky_apps.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
bool StickyApps::parseRule(const std::string& rule, SStickyRule& sticky, std::unique_ptr<VirtualDeskManager>& vdeskManager) {
|
||||
auto comma_pos = rule.find(",");
|
||||
if (comma_pos == std::string::npos)
|
||||
return false;
|
||||
auto window = rule.substr(0, comma_pos);
|
||||
auto vdesk = rule.substr(comma_pos + 1, rule.length());
|
||||
|
||||
try {
|
||||
sticky.vdesk = std::stoi(vdesk);
|
||||
} catch (std::exception const& ex) { sticky.vdesk = vdeskManager->getDeskIdFromName(vdesk); }
|
||||
|
||||
return parseWindowRule(window, sticky);
|
||||
}
|
||||
|
||||
bool StickyApps::parseWindowRule(const std::string& rule, SStickyRule& sticky) {
|
||||
auto colon_pos = rule.find(":");
|
||||
if (colon_pos == std::string::npos)
|
||||
return false;
|
||||
auto property = trim(rule.substr(0, colon_pos));
|
||||
auto value = trim(rule.substr(colon_pos + 1, rule.length()));
|
||||
sticky.property = property;
|
||||
sticky.value = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StickyApps::matchRules(const std::vector<SStickyRule>& rules, std::unique_ptr<VirtualDeskManager>& vdeskManager) {
|
||||
for (auto& r : rules) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
auto windowProp = extractProperty(r, w);
|
||||
if (windowProp == "")
|
||||
continue;
|
||||
if (ruleMatch(r.value, windowProp)) {
|
||||
printLog(std::format("rule matched {}: {}", r.value, windowProp));
|
||||
auto windowPidFmt = std::format("pid:{}", w->getPID());
|
||||
auto map = vdeskManager->vdesksMap;
|
||||
if (map.contains(r.vdesk) && map[r.vdesk]->isWorkspaceOnActiveLayout(w->m_iWorkspaceID))
|
||||
continue;
|
||||
vdeskManager->moveToDesk(windowPidFmt, r.vdesk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int StickyApps::matchRuleOnWindow(const std::vector<SStickyRule>& rules, std::unique_ptr<VirtualDeskManager>& vdeskManager, CWindow* window) {
|
||||
for (auto& r : rules) {
|
||||
auto windowProp = extractProperty(r, window);
|
||||
if (windowProp == "")
|
||||
continue;
|
||||
if (ruleMatch(r.value, windowProp)) {
|
||||
printLog(std::format("rule matched {}: {}", r.value, windowProp));
|
||||
auto windowPidFmt = std::format("pid:{}", window->getPID());
|
||||
auto map = vdeskManager->vdesksMap;
|
||||
if (map.find(r.vdesk) != map.end() && map[r.vdesk]->isWorkspaceOnActiveLayout(window->m_iWorkspaceID))
|
||||
continue;
|
||||
vdeskManager->moveToDesk(windowPidFmt, r.vdesk);
|
||||
return r.vdesk;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string StickyApps::extractProperty(const SStickyRule& rule, std::unique_ptr<CWindow>& window) {
|
||||
if (rule.property == TITLE) {
|
||||
return g_pXWaylandManager->getTitle(window.get());
|
||||
} else if (rule.property == INITIAL_TITLE) {
|
||||
return window->m_szInitialTitle;
|
||||
} else if (rule.property == CLASS) {
|
||||
return g_pXWaylandManager->getAppIDClass(window.get());
|
||||
} else if (rule.property == INITIAL_CLASS) {
|
||||
return window->m_szInitialClass;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::string StickyApps::extractProperty(const SStickyRule& rule, CWindow* window) {
|
||||
if (rule.property == TITLE) {
|
||||
return g_pXWaylandManager->getTitle(window);
|
||||
} else if (rule.property == INITIAL_TITLE) {
|
||||
return window->m_szInitialTitle;
|
||||
} else if (rule.property == CLASS) {
|
||||
return g_pXWaylandManager->getAppIDClass(window);
|
||||
} else if (rule.property == INITIAL_CLASS) {
|
||||
return window->m_szInitialClass;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool StickyApps::ruleMatch(const std::string& rule, const std::string& str) {
|
||||
try {
|
||||
std::regex ruleRegex(rule);
|
||||
return std::regex_search(str, ruleRegex);
|
||||
} catch (...) { printLog(std::format("Regex error for sticky app rule: {}", rule)); }
|
||||
return false;
|
||||
}
|
@ -51,6 +51,9 @@ RememberLayoutConf layoutConfFromString(const std::string& conf) {
|
||||
}
|
||||
|
||||
bool isVerbose() {
|
||||
// this might happen if called before plugin is initalized
|
||||
if (!PHANDLE)
|
||||
return true;
|
||||
static auto* const PVERBOSELOGS = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, VERBOSE_LOGS)->getDataStaticPtr();
|
||||
return **PVERBOSELOGS;
|
||||
}
|
||||
@ -74,3 +77,17 @@ std::vector<std::shared_ptr<CMonitor>> currentlyEnabledMonitors(const CMonitor*
|
||||
});
|
||||
return monitors;
|
||||
}
|
||||
|
||||
std::string ltrim(const std::string& s) {
|
||||
size_t start = s.find_first_not_of(" ");
|
||||
return (start == std::string::npos) ? "" : s.substr(start);
|
||||
}
|
||||
|
||||
std::string rtrim(const std::string& s) {
|
||||
size_t end = s.find_last_not_of(" ");
|
||||
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
|
||||
}
|
||||
|
||||
std::string trim(const std::string& s) {
|
||||
return ltrim(rtrim(s));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user