feature: multi-monitor support

This commit is contained in:
sandwich 2025-10-12 13:32:51 +02:00
parent 63cd656fc3
commit ee9d20498d
2 changed files with 68 additions and 14 deletions

View file

@ -126,6 +126,36 @@ static void failNotif(const std::string& reason) {
HyprlandAPI::addNotification(PHANDLE, "[hyprexpo] Failure in initialization: " + reason, CHyprColor{1.0, 0.2, 0.2, 1.0}, 5000);
}
static Hyprlang::CParseResult workspaceMethodKeyword(const char* LHS, const char* RHS) {
Hyprlang::CParseResult result;
if (g_unloading)
return result;
// Parse format: "workspace_method = MONITOR_NAME method workspace"
// Example: "workspace_method = DP-1 first 19"
CConstVarList data(RHS);
if (data.size() < 3) {
result.setError("workspace_method requires format: MONITOR_NAME <center|first> <workspace>");
return result;
}
const std::string monitorName = std::string{data[0]};
const std::string methodType = std::string{data[1]};
const std::string workspace = std::string{data[2]};
if (methodType != "center" && methodType != "first") {
result.setError(std::format("Invalid method type '{}', expected 'center' or 'first'", methodType).c_str());
return result;
}
// Store in global map
g_monitorWorkspaceMethods[monitorName] = methodType + " " + workspace;
return result;
}
static Hyprlang::CParseResult expoGestureKeyword(const char* LHS, const char* RHS) {
Hyprlang::CParseResult result;
@ -257,7 +287,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
HyprlandAPI::addDispatcherV2(PHANDLE, "hyprexpo:kb_select", ::onKbSelectTokenDispatcher);
HyprlandAPI::addDispatcherV2(PHANDLE, "hyprexpo:kb_selecti", ::onKbSelectIndexDispatcher);
HyprlandAPI::addConfigKeyword(PHANDLE, "hyprexpo-gesture", ::expoGestureKeyword, {});
HyprlandAPI::addConfigKeyword(PHANDLE, "hyprexpo_gesture", ::expoGestureKeyword, {});
HyprlandAPI::addConfigKeyword(PHANDLE, "workspace_method", ::workspaceMethodKeyword, {});
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:columns", Hyprlang::INT{3});
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:gaps_in", Hyprlang::INT{5});

View file

@ -243,6 +243,40 @@ static void removeOverview(WP<Hyprutils::Animation::CBaseAnimatedVariable> thisp
g_pOverview.reset();
}
// Get workspace method configuration for a specific monitor
// Returns pair of {isCenter, startWorkspaceID}
static std::pair<bool, int> getWorkspaceMethodForMonitor(PHLMONITOR monitor) {
static auto const* PMETHOD = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:workspace_method")->getDataStaticPtr();
// Try to get monitor-specific config from global map first
const std::string monitorName = monitor->m_name;
std::string methodStr;
auto it = g_monitorWorkspaceMethods.find(monitorName);
if (it != g_monitorWorkspaceMethods.end()) {
methodStr = it->second;
} else {
// Use global config
methodStr = std::string{*PMETHOD};
}
// Parse the method string
bool methodCenter = true;
int methodStartID = monitor->activeWorkspaceID();
CVarList method{methodStr, 0, 's', true};
if (method.size() < 2) {
Debug::log(ERR, "[he] invalid workspace_method for monitor {}: {}", monitorName, methodStr);
} else {
methodCenter = method[0] == "center";
methodStartID = getWorkspaceIDNameFromString(method[1]).id;
if (methodStartID == WORKSPACE_INVALID)
methodStartID = monitor->activeWorkspaceID();
}
return {methodCenter, methodStartID};
}
COverview::~COverview() {
g_pHyprRenderer->makeEGLCurrent();
images.clear(); // otherwise we get a vram leak
@ -259,24 +293,13 @@ COverview::COverview(PHLWORKSPACE startedOn_, bool swipe_) : startedOn(startedOn
static auto* const* PGAPS = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:gaps_in")->getDataStaticPtr();
static auto* const* PCOL = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:bg_col")->getDataStaticPtr();
static auto* const* PSKIP = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:skip_empty")->getDataStaticPtr();
static auto const* PMETHOD = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:workspace_method")->getDataStaticPtr();
SIDE_LENGTH = **PCOLUMNS;
GAP_WIDTH = **PGAPS;
BG_COLOR = **PCOL;
// process the method
bool methodCenter = true;
int methodStartID = pMonitor->activeWorkspaceID();
CVarList method{*PMETHOD, 0, 's', true};
if (method.size() < 2)
Debug::log(ERR, "[he] invalid workspace_method");
else {
methodCenter = method[0] == "center";
methodStartID = getWorkspaceIDNameFromString(method[1]).id;
if (methodStartID == WORKSPACE_INVALID)
methodStartID = pMonitor->activeWorkspaceID();
}
// Get workspace method for this specific monitor
auto [methodCenter, methodStartID] = getWorkspaceMethodForMonitor(pMonitor.lock());
images.resize(SIDE_LENGTH * SIDE_LENGTH);