diff options
author | Vaxry <[email protected]> | 2023-07-18 15:30:28 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2023-07-18 15:30:28 +0200 |
commit | 8370a7fcc4627e6f21395cc8b81298369be5cdaf (patch) | |
tree | 6be17dc7ba367ea7322d81f20b89b5cdf7defc4d | |
parent | 629e61c7a56561ee5d565dda6d0d8b7c41dbe9c7 (diff) | |
download | Hyprland-8370a7fcc4627e6f21395cc8b81298369be5cdaf.tar.gz Hyprland-8370a7fcc4627e6f21395cc8b81298369be5cdaf.zip |
internal: Protocol C++ Wraps + XDGOutput impl (#2733)
move to our own xdgoutput impl instead of wlr's
-rw-r--r-- | src/Compositor.cpp | 3 | ||||
-rw-r--r-- | src/Compositor.hpp | 1 | ||||
-rw-r--r-- | src/config/ConfigManager.cpp | 5 | ||||
-rw-r--r-- | src/events/Misc.cpp | 2 | ||||
-rw-r--r-- | src/events/Monitors.cpp | 5 | ||||
-rw-r--r-- | src/managers/ProtocolManager.cpp | 6 | ||||
-rw-r--r-- | src/managers/ProtocolManager.hpp | 5 | ||||
-rw-r--r-- | src/managers/XWaylandManager.cpp | 71 | ||||
-rw-r--r-- | src/managers/XWaylandManager.hpp | 4 | ||||
-rw-r--r-- | src/protocols/WaylandProtocol.cpp | 75 | ||||
-rw-r--r-- | src/protocols/WaylandProtocol.hpp | 35 | ||||
-rw-r--r-- | src/protocols/XDGOutput.cpp | 127 | ||||
-rw-r--r-- | src/protocols/XDGOutput.hpp | 31 | ||||
-rw-r--r-- | src/render/Renderer.cpp | 2 |
14 files changed, 284 insertions, 88 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cf4945a6..1c76beeb 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -196,8 +196,7 @@ void CCompositor::initServer() { m_sWLRXDGDecoMgr = wlr_xdg_decoration_manager_v1_create(m_sWLDisplay); wlr_server_decoration_manager_set_default_mode(m_sWLRServerDecoMgr, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); - m_sWLRXDGOutputMgr = wlr_xdg_output_manager_v1_create(m_sWLDisplay, m_sWLROutputLayout); - m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay); + m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay); m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay); m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index cfd1e3d4..35b292a9 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -61,7 +61,6 @@ class CCompositor { wlr_xcursor_manager* m_sWLRXCursorMgr; wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr; wlr_output_manager_v1* m_sWLROutputMgr; - wlr_xdg_output_manager_v1* m_sWLRXDGOutputMgr; wlr_presentation* m_sWLRPresentation; wlr_scene* m_sWLRScene; wlr_input_inhibit_manager* m_sWLRInhibitMgr; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c61bd15c..4899241b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1587,9 +1587,6 @@ void CConfigManager::loadConfigLoadVars() { // update layout g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue); - // update xwl scale - g_pXWaylandManager->updateXWaylandScale(); - // manual crash if (configValues["debug:manual_crash"].intValue && !m_bManualCrashInitiated) { m_bManualCrashInitiated = true; @@ -1972,6 +1969,8 @@ void CConfigManager::performMonitorReload() { g_pCompositor->m_bUnsafeState = false; m_bWantsMonitorReload = false; + + EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr); } SConfigValue* CConfigManager::getConfigValuePtr(const std::string& val) { diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index a422a21c..da680a00 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -74,8 +74,6 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) { } xcb_disconnect(XCBCONNECTION); - - g_pXWaylandManager->updateXWaylandScale(); #endif } diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 15ebf287..d748ef40 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -219,11 +219,8 @@ void Events::listener_monitorCommit(void* owner, void* data) { if (E->committed & WLR_OUTPUT_STATE_BUFFER) g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E); - - if (E->committed & (WLR_OUTPUT_STATE_SCALE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_MODE)) - g_pXWaylandManager->updateXWaylandScale(); } void Events::listener_monitorBind(void* owner, void* data) { - g_pXWaylandManager->updateXWaylandScale(); + ; } diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 205f3d02..bc3a4570 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -1,9 +1,13 @@ #include "ProtocolManager.hpp" +#include "xdg-output-unstable-v1-protocol.h" + CProtocolManager::CProtocolManager() { m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>(); m_pFractionalScaleProtocolManager = std::make_unique<CFractionalScaleProtocolManager>(); m_pTextInputV1ProtocolManager = std::make_unique<CTextInputV1ProtocolManager>(); m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>(); m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>(); -}
\ No newline at end of file + + m_pXDGOutputProtocol = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); +} diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index bc6b776e..223460a1 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -6,16 +6,21 @@ #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/Screencopy.hpp" +#include "../protocols/XDGOutput.hpp" class CProtocolManager { public: CProtocolManager(); + // TODO: rewrite to use the new protocol framework std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager; std::unique_ptr<CFractionalScaleProtocolManager> m_pFractionalScaleProtocolManager; std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager; std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager; std::unique_ptr<CScreencopyProtocolManager> m_pScreencopyProtocolManager; + + // New protocols + std::unique_ptr<CXDGOutputProtocol> m_pXDGOutputProtocol; }; inline std::unique_ptr<CProtocolManager> g_pProtocolManager; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 9ef02f71..556b40b7 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -295,73 +295,4 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) { MAXSIZE.y = 99999; return MAXSIZE; -} - -void CHyprXWaylandManager::updateXWaylandScale() { - static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; - - setXWaylandScale(*PXWLFORCESCALEZERO ? std::optional<double>{1.0} : std::optional<double>{}); -} - -void CHyprXWaylandManager::setXWaylandScale(std::optional<double> scale) { - Debug::log(LOG, "Overriding XWayland scale with %.2f", (float)scale.value_or(0.0)); - -#ifndef NO_XWAYLAND - wl_resource* res = nullptr; - for (auto& m : g_pCompositor->m_vMonitors) { - - if (!m->output || !m->m_bEnabled) - continue; - - const Vector2D LOGICALSIZE = m->vecTransformedSize / scale.value_or(m->scale); - - wl_resource* outputResource = nullptr; - bool needsDone = false; - - wl_list_for_each(res, &m->output->resources, link) { - const auto PCLIENT = wl_resource_get_client(res); - - if (PCLIENT == m_sWLRXWayland->server->client) { - const auto VERSION = wl_resource_get_version(res); - - wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, (int32_t)LOGICALSIZE.x, (int32_t)LOGICALSIZE.y, m->output->refresh); - - if (VERSION >= WL_OUTPUT_SCALE_SINCE_VERSION) - wl_output_send_scale(res, (uint32_t)ceil(scale.value_or(m->scale))); - - wl_output_send_name(res, getFormat("HL-X11-%d", m->ID).c_str()); - - outputResource = res; - needsDone = true; - - break; - } - } - - wlr_xdg_output_v1* output; - wl_list_for_each(output, &g_pCompositor->m_sWLRXDGOutputMgr->outputs, link) { - if (output->layout_output->output == m->output) { - wl_list_for_each(res, &output->resources, link) { - const auto PCLIENT = wl_resource_get_client(res); - - if (PCLIENT == m_sWLRXWayland->server->client) { - zxdg_output_v1_send_logical_size(res, LOGICALSIZE.x, LOGICALSIZE.y); - - if (wl_resource_get_version(res) < OUTPUT_DONE_DEPRECATED_SINCE_VERSION) - zxdg_output_v1_send_done(res); - - needsDone = true; - - break; - } - } - - break; - } - } - - if (needsDone && outputResource) - wl_output_send_done(outputResource); - } -#endif -} +}
\ No newline at end of file diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index e05551e4..27bce17d 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -26,10 +26,6 @@ class CHyprXWaylandManager { void moveXWaylandWindow(CWindow*, const Vector2D&); void checkBorders(CWindow*); Vector2D getMaxSizeForWindow(CWindow*); - void updateXWaylandScale(); - - private: - void setXWaylandScale(std::optional<double> scale); }; inline std::unique_ptr<CHyprXWaylandManager> g_pXWaylandManager;
\ No newline at end of file diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp new file mode 100644 index 00000000..b5acffea --- /dev/null +++ b/src/protocols/WaylandProtocol.cpp @@ -0,0 +1,75 @@ +#include "WaylandProtocol.hpp" +#include "../Compositor.hpp" + +CWaylandResource::CWaylandResource(wl_client* client, const wl_interface* wlInterface, uint32_t version, uint32_t id, bool destroyInDestructor) { + m_pWLResource = wl_resource_create(client, wlInterface, version, id); + + if (!m_pWLResource) { + wl_client_post_no_memory(client); + return; + } + + m_pWLClient = client; + m_bDestroyInDestructor = destroyInDestructor; + + Debug::log(LOG, "[wl res %lx] created", m_pWLResource); +} + +CWaylandResource::~CWaylandResource() { + if (m_pWLResource && m_bDestroyInDestructor) + wl_resource_destroy(m_pWLResource); + + Debug::log(LOG, "[wl res %lx] destroyed (wl_resource_destroy %s)", m_pWLResource, (m_pWLResource && m_bDestroyInDestructor ? "sent" : "not sent")); +} + +bool CWaylandResource::good() { + return resource(); +} + +wl_resource* CWaylandResource::resource() { + return m_pWLResource; +} + +uint32_t CWaylandResource::version() { + return wl_resource_get_version(m_pWLResource); +} + +void CWaylandResource::setImplementation(const void* impl, void* data, wl_resource_destroy_func_t df) { + RASSERT(!m_bImplementationSet, "Wayland Resource %lx already has an implementation, cannot re-set!", m_pWLResource); + + wl_resource_set_implementation(m_pWLResource, impl, data, df); + + Debug::log(LOG, "[wl res %lx] set impl to %lx", m_pWLResource, impl); + + m_bImplementationSet = true; +} + +static void bindManagerInternal(wl_client* client, void* data, uint32_t ver, uint32_t id) { + ((IWaylandProtocol*)data)->bindManager(client, data, ver, id); +} + +static void displayDestroyInternal(struct wl_listener* listener, void* data) { + ((IWaylandProtocol*)data)->onDisplayDestroy(); +} + +void IWaylandProtocol::onDisplayDestroy() { + wl_global_destroy(m_pGlobal); +} + +IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name) { + m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, iface, ver, this, &bindManagerInternal); + + if (!m_pGlobal) { + Debug::log(ERR, "[proto %s] could not create a global", name.c_str()); + return; + } + + m_liDisplayDestroy.notify = displayDestroyInternal; + wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); + + Debug::log(LOG, "[proto %s] started", name.c_str()); +} + +IWaylandProtocol::~IWaylandProtocol() { + onDisplayDestroy(); +} diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp new file mode 100644 index 00000000..04a58387 --- /dev/null +++ b/src/protocols/WaylandProtocol.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "../defines.hpp" + +class CWaylandResource { + public: + CWaylandResource(wl_client* client, const wl_interface* wlInterface, uint32_t version, uint32_t id, bool destroyInDestructor = false); + ~CWaylandResource(); + + bool good(); + wl_resource* resource(); + uint32_t version(); + + void setImplementation(const void* impl, void* data, wl_resource_destroy_func_t df); + + private: + bool m_bDestroyInDestructor = false; + bool m_bImplementationSet = false; + wl_client* m_pWLClient = nullptr; + wl_resource* m_pWLResource = nullptr; +}; + +interface IWaylandProtocol { + public: + IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name); + ~IWaylandProtocol(); + + virtual void onDisplayDestroy(); + + virtual void bindManager(wl_client * client, void* data, uint32_t ver, uint32_t id) = 0; + + private: + wl_global* m_pGlobal = nullptr; + wl_listener m_liDisplayDestroy; +};
\ No newline at end of file diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp new file mode 100644 index 00000000..ab0820e0 --- /dev/null +++ b/src/protocols/XDGOutput.cpp @@ -0,0 +1,127 @@ +#include "XDGOutput.hpp" +#include "../Compositor.hpp" + +#include "xdg-output-unstable-v1-protocol.h" + +#define OUTPUT_MANAGER_VERSION 3 +#define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3 +#define OUTPUT_DESCRIPTION_MUTABLE_SINCE_VERSION 3 + +static void destroyManagerResource(wl_client* client, wl_resource* resource) { + ((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onManagerResourceDestroy(resource); + // will be destroyed by the destruction of the unique_ptr +} + +static void destroyOutputResource(wl_client* client, wl_resource* resource) { + ((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onOutputResourceDestroy(resource); + wl_resource_destroy(resource); +} + +static void destroyOutputResourceOnly(wl_resource* resource) { + ((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onOutputResourceDestroy(resource); +} + +static void getXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) { + ((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onManagerGetXDGOutput(client, resource, id, outputResource); +} + +// + +static const struct zxdg_output_manager_v1_interface MANAGER_IMPL = { + .destroy = destroyManagerResource, + .get_xdg_output = getXDGOutput, +}; + +static const struct zxdg_output_v1_interface OUTPUT_IMPL = { + .destroy = destroyOutputResource, +}; + +void CXDGOutputProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_vManagerResources, [&](const auto& other) { return other->resource() == res; }); +} + +void CXDGOutputProtocol::onOutputResourceDestroy(wl_resource* res) { + std::erase_if(m_vXDGOutputs, [&](const auto& other) { return !other->resource || other->resource->resource() == res; }); +} + +void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagerResources.emplace_back(std::make_unique<CWaylandResource>(client, &zxdg_output_manager_v1_interface, ver, id, true)).get(); + + if (!RESOURCE->good()) { + Debug::log(LOG, "Couldn't bind XDGOutputMgr"); + return; + } + + RESOURCE->setImplementation(&MANAGER_IMPL, this, nullptr); +} + +CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + g_pHookSystem->hookDynamic("monitorLayoutChanged", [&](void* self, std::any param) { this->updateAllOutputs(); }); + g_pHookSystem->hookDynamic("configReloaded", [&](void* self, std::any param) { this->updateAllOutputs(); }); + g_pHookSystem->hookDynamic("monitorRemoved", [&](void* self, std::any param) { + const auto PMONITOR = std::any_cast<CMonitor*>(param); + std::erase_if(m_vXDGOutputs, [&](const auto& other) { return other->monitor == PMONITOR; }); + }); +} + +void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) { + const auto OUTPUT = wlr_output_from_resource(outputResource); + + if (!OUTPUT) + return; + + const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT); + + if (!PMONITOR) + return; + + SXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique<SXDGOutput>(PMONITOR)).get(); +#ifndef NO_XWAYLAND + if (g_pXWaylandManager->m_sWLRXWayland->server->client == client) + pXDGOutput->isXWayland = true; +#endif + pXDGOutput->client = client; + + pXDGOutput->resource = std::make_unique<CWaylandResource>(client, &zxdg_output_v1_interface, wl_resource_get_version(resource), id); + + if (!pXDGOutput->resource->good()) { + pXDGOutput->resource.release(); + return; + } + + pXDGOutput->resource->setImplementation(&OUTPUT_IMPL, this, destroyOutputResourceOnly); + const auto XDGVER = pXDGOutput->resource->version(); + + if (XDGVER >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) + zxdg_output_v1_send_name(pXDGOutput->resource->resource(), PMONITOR->szName.c_str()); + if (XDGVER >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION && PMONITOR->output->description) + zxdg_output_v1_send_description(pXDGOutput->resource->resource(), PMONITOR->output->description); + + updateOutputDetails(pXDGOutput); + + const auto OUTPUTVER = wl_resource_get_version(outputResource); + if (OUTPUTVER >= WL_OUTPUT_DONE_SINCE_VERSION && XDGVER >= OUTPUT_DONE_DEPRECATED_SINCE_VERSION) + wl_output_send_done(outputResource); +} + +void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { + static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; + + zxdg_output_v1_send_logical_position(pOutput->resource->resource(), pOutput->monitor->vecPosition.x, pOutput->monitor->vecPosition.y); + + if (*PXWLFORCESCALEZERO && pOutput->isXWayland) + zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecPixelSize.x, pOutput->monitor->vecPixelSize.y); + else + zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecSize.x, pOutput->monitor->vecSize.y); + + if (wl_resource_get_version(pOutput->resource->resource()) < OUTPUT_DONE_DEPRECATED_SINCE_VERSION) + zxdg_output_v1_send_done(pOutput->resource->resource()); +} + +void CXDGOutputProtocol::updateAllOutputs() { + for (auto& o : m_vXDGOutputs) { + updateOutputDetails(o.get()); + + wlr_output_schedule_done(o->monitor->output); + } +}
\ No newline at end of file diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp new file mode 100644 index 00000000..13b7029c --- /dev/null +++ b/src/protocols/XDGOutput.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "WaylandProtocol.hpp" + +class CMonitor; + +struct SXDGOutput { + CMonitor* monitor = nullptr; + std::unique_ptr<CWaylandResource> resource; + + wl_client* client = nullptr; + bool isXWayland = false; +}; + +class CXDGOutputProtocol : public IWaylandProtocol { + public: + CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + void onManagerResourceDestroy(wl_resource* res); + void onOutputResourceDestroy(wl_resource* res); + void onManagerGetXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource); + + private: + void updateOutputDetails(SXDGOutput* pOutput); + void updateAllOutputs(); + + std::vector<std::unique_ptr<CWaylandResource>> m_vManagerResources; + std::vector<std::unique_ptr<SXDGOutput>> m_vXDGOutputs; +};
\ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 743f0385..335c0475 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1891,7 +1891,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR (int)pMonitor->vecPixelSize.y, pMonitor->refreshRate, pMonitor->scale, (int)pMonitor->transform, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y, (int)pMonitor->enabled10bit); - g_pXWaylandManager->updateXWaylandScale(); + EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr); return true; } |