summaryrefslogtreecommitdiff
path: root/src/managers/ANRManager.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-02-21 21:26:53 +0100
committerGitHub <noreply@github.com>2025-02-21 21:26:53 +0100
commitf4b148df1e2d8edc96bd878a4cfde32ca6515ac8 (patch)
treec8c4976280c0bbf450b572df33f312bdb6caab44 /src/managers/ANRManager.cpp
parent0e24f9c0d55fcd9a5b2461a865d0e5dc2ea195c8 (diff)
anr: add xwayland support (#9456)
Adds XWayland support to ANR dialogs
Diffstat (limited to 'src/managers/ANRManager.cpp')
-rw-r--r--src/managers/ANRManager.cpp143
1 files changed, 108 insertions, 35 deletions
diff --git a/src/managers/ANRManager.cpp b/src/managers/ANRManager.cpp
index 3793f27f..ebf02001 100644
--- a/src/managers/ANRManager.cpp
+++ b/src/managers/ANRManager.cpp
@@ -7,6 +7,7 @@
#include "../protocols/XDGShell.hpp"
#include "./eventLoop/EventLoopManager.hpp"
#include "../config/ConfigValue.hpp"
+#include "../xwayland/XSurface.hpp"
using namespace Hyprutils::OS;
@@ -26,25 +27,19 @@ CANRManager::CANRManager() {
static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) {
auto window = std::any_cast<PHLWINDOW>(data);
- if (window->m_bIsX11)
- return;
-
- for (const auto& w : g_pCompositor->m_vWindows) {
- if (w->m_bIsX11 || w == window || !w->m_pXDGSurface)
- continue;
-
- if (w->m_pXDGSurface->owner == window->m_pXDGSurface->owner)
+ for (const auto& d : m_data) {
+ if (d->fitsWindow(window))
return;
}
- m_data[window->m_pXDGSurface->owner] = makeShared<SANRData>();
+ m_data.emplace_back(makeShared<SANRData>(window));
});
m_timer->updateTimeout(TIMER_TIMEOUT);
}
void CANRManager::onTick() {
- std::erase_if(m_data, [](const auto& e) { return e.first.expired(); });
+ std::erase_if(m_data, [](const auto& e) { return e->isDefunct(); });
static auto PENABLEANR = CConfigValue<Hyprlang::INT>("misc:enable_anr_dialog");
@@ -53,14 +48,14 @@ void CANRManager::onTick() {
return;
}
- for (auto& [wmBase, data] : m_data) {
+ for (auto& data : m_data) {
PHLWINDOW firstWindow;
int count = 0;
for (const auto& w : g_pCompositor->m_vWindows) {
- if (!w->m_bIsMapped || w->m_bIsX11 || !w->m_pXDGSurface)
+ if (!w->m_bIsMapped)
continue;
- if (w->m_pXDGSurface->owner != wmBase)
+ if (!data->fitsWindow(w))
continue;
count++;
@@ -73,15 +68,13 @@ void CANRManager::onTick() {
if (data->missedResponses > 0) {
if (!data->isThreadRunning() && !data->dialogThreadSaidWait) {
- pid_t pid = 0;
- wl_client_get_credentials(wmBase->client(), &pid, nullptr, nullptr);
- data->runDialog("Application Not Responding", firstWindow->m_szTitle, firstWindow->m_szClass, pid);
+ data->runDialog("Application Not Responding", firstWindow->m_szTitle, firstWindow->m_szClass, data->getPid());
for (const auto& w : g_pCompositor->m_vWindows) {
- if (!w->m_bIsMapped || w->m_bIsX11 || !w->m_pXDGSurface)
+ if (!w->m_bIsMapped)
continue;
- if (w->m_pXDGSurface->owner != wmBase)
+ if (!data->fitsWindow(w))
continue;
*w->m_notRespondingTint = 0.2F;
@@ -95,22 +88,81 @@ void CANRManager::onTick() {
data->missedResponses++;
- wmBase->ping();
+ data->ping();
}
m_timer->updateTimeout(TIMER_TIMEOUT);
}
void CANRManager::onResponse(SP<CXDGWMBase> wmBase) {
- if (!m_data.contains(wmBase))
+ const auto DATA = dataFor(wmBase);
+
+ if (!DATA)
return;
- auto& data = m_data.at(wmBase);
+ onResponse(DATA);
+}
+
+void CANRManager::onResponse(SP<CXWaylandSurface> pXwaylandSurface) {
+ const auto DATA = dataFor(pXwaylandSurface);
+
+ if (!DATA)
+ return;
+
+ onResponse(DATA);
+}
+
+void CANRManager::onResponse(SP<CANRManager::SANRData> data) {
data->missedResponses = 0;
if (data->isThreadRunning())
data->killDialog();
}
+bool CANRManager::isNotResponding(PHLWINDOW pWindow) {
+ const auto DATA = dataFor(pWindow);
+
+ if (!DATA)
+ return false;
+
+ return isNotResponding(DATA);
+}
+
+bool CANRManager::isNotResponding(SP<CANRManager::SANRData> data) {
+ return data->missedResponses > 1;
+}
+
+SP<CANRManager::SANRData> CANRManager::dataFor(PHLWINDOW pWindow) {
+ auto it = m_data.end();
+ if (pWindow->m_pXWaylandSurface)
+ it = std::ranges::find_if(m_data, [&pWindow](const auto& data) { return data->xwaylandSurface && data->xwaylandSurface == pWindow->m_pXWaylandSurface; });
+ else if (pWindow->m_pXDGSurface)
+ it = std::ranges::find_if(m_data, [&pWindow](const auto& data) { return data->xdgBase && data->xdgBase == pWindow->m_pXDGSurface->owner; });
+ return it == m_data.end() ? nullptr : *it;
+}
+
+SP<CANRManager::SANRData> CANRManager::dataFor(SP<CXDGWMBase> wmBase) {
+ auto it = std::ranges::find_if(m_data, [&wmBase](const auto& data) { return data->xdgBase && data->xdgBase == wmBase; });
+ return it == m_data.end() ? nullptr : *it;
+}
+
+SP<CANRManager::SANRData> CANRManager::dataFor(SP<CXWaylandSurface> pXwaylandSurface) {
+ auto it = std::ranges::find_if(m_data, [&pXwaylandSurface](const auto& data) { return data->xwaylandSurface && data->xwaylandSurface == pXwaylandSurface; });
+ return it == m_data.end() ? nullptr : *it;
+}
+
+CANRManager::SANRData::SANRData(PHLWINDOW pWindow) :
+ xwaylandSurface(pWindow->m_pXWaylandSurface), xdgBase(pWindow->m_pXDGSurface ? pWindow->m_pXDGSurface->owner : WP<CXDGWMBase>{}) {
+ ;
+}
+
+CANRManager::SANRData::~SANRData() {
+ if (dialogThread.joinable()) {
+ killDialog();
+ // dangerous: might lock if the above failed!!
+ dialogThread.join();
+ }
+}
+
void CANRManager::SANRData::runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID) {
if (!dialogThreadExited)
killDialog();
@@ -122,11 +174,11 @@ void CANRManager::SANRData::runDialog(const std::string& title, const std::strin
dialogThreadExited = false;
dialogThreadSaidWait = false;
dialogThread = std::thread([title, appName, appClass, dialogWmPID, this]() {
- SP<CProcess> proc =
- makeShared<CProcess>("hyprland-dialog",
- std::vector<std::string>{"--title", title, "--text",
- std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?", appName, appClass),
- "--buttons", "Terminate;Wait"});
+ SP<CProcess> proc = makeShared<CProcess>("hyprland-dialog",
+ std::vector<std::string>{"--title", title, "--text",
+ std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?",
+ appName.empty() ? "unknown" : appName, appClass.empty() ? "unknown" : appClass),
+ "--buttons", "Terminate;Wait"});
dialogProc = proc;
proc->runSync();
@@ -163,16 +215,37 @@ void CANRManager::SANRData::killDialog() const {
kill(dialogProc->pid(), SIGKILL);
}
-CANRManager::SANRData::~SANRData() {
- if (dialogThread.joinable()) {
- killDialog();
- // dangerous: might lock if the above failed!!
- dialogThread.join();
+bool CANRManager::SANRData::fitsWindow(PHLWINDOW pWindow) const {
+ if (pWindow->m_pXWaylandSurface)
+ return pWindow->m_pXWaylandSurface == xwaylandSurface;
+ else if (pWindow->m_pXDGSurface)
+ return pWindow->m_pXDGSurface->owner == xdgBase && xdgBase;
+ return false;
+}
+
+bool CANRManager::SANRData::isDefunct() const {
+ return xdgBase.expired() && xwaylandSurface.expired();
+}
+
+pid_t CANRManager::SANRData::getPid() const {
+ if (xdgBase) {
+ pid_t pid = 0;
+ wl_client_get_credentials(xdgBase->client(), &pid, nullptr, nullptr);
+ return pid;
}
+
+ if (xwaylandSurface)
+ return xwaylandSurface->pid;
+
+ return 0;
}
-bool CANRManager::isNotResponding(SP<CXDGWMBase> wmBase) {
- if (!m_data.contains(wmBase))
- return false;
- return m_data[wmBase]->missedResponses > 1;
+void CANRManager::SANRData::ping() {
+ if (xdgBase) {
+ xdgBase->ping();
+ return;
+ }
+
+ if (xwaylandSurface)
+ xwaylandSurface->ping();
}