kcontrol: do not change the window manager until the next session

for various reasons

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-05-12 13:55:58 +03:00
parent aa239e5701
commit e637b6dcdb
2 changed files with 18 additions and 173 deletions

View file

@ -16,67 +16,14 @@
#include "componentchooserwm.h" #include "componentchooserwm.h"
#include "moc_componentchooserwm.cpp" #include "moc_componentchooserwm.cpp"
#include <kdebug.h>
#include <kdesktopfile.h> #include <kdesktopfile.h>
#include <kmessagebox.h> #include <kmessagebox.h>
#include <kstandarddirs.h> #include <kstandarddirs.h>
#include <ktimerdialog.h> #include <kconfiggroup.h>
#include <kselectionowner.h> #include <kdebug.h>
#include <kprocess.h>
#include <kshell.h>
#include <qthread.h>
#include <qfileinfo.h> #include <qfileinfo.h>
#include <qdbusinterface.h> #include <qprocess.h>
#include <qdbusconnectioninterface.h>
#include <netwm.h> #include <netwm.h>
#include <qx11info_x11.h>
static const int s_eventstime = 500;
static const int s_sleeptime = 500;
// TODO: kill and start WM on each screen?
static int getWMScreen()
{
return QX11Info::appScreen();
}
static QByteArray getWMAtom()
{
char snprintfbuff[30];
::memset(snprintfbuff, '\0', sizeof(snprintfbuff));
::sprintf(snprintfbuff, "WM_S%d", getWMScreen());
return QByteArray(snprintfbuff);
}
void killWM()
{
const QByteArray wmatom = getWMAtom();
KSelectionOwner kselectionowner(wmatom.constData(), getWMScreen());
kselectionowner.claim(true);
kselectionowner.release();
}
bool startWM(const QString &wmexec)
{
// HACK: openbox crashes shortly after it is started if started from this process so start it
// via klauncher
if (wmexec.contains(QLatin1String("openbox"))) {
QDBusInterface klauncher(
"org.kde.klauncher", "/KLauncher","org.kde.KLauncher",
QDBusConnection::sessionBus()
);
QStringList wmcommand = KShell::splitArgs(wmexec);
if (wmcommand.isEmpty()) {
return false;
}
const QString wmprog = wmcommand.takeFirst();
QDBusReply<void> reply = klauncher.call("exec_blind", wmprog, wmcommand);
return reply.isValid();
}
KProcess kproc;
kproc.setShellCommand(wmexec);
return (kproc.startDetached() > 0);
}
CfgWm::CfgWm(QWidget *parent) CfgWm::CfgWm(QWidget *parent)
: QWidget(parent) : QWidget(parent)
@ -131,121 +78,17 @@ bool CfgWm::saveAndConfirm()
if (oldwm == currentWm()) { if (oldwm == currentWm()) {
return true; return true;
} }
if (tryWmLaunch()) {
oldwm = currentWm(); oldwm = currentWm();
cfg.sync(); cfg.sync();
KMessageBox::information( KMessageBox::information(
window(), window(),
i18n("A new window manager is running.\n" i18n(
"It is still recommended to restart this KDE session to make sure " "The change will take effect on the next KDE session."
"all running applications adjust for this change."), ),
i18n("Window Manager Replaced"), i18n("Window Manager Changed"),
"restartafterwmchange" "restartafterwmchange"
); );
return true; return true;
} else {
// revert config
emit changed(true);
c.writeEntry("windowManager", oldwm);
if (oldwm == "kwin") {
kwinRB->setChecked(true);
wmCombo->setEnabled(false);
} else {
differentRB->setChecked(true);
wmCombo->setEnabled(true);
for (QHash< QString, WmData >::ConstIterator it = wms.constBegin(); it != wms.constEnd(); ++it) {
if ((*it).internalName == oldwm) {
// make it selected
wmCombo->setCurrentIndex(wmCombo->findText(it.key()));
}
}
}
return false;
}
}
bool CfgWm::tryWmLaunch()
{
if (currentWm() == "kwin"
&& qstrcmp(NETRootInfo(QX11Info::display(), NET::SupportingWMCheck).wmName(), "KWin") == 0) {
// it is already running, don't necessarily restart e.g. after a failure with other WM
return true;
}
KMessageBox::information(
window(),
i18n("Your running window manager will be now replaced with the configured one."),
i18n("Window Manager Change"),
"windowmanagerchange"
);
bool ret = false;
setEnabled(false);
killWM();
if (startWM(currentWmData().exec)) {
// it's forked into background
ret = true;
// NOTE: wait for the WM to be operational otherwise the timer dialog may not
// show up and the configuration window becomes non-interactive until the timeout is
// reached
const QByteArray wmatom = getWMAtom();
KSelectionOwner kselectionowner(wmatom.constData(), getWMScreen());
ushort counter = 0;
while (counter < 10 && kselectionowner.currentOwnerWindow() == XNone) {
QCoreApplication::processEvents(QEventLoop::AllEvents, s_eventstime);
QThread::msleep(s_sleeptime);
counter++;
}
KTimerDialog* wmDialog = new KTimerDialog(
20000, KTimerDialog::CountDown, window(),
i18n("Config Window Manager Change"),
KTimerDialog::Ok | KTimerDialog::Cancel, KTimerDialog::Cancel
);
wmDialog->setButtonGuiItem(KDialog::Ok, KGuiItem(i18n("&Accept Change"), "dialog-ok"));
wmDialog->setButtonGuiItem(KDialog::Cancel, KGuiItem(i18n("&Revert to Previous"), "dialog-cancel"));
QLabel *label = new QLabel(
i18n( "The configured window manager is being launched.\n"
"Please check it has started properly and confirm the change.\n"
"The launch will be automatically reverted in 20 seconds." ), wmDialog );
label->setWordWrap(true);
wmDialog->setMainWidget(label);
if (wmDialog->exec() != QDialog::Accepted ) {
// cancelled for some reason
ret = false;
KMessageBox::sorry(
window(),
i18n("The running window manager has been reverted to the previous window manager.")
);
}
delete wmDialog;
wmDialog = NULL;
} else {
ret = false;
KMessageBox::sorry(
window(),
i18n("The new window manager has failed to start.\nThe running window manager has been reverted to the previous window manager.")
);
}
if (!ret) {
// case-insensitive search
foreach (const QString &wmkey, wms.keys()) {
if (wmkey.toLower() == oldwm) {
WmData oldwmdata = wms.value(wmkey);
killWM();
startWM(oldwmdata.exec);
break;
}
}
}
setEnabled(true);
return ret;
} }
void CfgWm::loadWMs(const QString &current) void CfgWm::loadWMs(const QString &current)

View file

@ -21,7 +21,7 @@
class CfgWm: public QWidget, public Ui::WmConfig_UI, public CfgPlugin class CfgWm: public QWidget, public Ui::WmConfig_UI, public CfgPlugin
{ {
Q_OBJECT Q_OBJECT
public: public:
CfgWm(QWidget *parent); CfgWm(QWidget *parent);
virtual ~CfgWm(); virtual ~CfgWm();
@ -36,18 +36,20 @@ protected Q_SLOTS:
Q_SIGNALS: Q_SIGNALS:
void changed(bool); void changed(bool);
private: private:
bool tryWmLaunch();
void loadWMs( const QString& current );
QString currentWm() const;
bool saveAndConfirm();
struct WmData { struct WmData {
QString internalName; QString internalName;
QString exec; QString exec;
QString configureCommand; QString configureCommand;
QString parentArgument; QString parentArgument;
}; };
void loadWMs(const QString &current);
QString currentWm() const;
bool saveAndConfirm();
WmData currentWmData() const; WmData currentWmData() const;
QHash<QString, WmData> wms; // i18n text -> data QHash<QString, WmData> wms; // i18n text -> data
QString oldwm; // the original value QString oldwm; // the original value
}; };