diff --git a/CMakeLists.txt b/CMakeLists.txt index 6821d00ad9..de7b03a8b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,7 @@ find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS Crash DBusAddons GlobalAccel + GuiAddons I18n IdleTime Package diff --git a/src/helpers/killer/CMakeLists.txt b/src/helpers/killer/CMakeLists.txt index bb6a5774a5..741773aa6d 100644 --- a/src/helpers/killer/CMakeLists.txt +++ b/src/helpers/killer/CMakeLists.txt @@ -8,7 +8,9 @@ qt6_generate_wayland_protocol_client_sources(kwin_killer_helper FILES ${WaylandP target_link_libraries(kwin_killer_helper KF6::AuthCore + KF6::GuiAddons KF6::I18n + KF6::Service KF6::WidgetsAddons Qt::GuiPrivate Qt::WaylandClient diff --git a/src/helpers/killer/killer.cpp b/src/helpers/killer/killer.cpp index fc8d2dd6cc..0d54f1e220 100644 --- a/src/helpers/killer/killer.cpp +++ b/src/helpers/killer/killer.cpp @@ -7,9 +7,11 @@ */ #include +#include #include #include #include +#include #include #include @@ -65,7 +67,7 @@ int main(int argc, char *argv[]) { KLocalizedString::setApplicationDomain(QByteArrayLiteral("kwin")); QApplication app(argc, argv); - QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("dialog-warning"))); + QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"))); QCoreApplication::setApplicationName(QStringLiteral("kwin_killer_helper")); QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); QApplication::setApplicationDisplayName(i18n("Window Manager")); @@ -126,23 +128,32 @@ int main(int argc, char *argv[]) } bool isLocal = hostname == QStringLiteral("localhost"); + const auto service = KService::serviceByDesktopName(appname); + if (service) { + appname = service->name(); + QApplication::setApplicationDisplayName(appname); + } + + // Drop redundant application name, cf. QXcbWindow::setWindowTitle. + const QString titleSeparator = QString::fromUtf8(" \xe2\x80\x94 "); // // U+2014, EM DASH + caption.remove(titleSeparator + appname); + caption.remove(QStringLiteral(" – ") + appname); // EN dash (Firefox) + caption.remove(QStringLiteral(" - ") + appname); // classic minus :-) + caption = caption.toHtmlEscaped(); appname = appname.toHtmlEscaped(); hostname = hostname.toHtmlEscaped(); QString pidString = QString::number(pid); // format pid ourself as it does not make sense to format an ID according to locale settings - QString question = i18nc("@info", "Application \"%1\" is not responding", appname); - question += isLocal - ? xi18nc("@info", "You tried to close window \"%1\" from application \"%2\" (Process ID: %3) but the application is not responding.", - caption, appname, pidString) - : xi18nc("@info", "You tried to close window \"%1\" from application \"%2\" (Process ID: %3), running on host \"%4\", but the application is not responding.", - caption, appname, pidString, hostname); + QString question = (caption == appname) ? xi18nc("@info", "%1 is not responding. Do you want to terminate this application?", + appname) + : xi18nc("@info \"window title\" of application name is not responding.", "\"%1\" of %2 is not responding. Do you want to terminate this application?", + caption, appname); question += xi18nc("@info", - "Do you want to terminate this application?" - "Terminating the application will close all of its child windows. Any unsaved data will be lost."); + "Terminating this application will close all of its windows. Any unsaved data will be lost."); - KGuiItem continueButton = KGuiItem(i18n("&Terminate Application %1", appname), QStringLiteral("edit-bomb")); - KGuiItem cancelButton = KGuiItem(i18n("Wait Longer"), QStringLiteral("chronometer")); + KGuiItem continueButton = KGuiItem(i18nc("@action:button Terminate app", "&Terminate %1", appname), QStringLiteral("application-exit")); + KGuiItem cancelButton = KGuiItem(i18nc("@action:button Wait for frozen app to maybe respond again", "&Wait Longer"), QStringLiteral("chronometer")); if (isX11) { QX11Info::setAppUserTime(timestamp); @@ -150,9 +161,27 @@ int main(int argc, char *argv[]) auto *dialog = new KMessageDialog(KMessageDialog::WarningContinueCancel, question); dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setCaption(QString()); // use default caption. - dialog->setIcon(QIcon()); // use default warning icon. + dialog->setCaption(i18nc("@title:window", "Not Responding")); + + QIcon icon; + if (service) { + const QIcon appIcon = QIcon::fromTheme(service->icon()); + if (!appIcon.isNull()) { + // emblem-warning is non-standard, fall back to emblem-important if necessary. + const QIcon warningBadge = QIcon::fromTheme(QStringLiteral("emblem-warning"), QIcon::fromTheme(QStringLiteral("emblem-important"))); + + icon = KIconUtils::addOverlay(appIcon, warningBadge, qApp->isRightToLeft() ? Qt::BottomLeftCorner : Qt::BottomRightCorner); + } + } + dialog->setIcon(icon); // null icon will result in default warning icon. dialog->setButtons(continueButton, KGuiItem(), cancelButton); + + QStringList details{ + i18nc("@info", "Process ID: %1", pidString)}; + if (!isLocal) { + details << i18nc("@info", "Host name: %1", hostname); + } + dialog->setDetails(details.join(QLatin1Char('\n'))); dialog->winId(); std::unique_ptr xdgImporter;