Changeset View
Changeset View
Standalone View
Standalone View
main_x11.cpp
Show All 22 Lines | |||||
23 | #include <config-kwin.h> | 23 | #include <config-kwin.h> | ||
24 | // kwin | 24 | // kwin | ||
25 | #include "platform.h" | 25 | #include "platform.h" | ||
26 | #include "sm.h" | 26 | #include "sm.h" | ||
27 | #include "workspace.h" | 27 | #include "workspace.h" | ||
28 | #include "xcbutils.h" | 28 | #include "xcbutils.h" | ||
29 | 29 | | |||
30 | // KDE | 30 | // KDE | ||
31 | #include <KConfigGroup> | ||||
32 | #include <KCrash> | ||||
31 | #include <KLocalizedString> | 33 | #include <KLocalizedString> | ||
32 | #include <KPluginLoader> | 34 | #include <KPluginLoader> | ||
33 | #include <KPluginMetaData> | 35 | #include <KPluginMetaData> | ||
34 | // Qt | 36 | // Qt | ||
35 | #include <qplatformdefs.h> | 37 | #include <qplatformdefs.h> | ||
38 | #include <QComboBox> | ||||
36 | #include <QCommandLineParser> | 39 | #include <QCommandLineParser> | ||
40 | #include <QDialog> | ||||
41 | #include <QDialogButtonBox> | ||||
42 | #include <QFile> | ||||
43 | #include <QLabel> | ||||
44 | #include <QPushButton> | ||||
45 | #include <QVBoxLayout> | ||||
37 | 46 | | |||
38 | // system | 47 | // system | ||
39 | #ifdef HAVE_UNISTD_H | 48 | #ifdef HAVE_UNISTD_H | ||
40 | #include <unistd.h> | 49 | #include <unistd.h> | ||
41 | #endif // HAVE_UNISTD_H | 50 | #endif // HAVE_UNISTD_H | ||
42 | #include <iostream> | 51 | #include <iostream> | ||
43 | 52 | | |||
53 | Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core", QtCriticalMsg) | ||||
54 | | ||||
44 | namespace KWin | 55 | namespace KWin | ||
45 | { | 56 | { | ||
46 | 57 | | |||
47 | static void sighandler(int) | 58 | static void sighandler(int) | ||
48 | { | 59 | { | ||
49 | QApplication::exit(); | 60 | QApplication::exit(); | ||
50 | } | 61 | } | ||
51 | 62 | | |||
63 | | ||||
64 | | ||||
65 | class AlternativeWMDialog : public QDialog | ||||
66 | { | ||||
67 | public: | ||||
68 | AlternativeWMDialog() | ||||
69 | : QDialog() { | ||||
70 | QWidget* mainWidget = new QWidget(this); | ||||
71 | QVBoxLayout* layout = new QVBoxLayout(mainWidget); | ||||
72 | QString text = i18n( | ||||
73 | "KWin is unstable.\n" | ||||
74 | "It seems to have crashed several times in a row.\n" | ||||
75 | "You can select another window manager to run:"); | ||||
76 | QLabel* textLabel = new QLabel(text, mainWidget); | ||||
77 | layout->addWidget(textLabel); | ||||
78 | wmList = new QComboBox(mainWidget); | ||||
79 | wmList->setEditable(true); | ||||
80 | layout->addWidget(wmList); | ||||
81 | | ||||
82 | addWM(QStringLiteral("metacity")); | ||||
83 | addWM(QStringLiteral("openbox")); | ||||
84 | addWM(QStringLiteral("fvwm2")); | ||||
85 | addWM(QStringLiteral(KWIN_INTERNAL_NAME_X11)); | ||||
86 | | ||||
87 | QVBoxLayout *mainLayout = new QVBoxLayout(this); | ||||
88 | mainLayout->addWidget(mainWidget); | ||||
89 | QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); | ||||
90 | buttons->button(QDialogButtonBox::Ok)->setDefault(true); | ||||
91 | connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); | ||||
92 | connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); | ||||
93 | mainLayout->addWidget(buttons); | ||||
94 | | ||||
95 | raise(); | ||||
96 | } | ||||
97 | | ||||
98 | void addWM(const QString& wm) { | ||||
99 | // TODO: Check if WM is installed | ||||
100 | if (!QStandardPaths::findExecutable(wm).isEmpty()) | ||||
101 | wmList->addItem(wm); | ||||
102 | } | ||||
103 | QString selectedWM() const { | ||||
104 | return wmList->currentText(); | ||||
105 | } | ||||
106 | | ||||
107 | private: | ||||
108 | QComboBox* wmList; | ||||
109 | }; | ||||
110 | | ||||
52 | //************************************ | 111 | //************************************ | ||
53 | // KWinSelectionOwner | 112 | // KWinSelectionOwner | ||
54 | //************************************ | 113 | //************************************ | ||
55 | 114 | | |||
56 | KWinSelectionOwner::KWinSelectionOwner(int screen_P) | 115 | KWinSelectionOwner::KWinSelectionOwner(int screen_P) | ||
57 | : KSelectionOwner(make_selection_atom(screen_P), screen_P) | 116 | : KSelectionOwner(make_selection_atom(screen_P), screen_P) | ||
58 | { | 117 | { | ||
59 | } | 118 | } | ||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Line(s) | 200 | { | |||
144 | destroyWorkspace(); | 203 | destroyWorkspace(); | ||
145 | // Remove windowmanager privileges | 204 | // Remove windowmanager privileges | ||
146 | Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE); | 205 | Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE); | ||
147 | quit(); | 206 | quit(); | ||
148 | } | 207 | } | ||
149 | 208 | | |||
150 | void ApplicationX11::performStartup() | 209 | void ApplicationX11::performStartup() | ||
151 | { | 210 | { | ||
211 | crashChecking(); | ||||
212 | | ||||
152 | if (Application::x11ScreenNumber() == -1) { | 213 | if (Application::x11ScreenNumber() == -1) { | ||
153 | Application::setX11ScreenNumber(QX11Info::appScreen()); | 214 | Application::setX11ScreenNumber(QX11Info::appScreen()); | ||
154 | } | 215 | } | ||
155 | 216 | | |||
156 | // QSessionManager for some reason triggers a very early commitDataRequest | 217 | // QSessionManager for some reason triggers a very early commitDataRequest | ||
157 | // and updates the key - before we create the workspace and load the session | 218 | // and updates the key - before we create the workspace and load the session | ||
158 | // data -> store and pass to the workspace constructor | 219 | // data -> store and pass to the workspace constructor | ||
159 | m_originalSessionKey = sessionKey(); | 220 | m_originalSessionKey = sessionKey(); | ||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | |||||
210 | 271 | | |||
211 | bool ApplicationX11::notify(QObject* o, QEvent* e) | 272 | bool ApplicationX11::notify(QObject* o, QEvent* e) | ||
212 | { | 273 | { | ||
213 | if (Workspace::self()->workspaceEvent(e)) | 274 | if (Workspace::self()->workspaceEvent(e)) | ||
214 | return true; | 275 | return true; | ||
215 | return QApplication::notify(o, e); | 276 | return QApplication::notify(o, e); | ||
216 | } | 277 | } | ||
217 | 278 | | |||
279 | void ApplicationX11::setupCrashHandler() | ||||
280 | { | ||||
281 | KCrash::setEmergencySaveFunction(ApplicationX11::crashHandler); | ||||
282 | } | ||||
283 | | ||||
284 | void ApplicationX11::crashChecking() | ||||
285 | { | ||||
286 | setupCrashHandler(); | ||||
287 | if (crashes >= 4) { | ||||
288 | // Something has gone seriously wrong | ||||
289 | AlternativeWMDialog dialog; | ||||
290 | QString cmd = QStringLiteral(KWIN_INTERNAL_NAME_X11); | ||||
291 | if (dialog.exec() == QDialog::Accepted) | ||||
292 | cmd = dialog.selectedWM(); | ||||
293 | else | ||||
294 | ::exit(1); | ||||
295 | if (cmd.length() > 500) { | ||||
296 | qCDebug(KWIN_CORE) << "Command is too long, truncating"; | ||||
297 | cmd = cmd.left(500); | ||||
298 | } | ||||
299 | qCDebug(KWIN_CORE) << "Starting" << cmd << "and exiting"; | ||||
300 | char buf[1024]; | ||||
301 | sprintf(buf, "%s &", cmd.toAscii().data()); | ||||
302 | system(buf); | ||||
303 | ::exit(1); | ||||
304 | } | ||||
305 | if (crashes >= 2) { | ||||
306 | // Disable compositing if we have had too many crashes | ||||
307 | qCDebug(KWIN_CORE) << "Too many crashes recently, disabling compositing"; | ||||
308 | KConfigGroup compgroup(KSharedConfig::openConfig(), "Compositing"); | ||||
309 | compgroup.writeEntry("Enabled", false); | ||||
310 | } | ||||
311 | // Reset crashes count if we stay up for more that 15 seconds | ||||
312 | QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount())); | ||||
313 | } | ||||
314 | | ||||
315 | void ApplicationX11::crashHandler(int signal) | ||||
316 | { | ||||
317 | crashes++; | ||||
318 | | ||||
319 | fprintf(stderr, "Application::crashHandler() called with signal %d; recent crashes: %d\n", signal, crashes); | ||||
320 | char cmd[1024]; | ||||
321 | sprintf(cmd, "%s --crashes %d &", | ||||
322 | QFile::encodeName(QCoreApplication::applicationFilePath()).constData(), crashes); | ||||
323 | | ||||
324 | sleep(1); | ||||
325 | system(cmd); | ||||
326 | } | ||||
327 | | ||||
218 | } // namespace | 328 | } // namespace | ||
219 | 329 | | |||
220 | extern "C" | 330 | extern "C" | ||
221 | KWIN_EXPORT int kdemain(int argc, char * argv[]) | 331 | KWIN_EXPORT int kdemain(int argc, char * argv[]) | ||
222 | { | 332 | { | ||
223 | KWin::Application::setupMalloc(); | 333 | KWin::Application::setupMalloc(); | ||
224 | KWin::Application::setupLocalizedString(); | 334 | KWin::Application::setupLocalizedString(); | ||
225 | 335 | | |||
▲ Show 20 Lines • Show All 132 Lines • Show Last 20 Lines |