diff --git a/.gitmodules b/.gitmodules index 638f8ba9..8c9b9336 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,7 @@ [submodule "subprojects/hyprland-protocols"] path = subprojects/hyprland-protocols - url = https://github.com/hyprwm/hyprland-protocols + url = https://github.com/3l0w/hyprland-protocols + branch = feat/input-capture-impl [submodule "subprojects/udis86"] path = subprojects/udis86 url = https://github.com/canihavesomecoffee/udis86 diff --git a/CMakeLists.txt b/CMakeLists.txt index c1ecb14c..c14ddf1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,6 +354,8 @@ protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) protocolnew("staging/security-context" "security-context-v1" false) +protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-input-capture-v1" + true) protocolwayland() # tools diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 85e1c601..852912e2 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -10,6 +10,7 @@ #include "eventLoop/EventLoopManager.hpp" #include "../render/pass/TexPassElement.hpp" #include "SeatManager.hpp" +#include "protocols/InputCapture.hpp" #include #include @@ -701,6 +702,9 @@ void CPointerManager::move(const Vector2D& deltaLogical) { const auto oldPos = pointerPos; auto newPos = oldPos + Vector2D{std::isnan(deltaLogical.x) ? 0.0 : deltaLogical.x, std::isnan(deltaLogical.y) ? 0.0 : deltaLogical.y}; + + PROTO::inputCapture->sendAbsoluteMotion(newPos, deltaLogical); + warpTo(newPos); } diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index b7d61f67..4da1eea2 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -47,6 +47,7 @@ #include "../protocols/SinglePixel.hpp" #include "../protocols/SecurityContext.hpp" #include "../protocols/CTMControl.hpp" +#include "../protocols/InputCapture.hpp" #include "../protocols/HyprlandSurface.hpp" #include "../protocols/core/Seat.hpp" @@ -166,6 +167,7 @@ CProtocolManager::CProtocolManager() { PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); PROTO::ctm = std::make_unique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); + PROTO::inputCapture = std::make_unique(&hyprland_input_capture_manager_v1_interface, 1, "InputCapture"); PROTO::hyprlandSurface = std::make_unique(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); if (*PENABLEXXCM) { @@ -245,6 +247,7 @@ CProtocolManager::~CProtocolManager() { PROTO::singlePixel.reset(); PROTO::securityContext.reset(); PROTO::ctm.reset(); + PROTO::inputCapture.reset(); PROTO::hyprlandSurface.reset(); PROTO::lease.reset(); diff --git a/src/managers/ProtocolManager.cpp.orig b/src/managers/ProtocolManager.cpp.orig new file mode 100644 index 00000000..29bca826 --- /dev/null +++ b/src/managers/ProtocolManager.cpp.orig @@ -0,0 +1,319 @@ +#include "ProtocolManager.hpp" + +#include "../config/ConfigValue.hpp" + +#include "../protocols/TearingControl.hpp" +#include "../protocols/FractionalScale.hpp" +#include "../protocols/XDGOutput.hpp" +#include "../protocols/CursorShape.hpp" +#include "../protocols/IdleInhibit.hpp" +#include "../protocols/RelativePointer.hpp" +#include "../protocols/XDGDecoration.hpp" +#include "../protocols/AlphaModifier.hpp" +#include "../protocols/GammaControl.hpp" +#include "../protocols/ForeignToplevel.hpp" +#include "../protocols/PointerGestures.hpp" +#include "../protocols/ForeignToplevelWlr.hpp" +#include "../protocols/ShortcutsInhibit.hpp" +#include "../protocols/TextInputV3.hpp" +#include "../protocols/PointerConstraints.hpp" +#include "../protocols/OutputPower.hpp" +#include "../protocols/XDGActivation.hpp" +#include "../protocols/IdleNotify.hpp" +#include "../protocols/SessionLock.hpp" +#include "../protocols/InputMethodV2.hpp" +#include "../protocols/VirtualKeyboard.hpp" +#include "../protocols/VirtualPointer.hpp" +#include "../protocols/OutputManagement.hpp" +#include "../protocols/ServerDecorationKDE.hpp" +#include "../protocols/FocusGrab.hpp" +#include "../protocols/Tablet.hpp" +#include "../protocols/LayerShell.hpp" +#include "../protocols/PresentationTime.hpp" +#include "../protocols/XDGShell.hpp" +#include "../protocols/DataDeviceWlr.hpp" +#include "../protocols/PrimarySelection.hpp" +#include "../protocols/XWaylandShell.hpp" +#include "../protocols/Viewporter.hpp" +#include "../protocols/MesaDRM.hpp" +#include "../protocols/LinuxDMABUF.hpp" +#include "../protocols/DRMLease.hpp" +#include "../protocols/DRMSyncobj.hpp" +#include "../protocols/Screencopy.hpp" +#include "../protocols/ToplevelExport.hpp" +#include "../protocols/TextInputV1.hpp" +#include "../protocols/GlobalShortcuts.hpp" +#include "../protocols/XDGDialog.hpp" +#include "../protocols/SinglePixel.hpp" +#include "../protocols/SecurityContext.hpp" +#include "../protocols/CTMControl.hpp" +<<<<<<< HEAD +#include "../protocols/HyprlandSurface.hpp" +======= +#include "../protocols/InputCapture.hpp" +>>>>>>> 7dad916b (WIP: input capture) + +#include "../protocols/core/Seat.hpp" +#include "../protocols/core/DataDevice.hpp" +#include "../protocols/core/Compositor.hpp" +#include "../protocols/core/Subcompositor.hpp" +#include "../protocols/core/Output.hpp" +#include "../protocols/core/Shm.hpp" +#include "../protocols/ColorManagement.hpp" +#include "../protocols/FrogColorManagement.hpp" + +#include "../helpers/Monitor.hpp" +#include "../render/Renderer.hpp" +#include "../Compositor.hpp" + +#include +#include + +void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) { + const bool ISMIRROR = pMonitor->isMirror(); + + // onModeChanged we check if the current mirror status matches the global. + // mirrored outputs should have their global removed, as they are not physical parts of the + // layout. + + if (ISMIRROR && PROTO::outputs.contains(pMonitor->szName)) + PROTO::outputs.at(pMonitor->szName)->remove(); + else if (!ISMIRROR && (!PROTO::outputs.contains(pMonitor->szName) || PROTO::outputs.at(pMonitor->szName)->isDefunct())) { + if (PROTO::outputs.contains(pMonitor->szName)) + PROTO::outputs.erase(pMonitor->szName); + PROTO::outputs.emplace(pMonitor->szName, makeShared(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock())); + } + + if (PROTO::colorManagement && g_pCompositor->shouldChangePreferredImageDescription()) + PROTO::colorManagement->onImagePreferredChanged(); +} + +CProtocolManager::CProtocolManager() { + + static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); + static const auto PENABLEXXCM = CConfigValue("experimental:xx_color_management_v4"); + + // Outputs are a bit dumb, we have to agree. + static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { + auto M = std::any_cast(param); + + // ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after + // this event is emitted iirc. + // also ignore the fallback + if (M->isMirror() || M == g_pCompositor->m_pUnsafeOutput) + return; + + if (PROTO::outputs.contains(M->szName)) + PROTO::outputs.erase(M->szName); + + auto ref = makeShared(&wl_output_interface, 4, std::format("WLOutput ({})", M->szName), M->self.lock()); + PROTO::outputs.emplace(M->szName, ref); + ref->self = ref; + + m_mModeChangeListeners[M->szName] = M->events.modeChanged.registerListener([M, this](std::any d) { onMonitorModeChange(M); }); + }); + + static auto P2 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { + auto M = std::any_cast(param); + if (!PROTO::outputs.contains(M->szName)) + return; + PROTO::outputs.at(M->szName)->remove(); + m_mModeChangeListeners.erase(M->szName); + }); + + // Core + PROTO::seat = std::make_unique(&wl_seat_interface, 9, "WLSeat"); + PROTO::data = std::make_unique(&wl_data_device_manager_interface, 3, "WLDataDevice"); + PROTO::compositor = std::make_unique(&wl_compositor_interface, 6, "WLCompositor"); + PROTO::subcompositor = std::make_unique(&wl_subcompositor_interface, 1, "WLSubcompositor"); + PROTO::shm = std::make_unique(&wl_shm_interface, 1, "WLSHM"); + + // Extensions + PROTO::viewport = std::make_unique(&wp_viewporter_interface, 1, "Viewporter"); + PROTO::tearing = std::make_unique(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); + PROTO::fractional = std::make_unique(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); + PROTO::xdgOutput = std::make_unique(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); + PROTO::cursorShape = std::make_unique(&wp_cursor_shape_manager_v1_interface, 1, "CursorShape"); + PROTO::idleInhibit = std::make_unique(&zwp_idle_inhibit_manager_v1_interface, 1, "IdleInhibit"); + PROTO::relativePointer = std::make_unique(&zwp_relative_pointer_manager_v1_interface, 1, "RelativePointer"); + PROTO::xdgDecoration = std::make_unique(&zxdg_decoration_manager_v1_interface, 1, "XDGDecoration"); + PROTO::alphaModifier = std::make_unique(&wp_alpha_modifier_v1_interface, 1, "AlphaModifier"); + PROTO::gamma = std::make_unique(&zwlr_gamma_control_manager_v1_interface, 1, "GammaControl"); + PROTO::foreignToplevel = std::make_unique(&ext_foreign_toplevel_list_v1_interface, 1, "ForeignToplevel"); + PROTO::pointerGestures = std::make_unique(&zwp_pointer_gestures_v1_interface, 3, "PointerGestures"); + PROTO::foreignToplevelWlr = std::make_unique(&zwlr_foreign_toplevel_manager_v1_interface, 3, "ForeignToplevelWlr"); + PROTO::shortcutsInhibit = std::make_unique(&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1, "ShortcutsInhibit"); + PROTO::textInputV1 = std::make_unique(&zwp_text_input_manager_v1_interface, 1, "TextInputV1"); + PROTO::textInputV3 = std::make_unique(&zwp_text_input_manager_v3_interface, 1, "TextInputV3"); + PROTO::constraints = std::make_unique(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints"); + PROTO::outputPower = std::make_unique(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); + PROTO::activation = std::make_unique(&xdg_activation_v1_interface, 1, "XDGActivation"); + PROTO::idle = std::make_unique(&ext_idle_notifier_v1_interface, 1, "IdleNotify"); + PROTO::sessionLock = std::make_unique(&ext_session_lock_manager_v1_interface, 1, "SessionLock"); + PROTO::ime = std::make_unique(&zwp_input_method_manager_v2_interface, 1, "IMEv2"); + PROTO::virtualKeyboard = std::make_unique(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard"); + PROTO::virtualPointer = std::make_unique(&zwlr_virtual_pointer_manager_v1_interface, 2, "VirtualPointer"); + PROTO::outputManagement = std::make_unique(&zwlr_output_manager_v1_interface, 4, "OutputManagement"); + PROTO::serverDecorationKDE = std::make_unique(&org_kde_kwin_server_decoration_manager_interface, 1, "ServerDecorationKDE"); + PROTO::focusGrab = std::make_unique(&hyprland_focus_grab_manager_v1_interface, 1, "FocusGrab"); + PROTO::tablet = std::make_unique(&zwp_tablet_manager_v2_interface, 1, "TabletV2"); + PROTO::layerShell = std::make_unique(&zwlr_layer_shell_v1_interface, 5, "LayerShell"); + PROTO::presentation = std::make_unique(&wp_presentation_interface, 1, "Presentation"); + PROTO::xdgShell = std::make_unique(&xdg_wm_base_interface, 6, "XDGShell"); + PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); + PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); + PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + PROTO::screencopy = std::make_unique(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy"); + PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); + PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); + PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); + PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); + PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); + PROTO::ctm = std::make_unique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); +<<<<<<< HEAD + PROTO::hyprlandSurface = std::make_unique(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); + + if (*PENABLEXXCM) { + PROTO::colorManagement = std::make_unique(&xx_color_manager_v4_interface, 1, "ColorManagement"); + PROTO::frogColorManagement = std::make_unique(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement"); + } +======= + PROTO::inputCapture = std::make_unique(&hyprland_input_capture_manager_v1_interface, 1, "InputCapture"); +>>>>>>> 7dad916b (WIP: input capture) + + for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { + if (b->type() != Aquamarine::AQ_BACKEND_DRM) + continue; + + PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + if (*PENABLEEXPLICIT) + PROTO::sync = std::make_unique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); + break; + } + + if (g_pHyprOpenGL->getDRMFormats().size() > 0) { + PROTO::mesaDRM = std::make_unique(&wl_drm_interface, 2, "MesaDRM"); + PROTO::linuxDma = std::make_unique(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); + } else + Debug::log(WARN, "ProtocolManager: Not binding linux-dmabuf and MesaDRM: DMABUF not available"); +} + +CProtocolManager::~CProtocolManager() { + // this is dumb but i don't want to replace all 600 PROTO with the right thing + + // Output + PROTO::outputs.clear(); + + // Core + PROTO::seat.reset(); + PROTO::data.reset(); + PROTO::compositor.reset(); + PROTO::subcompositor.reset(); + PROTO::shm.reset(); + + // Extensions + PROTO::viewport.reset(); + PROTO::tearing.reset(); + PROTO::fractional.reset(); + PROTO::xdgOutput.reset(); + PROTO::cursorShape.reset(); + PROTO::idleInhibit.reset(); + PROTO::relativePointer.reset(); + PROTO::xdgDecoration.reset(); + PROTO::alphaModifier.reset(); + PROTO::gamma.reset(); + PROTO::foreignToplevel.reset(); + PROTO::pointerGestures.reset(); + PROTO::foreignToplevelWlr.reset(); + PROTO::shortcutsInhibit.reset(); + PROTO::textInputV1.reset(); + PROTO::textInputV3.reset(); + PROTO::constraints.reset(); + PROTO::outputPower.reset(); + PROTO::activation.reset(); + PROTO::idle.reset(); + PROTO::sessionLock.reset(); + PROTO::ime.reset(); + PROTO::virtualKeyboard.reset(); + PROTO::virtualPointer.reset(); + PROTO::outputManagement.reset(); + PROTO::serverDecorationKDE.reset(); + PROTO::focusGrab.reset(); + PROTO::tablet.reset(); + PROTO::layerShell.reset(); + PROTO::presentation.reset(); + PROTO::xdgShell.reset(); + PROTO::dataWlr.reset(); + PROTO::primarySelection.reset(); + PROTO::xwaylandShell.reset(); + PROTO::screencopy.reset(); + PROTO::toplevelExport.reset(); + PROTO::globalShortcuts.reset(); + PROTO::xdgDialog.reset(); + PROTO::singlePixel.reset(); + PROTO::securityContext.reset(); + PROTO::ctm.reset(); +<<<<<<< HEAD + PROTO::hyprlandSurface.reset(); +======= + PROTO::inputCapture.reset(); +>>>>>>> 7dad916b (WIP: input capture) + + PROTO::lease.reset(); + PROTO::sync.reset(); + PROTO::mesaDRM.reset(); + PROTO::linuxDma.reset(); +} + +bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { + if (!global) + return false; + + for (auto& [k, v] : PROTO::outputs) { + if (global == v->getGlobal()) + return false; + } + + // this is a static whitelist of allowed protocols, + // outputs are dynamic so we checked them above + // clang-format off + static const std::vector ALLOWED_WHITELIST = { + PROTO::seat->getGlobal(), + PROTO::data->getGlobal(), + PROTO::compositor->getGlobal(), + PROTO::subcompositor->getGlobal(), + PROTO::shm->getGlobal(), + PROTO::viewport->getGlobal(), + PROTO::tearing->getGlobal(), + PROTO::fractional->getGlobal(), + PROTO::cursorShape->getGlobal(), + PROTO::idleInhibit->getGlobal(), + PROTO::relativePointer->getGlobal(), + PROTO::xdgDecoration->getGlobal(), + PROTO::alphaModifier->getGlobal(), + PROTO::pointerGestures->getGlobal(), + PROTO::shortcutsInhibit->getGlobal(), + PROTO::textInputV1->getGlobal(), + PROTO::textInputV3->getGlobal(), + PROTO::constraints->getGlobal(), + PROTO::activation->getGlobal(), + PROTO::idle->getGlobal(), + PROTO::ime->getGlobal(), + PROTO::virtualKeyboard->getGlobal(), + PROTO::virtualPointer->getGlobal(), + PROTO::serverDecorationKDE->getGlobal(), + PROTO::tablet->getGlobal(), + PROTO::presentation->getGlobal(), + PROTO::xdgShell->getGlobal(), + PROTO::xdgDialog->getGlobal(), + PROTO::singlePixel->getGlobal(), + PROTO::primarySelection->getGlobal(), + PROTO::hyprlandSurface->getGlobal(), + PROTO::sync ? PROTO::sync->getGlobal() : nullptr, + PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, + PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, + }; + // clang-format on + + return std::find(ALLOWED_WHITELIST.begin(), ALLOWED_WHITELIST.end(), global) == ALLOWED_WHITELIST.end(); +} diff --git a/src/protocols/InputCapture.cpp b/src/protocols/InputCapture.cpp new file mode 100644 index 00000000..889f2599 --- /dev/null +++ b/src/protocols/InputCapture.cpp @@ -0,0 +1,33 @@ +#include "InputCapture.hpp" +#include "hyprland-input-capture-v1.hpp" +#include +#include +#include + +CInputCaptureProtocol::CInputCaptureProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CInputCaptureProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + + RESOURCE->setOnDestroy([this](CHyprlandInputCaptureManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); + + RESOURCE->setCapture([this](CHyprlandInputCaptureManagerV1* p) { this->onCapture(p); }); + RESOURCE->setRelease([this](CHyprlandInputCaptureManagerV1* p) { this->onRelease(p); }); +} + +void CInputCaptureProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); +} + +void CInputCaptureProtocol::onCapture(CHyprlandInputCaptureManagerV1* pMgr) {} + +void CInputCaptureProtocol::onRelease(CHyprlandInputCaptureManagerV1* pMgr) {} + +void CInputCaptureProtocol::sendAbsoluteMotion(const Vector2D& absolutePosition, const Vector2D& delta) { + for (const UP& manager : m_vManagers) { + manager->sendAbsoluteMotion(wl_fixed_from_double(absolutePosition.x), wl_fixed_from_double(absolutePosition.y), wl_fixed_from_double(delta.x), + wl_fixed_from_double(delta.y)); + } +} diff --git a/src/protocols/InputCapture.hpp b/src/protocols/InputCapture.hpp new file mode 100644 index 00000000..172c17dc --- /dev/null +++ b/src/protocols/InputCapture.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "WaylandProtocol.hpp" +#include "hyprland-input-capture-v1.hpp" +#include + +class CInputCaptureProtocol : public IWaylandProtocol { + public: + CInputCaptureProtocol(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 sendAbsoluteMotion(const Vector2D& absolutePosition, const Vector2D& delta); + + private: + void onManagerResourceDestroy(wl_resource* res); + void onCapture(CHyprlandInputCaptureManagerV1* pMgr); + void onRelease(CHyprlandInputCaptureManagerV1* pMgr); + + std::vector> m_vManagers; +}; + +namespace PROTO { + inline UP inputCapture; +} diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index db580457..ea4183d7 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -74,6 +74,8 @@ void CWLOutputResource::updateState() { if (resource->version() >= 2) resource->sendScale(std::ceil(monitor->scale)); + resource->sendGeometry(monitor->vecPosition.x, monitor->vecPosition.y, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), + monitor->output->model.c_str(), monitor->transform); resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 271df559..cb1b99ca 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 271df559dd30e4bc5ec6af02d017ac0aaabd63a7 +Subproject commit cb1b99ca037311417f9fde600732f21dc9ed983e