anr: open anr dialog on parent's workspace (#12509)
This commit is contained in:
parent
9817553c66
commit
cbfbd9712a
4 changed files with 147 additions and 15 deletions
|
|
@ -18,6 +18,121 @@ using namespace Hyprutils::Memory;
|
||||||
#define UP CUniquePointer
|
#define UP CUniquePointer
|
||||||
#define SP CSharedPointer
|
#define SP CSharedPointer
|
||||||
|
|
||||||
|
// Uncomment once test vm can run hyprland-dialog
|
||||||
|
// static void testAnrDialogs() {
|
||||||
|
// NLog::log("{}Testing ANR dialogs", Colors::YELLOW);
|
||||||
|
//
|
||||||
|
// OK(getFromSocket("/keyword misc:enable_anr_dialog true"));
|
||||||
|
// OK(getFromSocket("/keyword misc:anr_missed_pings 1"));
|
||||||
|
//
|
||||||
|
// NLog::log("{}ANR dialog: regular workspaces", Colors::YELLOW);
|
||||||
|
// {
|
||||||
|
// OK(getFromSocket("/dispatch workspace 2"));
|
||||||
|
//
|
||||||
|
// auto kitty = Tests::spawnKitty("bad_kitty");
|
||||||
|
//
|
||||||
|
// if (!kitty) {
|
||||||
|
// ret = 1;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// auto str = getFromSocket("/activewindow");
|
||||||
|
// EXPECT_CONTAINS(str, "workspace: 2");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// OK(getFromSocket("/dispatch workspace 1"));
|
||||||
|
//
|
||||||
|
// ::kill(kitty->pid(), SIGSTOP);
|
||||||
|
// Tests::waitUntilWindowsN(2);
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// auto str = getFromSocket("/activeworkspace");
|
||||||
|
// EXPECT_CONTAINS(str, "windows: 0");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// OK(getFromSocket("/dispatch focuswindow class:hyprland-dialog"))
|
||||||
|
// auto str = getFromSocket("/activewindow");
|
||||||
|
// EXPECT_CONTAINS(str, "workspace: 2");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Tests::killAllWindows();
|
||||||
|
//
|
||||||
|
// NLog::log("{}ANR dialog: named workspaces", Colors::YELLOW);
|
||||||
|
// {
|
||||||
|
// OK(getFromSocket("/dispatch workspace name:yummy"));
|
||||||
|
//
|
||||||
|
// auto kitty = Tests::spawnKitty("bad_kitty");
|
||||||
|
//
|
||||||
|
// if (!kitty) {
|
||||||
|
// ret = 1;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// auto str = getFromSocket("/activewindow");
|
||||||
|
// EXPECT_CONTAINS(str, "yummy");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// OK(getFromSocket("/dispatch workspace 1"));
|
||||||
|
//
|
||||||
|
// ::kill(kitty->pid(), SIGSTOP);
|
||||||
|
// Tests::waitUntilWindowsN(2);
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// auto str = getFromSocket("/activeworkspace");
|
||||||
|
// EXPECT_CONTAINS(str, "windows: 0");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// OK(getFromSocket("/dispatch focuswindow class:hyprland-dialog"))
|
||||||
|
// auto str = getFromSocket("/activewindow");
|
||||||
|
// EXPECT_CONTAINS(str, "yummy");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Tests::killAllWindows();
|
||||||
|
//
|
||||||
|
// NLog::log("{}ANR dialog: special workspaces", Colors::YELLOW);
|
||||||
|
// {
|
||||||
|
// OK(getFromSocket("/dispatch workspace special:apple"));
|
||||||
|
//
|
||||||
|
// auto kitty = Tests::spawnKitty("bad_kitty");
|
||||||
|
//
|
||||||
|
// if (!kitty) {
|
||||||
|
// ret = 1;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// auto str = getFromSocket("/activewindow");
|
||||||
|
// EXPECT_CONTAINS(str, "special:apple");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// OK(getFromSocket("/dispatch togglespecialworkspace apple"));
|
||||||
|
// OK(getFromSocket("/dispatch workspace 1"));
|
||||||
|
//
|
||||||
|
// ::kill(kitty->pid(), SIGSTOP);
|
||||||
|
// Tests::waitUntilWindowsN(2);
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// auto str = getFromSocket("/activeworkspace");
|
||||||
|
// EXPECT_CONTAINS(str, "windows: 0");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// OK(getFromSocket("/dispatch focuswindow class:hyprland-dialog"))
|
||||||
|
// auto str = getFromSocket("/activewindow");
|
||||||
|
// EXPECT_CONTAINS(str, "special:apple");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// OK(getFromSocket("/reload"));
|
||||||
|
// Tests::killAllWindows();
|
||||||
|
// }
|
||||||
|
|
||||||
static bool test() {
|
static bool test() {
|
||||||
NLog::log("{}Testing config: misc:", Colors::GREEN);
|
NLog::log("{}Testing config: misc:", Colors::GREEN);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||||
|
#include "../desktop/rule/windowRule/WindowRule.hpp"
|
||||||
|
#include "../desktop/rule/Engine.hpp"
|
||||||
|
|
||||||
using namespace Hyprutils::OS;
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
|
|
@ -119,6 +121,9 @@ SP<CPromise<std::string>> CAsyncDialogBox::open() {
|
||||||
|
|
||||||
m_selfReference = m_selfWeakReference.lock();
|
m_selfReference = m_selfWeakReference.lock();
|
||||||
|
|
||||||
|
if (!m_execRuleToken.empty())
|
||||||
|
proc.addEnv(Desktop::Rule::EXEC_RULE_ENV_NAME, m_execRuleToken);
|
||||||
|
|
||||||
if (!proc.runAsync()) {
|
if (!proc.runAsync()) {
|
||||||
Log::logger->log(Log::ERR, "CAsyncDialogBox::open: failed to run async");
|
Log::logger->log(Log::ERR, "CAsyncDialogBox::open: failed to run async");
|
||||||
wl_event_source_remove(m_readEventSource);
|
wl_event_source_remove(m_readEventSource);
|
||||||
|
|
@ -154,3 +159,9 @@ pid_t CAsyncDialogBox::getPID() const {
|
||||||
SP<CAsyncDialogBox> CAsyncDialogBox::lockSelf() {
|
SP<CAsyncDialogBox> CAsyncDialogBox::lockSelf() {
|
||||||
return m_selfWeakReference.lock();
|
return m_selfWeakReference.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CAsyncDialogBox::setExecRule(std::string&& s) {
|
||||||
|
auto rule = Desktop::Rule::CWindowRule::buildFromExecString(std::move(s));
|
||||||
|
m_execRuleToken = rule->execToken();
|
||||||
|
Desktop::Rule::ruleEngine()->registerRule(std::move(rule));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class CAsyncDialogBox {
|
||||||
void kill();
|
void kill();
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
pid_t getPID() const;
|
pid_t getPID() const;
|
||||||
|
void setExecRule(std::string&& s);
|
||||||
|
|
||||||
SP<CAsyncDialogBox> lockSelf();
|
SP<CAsyncDialogBox> lockSelf();
|
||||||
|
|
||||||
|
|
@ -41,7 +42,8 @@ class CAsyncDialogBox {
|
||||||
pid_t m_dialogPid = 0;
|
pid_t m_dialogPid = 0;
|
||||||
wl_event_source* m_readEventSource = nullptr;
|
wl_event_source* m_readEventSource = nullptr;
|
||||||
Hyprutils::OS::CFileDescriptor m_pipeReadFd;
|
Hyprutils::OS::CFileDescriptor m_pipeReadFd;
|
||||||
std::string m_stdout = "";
|
std::string m_stdout = "";
|
||||||
|
std::string m_execRuleToken = "";
|
||||||
|
|
||||||
const std::string m_title;
|
const std::string m_title;
|
||||||
const std::string m_description;
|
const std::string m_description;
|
||||||
|
|
|
||||||
|
|
@ -188,21 +188,25 @@ void CANRManager::SANRData::runDialog(const std::string& appName, const std::str
|
||||||
|
|
||||||
const auto OPTION_TERMINATE_STR = I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_OPTION_TERMINATE, {});
|
const auto OPTION_TERMINATE_STR = I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_OPTION_TERMINATE, {});
|
||||||
const auto OPTION_WAIT_STR = I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_OPTION_WAIT, {});
|
const auto OPTION_WAIT_STR = I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_OPTION_WAIT, {});
|
||||||
|
const auto OPTIONS = std::vector{OPTION_TERMINATE_STR, OPTION_WAIT_STR};
|
||||||
|
const auto CLASS_STR = appClass.empty() ? I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_PROP_UNKNOWN, {}) : appClass;
|
||||||
|
const auto TITLE_STR = appName.empty() ? I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_PROP_UNKNOWN, {}) : appName;
|
||||||
|
const auto DESCRIPTION_STR = I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_CONTENT, {{"title", TITLE_STR}, {"class", CLASS_STR}});
|
||||||
|
|
||||||
dialogBox =
|
dialogBox = CAsyncDialogBox::create(I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_TITLE, {}), DESCRIPTION_STR, OPTIONS);
|
||||||
CAsyncDialogBox::create(I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_TITLE, {}),
|
|
||||||
I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_CONTENT,
|
for (const auto& w : g_pCompositor->m_windows) {
|
||||||
{
|
if (!w->m_isMapped)
|
||||||
//
|
continue;
|
||||||
{"class", appClass.empty() ? I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_PROP_UNKNOWN, {}) : appClass}, //
|
|
||||||
{"title", appName.empty() ? I18n::i18nEngine()->localize(I18n::TXT_KEY_ANR_PROP_UNKNOWN, {}) : appName} //
|
if (!fitsWindow(w))
|
||||||
}),
|
continue;
|
||||||
std::vector<std::string>{
|
|
||||||
//
|
if (w->m_workspace)
|
||||||
OPTION_TERMINATE_STR, //
|
dialogBox->setExecRule(std::format("workspace {} silent", w->m_workspace->getConfigName()));
|
||||||
OPTION_WAIT_STR //
|
|
||||||
} //
|
break;
|
||||||
);
|
}
|
||||||
|
|
||||||
dialogBox->open()->then([dialogWmPID, this, OPTION_TERMINATE_STR, OPTION_WAIT_STR](SP<CPromiseResult<std::string>> r) {
|
dialogBox->open()->then([dialogWmPID, this, OPTION_TERMINATE_STR, OPTION_WAIT_STR](SP<CPromiseResult<std::string>> r) {
|
||||||
if (r->hasError()) {
|
if (r->hasError()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue