aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-04-19 22:16:35 +0100
committerGitHub <[email protected]>2024-04-19 22:16:35 +0100
commitb52a49b4c4c344784b3085cb93d3882d3ce9b4bb (patch)
treea8c3ab6cf77cec5e22565f0f2a3adacfaa6edf30
parent1016faea53fd2d6a9bc12340425230b84676d7cd (diff)
downloadHyprland-b52a49b4c4c344784b3085cb93d3882d3ce9b4bb.tar.gz
Hyprland-b52a49b4c4c344784b3085cb93d3882d3ce9b4bb.zip
tearing-control: hyprland impl (#5655)
* tearing: hl impl * format
-rwxr-xr-xCMakeLists.txt1
-rw-r--r--src/Compositor.cpp6
-rw-r--r--src/Compositor.hpp1
-rw-r--r--src/desktop/Window.cpp8
-rw-r--r--src/events/Events.hpp3
-rw-r--r--src/events/Misc.cpp31
-rw-r--r--src/helpers/WLClasses.hpp11
-rw-r--r--src/includes.hpp1
-rw-r--r--src/managers/ProtocolManager.cpp4
-rw-r--r--src/protocols/TearingControl.cpp106
-rw-r--r--src/protocols/TearingControl.hpp60
-rw-r--r--src/protocols/WaylandProtocol.cpp11
-rw-r--r--src/protocols/WaylandProtocol.hpp20
-rw-r--r--src/render/Renderer.hpp18
14 files changed, 207 insertions, 74 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c949928..b056402a 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -263,6 +263,7 @@ protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1
protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
+protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
# tools
add_subdirectory(hyprctl)
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index ae1c352c..6e739c5f 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -253,8 +253,6 @@ void CCompositor::initServer() {
m_sWLRCursorShapeMgr = wlr_cursor_shape_manager_v1_create(m_sWLDisplay, 1);
- m_sWLRTearingControlMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1);
-
if (!m_sWLRHeadlessBackend) {
Debug::log(CRIT, "Couldn't create the headless backend");
throwError("wlr_headless_backend_create() failed!");
@@ -311,7 +309,6 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr");
- addWLSignal(&m_sWLRTearingControlMgr->events.new_object, &Events::listen_newTearingHint, m_sWLRTearingControlMgr, "TearingControlMgr");
addWLSignal(&m_sWLRKbShInhibitMgr->events.new_inhibitor, &Events::listen_newShortcutInhibitor, m_sWLRKbShInhibitMgr, "ShortcutInhibitMgr");
if (m_sWRLDRMLeaseMgr)
@@ -365,7 +362,6 @@ void CCompositor::removeAllSignals() {
removeWLSignal(&Events::listen_newSessionLock);
removeWLSignal(&Events::listen_setGamma);
removeWLSignal(&Events::listen_setCursorShape);
- removeWLSignal(&Events::listen_newTearingHint);
removeWLSignal(&Events::listen_newShortcutInhibitor);
if (m_sWRLDRMLeaseMgr)
@@ -695,6 +691,8 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
if (windowExists(pWindow) && !pWindow->m_bFadingOut) {
+ EMIT_HOOK_EVENT("destroyWindow", pWindow);
+
std::erase_if(m_vWindows, [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; });
std::erase_if(m_vWindowsFadingOut, [&](CWindow* el) { return el == pWindow; });
}
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 11c02814..9244c673 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -82,7 +82,6 @@ class CCompositor {
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;
wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr;
wlr_cursor_shape_manager_v1* m_sWLRCursorShapeMgr;
- wlr_tearing_control_manager_v1* m_sWLRTearingControlMgr;
// ------------------------------------------------- //
std::string m_szWLDisplaySocket = "";
diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp
index 737d5ef7..35b4ff97 100644
--- a/src/desktop/Window.cpp
+++ b/src/desktop/Window.cpp
@@ -535,14 +535,6 @@ void CWindow::onMap() {
m_vReportedSize = m_vPendingReportedSize;
m_bAnimatingIn = true;
- for (const auto& ctrl : g_pHyprRenderer->m_vTearingControllers) {
- if (ctrl->pWlrHint->surface != m_pWLSurface.wlr())
- continue;
-
- m_bTearingHint = ctrl->pWlrHint->current;
- break;
- }
-
if (m_bIsX11)
return;
diff --git a/src/events/Events.hpp b/src/events/Events.hpp
index 9dbd75df..4c4503ad 100644
--- a/src/events/Events.hpp
+++ b/src/events/Events.hpp
@@ -144,9 +144,6 @@ namespace Events {
// Cursor shape
LISTENER(setCursorShape);
- // Tearing hints
- LISTENER(newTearingHint);
-
// Shortcut inhibitor
LISTENER(newShortcutInhibitor);
};
diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp
index 8d0a9710..53bd6f9f 100644
--- a/src/events/Misc.cpp
+++ b/src/events/Misc.cpp
@@ -245,37 +245,6 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) {
g_pInputManager->processMouseRequest(E);
}
-void Events::listener_newTearingHint(wl_listener* listener, void* data) {
- Debug::log(LOG, "New tearing hint at {:x}", (uintptr_t)data);
-
- const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
- NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
-
- NEWCTRL->hyprListener_destroy.initCallback(
- &NEWCTRL->pWlrHint->events.destroy,
- [&](void* owner, void* data) {
- Debug::log(LOG, "Destroyed {:x} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
-
- std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
- },
- NEWCTRL, "TearingController");
-
- NEWCTRL->hyprListener_set.initCallback(
- &NEWCTRL->pWlrHint->events.set_hint,
- [&](void* owner, void* data) {
- const auto TEARINGHINT = (STearingController*)owner;
-
- const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface);
-
- if (PWINDOW) {
- PWINDOW->m_bTearingHint = (bool)TEARINGHINT->pWlrHint->current;
-
- Debug::log(LOG, "Hint {:x} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->current);
- }
- },
- NEWCTRL, "TearingController");
-}
-
void Events::listener_newShortcutInhibitor(wl_listener* listener, void* data) {
const auto INHIBITOR = (wlr_keyboard_shortcuts_inhibitor_v1*)data;
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index 5d93b91d..b85517e8 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -329,17 +329,6 @@ struct SSwitchDevice {
}
};
-struct STearingController {
- wlr_tearing_control_v1* pWlrHint = nullptr;
-
- DYNLISTENER(set);
- DYNLISTENER(destroy);
-
- bool operator==(const STearingController& other) const {
- return pWlrHint == other.pWlrHint;
- }
-};
-
struct SShortcutInhibitor {
wlr_keyboard_shortcuts_inhibitor_v1* pWlrInhibitor = nullptr;
diff --git a/src/includes.hpp b/src/includes.hpp
index 6a1e5bc3..c43c2eaf 100644
--- a/src/includes.hpp
+++ b/src/includes.hpp
@@ -103,7 +103,6 @@ extern "C" {
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_cursor_shape_v1.h>
-#include <wlr/types/wlr_tearing_control_v1.h>
#include <wlr/util/box.h>
#include <wlr/util/transform.h>
#include <wlr/render/swapchain.h>
diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp
index bc3a4570..f6cb66df 100644
--- a/src/managers/ProtocolManager.cpp
+++ b/src/managers/ProtocolManager.cpp
@@ -1,6 +1,9 @@
#include "ProtocolManager.hpp"
+#include "../protocols/TearingControl.hpp"
+
#include "xdg-output-unstable-v1-protocol.h"
+#include "tearing-control-v1-protocol.h"
CProtocolManager::CProtocolManager() {
m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>();
@@ -10,4 +13,5 @@ CProtocolManager::CProtocolManager() {
m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>();
m_pXDGOutputProtocol = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput");
+ PROTO::tearing = std::make_unique<CTearingControlProtocol>(&wp_tearing_control_manager_v1_interface, 1, "TearingControl");
}
diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp
new file mode 100644
index 00000000..0ed495bd
--- /dev/null
+++ b/src/protocols/TearingControl.cpp
@@ -0,0 +1,106 @@
+#include "TearingControl.hpp"
+#include "tearing-control-v1-protocol.h"
+#include "../managers/ProtocolManager.hpp"
+#include "../desktop/Window.hpp"
+#include "../Compositor.hpp"
+
+static void destroyManager(wl_client* client, wl_resource* resource) {
+ RESOURCE_OR_BAIL(PRESOURCE);
+ reinterpret_cast<CTearingControlProtocol*>(PRESOURCE->data())->onManagerResourceDestroy(resource);
+}
+
+static void getTearingControl(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface) {
+ RESOURCE_OR_BAIL(PRESOURCE);
+ reinterpret_cast<CTearingControlProtocol*>(PRESOURCE->data())->onGetController(client, resource, id, wlr_surface_from_resource(surface));
+}
+
+//
+
+CTearingControlProtocol::CTearingControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ g_pHookSystem->hookDynamic("destroyWindow", [this](void* self, SCallbackInfo& info, std::any param) { this->onWindowDestroy(std::any_cast<CWindow*>(param)); });
+}
+
+static const struct wp_tearing_control_manager_v1_interface MANAGER_IMPL = {
+ .destroy = ::destroyManager,
+ .get_tearing_control = ::getTearingControl,
+};
+
+void CTearingControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CWaylandResource>(client, &wp_tearing_control_manager_v1_interface, ver, id)).get();
+
+ if (!RESOURCE->good()) {
+ Debug::log(LOG, "Couldn't bind TearingControlMgr");
+ return;
+ }
+
+ RESOURCE->setImplementation(&MANAGER_IMPL, nullptr);
+ RESOURCE->setData(this);
+}
+
+void CTearingControlProtocol::onManagerResourceDestroy(wl_resource* res) {
+ std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
+}
+
+void CTearingControlProtocol::onGetController(wl_client* client, wl_resource* resource, uint32_t id, wlr_surface* surf) {
+ const auto CONTROLLER = m_vTearingControllers
+ .emplace_back(std::make_unique<CTearingControl>(
+ std::make_shared<CWaylandResource>(client, &wp_tearing_control_v1_interface, wl_resource_get_version(resource), id), surf))
+ .get();
+
+ if (!CONTROLLER->good()) {
+ m_vTearingControllers.pop_back();
+ return;
+ }
+}
+
+void CTearingControlProtocol::onControllerDestroy(CTearingControl* control) {
+ std::erase_if(m_vTearingControllers, [control](const auto& other) { return other.get() == control; });
+}
+
+void CTearingControlProtocol::onWindowDestroy(CWindow* pWindow) {
+ for (auto& c : m_vTearingControllers) {
+ if (c->pWindow == pWindow)
+ c->pWindow = nullptr;
+ }
+}
+
+//
+
+static void destroyController(wl_client* client, wl_resource* resource) {
+ RESOURCE_OR_BAIL(PRESOURCE);
+ PROTO::tearing->onControllerDestroy(reinterpret_cast<CTearingControl*>(PRESOURCE->data()));
+}
+
+static void setPresentationHint(wl_client* client, wl_resource* resource, uint32_t hint) {
+ RESOURCE_OR_BAIL(PRESOURCE);
+ reinterpret_cast<CTearingControl*>(PRESOURCE->data())->onHint(hint);
+}
+
+static const struct wp_tearing_control_v1_interface CONTROLLER_IMPL = {
+ .set_presentation_hint = ::setPresentationHint,
+ .destroy = ::destroyController,
+};
+
+CTearingControl::CTearingControl(SP<CWaylandResource> resource_, wlr_surface* surf_) : resource(resource_) {
+ resource->setImplementation(&CONTROLLER_IMPL, nullptr);
+ resource->setData(this);
+ resource->setOnDestroyHandler([](CWaylandResource* res) { PROTO::tearing->onControllerDestroy(reinterpret_cast<CTearingControl*>(res->data())); });
+
+ pWindow = g_pCompositor->getWindowFromSurface(surf_);
+}
+
+void CTearingControl::onHint(uint32_t hint_) {
+ hint = hint_ == WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC ? TEARING_VSYNC : TEARING_ASYNC;
+ updateWindow();
+}
+
+void CTearingControl::updateWindow() {
+ if (!pWindow)
+ return;
+
+ pWindow->m_bTearingHint = hint == TEARING_ASYNC;
+}
+
+bool CTearingControl::good() {
+ return resource->good();
+}
diff --git a/src/protocols/TearingControl.hpp b/src/protocols/TearingControl.hpp
new file mode 100644
index 00000000..f0dd8bfa
--- /dev/null
+++ b/src/protocols/TearingControl.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <memory>
+#include "WaylandProtocol.hpp"
+
+class CWindow;
+
+enum eTearingPresentationHint {
+ TEARING_VSYNC = 0,
+ TEARING_ASYNC,
+};
+
+class CTearingControlProtocol;
+
+class CTearingControl {
+ public:
+ CTearingControl(SP<CWaylandResource> resource_, wlr_surface* surf_);
+
+ void onHint(uint32_t hint_);
+
+ bool good();
+
+ bool operator==(const wl_resource* other) const {
+ return other == resource->resource();
+ }
+
+ bool operator==(const CTearingControl* other) const {
+ return other->resource == resource;
+ }
+
+ private:
+ void updateWindow();
+
+ SP<CWaylandResource> resource;
+ CWindow* pWindow = nullptr;
+ eTearingPresentationHint hint = TEARING_VSYNC;
+
+ friend class CTearingControlProtocol;
+};
+
+class CTearingControlProtocol : public IWaylandProtocol {
+ public:
+ CTearingControlProtocol(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 onControllerDestroy(CTearingControl* control);
+ void onGetController(wl_client* client, wl_resource* resource, uint32_t id, wlr_surface* surf);
+
+ private:
+ void onWindowDestroy(CWindow* pWindow);
+
+ std::vector<UP<CWaylandResource>> m_vManagers;
+ std::vector<UP<CTearingControl>> m_vTearingControllers;
+};
+
+namespace PROTO {
+ inline UP<CTearingControlProtocol> tearing;
+}; \ No newline at end of file
diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp
index 4600126c..76f5eba0 100644
--- a/src/protocols/WaylandProtocol.cpp
+++ b/src/protocols/WaylandProtocol.cpp
@@ -31,7 +31,14 @@ void CWaylandResource::markDefunct() {
Debug::log(TRACE, "[wl res {:x}] now defunct", (uintptr_t)m_pWLResource);
m_bDefunct = true;
+
wl_resource_set_user_data(m_pWLResource, nullptr);
+
+ // we call it here because we need defunct to be set to true.
+ // if this function destroys us, we can't call wl_resource_set_user_data or
+ // destroy the resource.
+ if (m_fOnDestroyHandler)
+ m_fOnDestroyHandler(this);
}
CWaylandResource::~CWaylandResource() {
@@ -80,6 +87,10 @@ void* CWaylandResource::data() {
return m_pData;
}
+void CWaylandResource::setOnDestroyHandler(std::function<void(CWaylandResource* res)> fn) {
+ m_fOnDestroyHandler = fn;
+}
+
static void bindManagerInternal(wl_client* client, void* data, uint32_t ver, uint32_t id) {
((IWaylandProtocol*)data)->bindManager(client, data, ver, id);
}
diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp
index a87bd519..cc8a0e53 100644
--- a/src/protocols/WaylandProtocol.hpp
+++ b/src/protocols/WaylandProtocol.hpp
@@ -2,11 +2,18 @@
#include "../defines.hpp"
+#include <functional>
+
#define RESOURCE_OR_BAIL(resname) \
const auto resname = (CWaylandResource*)wl_resource_get_user_data(resource); \
if (!resname) \
return;
+#define SP std::shared_ptr
+#define UP std::unique_ptr
+
+#define PROTO NProtocols
+
class CWaylandResource {
public:
CWaylandResource(wl_client* client, const wl_interface* wlInterface, uint32_t version, uint32_t id);
@@ -24,12 +31,15 @@ class CWaylandResource {
void* data();
void setData(void* data);
+ void setOnDestroyHandler(std::function<void(CWaylandResource* res)> fn);
+
private:
- bool m_bImplementationSet = false;
- bool m_bDefunct = false; // m_liResourceDestroy fired
- wl_client* m_pWLClient = nullptr;
- wl_resource* m_pWLResource = nullptr;
- void* m_pData = nullptr;
+ bool m_bImplementationSet = false;
+ bool m_bDefunct = false; // m_liResourceDestroy fired
+ wl_client* m_pWLClient = nullptr;
+ wl_resource* m_pWLResource = nullptr;
+ void* m_pData = nullptr;
+ std::function<void(CWaylandResource* res)> m_fOnDestroyHandler;
};
class IWaylandProtocol {
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index bc5ff43c..2e2b8b92 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -89,18 +89,16 @@ class CHyprRenderer {
DAMAGETRACKINGMODES
damageTrackingModeFromStr(const std::string&);
- bool attemptDirectScanout(CMonitor*);
- void setWindowScanoutMode(CWindow*);
- void initiateManualCrash();
+ bool attemptDirectScanout(CMonitor*);
+ void setWindowScanoutMode(CWindow*);
+ void initiateManualCrash();
- bool m_bCrashingInProgress = false;
- float m_fCrashingDistort = 0.5f;
- wl_event_source* m_pCrashingLoop = nullptr;
- wl_event_source* m_pCursorTicker = nullptr;
+ bool m_bCrashingInProgress = false;
+ float m_fCrashingDistort = 0.5f;
+ wl_event_source* m_pCrashingLoop = nullptr;
+ wl_event_source* m_pCursorTicker = nullptr;
- std::vector<std::unique_ptr<STearingController>> m_vTearingControllers;
-
- CTimer m_tRenderTimer;
+ CTimer m_tRenderTimer;
struct {
int hotspotX;