From d6c2553af2fc42b3ea61a1bd5f6e2cc395deccbe Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:56:33 +0100 Subject: [PATCH] start handling monitors --- example/hyprland.conf | 2 + src/Compositor.hpp | 6 ++- src/config/ConfigManager.cpp | 77 ++++++++++++++++++++++++++++++++++++ src/config/ConfigManager.hpp | 14 +++++++ src/events/Events.cpp | 54 +++++++++++++++++++++++-- src/events/Events.hpp | 3 ++ src/helpers/Monitor.hpp | 17 ++++++++ src/input/InputManager.cpp | 7 +++- src/input/InputManager.hpp | 2 +- 9 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 src/helpers/Monitor.hpp diff --git a/example/hyprland.conf b/example/hyprland.conf index 72de4d5e..46bc1a1b 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -3,6 +3,8 @@ # # Refer to the wiki for more information. +monitor=,1280x720,0x0,0.5,1 + general { max_fps=240 gaps_in=5 diff --git a/src/Compositor.hpp b/src/Compositor.hpp index b2ec10a2..149321ac 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "defines.hpp" #include "debug/Log.hpp" @@ -8,6 +9,7 @@ #include "config/ConfigManager.hpp" #include "ManagerThread.hpp" #include "input/InputManager.hpp" +#include "helpers/Monitor.hpp" class CCompositor { public: @@ -36,7 +38,9 @@ public: const char* m_szWLDisplaySocket; - void startCompositor(); + std::deque m_vMonitors; + + void startCompositor(); }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index eccad341..47255651 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -66,6 +66,52 @@ void CConfigManager::handleRawExec(const std::string& command, const std::string } } +void CConfigManager::handleMonitor(const std::string& command, const std::string& args) { + + // get the monitor config + SMonitorRule newrule; + + std::string curitem = ""; + + std::string argZ = args; + + auto nextItem = [&]() { + auto idx = argZ.find_first_of(','); + + if (idx != std::string::npos) { + curitem = argZ.substr(0, idx); + argZ = argZ.substr(idx + 1); + } else { + argZ = ""; + curitem = argZ; + } + }; + + nextItem(); + + newrule.name = curitem; + + nextItem(); + + newrule.resolution.x = stoi(curitem.substr(0, curitem.find_first_of('x'))); + newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1)); + + nextItem(); + + newrule.offset.x = stoi(curitem.substr(0, curitem.find_first_of('x'))); + newrule.offset.y = stoi(curitem.substr(curitem.find_first_of('x') + 1)); + + nextItem(); + + newrule.mfact = stof(curitem); + + nextItem(); + + newrule.scale = stof(curitem); + + m_dMonitorRules.push_back(newrule); +} + void CConfigManager::parseLine(std::string& line) { // first check if its not a comment const auto COMMENTSTART = line.find_first_of('#'); @@ -111,6 +157,9 @@ void CConfigManager::parseLine(std::string& line) { handleRawExec(COMMAND, VALUE); return; } + } else if (COMMAND == "monitor") { + handleMonitor(COMMAND, VALUE); + return; } configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); @@ -121,6 +170,8 @@ void CConfigManager::loadConfigLoadVars() { parseError = ""; // reset the error currentCategory = ""; // reset the category + m_dMonitorRules.clear(); + const char* const ENVHOME = getenv("HOME"); const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf"); @@ -199,3 +250,29 @@ float CConfigManager::getFloat(std::string v) { std::string CConfigManager::getString(std::string v) { return getConfigValueSafe(v).strValue; } + +SMonitorRule CConfigManager::getMonitorRuleFor(std::string name) { + SMonitorRule* found = nullptr; + + for (auto& r : m_dMonitorRules) { + if (r.name == name) { + found = &r; + break; + } + } + + if (found) + return *found; + + for (auto& r : m_dMonitorRules) { + if (r.name == "") { + found = &r; + break; + } + } + + if (found) + return *found; + + return SMonitorRule{.name = "", .resolution = Vector2D(1280, 720), .offset = Vector2D(0, 0), .mfact = 0.5f, .scale = 1}; +} \ No newline at end of file diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 5e58173a..eda06044 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -5,6 +5,7 @@ #include #include "../defines.hpp" #include +#include struct SConfigValue { int64_t intValue = -1; @@ -12,6 +13,14 @@ struct SConfigValue { std::string strValue = ""; }; +struct SMonitorRule { + std::string name = ""; + Vector2D resolution = Vector2D(1280,720); + Vector2D offset = Vector2D(0,0); + float mfact = 0.5; + float scale = 1; +}; + class CConfigManager { public: CConfigManager(); @@ -22,6 +31,8 @@ public: float getFloat(std::string); std::string getString(std::string); + SMonitorRule getMonitorRuleFor(std::string); + private: std::unordered_map configValues; time_t lastModifyTime = 0; // for reloading the config if changed @@ -32,12 +43,15 @@ private: bool isFirstLaunch = true; // For exec-once + std::deque m_dMonitorRules; + // internal methods void loadConfigLoadVars(); SConfigValue getConfigValueSafe(std::string); void parseLine(std::string&); void configSetValueSafe(const std::string&, const std::string&); void handleRawExec(const std::string&, const std::string&); + void handleMonitor(const std::string&, const std::string&); }; inline std::unique_ptr g_pConfigManager; \ No newline at end of file diff --git a/src/events/Events.cpp b/src/events/Events.cpp index a5b093f0..8bdaa232 100644 --- a/src/events/Events.cpp +++ b/src/events/Events.cpp @@ -1,11 +1,61 @@ #include "Events.hpp" #include "../input/InputManager.hpp" +#include "../Compositor.hpp" void Events::listener_activate(wl_listener* listener, void* data) { } void Events::listener_change(wl_listener* listener, void* data) { + // layout got changed, let's update monitors. + const auto CONFIG = wlr_output_configuration_v1_create(); + + const auto GEOMETRY = wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, NULL); +} + +void Events::listener_newOutput(wl_listener* listener, void* data) { + // new monitor added, let's accomodate for that. + const auto OUTPUT = (wlr_output*)data; + + SMonitor newMonitor; + + wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer); + + // get monitor rule that matches + SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name); + + wlr_output_set_scale(OUTPUT, monitorRule.scale); + wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale); + wlr_output_set_transform(OUTPUT, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms + + wlr_output_set_mode(OUTPUT, wlr_output_preferred_mode(OUTPUT)); + wlr_output_enable_adaptive_sync(OUTPUT, 1); + + wl_signal_add(&OUTPUT->events.frame, &Events::listen_monitorFrame); + wl_signal_add(&OUTPUT->events.destroy, &Events::listen_monitorDestroy); + + wlr_output_enable(OUTPUT, 1); + if (!wlr_output_commit(OUTPUT)) { + Debug::log(ERR, "Couldn't commit output named %s", OUTPUT->name); + return; + } + + wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, OUTPUT, monitorRule.offset.x, monitorRule.offset.y); + + // add new monitor to our internal arr + newMonitor.ID = g_pCompositor->m_vMonitors.size(); + newMonitor.szName = OUTPUT->name; + newMonitor.vecPosition = monitorRule.offset; + newMonitor.vecSize = monitorRule.resolution; + + g_pCompositor->m_vMonitors.push_back(newMonitor); +} + +void Events::listener_monitorFrame(wl_listener* listener, void* data) { + +} + +void Events::listener_monitorDestroy(wl_listener* listener, void* data) { } @@ -41,10 +91,6 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) { } -void Events::listener_newOutput(wl_listener* listener, void* data) { - -} - void Events::listener_newXDGSurface(wl_listener* listener, void* data) { } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 7bd24e60..ac77257f 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -22,4 +22,7 @@ namespace Events { LISTENER(outputMgrApply); LISTENER(outputMgrTest); + + LISTENER(monitorFrame); + LISTENER(monitorDestroy); }; \ No newline at end of file diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp new file mode 100644 index 00000000..6931db1e --- /dev/null +++ b/src/helpers/Monitor.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "../defines.hpp" + +struct SMonitor { + Vector2D vecPosition = Vector2D(0,0); + Vector2D vecSize = Vector2D(0,0); + + bool primary = false; + + int ID = -1; + + std::string szName = ""; + + Vector2D vecReservedTopLeft = Vector2D(0,0); + Vector2D vecReservedBottomRight = Vector2D(0,0); +}; \ No newline at end of file diff --git a/src/input/InputManager.cpp b/src/input/InputManager.cpp index 3140e22d..4e099593 100644 --- a/src/input/InputManager.cpp +++ b/src/input/InputManager.cpp @@ -14,4 +14,9 @@ void CInputManager::onMouseMoved(wlr_event_pointer_motion* e) { wlr_cursor_move(g_pCompositor->m_sWLRCursor, e->device, delta.floor().x, delta.floor().y); } -} \ No newline at end of file +} + +void CInputManager::onMouseWarp(wlr_event_pointer_motion_absolute* e) { + wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, e->device, e->x, e->y); +} + diff --git a/src/input/InputManager.hpp b/src/input/InputManager.hpp index 38ec419a..10492732 100644 --- a/src/input/InputManager.hpp +++ b/src/input/InputManager.hpp @@ -6,7 +6,7 @@ class CInputManager { public: void onMouseMoved(wlr_event_pointer_motion*); - void onMouseButton(int); + void onMouseWarp(wlr_event_pointer_motion_absolute*); private: Vector2D m_vMouseCoords = Vector2D(0,0);