aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile22
-rw-r--r--src/Compositor.cpp5
-rw-r--r--src/Compositor.hpp1
-rw-r--r--src/Window.cpp5
-rw-r--r--src/Window.hpp5
-rw-r--r--src/config/ConfigManager.cpp1
-rw-r--r--src/debug/Log.cpp2
-rw-r--r--src/events/Events.hpp5
-rw-r--r--src/events/Misc.cpp29
-rw-r--r--src/events/Monitors.cpp10
-rw-r--r--src/events/Windows.cpp6
-rw-r--r--src/helpers/Monitor.cpp6
-rw-r--r--src/helpers/Monitor.hpp4
-rw-r--r--src/helpers/SubsurfaceTree.cpp12
-rw-r--r--src/helpers/WLClasses.hpp11
-rw-r--r--src/includes.hpp1
-rw-r--r--src/main.cpp5
-rw-r--r--src/render/Renderer.cpp7
-rw-r--r--src/render/Renderer.hpp2
19 files changed, 131 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 1a193086..b8f27fcc 100644
--- a/Makefile
+++ b/Makefile
@@ -81,6 +81,16 @@ idle-protocol.c:
idle-protocol.o: idle-protocol.h
+tearing-control-v1-protocol.h:
+ $(WAYLAND_SCANNER) server-header \
+ $(WAYLAND_PROTOCOLS)/staging/tearing-control/tearing-control-v1.xml $@
+
+tearing-control-v1-protocol.c:
+ $(WAYLAND_SCANNER) private-code \
+ $(WAYLAND_PROTOCOLS)/staging/tearing-control/tearing-control-v1.xml $@
+
+tearing-control-v1-protocol.o: tearing-control-v1-protocol.h
+
wlr-output-power-management-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
protocols/wlr-output-power-management-unstable-v1.xml $@
@@ -179,7 +189,7 @@ uninstall:
rm -f ${PREFIX}/share/man/man1/Hyprland.1
rm -f ${PREFIX}/share/man/man1/hyprctl.1
-protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o
+protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o tearing-control-v1-protocol.o
fixwlr:
sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
@@ -196,6 +206,16 @@ config:
cd subprojects/wlroots && ninja -C build/ install
+configdebug:
+ make protocols
+
+ make fixwlr
+
+ cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=debug -Dwerror=false -Dexamples=false
+ cd subprojects/wlroots && ninja -C build/
+
+ cd subprojects/wlroots && ninja -C build/ install
+
man:
pandoc ./docs/Hyprland.1.rst \
--standalone \
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index f698f05a..baa97bd3 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -179,6 +179,8 @@ CCompositor::CCompositor() {
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
+ m_sWLRTearingMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1);
+
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLDisplay);
if (!m_sWLRHeadlessBackend) {
@@ -244,6 +246,7 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
+ addWLSignal(&m_sWLRTearingMgr->events.new_object, &Events::listen_tearingNew, m_sWLRTearingMgr, "TearingMgr");
if(m_sWRLDRMLeaseMgr)
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
@@ -1759,6 +1762,8 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
// DMAbuf stuff for direct scanout
g_pHyprRenderer->setWindowScanoutMode(pWindow);
+
+ g_pHyprRenderer->damageMonitor(PMONITOR);
}
void CCompositor::moveUnmanagedX11ToWindows(CWindow* pWindow) {
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 9cf73acc..87f648ef 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -72,6 +72,7 @@ public:
wlr_xdg_activation_v1* m_sWLRActivation;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
wlr_backend* m_sWLRHeadlessBackend;
+ wlr_tearing_control_manager_v1* m_sWLRTearingMgr;
// ------------------------------------------------- //
diff --git a/src/Window.cpp b/src/Window.cpp
index e98193e1..083c676b 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -379,3 +379,8 @@ void CWindow::updateDynamicRules() {
applyDynamicRule(r);
}
}
+
+bool CWindow::shouldImmediate() {
+ return false; // safeguard. Disabled for now.
+ return m_bTearingHint == 1 || m_sAdditionalConfigData.forceTearing;
+}
diff --git a/src/Window.hpp b/src/Window.hpp
index b0014af9..01483d62 100644
--- a/src/Window.hpp
+++ b/src/Window.hpp
@@ -37,6 +37,7 @@ struct SWindowAdditionalConfigData {
bool forceNoBorder = false;
bool forceNoShadow = false;
bool windowDanceCompat = false;
+ bool forceTearing = false;
};
struct SWindowRule {
@@ -180,6 +181,9 @@ public:
// for idle inhibiting windows
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
+ // tearing hints
+ bool m_bTearingHint = false;
+
// For the list lookup
bool operator==(const CWindow& rhs) {
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
@@ -204,6 +208,7 @@ public:
bool isHidden();
void applyDynamicRule(const SWindowRule& r);
void updateDynamicRules();
+ bool shouldImmediate();
private:
// For hidden windows and stuff
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 1b5ee4ae..d1f8cd19 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -681,6 +681,7 @@ bool windowRuleValid(const std::string& RULE) {
&& RULE != "pin"
&& RULE != "noanim"
&& RULE != "windowdance"
+ && RULE != "immediate"
&& RULE.find("animation") != 0
&& RULE.find("rounding") != 0
&& RULE.find("workspace") != 0
diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp
index dab8f0a7..2f1bc0b3 100644
--- a/src/debug/Log.cpp
+++ b/src/debug/Log.cpp
@@ -23,6 +23,8 @@ void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
ofs << "[wlr] " << output << "\n";
ofs.close();
+
+ std::cout << "[wlr] " << output << "\n";
}
void Debug::log(LogLevel level, const char* fmt, ...) {
diff --git a/src/events/Events.hpp b/src/events/Events.hpp
index e3088110..e8b862fe 100644
--- a/src/events/Events.hpp
+++ b/src/events/Events.hpp
@@ -157,4 +157,9 @@ namespace Events {
LISTENER(holdBegin);
LISTENER(holdEnd);
+
+ // Tearing
+ LISTENER(tearingNew);
+ DYNLISTENFUNC(tearingSet);
+ DYNLISTENFUNC(tearingDestroy);
};
diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp
index 1edea5ba..cf7b27f6 100644
--- a/src/events/Misc.cpp
+++ b/src/events/Misc.cpp
@@ -213,3 +213,32 @@ void Events::listener_newTextInput(wl_listener* listener, void* data) {
g_pInputManager->m_sIMERelay.onNewTextInput((wlr_text_input_v3*)data);
}
+
+void Events::listener_tearingNew(wl_listener* listener, void* data) {
+ Debug::log(LOG, "New tearing object at %x", data);
+
+ const auto foundHint = wlr_tearing_control_manager_v1_surface_hint_from_surface(g_pCompositor->m_sWLRTearingMgr, ((wlr_tearing_control_v1*)data)->surface);
+
+ Debug::log(LOG, "Surface associated: %x, check 2: %i", ((wlr_tearing_control_v1*)data)->surface, foundHint);
+
+ const auto NEWCTRL = &g_pHyprRenderer->m_lTearingControllers.emplace_back();
+ 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", ((STearingController*)owner)->pWlrHint);
+
+ g_pHyprRenderer->m_lTearingControllers.remove(*((STearingController*)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 = TEARINGHINT->pWlrHint->hint;
+
+ Debug::log(LOG, "Hint %x (window %x) set tearing hint to %d", TEARINGHINT->pWlrHint, PWINDOW, TEARINGHINT->pWlrHint->hint);
+ }
+ }, NEWCTRL, "TearingController");
+} \ No newline at end of file
diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp
index 4414187a..116a6f32 100644
--- a/src/events/Monitors.cpp
+++ b/src/events/Monitors.cpp
@@ -168,6 +168,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
}
+ // check if we have a solitary client. If so, reject any draws not queued by our client (passed in data)
+ if (PMONITOR->solitaryClient && data != PMONITOR->solitaryClient && PMONITOR->solitaryClient->shouldImmediate())
+ return;
+
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -188,6 +192,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
+ if (PMONITOR->solitaryClient) {
+ // force damage
+ hasChanged = true;
+ pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10);
+ }
+
// we need to cleanup fading out when rendering the appropriate context
g_pCompositor->cleanupFadingOut(PMONITOR->ID);
diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp
index 24a3fcd4..fe414ec8 100644
--- a/src/events/Windows.cpp
+++ b/src/events/Windows.cpp
@@ -183,6 +183,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
} else {
Debug::log(ERR, "Rule idleinhibit: unknown mode %s", IDLERULE.c_str());
}
+ } else if (r.szRule == "immediate") {
+ PWINDOW->m_sAdditionalConfigData.forceTearing = true;
}
PWINDOW->applyDynamicRule(r);
}
@@ -659,12 +661,10 @@ void Events::listener_unmapWindow(void* owner, void* data) {
void Events::listener_commitWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
- if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
+ if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden())
return;
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
-
- // Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
}
void Events::listener_destroyWindow(void* owner, void* data) {
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index eb481748..a05c27e5 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -229,10 +229,16 @@ void CMonitor::onDisconnect() {
}
void CMonitor::addDamage(pixman_region32_t* rg) {
+ if (solitaryClient) // when there is a solitary client, we adjust to its commits.
+ return;
+
wlr_output_damage_add(damage, rg);
}
void CMonitor::addDamage(wlr_box* box) {
+ if (solitaryClient)
+ return;
+
wlr_output_damage_add_box(damage, box);
}
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index c2cc179b..19fd476e 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -42,6 +42,9 @@ public:
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
bool createdByUser = false;
+ // will attempt DS
+ CWindow* solitaryClient = nullptr; // used for stuff like tearing / VRR
+
// mirroring
CMonitor* pMirrorOf = nullptr;
std::vector<CMonitor*> mirrors;
@@ -68,6 +71,7 @@ public:
void onDisconnect();
void addDamage(pixman_region32_t* rg);
void addDamage(wlr_box* box);
+ void forceDamageEntire();
void setMirror(const std::string&);
bool isMirror();
diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp
index a41030f5..3b3a3432 100644
--- a/src/helpers/SubsurfaceTree.cpp
+++ b/src/helpers/SubsurfaceTree.cpp
@@ -224,6 +224,18 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
}
}
+ // check window if X11, we have a special case
+ if (pNode->pWindowOwner) {
+ const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
+
+ if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->shouldImmediate()) {
+ // TODO: we should do an asynchronous flip here. wlr patch needed.
+ listener_monitorFrame(PMONITOR, pNode->pWindowOwner);
+
+ Debug::log(LOG, "damage commit!");
+ }
+ }
+
g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly);
}
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index c340a516..dde1ee5d 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -349,3 +349,14 @@ struct SSwitchDevice {
return pWlrDevice == other.pWlrDevice;
}
};
+
+struct STearingController {
+ wlr_tearing_control_v1* pWlrHint = nullptr;
+
+ DYNLISTENER(set);
+ DYNLISTENER(destroy);
+
+ bool operator==(const STearingController& other) {
+ return pWlrHint == other.pWlrHint;
+ }
+};
diff --git a/src/includes.hpp b/src/includes.hpp
index 55c795f5..1c0558f8 100644
--- a/src/includes.hpp
+++ b/src/includes.hpp
@@ -103,6 +103,7 @@ extern "C" {
#include <wlr/backend/headless.h>
#include <wlr/backend/multi.h>
#include <wlr/backend/wayland.h>
+#include <wlr/types/wlr_tearing_control_v1.h>
#include <drm_fourcc.h>
diff --git a/src/main.cpp b/src/main.cpp
index 9f34c088..92b09577 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,6 +23,7 @@ int main(int argc, char** argv) {
setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 0);
// parse some args
+ bool logWlr = false;
std::string configPath;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--i-am-really-stupid"))
@@ -30,6 +31,8 @@ int main(int argc, char** argv) {
else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) {
configPath = std::string(argv[++i]);
Debug::log(LOG, "Using config location %s.", configPath.c_str());
+ } else if (!strcmp(argv[i], "--log-wlr")) {
+ logWlr = true;
} else {
std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n" <<
"--help -h | Show this help message\n" <<
@@ -53,7 +56,7 @@ int main(int argc, char** argv) {
std::cout << "Welcome to Hyprland!\n";
const auto LOGWLR = getenv("HYPRLAND_LOG_WLR");
- if (LOGWLR && std::string(LOGWLR) == "1")
+ if ((LOGWLR && std::string(LOGWLR) == "1") || logWlr)
wlr_log_init(WLR_DEBUG, Debug::wlrLog);
// let's init the compositor.
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 4ede58b4..38fa386a 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -556,6 +556,8 @@ void countSubsurfacesIter(wlr_surface* pSurface, int x, int y, void* data) {
}
bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
+ pMonitor->solitaryClient = nullptr;
+
if (!pMonitor->mirrors.empty())
return false; // do not DS if this monitor is being mirrored. Will break the functionality.
@@ -609,6 +611,7 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
// finally, we should be GTG.
wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base);
+ pMonitor->solitaryClient = PCANDIDATE;
if (!wlr_output_test(pMonitor->output)) {
return false;
@@ -620,10 +623,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, PSURFACE, pMonitor->output);
if (wlr_output_commit(pMonitor->output)) {
- if (!m_pLastScanout) {
+ if (!m_pLastScanout)
m_pLastScanout = PCANDIDATE;
- Debug::log(LOG, "Entered a direct scanout to %x: \"%s\"", PCANDIDATE, PCANDIDATE->m_szTitle.c_str());
- }
} else {
m_pLastScanout = nullptr;
return false;
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index 8bd65418..c2cd9518 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -51,6 +51,8 @@ public:
bool attemptDirectScanout(CMonitor*);
void setWindowScanoutMode(CWindow*);
+ std::list<STearingController> m_lTearingControllers;
+
private:
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*);
void renderWorkspaceWithFullscreenWindow(CMonitor*, CWorkspace*, timespec*);