summaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
authorUjinT34 <41110182+UjinT34@users.noreply.github.com>2025-08-22 20:24:25 +0300
committerGitHub <noreply@github.com>2025-08-22 18:24:25 +0100
commit0d45b277d6c750377b336034b8adc53eae238d91 (patch)
tree0489c239e9ef6ab6e3c1ee70b8baa03d7b5cf2d7 /src/debug
parente95ba5bf5911fbc5e33d10e3f1ae1291f906a19f (diff)
internal: Solitary clients with single subsurface & verbose solitary/tearing/DS checks (#11228)
Adds more verbose checks for various conditional rendering mechanisms
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/HyprCtl.cpp107
-rw-r--r--src/debug/HyprCtl.hpp3
2 files changed, 103 insertions, 7 deletions
diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp
index 45aeb4f1..5af8ef80 100644
--- a/src/debug/HyprCtl.cpp
+++ b/src/debug/HyprCtl.cpp
@@ -1,4 +1,5 @@
#include "HyprCtl.hpp"
+#include "helpers/Monitor.hpp"
#include <algorithm>
#include <format>
@@ -109,6 +110,91 @@ static std::string availableModesForOutput(PHLMONITOR pMonitor, eHyprCtlOutputFo
return result;
}
+const std::array<const char*, CMonitor::SC_CHECKS_COUNT> SOLITARY_REASONS_JSON = {
+ "\"UNKNOWN\"", "\"NOTIFICATION\"", "\"LOCK\"", "\"WORKSPACE\"", "\"WINDOWED\"", "\"DND\"", "\"SPECIAL\"", "\"ALPHA\"",
+ "\"OFFSET\"", "\"CANDIDATE\"", "\"OPAQUE\"", "\"TRANSFORM\"", "\"OVERLAYS\"", "\"FLOAT\"", "\"WORKSPACES\"", "\"SURFACES\"",
+};
+
+const std::array<const char*, CMonitor::SC_CHECKS_COUNT> SOLITARY_REASONS_TEXT = {
+ "unknown reason", "notification", "session lock", "invalid workspace", "windowed mode", "dnd active", "special workspace", "alpha channel",
+ "workspace offset", "missing candidate", "not opaque", "surface transformations", "other overlays", "floating windows", "other workspaces", "subsurfaces",
+};
+
+std::string CHyprCtl::getSolitaryBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
+ const auto reasons = m->isSolitaryBlocked(true);
+ if (!reasons)
+ return "null";
+
+ std::string reasonStr = "";
+ const auto TEXTS = format == eHyprCtlOutputFormat::FORMAT_JSON ? SOLITARY_REASONS_JSON : SOLITARY_REASONS_TEXT;
+
+ for (int i = 0; i < CMonitor::SC_CHECKS_COUNT; i++) {
+ if (reasons & (1 << i)) {
+ if (reasonStr != "")
+ reasonStr += ",";
+ reasonStr += TEXTS[i];
+ }
+ }
+
+ return format == eHyprCtlOutputFormat::FORMAT_JSON ? "[" + reasonStr + "]" : reasonStr;
+}
+
+const std::array<const char*, CMonitor::DS_CHECKS_COUNT> DS_REASONS_JSON = {
+ "\"UNKNOWN\"", "\"USER\"", "\"WINDOWED\"", "\"CONTENT\"", "\"MIRROR\"", "\"RECORD\"", "\"SW\"",
+ "\"CANDIDATE\"", "\"SURFACE\"", "\"TRANSFORM\"", "\"DMA\"", "\"TEARING\"", "\"FAILED\"",
+};
+
+const std::array<const char*, CMonitor::DS_CHECKS_COUNT> DS_REASONS_TEXT = {
+ "unknown reason", "user settings", "windowed mode", "content type", "monitor mirrors", "screen record/screenshot", "software renders/cursors",
+ "missing candidate", "invalid surface", "surface transformations", "invalid buffer", "tearing", "activation failed",
+};
+
+std::string CHyprCtl::getDSBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
+ const auto reasons = m->isDSBlocked(true);
+ if (!reasons)
+ return "null";
+
+ std::string reasonStr = "";
+ const auto TEXTS = format == eHyprCtlOutputFormat::FORMAT_JSON ? DS_REASONS_JSON : DS_REASONS_TEXT;
+
+ for (int i = 0; i < CMonitor::DS_CHECKS_COUNT; i++) {
+ if (reasons & (1 << i)) {
+ if (reasonStr != "")
+ reasonStr += ",";
+ reasonStr += TEXTS[i];
+ }
+ }
+
+ return format == eHyprCtlOutputFormat::FORMAT_JSON ? "[" + reasonStr + "]" : reasonStr;
+}
+
+const std::array<const char*, CMonitor::TC_CHECKS_COUNT> TEARING_REASONS_JSON = {
+ "\"UNKNOWN\"", "\"NOT_TORN\"", "\"USER\"", "\"ZOOM\"", "\"SUPPORT\"", "\"CANDIDATE\"", "\"WINDOW\"",
+};
+
+const std::array<const char*, CMonitor::TC_CHECKS_COUNT> TEARING_REASONS_TEXT = {
+ "unknown reason", "next frame is not torn", "user settings", "zoom", "not supported by monitor", "missing candidate", "window settings",
+};
+
+std::string CHyprCtl::getTearingBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
+ const auto reasons = m->isTearingBlocked(true);
+ if (!reasons || (reasons == CMonitor::TC_NOT_TORN && m->m_tearingState.activelyTearing))
+ return "null";
+
+ std::string reasonStr = "";
+ const auto TEXTS = format == eHyprCtlOutputFormat::FORMAT_JSON ? TEARING_REASONS_JSON : TEARING_REASONS_TEXT;
+
+ for (int i = 0; i < CMonitor::TC_CHECKS_COUNT; i++) {
+ if (reasons & (1 << i)) {
+ if (reasonStr != "")
+ reasonStr += ",";
+ reasonStr += TEXTS[i];
+ }
+ }
+
+ return format == eHyprCtlOutputFormat::FORMAT_JSON ? "[" + reasonStr + "]" : reasonStr;
+}
+
std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
std::string result;
if (!m->m_output || m->m_id == -1)
@@ -146,8 +232,11 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
"dpmsStatus": {},
"vrr": {},
"solitary": "{:x}",
+ "solitaryBlockedBy": {},
"activelyTearing": {},
+ "tearingBlockedBy": {},
"directScanoutTo": "{:x}",
+ "directScanoutBlockedBy": {},
"disabled": {},
"currentFormat": "{}",
"mirrorOf": "{}",
@@ -155,28 +244,32 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
}},)#",
m->m_id, escapeJSONStrings(m->m_name), escapeJSONStrings(m->m_shortDescription), escapeJSONStrings(m->m_output->make), escapeJSONStrings(m->m_output->model),
- escapeJSONStrings(m->m_output->serial), sc<int>(m->m_pixelSize.x), m->m_pixelSize.y, sc<int>(m->m_output->physicalSize.x), sc<int>(m->m_output->physicalSize.y),
- m->m_refreshRate, sc<int>(m->m_position.x), sc<int>(m->m_position.y), m->activeWorkspaceID(),
+ escapeJSONStrings(m->m_output->serial), sc<int>(m->m_pixelSize.x), sc<int>(m->m_pixelSize.y), sc<int>(m->m_output->physicalSize.x),
+ sc<int>(m->m_output->physicalSize.y), m->m_refreshRate, sc<int>(m->m_position.x), sc<int>(m->m_position.y), m->activeWorkspaceID(),
(!m->m_activeWorkspace ? "" : escapeJSONStrings(m->m_activeWorkspace->m_name)), m->activeSpecialWorkspaceID(),
escapeJSONStrings(m->m_activeSpecialWorkspace ? m->m_activeSpecialWorkspace->m_name : ""), sc<int>(m->m_reservedTopLeft.x), sc<int>(m->m_reservedTopLeft.y),
sc<int>(m->m_reservedBottomRight.x), sc<int>(m->m_reservedBottomRight.y), m->m_scale, sc<int>(m->m_transform), (m == g_pCompositor->m_lastMonitor ? "true" : "false"),
(m->m_dpmsStatus ? "true" : "false"), (m->m_output->state->state().adaptiveSync ? "true" : "false"), rc<uint64_t>(m->m_solitaryClient.get()),
- (m->m_tearingState.activelyTearing ? "true" : "false"), rc<uint64_t>(m->m_lastScanout.get()), (m->m_enabled ? "false" : "true"),
- formatToString(m->m_output->state->state().drmFormat), m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format));
+ getSolitaryBlockedReason(m, format), (m->m_tearingState.activelyTearing ? "true" : "false"), getTearingBlockedReason(m, format), rc<uint64_t>(m->m_lastScanout.get()),
+ getDSBlockedReason(m, format), (m->m_enabled ? "false" : "true"), formatToString(m->m_output->state->state().drmFormat),
+ m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format));
} else {
result += std::format(
"Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tphysical size (mm): {}x{}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
- "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdirectScanoutTo: {:x}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tmirrorOf: "
+ "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tsolitaryBlockedBy: {}\n\tactivelyTearing: {}\n\ttearingBlockedBy: {}\n\tdirectScanoutTo: "
+ "{:x}\n\tdirectScanoutBlockedBy: {}\n\tdisabled: "
+ "{}\n\tcurrentFormat: {}\n\tmirrorOf: "
"{}\n\tavailableModes: {}\n\n",
m->m_name, m->m_id, sc<int>(m->m_pixelSize.x), sc<int>(m->m_pixelSize.y), m->m_refreshRate, sc<int>(m->m_position.x), sc<int>(m->m_position.y), m->m_shortDescription,
m->m_output->make, m->m_output->model, sc<int>(m->m_output->physicalSize.x), sc<int>(m->m_output->physicalSize.y), m->m_output->serial, m->activeWorkspaceID(),
(!m->m_activeWorkspace ? "" : m->m_activeWorkspace->m_name), m->activeSpecialWorkspaceID(), (m->m_activeSpecialWorkspace ? m->m_activeSpecialWorkspace->m_name : ""),
sc<int>(m->m_reservedTopLeft.x), sc<int>(m->m_reservedTopLeft.y), sc<int>(m->m_reservedBottomRight.x), sc<int>(m->m_reservedBottomRight.y), m->m_scale,
sc<int>(m->m_transform), (m == g_pCompositor->m_lastMonitor ? "yes" : "no"), sc<int>(m->m_dpmsStatus), m->m_output->state->state().adaptiveSync,
- rc<uint64_t>(m->m_solitaryClient.get()), m->m_tearingState.activelyTearing, rc<uint64_t>(m->m_lastScanout.get()), !m->m_enabled,
- formatToString(m->m_output->state->state().drmFormat), m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format));
+ rc<uint64_t>(m->m_solitaryClient.get()), getSolitaryBlockedReason(m, format), m->m_tearingState.activelyTearing, getTearingBlockedReason(m, format),
+ rc<uint64_t>(m->m_lastScanout.get()), getDSBlockedReason(m, format), !m->m_enabled, formatToString(m->m_output->state->state().drmFormat),
+ m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format));
}
return result;
diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp
index b4f3d690..95bb65b8 100644
--- a/src/debug/HyprCtl.hpp
+++ b/src/debug/HyprCtl.hpp
@@ -33,6 +33,9 @@ class CHyprCtl {
static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format);
static std::string getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format);
+ static std::string getSolitaryBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format);
+ static std::string getDSBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format);
+ static std::string getTearingBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format);
static std::string getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format);
private: