parent
0e24f9c0d5
commit
f4b148df1e
7 changed files with 184 additions and 58 deletions
|
|
@ -1801,8 +1801,5 @@ void CWindow::deactivateGroupMembers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::isNotResponding() {
|
bool CWindow::isNotResponding() {
|
||||||
if (!m_pXDGSurface)
|
return g_pANRManager->isNotResponding(m_pSelf.lock());
|
||||||
return false;
|
|
||||||
|
|
||||||
return g_pANRManager->isNotResponding(m_pXDGSurface->owner.lock());
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../protocols/XDGShell.hpp"
|
#include "../protocols/XDGShell.hpp"
|
||||||
#include "./eventLoop/EventLoopManager.hpp"
|
#include "./eventLoop/EventLoopManager.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "../xwayland/XSurface.hpp"
|
||||||
|
|
||||||
using namespace Hyprutils::OS;
|
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) {
|
static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||||
auto window = std::any_cast<PHLWINDOW>(data);
|
auto window = std::any_cast<PHLWINDOW>(data);
|
||||||
|
|
||||||
if (window->m_bIsX11)
|
for (const auto& d : m_data) {
|
||||||
return;
|
if (d->fitsWindow(window))
|
||||||
|
|
||||||
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)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data[window->m_pXDGSurface->owner] = makeShared<SANRData>();
|
m_data.emplace_back(makeShared<SANRData>(window));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_timer->updateTimeout(TIMER_TIMEOUT);
|
m_timer->updateTimeout(TIMER_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANRManager::onTick() {
|
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");
|
static auto PENABLEANR = CConfigValue<Hyprlang::INT>("misc:enable_anr_dialog");
|
||||||
|
|
||||||
|
|
@ -53,14 +48,14 @@ void CANRManager::onTick() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& [wmBase, data] : m_data) {
|
for (auto& data : m_data) {
|
||||||
PHLWINDOW firstWindow;
|
PHLWINDOW firstWindow;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (const auto& w : g_pCompositor->m_vWindows) {
|
for (const auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (!w->m_bIsMapped || w->m_bIsX11 || !w->m_pXDGSurface)
|
if (!w->m_bIsMapped)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (w->m_pXDGSurface->owner != wmBase)
|
if (!data->fitsWindow(w))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -73,15 +68,13 @@ void CANRManager::onTick() {
|
||||||
|
|
||||||
if (data->missedResponses > 0) {
|
if (data->missedResponses > 0) {
|
||||||
if (!data->isThreadRunning() && !data->dialogThreadSaidWait) {
|
if (!data->isThreadRunning() && !data->dialogThreadSaidWait) {
|
||||||
pid_t pid = 0;
|
data->runDialog("Application Not Responding", firstWindow->m_szTitle, firstWindow->m_szClass, data->getPid());
|
||||||
wl_client_get_credentials(wmBase->client(), &pid, nullptr, nullptr);
|
|
||||||
data->runDialog("Application Not Responding", firstWindow->m_szTitle, firstWindow->m_szClass, pid);
|
|
||||||
|
|
||||||
for (const auto& w : g_pCompositor->m_vWindows) {
|
for (const auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (!w->m_bIsMapped || w->m_bIsX11 || !w->m_pXDGSurface)
|
if (!w->m_bIsMapped)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (w->m_pXDGSurface->owner != wmBase)
|
if (!data->fitsWindow(w))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
*w->m_notRespondingTint = 0.2F;
|
*w->m_notRespondingTint = 0.2F;
|
||||||
|
|
@ -95,22 +88,81 @@ void CANRManager::onTick() {
|
||||||
|
|
||||||
data->missedResponses++;
|
data->missedResponses++;
|
||||||
|
|
||||||
wmBase->ping();
|
data->ping();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_timer->updateTimeout(TIMER_TIMEOUT);
|
m_timer->updateTimeout(TIMER_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANRManager::onResponse(SP<CXDGWMBase> wmBase) {
|
void CANRManager::onResponse(SP<CXDGWMBase> wmBase) {
|
||||||
if (!m_data.contains(wmBase))
|
const auto DATA = dataFor(wmBase);
|
||||||
|
|
||||||
|
if (!DATA)
|
||||||
return;
|
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;
|
data->missedResponses = 0;
|
||||||
if (data->isThreadRunning())
|
if (data->isThreadRunning())
|
||||||
data->killDialog();
|
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) {
|
void CANRManager::SANRData::runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID) {
|
||||||
if (!dialogThreadExited)
|
if (!dialogThreadExited)
|
||||||
killDialog();
|
killDialog();
|
||||||
|
|
@ -122,11 +174,11 @@ void CANRManager::SANRData::runDialog(const std::string& title, const std::strin
|
||||||
dialogThreadExited = false;
|
dialogThreadExited = false;
|
||||||
dialogThreadSaidWait = false;
|
dialogThreadSaidWait = false;
|
||||||
dialogThread = std::thread([title, appName, appClass, dialogWmPID, this]() {
|
dialogThread = std::thread([title, appName, appClass, dialogWmPID, this]() {
|
||||||
SP<CProcess> proc =
|
SP<CProcess> proc = makeShared<CProcess>("hyprland-dialog",
|
||||||
makeShared<CProcess>("hyprland-dialog",
|
std::vector<std::string>{"--title", title, "--text",
|
||||||
std::vector<std::string>{"--title", title, "--text",
|
std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?",
|
||||||
std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?", appName, appClass),
|
appName.empty() ? "unknown" : appName, appClass.empty() ? "unknown" : appClass),
|
||||||
"--buttons", "Terminate;Wait"});
|
"--buttons", "Terminate;Wait"});
|
||||||
|
|
||||||
dialogProc = proc;
|
dialogProc = proc;
|
||||||
proc->runSync();
|
proc->runSync();
|
||||||
|
|
@ -163,16 +215,37 @@ void CANRManager::SANRData::killDialog() const {
|
||||||
kill(dialogProc->pid(), SIGKILL);
|
kill(dialogProc->pid(), SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CANRManager::SANRData::~SANRData() {
|
bool CANRManager::SANRData::fitsWindow(PHLWINDOW pWindow) const {
|
||||||
if (dialogThread.joinable()) {
|
if (pWindow->m_pXWaylandSurface)
|
||||||
killDialog();
|
return pWindow->m_pXWaylandSurface == xwaylandSurface;
|
||||||
// dangerous: might lock if the above failed!!
|
else if (pWindow->m_pXDGSurface)
|
||||||
dialogThread.join();
|
return pWindow->m_pXDGSurface->owner == xdgBase && xdgBase;
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CANRManager::isNotResponding(SP<CXDGWMBase> wmBase) {
|
bool CANRManager::SANRData::isDefunct() const {
|
||||||
if (!m_data.contains(wmBase))
|
return xdgBase.expired() && xwaylandSurface.expired();
|
||||||
return false;
|
}
|
||||||
return m_data[wmBase]->missedResponses > 1;
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CANRManager::SANRData::ping() {
|
||||||
|
if (xdgBase) {
|
||||||
|
xdgBase->ping();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xwaylandSurface)
|
||||||
|
xwaylandSurface->ping();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,22 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <hyprutils/os/Process.hpp>
|
#include <hyprutils/os/Process.hpp>
|
||||||
#include <hyprutils/os/FileDescriptor.hpp>
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
#include <map>
|
|
||||||
#include "./eventLoop/EventLoopTimer.hpp"
|
#include "./eventLoop/EventLoopTimer.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class CXDGWMBase;
|
class CXDGWMBase;
|
||||||
|
class CXWaylandSurface;
|
||||||
|
|
||||||
class CANRManager {
|
class CANRManager {
|
||||||
public:
|
public:
|
||||||
CANRManager();
|
CANRManager();
|
||||||
|
|
||||||
void onResponse(SP<CXDGWMBase> wmBase);
|
void onResponse(SP<CXDGWMBase> wmBase);
|
||||||
bool isNotResponding(SP<CXDGWMBase> wmBase);
|
void onResponse(SP<CXWaylandSurface> xwaylandSurface);
|
||||||
|
bool isNotResponding(PHLWINDOW pWindow);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_active = false;
|
bool m_active = false;
|
||||||
|
|
@ -27,8 +29,12 @@ class CANRManager {
|
||||||
void onTick();
|
void onTick();
|
||||||
|
|
||||||
struct SANRData {
|
struct SANRData {
|
||||||
|
SANRData(PHLWINDOW pWindow);
|
||||||
~SANRData();
|
~SANRData();
|
||||||
|
|
||||||
|
WP<CXWaylandSurface> xwaylandSurface;
|
||||||
|
WP<CXDGWMBase> xdgBase;
|
||||||
|
|
||||||
int missedResponses = 0;
|
int missedResponses = 0;
|
||||||
std::thread dialogThread;
|
std::thread dialogThread;
|
||||||
SP<Hyprutils::OS::CProcess> dialogProc;
|
SP<Hyprutils::OS::CProcess> dialogProc;
|
||||||
|
|
@ -38,9 +44,19 @@ class CANRManager {
|
||||||
void runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID);
|
void runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID);
|
||||||
bool isThreadRunning();
|
bool isThreadRunning();
|
||||||
void killDialog() const;
|
void killDialog() const;
|
||||||
|
bool isDefunct() const;
|
||||||
|
bool fitsWindow(PHLWINDOW pWindow) const;
|
||||||
|
pid_t getPid() const;
|
||||||
|
void ping();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<WP<CXDGWMBase>, SP<SANRData>> m_data;
|
void onResponse(SP<SANRData> data);
|
||||||
|
bool isNotResponding(SP<SANRData> data);
|
||||||
|
SP<SANRData> dataFor(PHLWINDOW pWindow);
|
||||||
|
SP<SANRData> dataFor(SP<CXDGWMBase> wmBase);
|
||||||
|
SP<SANRData> dataFor(SP<CXWaylandSurface> pXwaylandSurface);
|
||||||
|
|
||||||
|
std::vector<SP<SANRData>> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline UP<CANRManager> g_pANRManager;
|
inline UP<CANRManager> g_pANRManager;
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "XWayland.hpp"
|
#include "XWayland.hpp"
|
||||||
#include "../protocols/XWaylandShell.hpp"
|
#include "../protocols/XWaylandShell.hpp"
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
|
#include "../managers/ANRManager.hpp"
|
||||||
|
|
||||||
#ifndef NO_XWAYLAND
|
#ifndef NO_XWAYLAND
|
||||||
|
|
||||||
|
|
@ -243,6 +244,28 @@ void CXWaylandSurface::setWithdrawn(bool withdrawn_) {
|
||||||
xcb_change_property(g_pXWayland->pWM->connection, XCB_PROP_MODE_REPLACE, xID, HYPRATOMS["WM_STATE"], HYPRATOMS["WM_STATE"], 32, props.size(), props.data());
|
xcb_change_property(g_pXWayland->pWM->connection, XCB_PROP_MODE_REPLACE, xID, HYPRATOMS["WM_STATE"], HYPRATOMS["WM_STATE"], 32, props.size(), props.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXWaylandSurface::ping() {
|
||||||
|
bool supportsPing = std::ranges::find(protocols, HYPRATOMS["_NET_WM_PING"]) != protocols.end();
|
||||||
|
|
||||||
|
if (!supportsPing) {
|
||||||
|
Debug::log(TRACE, "CXWaylandSurface: XID {} does not support ping, just sending an instant reply", xID);
|
||||||
|
g_pANRManager->onResponse(self.lock());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
xcb_client_message_data_t msg = {};
|
||||||
|
msg.data32[0] = HYPRATOMS["_NET_WM_PING"];
|
||||||
|
msg.data32[1] = now.tv_sec * 1000 + now.tv_nsec / 1000000;
|
||||||
|
msg.data32[2] = xID;
|
||||||
|
|
||||||
|
lastPingSeq = msg.data32[1];
|
||||||
|
|
||||||
|
g_pXWayland->pWM->sendWMMessage(self.lock(), &msg, XCB_EVENT_MASK_PROPERTY_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) {
|
CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) {
|
||||||
|
|
@ -297,4 +320,8 @@ void CXWaylandSurface::setWithdrawn(bool withdrawn) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXWaylandSurface::ping() {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,11 @@ class CXWaylandSurface {
|
||||||
std::optional<bool> requestsMinimize;
|
std::optional<bool> requestsMinimize;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
uint32_t xID = 0;
|
uint32_t xID = 0;
|
||||||
uint64_t wlID = 0;
|
uint64_t wlID = 0;
|
||||||
uint64_t wlSerial = 0;
|
uint64_t wlSerial = 0;
|
||||||
pid_t pid = 0;
|
uint32_t lastPingSeq = 0;
|
||||||
|
pid_t pid = 0;
|
||||||
CBox geometry;
|
CBox geometry;
|
||||||
bool overrideRedirect = false;
|
bool overrideRedirect = false;
|
||||||
bool withdrawn = false;
|
bool withdrawn = false;
|
||||||
|
|
@ -88,7 +89,7 @@ class CXWaylandSurface {
|
||||||
|
|
||||||
UP<xcb_icccm_wm_hints_t> hints;
|
UP<xcb_icccm_wm_hints_t> hints;
|
||||||
UP<xcb_size_hints_t> sizeHints;
|
UP<xcb_size_hints_t> sizeHints;
|
||||||
std::vector<uint32_t> atoms;
|
std::vector<uint32_t> atoms, protocols;
|
||||||
std::string role = "";
|
std::string role = "";
|
||||||
bool transient = false;
|
bool transient = false;
|
||||||
|
|
||||||
|
|
@ -99,6 +100,7 @@ class CXWaylandSurface {
|
||||||
void setMinimized(bool mz);
|
void setMinimized(bool mz);
|
||||||
void restackToTop();
|
void restackToTop();
|
||||||
void close();
|
void close();
|
||||||
|
void ping();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CXWaylandSurface(uint32_t xID, CBox geometry, bool OR);
|
CXWaylandSurface(uint32_t xID, CBox geometry, bool OR);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../protocols/core/Seat.hpp"
|
#include "../protocols/core/Seat.hpp"
|
||||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||||
#include "../managers/SeatManager.hpp"
|
#include "../managers/SeatManager.hpp"
|
||||||
|
#include "../managers/ANRManager.hpp"
|
||||||
#include "../protocols/XWaylandShell.hpp"
|
#include "../protocols/XWaylandShell.hpp"
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
using namespace Hyprutils::OS;
|
using namespace Hyprutils::OS;
|
||||||
|
|
@ -283,6 +284,16 @@ void CXWM::readProp(SP<CXWaylandSurface> XSURF, uint32_t atom, xcb_get_property_
|
||||||
XSURF->sizeHints->max_height = -1;
|
XSURF->sizeHints->max_height = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (atom == HYPRATOMS["WM_PROTOCOLS"]) {
|
||||||
|
if (reply->type == XCB_ATOM_ATOM) {
|
||||||
|
auto atoms = (xcb_atom_t*)xcb_get_property_value(reply);
|
||||||
|
std::vector<uint32_t> vec;
|
||||||
|
vec.reserve(reply->value_len);
|
||||||
|
for (size_t i = 0; i < reply->value_len; ++i) {
|
||||||
|
vec.emplace_back(atoms[i]);
|
||||||
|
}
|
||||||
|
XSURF->protocols = vec;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(TRACE, "[xwm] Unhandled prop {} -> {}", atom, propName);
|
Debug::log(TRACE, "[xwm] Unhandled prop {} -> {}", atom, propName);
|
||||||
return;
|
return;
|
||||||
|
|
@ -315,16 +326,14 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) {
|
||||||
if (!XSURF)
|
if (!XSURF)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string propName = "?";
|
std::string propName = getAtomName(e->type);
|
||||||
for (auto const& ha : HYPRATOMS) {
|
|
||||||
if (ha.second != e->type)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
propName = ha.first;
|
if (e->type == HYPRATOMS["WM_PROTOCOLS"]) {
|
||||||
break;
|
if (e->data.data32[1] == XSURF->lastPingSeq && e->data.data32[0] == HYPRATOMS["_NET_WM_PING"]) {
|
||||||
}
|
g_pANRManager->onResponse(XSURF);
|
||||||
|
return;
|
||||||
if (e->type == HYPRATOMS["WL_SURFACE_ID"]) {
|
}
|
||||||
|
} else if (e->type == HYPRATOMS["WL_SURFACE_ID"]) {
|
||||||
if (XSURF->surface) {
|
if (XSURF->surface) {
|
||||||
Debug::log(WARN, "[xwm] Re-assignment of WL_SURFACE_ID");
|
Debug::log(WARN, "[xwm] Re-assignment of WL_SURFACE_ID");
|
||||||
dissociate(XSURF);
|
dissociate(XSURF);
|
||||||
|
|
@ -1056,9 +1065,10 @@ void CXWM::onNewResource(SP<CXWaylandSurfaceResource> resource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWM::readWindowData(SP<CXWaylandSurface> surf) {
|
void CXWM::readWindowData(SP<CXWaylandSurface> surf) {
|
||||||
const std::array<xcb_atom_t, 8> interestingProps = {
|
const std::array<xcb_atom_t, 9> interestingProps = {
|
||||||
XCB_ATOM_WM_CLASS, XCB_ATOM_WM_NAME, XCB_ATOM_WM_TRANSIENT_FOR, HYPRATOMS["WM_HINTS"],
|
XCB_ATOM_WM_CLASS, XCB_ATOM_WM_NAME, XCB_ATOM_WM_TRANSIENT_FOR, HYPRATOMS["WM_HINTS"],
|
||||||
HYPRATOMS["_NET_WM_STATE"], HYPRATOMS["_NET_WM_NAME"], HYPRATOMS["_NET_WM_WINDOW_TYPE"], HYPRATOMS["WM_NORMAL_HINTS"],
|
HYPRATOMS["_NET_WM_STATE"], HYPRATOMS["_NET_WM_NAME"], HYPRATOMS["_NET_WM_WINDOW_TYPE"], HYPRATOMS["WM_NORMAL_HINTS"],
|
||||||
|
HYPRATOMS["WM_PROTOCOLS"],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < interestingProps.size(); i++) {
|
for (size_t i = 0; i < interestingProps.size(); i++) {
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ inline std::unordered_map<std::string, uint32_t> HYPRATOMS = {
|
||||||
HYPRATOM("_NET_WORKAREA"),
|
HYPRATOM("_NET_WORKAREA"),
|
||||||
HYPRATOM("_NET_WM_ICON"),
|
HYPRATOM("_NET_WM_ICON"),
|
||||||
HYPRATOM("_NET_WM_CM_S0"),
|
HYPRATOM("_NET_WM_CM_S0"),
|
||||||
|
HYPRATOM("_NET_WM_PING"),
|
||||||
HYPRATOM("WM_PROTOCOLS"),
|
HYPRATOM("WM_PROTOCOLS"),
|
||||||
HYPRATOM("WM_HINTS"),
|
HYPRATOM("WM_HINTS"),
|
||||||
HYPRATOM("WM_DELETE_WINDOW"),
|
HYPRATOM("WM_DELETE_WINDOW"),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue