summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2022-11-05 18:04:44 +0000
committervaxerski <43317083+vaxerski@users.noreply.github.com>2022-11-05 18:04:44 +0000
commit5a750b485aca8b2fd5545cfe86b3a48c69355d65 (patch)
treeb5624dc630450152a52889968805e2f7faee0c40 /src
parenta71f44baa521e2fb867db8536d7766e7d02f3e32 (diff)
Added creating / destroying outputs on a multi-backend + headless backend
See `hyprctl output`.
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.cpp9
-rw-r--r--src/Compositor.hpp1
-rw-r--r--src/debug/HyprCtl.cpp82
-rw-r--r--src/helpers/Monitor.cpp3
-rw-r--r--src/helpers/Monitor.hpp1
-rw-r--r--src/helpers/XWaylandStubs.hpp6
-rw-r--r--src/includes.hpp5
-rw-r--r--src/render/Renderer.cpp7
8 files changed, 113 insertions, 1 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 1b2341fd..60779420 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -180,6 +180,15 @@ CCompositor::CCompositor() {
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
+
+ m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLDisplay);
+
+ if (!m_sWLRHeadlessBackend) {
+ Debug::log(CRIT, "Couldn't create the headless backend");
+ throw std::runtime_error("wlr_headless_backend_create() failed!");
+ }
+
+ wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend);
}
CCompositor::~CCompositor() {
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 7264a00a..c5cc5127 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -71,6 +71,7 @@ public:
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
wlr_xdg_activation_v1* m_sWLRActivation;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
+ wlr_backend* m_sWLRHeadlessBackend;
// ------------------------------------------------- //
diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp
index 494efcd4..e0438c09 100644
--- a/src/debug/HyprCtl.cpp
+++ b/src/debug/HyprCtl.cpp
@@ -743,6 +743,86 @@ R"#(
}
}
+void createOutputIter(wlr_backend* backend, void* data) {
+ const auto DATA = (std::pair<std::string, bool>*)data;
+
+ if (DATA->second)
+ return;
+
+ if (DATA->first.empty() || DATA->first == "auto") {
+ if (wlr_backend_is_wl(backend)) {
+ wlr_wl_output_create(backend);
+ DATA->second = true;
+ } else if (wlr_backend_is_x11(backend)) {
+ wlr_x11_output_create(backend);
+ DATA->second = true;
+ } else if (wlr_backend_is_headless(backend)) {
+ wlr_headless_add_output(backend, 1920, 1080);
+ DATA->second = true;
+ }
+ } else {
+ if (wlr_backend_is_wl(backend) && DATA->first == "wayland") {
+ wlr_wl_output_create(backend);
+ DATA->second = true;
+ } else if (wlr_backend_is_x11(backend) && DATA->first == "x11") {
+ wlr_x11_output_create(backend);
+ DATA->second = true;
+ } else if (wlr_backend_is_headless(backend) && DATA->first == "headless") {
+ wlr_headless_add_output(backend, 1920, 1080);
+ DATA->second = true;
+ }
+ }
+}
+
+std::string dispatchOutput(std::string request) {
+ std::string curitem = "";
+
+ auto nextItem = [&]() {
+ auto idx = request.find_first_of(' ');
+
+ if (idx != std::string::npos) {
+ curitem = request.substr(0, idx);
+ request = request.substr(idx + 1);
+ } else {
+ curitem = request;
+ request = "";
+ }
+
+ curitem = removeBeginEndSpacesTabs(curitem);
+ };
+
+ nextItem();
+ nextItem();
+
+ const auto MODE = curitem;
+
+ nextItem();
+
+ const auto NAME = curitem;
+
+ if (MODE == "create" || MODE == "add") {
+ std::pair<std::string, bool> result = { NAME, false };
+
+ wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result);
+
+ if (!result.second)
+ return "no backend replied to the request";
+
+ } else if (MODE == "destroy" || MODE == "remove") {
+ const auto PMONITOR = g_pCompositor->getMonitorFromName(NAME);
+
+ if (!PMONITOR)
+ return "output not found";
+
+ if (!PMONITOR->createdByUser)
+ return "cannot remove a real display. Use the monitor keyword.";
+
+ wlr_output_destroy(PMONITOR->output);
+ }
+
+ return "ok";
+}
+
std::string getReply(std::string request) {
auto format = HyprCtl::FORMAT_NORMAL;
@@ -786,6 +866,8 @@ std::string getReply(std::string request) {
return splashRequest();
else if (request == "cursorpos")
return cursorPosRequest(format);
+ else if (request.find("output") == 0)
+ return dispatchOutput(request);
else if (request.find("dispatch") == 0)
return dispatchRequest(request);
else if (request.find("keyword") == 0)
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index 17643b3f..6849c227 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -8,6 +8,9 @@ void CMonitor::onConnect(bool noRule) {
szName = output->name;
+ if (!wlr_backend_is_drm(output->backend))
+ createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
+
// get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index 476dd2ce..0f789781 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -40,6 +40,7 @@ public:
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;
// mirroring
CMonitor* pMirrorOf = nullptr;
diff --git a/src/helpers/XWaylandStubs.hpp b/src/helpers/XWaylandStubs.hpp
index 395a7575..97147f76 100644
--- a/src/helpers/XWaylandStubs.hpp
+++ b/src/helpers/XWaylandStubs.hpp
@@ -154,4 +154,8 @@ inline void wlr_xwayland_surface_close(wlr_xwayland_surface*) { }
inline void wlr_xwayland_surface_set_fullscreen(wlr_xwayland_surface*, bool) { }
-inline void wlr_xwayland_surface_set_minimized(wlr_xwayland_surface *, bool) {}
+inline void wlr_xwayland_surface_set_minimized(wlr_xwayland_surface *, bool) { }
+
+inline bool wlr_backend_is_x11(void*) { return false; }
+
+inline void wlr_x11_output_create(void*) { } \ No newline at end of file
diff --git a/src/includes.hpp b/src/includes.hpp
index a983ebb8..55c795f5 100644
--- a/src/includes.hpp
+++ b/src/includes.hpp
@@ -99,10 +99,15 @@ extern "C" {
#include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/types/wlr_switch.h>
+#include <wlr/config.h>
+#include <wlr/backend/headless.h>
+#include <wlr/backend/multi.h>
+#include <wlr/backend/wayland.h>
#include <drm_fourcc.h>
#ifndef NO_XWAYLAND
+#include <wlr/backend/x11.h>
#include <wlr/xwayland.h>
#include <X11/Xproto.h>
#endif
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 3858b24e..2e7c5433 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1347,6 +1347,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
pMonitor->vecTransformedSize = Vector2D(x,y);
+ if (pMonitor->createdByUser) {
+ wlr_box transformedBox = { 0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y };
+ wlr_box_transform(&transformedBox, &transformedBox, wlr_output_transform_invert(pMonitor->output->transform), (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
+
+ pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
+ }
+
if (pMonitorRule->offset == Vector2D(-1, -1) && pMonitor->vecPosition == Vector2D(-1, -1)) {
// let's find manually a sensible position for it, to the right.
Vector2D finalPos;