mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-07 21:25:58 +01:00
tearing: hl impl
This commit is contained in:
parent
e57a2d7ec8
commit
0465472702
14 changed files with 207 additions and 74 deletions
|
@ -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)
|
||||
|
|
|
@ -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; });
|
||||
}
|
||||
|
|
|
@ -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 = "";
|
||||
|
|
|
@ -530,14 +530,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;
|
||||
|
||||
|
|
|
@ -144,9 +144,6 @@ namespace Events {
|
|||
// Cursor shape
|
||||
LISTENER(setCursorShape);
|
||||
|
||||
// Tearing hints
|
||||
LISTENER(newTearingHint);
|
||||
|
||||
// Shortcut inhibitor
|
||||
LISTENER(newShortcutInhibitor);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
106
src/protocols/TearingControl.cpp
Normal file
106
src/protocols/TearingControl.cpp
Normal file
|
@ -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();
|
||||
}
|
60
src/protocols/TearingControl.hpp
Normal file
60
src/protocols/TearingControl.hpp
Normal file
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue