Changeset View
Changeset View
Standalone View
Standalone View
main.cpp
Show All 30 Lines | |||||
31 | #include "options.h" | 31 | #include "options.h" | ||
32 | #include "screens.h" | 32 | #include "screens.h" | ||
33 | #include "sm.h" | 33 | #include "sm.h" | ||
34 | #include "workspace.h" | 34 | #include "workspace.h" | ||
35 | #include "xcbutils.h" | 35 | #include "xcbutils.h" | ||
36 | 36 | | |||
37 | // KDE | 37 | // KDE | ||
38 | #include <KAboutData> | 38 | #include <KAboutData> | ||
39 | #include <KConfig> | | |||
40 | #include <KConfigGroup> | | |||
41 | #include <KCrash> | | |||
42 | #include <KLocalizedString> | 39 | #include <KLocalizedString> | ||
43 | #include <KPluginMetaData> | 40 | #include <KPluginMetaData> | ||
44 | #include <KSharedConfig> | 41 | #include <KSharedConfig> | ||
45 | // Qt | 42 | // Qt | ||
46 | #include <qplatformdefs.h> | 43 | #include <qplatformdefs.h> | ||
47 | #include <QComboBox> | | |||
48 | #include <qcommandlineparser.h> | 44 | #include <qcommandlineparser.h> | ||
49 | #include <QDialog> | | |||
50 | #include <QDialogButtonBox> | | |||
51 | #include <QLabel> | | |||
52 | #include <QPushButton> | | |||
53 | #include <QQuickWindow> | 45 | #include <QQuickWindow> | ||
54 | #include <QStandardPaths> | 46 | #include <QStandardPaths> | ||
55 | #include <QVBoxLayout> | | |||
56 | #include <QtDBus/QtDBus> | 47 | #include <QtDBus/QtDBus> | ||
57 | 48 | | |||
58 | // system | 49 | // system | ||
59 | #ifdef HAVE_UNISTD_H | 50 | #ifdef HAVE_UNISTD_H | ||
60 | #include <unistd.h> | 51 | #include <unistd.h> | ||
61 | #endif // HAVE_UNISTD_H | 52 | #endif // HAVE_UNISTD_H | ||
62 | 53 | | |||
63 | #ifdef HAVE_MALLOC_H | 54 | #ifdef HAVE_MALLOC_H | ||
Show All 11 Lines | |||||
75 | 66 | | |||
76 | Options* options; | 67 | Options* options; | ||
77 | 68 | | |||
78 | Atoms* atoms; | 69 | Atoms* atoms; | ||
79 | 70 | | |||
80 | int screen_number = -1; | 71 | int screen_number = -1; | ||
81 | bool is_multihead = false; | 72 | bool is_multihead = false; | ||
82 | 73 | | |||
83 | class AlternativeWMDialog : public QDialog | | |||
84 | { | | |||
85 | public: | | |||
86 | AlternativeWMDialog() | | |||
87 | : QDialog() { | | |||
88 | QWidget* mainWidget = new QWidget(this); | | |||
89 | QVBoxLayout* layout = new QVBoxLayout(mainWidget); | | |||
90 | QString text = i18n( | | |||
91 | "KWin is unstable.\n" | | |||
92 | "It seems to have crashed several times in a row.\n" | | |||
93 | "You can select another window manager to run:"); | | |||
94 | QLabel* textLabel = new QLabel(text, mainWidget); | | |||
95 | layout->addWidget(textLabel); | | |||
96 | wmList = new QComboBox(mainWidget); | | |||
97 | wmList->setEditable(true); | | |||
98 | layout->addWidget(wmList); | | |||
99 | | ||||
100 | addWM(QStringLiteral("metacity")); | | |||
101 | addWM(QStringLiteral("openbox")); | | |||
102 | addWM(QStringLiteral("fvwm2")); | | |||
103 | addWM(QStringLiteral(KWIN_INTERNAL_NAME_X11)); | | |||
104 | | ||||
105 | QVBoxLayout *mainLayout = new QVBoxLayout(this); | | |||
106 | mainLayout->addWidget(mainWidget); | | |||
107 | QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); | | |||
108 | buttons->button(QDialogButtonBox::Ok)->setDefault(true); | | |||
109 | connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); | | |||
110 | connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); | | |||
111 | mainLayout->addWidget(buttons); | | |||
112 | | ||||
113 | raise(); | | |||
114 | } | | |||
115 | | ||||
116 | void addWM(const QString& wm) { | | |||
117 | // TODO: Check if WM is installed | | |||
118 | if (!QStandardPaths::findExecutable(wm).isEmpty()) | | |||
119 | wmList->addItem(wm); | | |||
120 | } | | |||
121 | QString selectedWM() const { | | |||
122 | return wmList->currentText(); | | |||
123 | } | | |||
124 | | ||||
125 | private: | | |||
126 | QComboBox* wmList; | | |||
127 | }; | | |||
128 | | ||||
129 | int Application::crashes = 0; | 74 | int Application::crashes = 0; | ||
130 | 75 | | |||
131 | bool Application::isX11MultiHead() | 76 | bool Application::isX11MultiHead() | ||
132 | { | 77 | { | ||
133 | return is_multihead; | 78 | return is_multihead; | ||
134 | } | 79 | } | ||
135 | 80 | | |||
136 | void Application::setX11MultiHead(bool multiHead) | 81 | void Application::setX11MultiHead(bool multiHead) | ||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Line(s) | 135 | if (!m_config) { | |||
191 | m_config = KSharedConfig::openConfig(); | 136 | m_config = KSharedConfig::openConfig(); | ||
192 | } | 137 | } | ||
193 | if (!m_config->isImmutable() && m_configLock) { | 138 | if (!m_config->isImmutable() && m_configLock) { | ||
194 | // TODO: This shouldn't be necessary | 139 | // TODO: This shouldn't be necessary | ||
195 | //config->setReadOnly( true ); | 140 | //config->setReadOnly( true ); | ||
196 | m_config->reparseConfiguration(); | 141 | m_config->reparseConfiguration(); | ||
197 | } | 142 | } | ||
198 | 143 | | |||
199 | crashChecking(); | | |||
200 | | ||||
201 | performStartup(); | 144 | performStartup(); | ||
202 | } | 145 | } | ||
203 | 146 | | |||
204 | Application::~Application() | 147 | Application::~Application() | ||
205 | { | 148 | { | ||
206 | delete options; | 149 | delete options; | ||
207 | destroyAtoms(); | 150 | destroyAtoms(); | ||
208 | } | 151 | } | ||
209 | 152 | | |||
210 | void Application::destroyAtoms() | 153 | void Application::destroyAtoms() | ||
211 | { | 154 | { | ||
212 | delete atoms; | 155 | delete atoms; | ||
213 | atoms = nullptr; | 156 | atoms = nullptr; | ||
214 | } | 157 | } | ||
215 | 158 | | |||
216 | void Application::setupCrashHandler() | | |||
217 | { | | |||
218 | KCrash::setEmergencySaveFunction(Application::crashHandler); | | |||
219 | } | | |||
220 | | ||||
221 | void Application::crashChecking() | | |||
222 | { | | |||
223 | setupCrashHandler(); | | |||
224 | if (crashes >= 4) { | | |||
225 | // Something has gone seriously wrong | | |||
226 | AlternativeWMDialog dialog; | | |||
227 | QString cmd = QStringLiteral(KWIN_INTERNAL_NAME_X11); | | |||
228 | if (dialog.exec() == QDialog::Accepted) | | |||
229 | cmd = dialog.selectedWM(); | | |||
230 | else | | |||
231 | ::exit(1); | | |||
232 | if (cmd.length() > 500) { | | |||
233 | qCDebug(KWIN_CORE) << "Command is too long, truncating"; | | |||
234 | cmd = cmd.left(500); | | |||
235 | } | | |||
236 | qCDebug(KWIN_CORE) << "Starting" << cmd << "and exiting"; | | |||
237 | char buf[1024]; | | |||
238 | sprintf(buf, "%s &", cmd.toAscii().data()); | | |||
239 | system(buf); | | |||
240 | ::exit(1); | | |||
241 | } | | |||
242 | if (crashes >= 2) { | | |||
243 | // Disable compositing if we have had too many crashes | | |||
244 | qCDebug(KWIN_CORE) << "Too many crashes recently, disabling compositing"; | | |||
245 | KConfigGroup compgroup(KSharedConfig::openConfig(), "Compositing"); | | |||
246 | compgroup.writeEntry("Enabled", false); | | |||
247 | } | | |||
248 | // Reset crashes count if we stay up for more that 15 seconds | | |||
249 | QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount())); | | |||
250 | } | | |||
251 | | ||||
252 | void Application::crashHandler(int signal) | | |||
253 | { | | |||
254 | crashes++; | | |||
255 | | ||||
256 | fprintf(stderr, "Application::crashHandler() called with signal %d; recent crashes: %d\n", signal, crashes); | | |||
257 | char cmd[1024]; | | |||
258 | sprintf(cmd, "%s --crashes %d &", | | |||
259 | QFile::encodeName(QCoreApplication::applicationFilePath()).constData(), crashes); | | |||
260 | | ||||
261 | sleep(1); | | |||
262 | system(cmd); | | |||
263 | } | | |||
264 | | ||||
265 | void Application::resetCrashesCount() | 159 | void Application::resetCrashesCount() | ||
266 | { | 160 | { | ||
267 | crashes = 0; | 161 | crashes = 0; | ||
268 | } | 162 | } | ||
269 | 163 | | |||
270 | void Application::setCrashCount(int count) | 164 | void Application::setCrashCount(int count) | ||
271 | { | 165 | { | ||
272 | crashes = count; | 166 | crashes = count; | ||
▲ Show 20 Lines • Show All 284 Lines • Show Last 20 Lines |