13#include <config-kwin.h>
28#include <KConfigGroup>
30#include <KGlobalAccel>
31#include <KLocalizedString>
32#include <KSelectionOwner>
33#include <KSignalHandler>
37#include <QCommandLineParser>
39#include <QDialogButtonBox>
43#include <QSurfaceFormat>
45#include <qplatformdefs.h>
46#include <private/qtx11extras_p.h>
53Q_LOGGING_CATEGORY(KWIN_CORE,
"kwin_core", QtWarningMsg)
64 QWidget *mainWidget =
new QWidget(
this);
65 QVBoxLayout *layout =
new QVBoxLayout(mainWidget);
66 QString text = i18n(
"KWin is unstable.\n"
67 "It seems to have crashed several times in a row.\n"
68 "You can select another window manager to run:");
69 QLabel *textLabel =
new QLabel(text, mainWidget);
70 layout->addWidget(textLabel);
71 wmList =
new QComboBox(mainWidget);
72 wmList->setEditable(
true);
73 layout->addWidget(wmList);
75 addWM(QStringLiteral(
"metacity"));
76 addWM(QStringLiteral(
"openbox"));
77 addWM(QStringLiteral(
"fvwm2"));
78 addWM(QStringLiteral(
"kwin_x11"));
80 QVBoxLayout *mainLayout =
new QVBoxLayout(
this);
81 mainLayout->addWidget(mainWidget);
82 QDialogButtonBox *buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
this);
83 buttons->button(QDialogButtonBox::Ok)->setDefault(
true);
84 connect(buttons, &QDialogButtonBox::accepted,
this, &QDialog::accept);
85 connect(buttons, &QDialogButtonBox::rejected,
this, &QDialog::reject);
86 mainLayout->addWidget(buttons);
94 if (!QStandardPaths::findExecutable(wm).isEmpty()) {
100 return wmList->currentText();
112 : KSelectionOwner(make_selection_atom())
117 bool genericReply(xcb_atom_t target_P, xcb_atom_t property_P, xcb_window_t requestor_P)
override
119 if (target_P == xa_version) {
121 xcb_change_property(kwinApp()->x11Connection(), XCB_PROP_MODE_REPLACE, requestor_P,
122 property_P, XCB_ATOM_INTEGER, 32, 2,
version);
124 return KSelectionOwner::genericReply(target_P, property_P, requestor_P);
129 void replyTargets(xcb_atom_t property_P, xcb_window_t requestor_P)
override
131 KSelectionOwner::replyTargets(property_P, requestor_P);
132 xcb_atom_t
atoms[1] = {xa_version};
134 xcb_change_property(kwinApp()->x11Connection(), XCB_PROP_MODE_APPEND, requestor_P,
135 property_P, XCB_ATOM_ATOM, 32, 1,
atoms);
138 void getAtoms()
override
140 KSelectionOwner::getAtoms();
141 if (xa_version == XCB_ATOM_NONE) {
142 constexpr QByteArrayView name{
"VERSION"};
143 UniqueCPtr<xcb_intern_atom_reply_t> atom(xcb_intern_atom_reply(
144 kwinApp()->x11Connection(),
145 xcb_intern_atom_unchecked(kwinApp()->x11Connection(),
false, name.length(), name.constData()),
148 xa_version = atom->atom;
153 xcb_atom_t make_selection_atom()
155 constexpr QByteArrayView screen{
"WM_S0"};
156 UniqueCPtr<xcb_intern_atom_reply_t> atom(xcb_intern_atom_reply(
157 kwinApp()->x11Connection(),
158 xcb_intern_atom_unchecked(kwinApp()->x11Connection(),
false, screen.length(), screen.constData()),
161 return XCB_ATOM_NONE;
165 static xcb_atom_t xa_version;
167xcb_atom_t KWinSelectionOwner::xa_version = XCB_ATOM_NONE;
194 if (owner !=
nullptr && owner->ownerWindow() != XCB_WINDOW_NONE) {
195 Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT);
218 return outlineVisual;
243void ApplicationX11::lostSelection()
255 Xcb::selectInput(kwinApp()->
x11RootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE);
264 owner = std::make_unique<KWinSelectionOwner>();
265 connect(owner.get(), &KSelectionOwner::failedToClaimOwnership, [] {
266 fputs(i18n(
"kwin: unable to claim manager selection, another wm running? (try using --replace)\n").toLocal8Bit().constData(), stderr);
269 connect(owner.get(), &KSelectionOwner::lostOwnership,
this, &ApplicationX11::lostSelection);
270 connect(owner.get(), &KSelectionOwner::claimedOwnership,
this, [
this] {
271 installNativeX11EventFilter();
274 if (!outputBackend()->initialize()) {
279 const uint32_t maskValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
281 xcb_change_window_attributes_checked(kwinApp()->
x11Connection(),
286 fputs(i18n(
"kwin: another window manager is running (try using --replace)\n").toLocal8Bit().constData(), stderr);
294 connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutActiveChanged,
this, [
this](QAction *triggeredAction) {
295 QVariant timestamp = triggeredAction->property(
"org.kde.kglobalaccel.activationTimestamp");
297 const quint32 t = timestamp.toULongLong(&ok);
316 owner->claim(m_replace || wasCrash(),
true);
320 createTabletModeManager();
323void ApplicationX11::setupCrashHandler()
325 KCrash::setEmergencySaveFunction(ApplicationX11::crashHandler);
328void ApplicationX11::crashChecking()
333 AlternativeWMDialog dialog;
334 QString cmd = QStringLiteral(
"kwin_x11");
335 if (dialog.exec() == QDialog::Accepted) {
336 cmd = dialog.selectedWM();
340 if (cmd.length() > 500) {
341 qCDebug(KWIN_CORE) <<
"Command is too long, truncating";
344 qCDebug(KWIN_CORE) <<
"Starting" << cmd <<
"and exiting";
346 sprintf(buf,
"%s &", cmd.toLatin1().data());
351 QTimer::singleShot(15 * 1000,
this, &Application::resetCrashesCount);
354void ApplicationX11::notifyKSplash()
357 QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral(
"org.kde.KSplash"),
358 QStringLiteral(
"/KSplash"),
359 QStringLiteral(
"org.kde.KSplash"),
360 QStringLiteral(
"setStage"));
361 ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral(
"wm"));
362 QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
365void ApplicationX11::crashHandler(
int signal)
369 fprintf(stderr,
"Application::crashHandler() called with signal %d; recent crashes: %d\n", signal, crashes);
371 sprintf(cmd,
"%s --crashes %d &",
372 QFile::encodeName(QCoreApplication::applicationFilePath()).constData(), crashes);
380int main(
int argc,
char *argv[])
385 signal(SIGPIPE, SIG_IGN);
388 setenv(
"QT_QPA_PLATFORM",
"xcb",
true);
391 setenv(
"QT_ENABLE_HIGHDPI_SCALING",
"0",
true);
393 qunsetenv(
"QT_SCALE_FACTOR");
394 qunsetenv(
"QT_SCREEN_SCALE_FACTORS");
397 QCoreApplication::setAttribute(Qt::AA_DisableSessionManager);
399 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
401 QSurfaceFormat format = QSurfaceFormat::defaultFormat();
403 format.setOptions(QSurfaceFormat::ResetNotification);
405 format.setSwapInterval(0);
406 QSurfaceFormat::setDefaultFormat(format);
411 qunsetenv(
"QT_QPA_PLATFORM");
412 qunsetenv(
"QT_ENABLE_HIGHDPI_SCALING");
416 KSignalHandler::self()->watchSignal(SIGTERM);
417 KSignalHandler::self()->watchSignal(SIGINT);
418 KSignalHandler::self()->watchSignal(SIGHUP);
419 QObject::connect(KSignalHandler::self(), &KSignalHandler::signalReceived,
420 &a, &QCoreApplication::exit);
424 QCommandLineOption replaceOption(QStringLiteral(
"replace"), i18n(
"Replace already-running ICCCM2.0-compliant window manager"));
426 QCommandLineParser parser;
428 parser.addOption(replaceOption);
429#if KWIN_BUILD_ACTIVITIES
430 QCommandLineOption noActivitiesOption(QStringLiteral(
"no-kactivities"),
431 i18n(
"Disable KActivities integration."));
432 parser.addOption(noActivitiesOption);
438#if KWIN_BUILD_ACTIVITIES
439 if (parser.isSet(noActivitiesOption)) {
440 a.setUseKActivities(
false);
445 if (a.platformName().toLower() != QStringLiteral(
"xcb")) {
446 fprintf(stderr,
"%s: FATAL ERROR expecting platform xcb but got platform %s\n",
447 argv[0], qPrintable(a.platformName()));
450 if (!QX11Info::display()) {
451 fprintf(stderr,
"%s: FATAL ERROR KWin requires Xlib support in the xcb plugin. Do not configure Qt with -no-xcb-xlib\n",
463#include "main_x11.moc"
465#include "moc_main_x11.cpp"
void addWM(const QString &wm)
QString selectedWM() const
OutputBackend * outputBackend() const
void destroyColorManager()
static void createAboutData()
virtual std::unique_ptr< OutlineVisual > createOutline(Outline *outline)
void setX11RootWindow(xcb_window_t root)
static void setupMalloc()
void setSession(std::unique_ptr< Session > &&session)
void setOutputBackend(std::unique_ptr< OutputBackend > &&backend)
void setX11Time(xcb_timestamp_t timestamp, TimestampUpdate force=TimestampUpdate::OnlyIfLarger)
void processCommandLine(QCommandLineParser *parser)
void setProcessStartupEnvironment(const QProcessEnvironment &environment)
void removeNativeX11EventFilter()
void createColorManager()
static void setupLocalizedString()
void setupCommandLine(QCommandLineParser *parser)
void setX11Connection(xcb_connection_t *c)
ApplicationX11(int &argc, char **argv)
void setReplace(bool replace)
void startInteractiveWindowSelection(std::function< void(KWin::Window *)> callback, const QByteArray &cursorName=QByteArray()) override
std::unique_ptr< OutlineVisual > createOutline(Outline *outline) override
void performStartup() override
void startInteractivePositionSelection(std::function< void(const QPointF &)> callback) override
std::unique_ptr< Edge > createScreenEdge(ScreenEdges *parent) override
std::unique_ptr< Cursor > createPlatformCursor() override
PlatformCursorImage cursorImage() const override
~ApplicationX11() override
void createEffectsHandler(Compositor *compositor, WorkspaceScene *scene) override
This class is used to show the outline of a given geometry.
Class for controlling screen edges.
static std::unique_ptr< Session > create()
static X11Compositor * create(QObject *parent=nullptr)
KWIN_EXPORT Atoms * atoms
std::unique_ptr< T, CDeleter > UniqueCPtr