diff --git a/CMakeLists.txt b/CMakeLists.txt
index e645349b6d..39c35a232c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -485,7 +485,6 @@ set(kwin_KDE_LIBS
KF5::ConfigCore
KF5::CoreAddons
KF5::ConfigWidgets
- KF5::Crash
KF5::GlobalAccel
KF5::GlobalAccelPrivate
KF5::I18n
@@ -570,7 +569,7 @@ target_link_libraries(kwin ${DL_LIBRARY})
endif()
kf5_add_kdeinit_executable(kwin_x11 main_x11.cpp)
-target_link_libraries(kdeinit_kwin_x11 kwin)
+target_link_libraries(kdeinit_kwin_x11 kwin KF5::Crash)
install(TARGETS kwin ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP )
install(TARGETS kdeinit_kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} )
diff --git a/main.cpp b/main.cpp
index 716717bdb6..d99aedb567 100644
--- a/main.cpp
+++ b/main.cpp
@@ -36,23 +36,14 @@ along with this program. If not, see .
// KDE
#include
-#include
-#include
-#include
#include
#include
#include
// Qt
#include
-#include
#include
-#include
-#include
-#include
-#include
#include
#include
-#include
#include
// system
@@ -80,52 +71,6 @@ Atoms* atoms;
int screen_number = -1;
bool is_multihead = false;
-class AlternativeWMDialog : public QDialog
-{
-public:
- AlternativeWMDialog()
- : QDialog() {
- QWidget* mainWidget = new QWidget(this);
- QVBoxLayout* layout = new QVBoxLayout(mainWidget);
- QString text = i18n(
- "KWin is unstable.\n"
- "It seems to have crashed several times in a row.\n"
- "You can select another window manager to run:");
- QLabel* textLabel = new QLabel(text, mainWidget);
- layout->addWidget(textLabel);
- wmList = new QComboBox(mainWidget);
- wmList->setEditable(true);
- layout->addWidget(wmList);
-
- addWM(QStringLiteral("metacity"));
- addWM(QStringLiteral("openbox"));
- addWM(QStringLiteral("fvwm2"));
- addWM(QStringLiteral(KWIN_INTERNAL_NAME_X11));
-
- QVBoxLayout *mainLayout = new QVBoxLayout(this);
- mainLayout->addWidget(mainWidget);
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
- buttons->button(QDialogButtonBox::Ok)->setDefault(true);
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- mainLayout->addWidget(buttons);
-
- raise();
- }
-
- void addWM(const QString& wm) {
- // TODO: Check if WM is installed
- if (!QStandardPaths::findExecutable(wm).isEmpty())
- wmList->addItem(wm);
- }
- QString selectedWM() const {
- return wmList->currentText();
- }
-
-private:
- QComboBox* wmList;
-};
-
int Application::crashes = 0;
bool Application::isX11MultiHead()
@@ -196,8 +141,6 @@ void Application::start()
m_config->reparseConfiguration();
}
- crashChecking();
-
performStartup();
}
@@ -213,55 +156,6 @@ void Application::destroyAtoms()
atoms = nullptr;
}
-void Application::setupCrashHandler()
-{
- KCrash::setEmergencySaveFunction(Application::crashHandler);
-}
-
-void Application::crashChecking()
-{
- setupCrashHandler();
- if (crashes >= 4) {
- // Something has gone seriously wrong
- AlternativeWMDialog dialog;
- QString cmd = QStringLiteral(KWIN_INTERNAL_NAME_X11);
- if (dialog.exec() == QDialog::Accepted)
- cmd = dialog.selectedWM();
- else
- ::exit(1);
- if (cmd.length() > 500) {
- qCDebug(KWIN_CORE) << "Command is too long, truncating";
- cmd = cmd.left(500);
- }
- qCDebug(KWIN_CORE) << "Starting" << cmd << "and exiting";
- char buf[1024];
- sprintf(buf, "%s &", cmd.toAscii().data());
- system(buf);
- ::exit(1);
- }
- if (crashes >= 2) {
- // Disable compositing if we have had too many crashes
- qCDebug(KWIN_CORE) << "Too many crashes recently, disabling compositing";
- KConfigGroup compgroup(KSharedConfig::openConfig(), "Compositing");
- compgroup.writeEntry("Enabled", false);
- }
- // Reset crashes count if we stay up for more that 15 seconds
- QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount()));
-}
-
-void Application::crashHandler(int signal)
-{
- crashes++;
-
- fprintf(stderr, "Application::crashHandler() called with signal %d; recent crashes: %d\n", signal, crashes);
- char cmd[1024];
- sprintf(cmd, "%s --crashes %d &",
- QFile::encodeName(QCoreApplication::applicationFilePath()).constData(), crashes);
-
- sleep(1);
- system(cmd);
-}
-
void Application::resetCrashesCount()
{
crashes = 0;
diff --git a/main.h b/main.h
index 83fbfb9f40..a0c6e7637b 100644
--- a/main.h
+++ b/main.h
@@ -185,7 +185,6 @@ Q_SIGNALS:
protected:
Application(OperationMode mode, int &argc, char **argv);
virtual void performStartup() = 0;
- virtual void setupCrashHandler();
void notifyKSplash();
void createInput();
@@ -213,16 +212,14 @@ protected:
}
void destroyAtoms();
- static void crashHandler(int signal);
-
protected:
QString m_originalSessionKey;
+ static int crashes;
private Q_SLOTS:
void resetCrashesCount();
private:
- void crashChecking();
QScopedPointer m_eventFilter;
bool m_configLock;
KSharedConfigPtr m_config;
@@ -234,7 +231,6 @@ private:
bool m_useKActivities = true;
#endif
Platform *m_platform = nullptr;
- static int crashes;
};
inline static Application *kwinApp()
diff --git a/main_wayland.cpp b/main_wayland.cpp
index ceac601df7..7d3b71a6b9 100644
--- a/main_wayland.cpp
+++ b/main_wayland.cpp
@@ -123,12 +123,6 @@ void ApplicationWayland::performStartup()
createBackend();
}
-void ApplicationWayland::setupCrashHandler()
-{
- // this disables auto-restart of kwin_wayland
- // do nothing hence allowing OS to create dump and so on
-}
-
void ApplicationWayland::createBackend()
{
connect(platform(), &Platform::screensQueried, this, &ApplicationWayland::continueStartupWithScreens);
diff --git a/main_wayland.h b/main_wayland.h
index b3a63fc8ff..c7f67410f5 100644
--- a/main_wayland.h
+++ b/main_wayland.h
@@ -56,7 +56,6 @@ public:
protected:
void performStartup() override;
- void setupCrashHandler() override;
private:
void createBackend();
diff --git a/main_x11.cpp b/main_x11.cpp
index 194ee54f9a..e4db348bf6 100644
--- a/main_x11.cpp
+++ b/main_x11.cpp
@@ -28,12 +28,21 @@ along with this program. If not, see .
#include "xcbutils.h"
// KDE
+#include
+#include
#include
#include
#include
// Qt
#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
// system
#ifdef HAVE_UNISTD_H
@@ -41,6 +50,8 @@ along with this program. If not, see .
#endif // HAVE_UNISTD_H
#include
+Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core", QtCriticalMsg)
+
namespace KWin
{
@@ -49,6 +60,54 @@ static void sighandler(int)
QApplication::exit();
}
+
+
+class AlternativeWMDialog : public QDialog
+{
+public:
+ AlternativeWMDialog()
+ : QDialog() {
+ QWidget* mainWidget = new QWidget(this);
+ QVBoxLayout* layout = new QVBoxLayout(mainWidget);
+ QString text = i18n(
+ "KWin is unstable.\n"
+ "It seems to have crashed several times in a row.\n"
+ "You can select another window manager to run:");
+ QLabel* textLabel = new QLabel(text, mainWidget);
+ layout->addWidget(textLabel);
+ wmList = new QComboBox(mainWidget);
+ wmList->setEditable(true);
+ layout->addWidget(wmList);
+
+ addWM(QStringLiteral("metacity"));
+ addWM(QStringLiteral("openbox"));
+ addWM(QStringLiteral("fvwm2"));
+ addWM(QStringLiteral(KWIN_INTERNAL_NAME_X11));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+ mainLayout->addWidget(mainWidget);
+ QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ buttons->button(QDialogButtonBox::Ok)->setDefault(true);
+ connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ mainLayout->addWidget(buttons);
+
+ raise();
+ }
+
+ void addWM(const QString& wm) {
+ // TODO: Check if WM is installed
+ if (!QStandardPaths::findExecutable(wm).isEmpty())
+ wmList->addItem(wm);
+ }
+ QString selectedWM() const {
+ return wmList->currentText();
+ }
+
+private:
+ QComboBox* wmList;
+};
+
//************************************
// KWinSelectionOwner
//************************************
@@ -149,6 +208,8 @@ void ApplicationX11::lostSelection()
void ApplicationX11::performStartup()
{
+ crashChecking();
+
if (Application::x11ScreenNumber() == -1) {
Application::setX11ScreenNumber(QX11Info::appScreen());
}
@@ -215,6 +276,55 @@ bool ApplicationX11::notify(QObject* o, QEvent* e)
return QApplication::notify(o, e);
}
+void ApplicationX11::setupCrashHandler()
+{
+ KCrash::setEmergencySaveFunction(ApplicationX11::crashHandler);
+}
+
+void ApplicationX11::crashChecking()
+{
+ setupCrashHandler();
+ if (crashes >= 4) {
+ // Something has gone seriously wrong
+ AlternativeWMDialog dialog;
+ QString cmd = QStringLiteral(KWIN_INTERNAL_NAME_X11);
+ if (dialog.exec() == QDialog::Accepted)
+ cmd = dialog.selectedWM();
+ else
+ ::exit(1);
+ if (cmd.length() > 500) {
+ qCDebug(KWIN_CORE) << "Command is too long, truncating";
+ cmd = cmd.left(500);
+ }
+ qCDebug(KWIN_CORE) << "Starting" << cmd << "and exiting";
+ char buf[1024];
+ sprintf(buf, "%s &", cmd.toAscii().data());
+ system(buf);
+ ::exit(1);
+ }
+ if (crashes >= 2) {
+ // Disable compositing if we have had too many crashes
+ qCDebug(KWIN_CORE) << "Too many crashes recently, disabling compositing";
+ KConfigGroup compgroup(KSharedConfig::openConfig(), "Compositing");
+ compgroup.writeEntry("Enabled", false);
+ }
+ // Reset crashes count if we stay up for more that 15 seconds
+ QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount()));
+}
+
+void ApplicationX11::crashHandler(int signal)
+{
+ crashes++;
+
+ fprintf(stderr, "Application::crashHandler() called with signal %d; recent crashes: %d\n", signal, crashes);
+ char cmd[1024];
+ sprintf(cmd, "%s --crashes %d &",
+ QFile::encodeName(QCoreApplication::applicationFilePath()).constData(), crashes);
+
+ sleep(1);
+ system(cmd);
+}
+
} // namespace
extern "C"
diff --git a/main_x11.h b/main_x11.h
index ca25bf486a..2d8e4c6df7 100644
--- a/main_x11.h
+++ b/main_x11.h
@@ -56,6 +56,11 @@ private Q_SLOTS:
void lostSelection();
private:
+ void crashChecking();
+ void setupCrashHandler();
+
+ static void crashHandler(int signal);
+
QScopedPointer owner;
bool m_replace;
};