2014-11-15 03:14:34 +02:00
|
|
|
/***************************************************************************
|
|
|
|
componentchooserwm.cpp - description
|
|
|
|
-------------------
|
|
|
|
copyright : (C) 2002 by Joseph Wenninger
|
|
|
|
email : jowenn@kde.org
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License verstion 2 as *
|
|
|
|
* published by the Free Software Foundation *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "componentchooserwm.h"
|
2015-02-27 09:28:46 +00:00
|
|
|
#include "moc_componentchooserwm.cpp"
|
2014-11-15 03:14:34 +02:00
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kdesktopfile.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <ktimerdialog.h>
|
2022-12-09 10:17:40 +02:00
|
|
|
#include <kselectionowner.h>
|
2022-12-10 14:41:47 +02:00
|
|
|
#include <kprocess.h>
|
2022-12-09 10:17:40 +02:00
|
|
|
#include <qthread.h>
|
2014-11-15 03:14:34 +02:00
|
|
|
#include <qdbusinterface.h>
|
|
|
|
#include <qdbusconnectioninterface.h>
|
|
|
|
#include <netwm.h>
|
|
|
|
#include <qx11info_x11.h>
|
|
|
|
|
2022-12-10 10:33:25 +02:00
|
|
|
static const int s_eventstime = 500;
|
|
|
|
static const int s_sleeptime = 500;
|
2022-12-09 10:17:40 +02:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
2014-11-15 03:14:34 +02:00
|
|
|
CfgWm::CfgWm(QWidget *parent)
|
2022-12-10 14:26:38 +02:00
|
|
|
: QWidget(parent)
|
|
|
|
, Ui::WmConfig_UI()
|
|
|
|
, CfgPlugin()
|
2014-11-15 03:14:34 +02:00
|
|
|
{
|
|
|
|
setupUi(this);
|
|
|
|
connect(wmCombo,SIGNAL(activated(int)), this, SLOT(configChanged()));
|
|
|
|
connect(kwinRB,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
|
|
|
|
connect(differentRB,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
|
|
|
|
connect(differentRB,SIGNAL(toggled(bool)),this,SLOT(checkConfigureWm()));
|
|
|
|
connect(wmCombo,SIGNAL(activated(int)),this,SLOT(checkConfigureWm()));
|
|
|
|
connect(configureButton,SIGNAL(clicked()),this,SLOT(configureWm()));
|
|
|
|
|
|
|
|
KGlobal::dirs()->addResourceType( "windowmanagers", "data", "ksmserver/windowmanagers" );
|
|
|
|
}
|
|
|
|
|
|
|
|
CfgWm::~CfgWm()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CfgWm::configChanged()
|
|
|
|
{
|
|
|
|
emit changed(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CfgWm::defaults()
|
|
|
|
{
|
|
|
|
wmCombo->setCurrentIndex( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CfgWm::load(KConfig *)
|
|
|
|
{
|
|
|
|
KConfig cfg("ksmserverrc", KConfig::NoGlobals);
|
|
|
|
KConfigGroup c( &cfg, "General");
|
|
|
|
loadWMs(c.readEntry("windowManager", "kwin"));
|
|
|
|
emit changed(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CfgWm::save(KConfig *)
|
|
|
|
{
|
|
|
|
saveAndConfirm();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CfgWm::saveAndConfirm()
|
|
|
|
{
|
|
|
|
KConfig cfg("ksmserverrc", KConfig::NoGlobals);
|
|
|
|
KConfigGroup c( &cfg, "General");
|
|
|
|
c.writeEntry("windowManager", currentWm());
|
|
|
|
emit changed(false);
|
2022-12-10 14:26:38 +02:00
|
|
|
if (oldwm == currentWm()) {
|
2014-11-15 03:14:34 +02:00
|
|
|
return true;
|
2022-12-10 14:26:38 +02:00
|
|
|
}
|
|
|
|
if (tryWmLaunch()) {
|
2014-11-15 03:14:34 +02:00
|
|
|
oldwm = currentWm();
|
2022-12-09 10:17:40 +02:00
|
|
|
cfg.sync();
|
2022-12-10 14:26:38 +02:00
|
|
|
QDBusInterface ksmserver("org.kde.ksmserver", "/KSMServer");
|
|
|
|
ksmserver.call(QDBus::NoBlock, "wmChanged");
|
2022-12-09 10:17:40 +02:00
|
|
|
KMessageBox::information( window(),
|
2022-12-10 14:26:38 +02:00
|
|
|
i18n("A new window manager is running.\n"
|
|
|
|
"It is still recommended to restart this KDE session to make sure "
|
|
|
|
"all running applications adjust for this change."),
|
|
|
|
i18n( "Window Manager Replaced"), "restartafterwmchange");
|
2014-11-15 03:14:34 +02:00
|
|
|
return true;
|
2022-12-10 14:26:38 +02:00
|
|
|
} else {
|
|
|
|
// revert config
|
2022-12-09 10:17:40 +02:00
|
|
|
emit changed(true);
|
|
|
|
c.writeEntry("windowManager", oldwm);
|
2022-12-10 14:26:38 +02:00
|
|
|
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
|
2022-12-09 10:17:40 +02:00
|
|
|
wmCombo->setCurrentIndex( wmCombo->findText( it.key()));
|
2022-12-10 14:26:38 +02:00
|
|
|
}
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
}
|
2022-12-09 10:17:40 +02:00
|
|
|
return false;
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CfgWm::tryWmLaunch()
|
|
|
|
{
|
2022-12-10 14:26:38 +02:00
|
|
|
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;
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
2022-12-10 14:26:38 +02:00
|
|
|
KMessageBox::information(
|
|
|
|
window(),
|
|
|
|
i18n("Your running window manager will be now replaced with the configured one."),
|
|
|
|
i18n("Window Manager Change"),
|
|
|
|
"windowmanagerchange"
|
|
|
|
);
|
2022-03-26 19:37:33 +02:00
|
|
|
|
|
|
|
bool ret = false;
|
2022-12-09 10:45:47 +02:00
|
|
|
setEnabled(false);
|
2022-12-09 10:17:40 +02:00
|
|
|
killWM();
|
2022-12-10 14:41:47 +02:00
|
|
|
KProcess kproc(this);
|
|
|
|
kproc.setShellCommand(currentWmData().exec);
|
|
|
|
if (kproc.startDetached()) {
|
2022-12-09 10:17:40 +02:00
|
|
|
// it's forked into background
|
2022-03-26 19:37:33 +02:00
|
|
|
ret = true;
|
|
|
|
|
2022-12-09 10:17:40 +02:00
|
|
|
// 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());
|
2022-12-10 10:33:25 +02:00
|
|
|
ushort counter = 0;
|
|
|
|
while (counter < 10 && kselectionowner.currentOwnerWindow() == XNone) {
|
2022-12-09 10:17:40 +02:00
|
|
|
QCoreApplication::processEvents(QEventLoop::AllEvents, s_eventstime);
|
|
|
|
QThread::msleep(s_sleeptime);
|
2022-12-10 10:33:25 +02:00
|
|
|
counter++;
|
2022-03-26 19:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
KTimerDialog* wmDialog = new KTimerDialog( 20000, KTimerDialog::CountDown, window(), i18n( "Config Window Manager Change" ),
|
|
|
|
KTimerDialog::Ok | KTimerDialog::Cancel, KTimerDialog::Cancel );
|
2022-12-10 14:26:38 +02:00
|
|
|
wmDialog->setButtonGuiItem(KDialog::Ok, KGuiItem(i18n("&Accept Change"), "dialog-ok"));
|
|
|
|
wmDialog->setButtonGuiItem(KDialog::Cancel, KGuiItem(i18n("&Revert to Previous"), "dialog-cancel"));
|
2022-03-26 19:37:33 +02:00
|
|
|
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 );
|
2022-12-10 14:26:38 +02:00
|
|
|
label->setWordWrap(true);
|
|
|
|
wmDialog->setMainWidget(label);
|
2022-03-26 19:37:33 +02:00
|
|
|
|
2022-12-10 14:26:38 +02:00
|
|
|
if (wmDialog->exec() != QDialog::Accepted ) {
|
2022-03-26 19:37:33 +02:00
|
|
|
// cancelled for some reason
|
|
|
|
ret = false;
|
|
|
|
|
2022-12-10 14:26:38 +02:00
|
|
|
KMessageBox::sorry(
|
|
|
|
window(),
|
|
|
|
i18n("The running window manager has been reverted to the previous window manager.")
|
|
|
|
);
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
|
2022-03-26 19:37:33 +02:00
|
|
|
delete wmDialog;
|
|
|
|
wmDialog = NULL;
|
|
|
|
} else {
|
|
|
|
ret = false;
|
2014-11-15 03:14:34 +02:00
|
|
|
|
2022-12-10 14:26:38 +02:00
|
|
|
KMessageBox::sorry(
|
|
|
|
window(),
|
|
|
|
i18n("The new window manager has failed to start.\nThe running window manager has been reverted to the previous window manager.")
|
|
|
|
);
|
2022-03-26 19:37:33 +02:00
|
|
|
}
|
2014-11-15 03:14:34 +02:00
|
|
|
|
2022-03-26 19:37:33 +02:00
|
|
|
if (!ret) {
|
|
|
|
// case-insensitive search
|
|
|
|
foreach (const QString &wmkey, wms.keys()) {
|
|
|
|
if (wmkey.toLower() == oldwm) {
|
|
|
|
WmData oldwmdata = wms.value(wmkey);
|
2022-12-09 10:17:40 +02:00
|
|
|
killWM();
|
2022-12-10 14:41:47 +02:00
|
|
|
kproc.setShellCommand(oldwmdata.exec);
|
|
|
|
kproc.startDetached();
|
2022-03-26 19:37:33 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
2022-03-26 19:37:33 +02:00
|
|
|
}
|
|
|
|
|
2022-12-09 10:45:47 +02:00
|
|
|
setEnabled(true);
|
2022-03-26 19:37:33 +02:00
|
|
|
return ret;
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
|
2022-12-10 14:26:38 +02:00
|
|
|
void CfgWm::loadWMs(const QString& current)
|
2014-11-15 03:14:34 +02:00
|
|
|
{
|
|
|
|
WmData kwin;
|
|
|
|
kwin.internalName = "kwin";
|
|
|
|
kwin.exec = "kwin";
|
|
|
|
kwin.configureCommand = "";
|
|
|
|
kwin.parentArgument = "";
|
|
|
|
wms[ "KWin" ] = kwin;
|
|
|
|
oldwm = "kwin";
|
|
|
|
kwinRB->setChecked( true );
|
|
|
|
wmCombo->setEnabled( false );
|
|
|
|
|
2022-12-10 14:26:38 +02:00
|
|
|
QStringList list = KGlobal::dirs()->findAllResources("windowmanagers", QString(), KStandardDirs::NoDuplicates);
|
|
|
|
QRegExp reg( ".*/([^/\\.]*)\\.[^/\\.]*");
|
|
|
|
foreach (const QString& wmfile, list) {
|
2014-11-15 03:14:34 +02:00
|
|
|
KDesktopFile file( wmfile );
|
2022-12-10 14:26:38 +02:00
|
|
|
if (file.noDisplay())
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
2022-12-10 14:26:38 +02:00
|
|
|
if (!file.tryExec())
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
2022-12-10 14:26:38 +02:00
|
|
|
QString testexec = file.desktopGroup().readEntry("X-KDE-WindowManagerTestExec");
|
|
|
|
if (!testexec.isEmpty()) {
|
|
|
|
if (QProcess::execute(testexec) != 0) {
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
2022-12-10 14:26:38 +02:00
|
|
|
}
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
QString name = file.readName();
|
2022-12-10 14:26:38 +02:00
|
|
|
if (name.isEmpty())
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
2022-12-10 14:26:38 +02:00
|
|
|
if (!reg.exactMatch(wmfile))
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
2022-12-10 14:26:38 +02:00
|
|
|
QString wm = reg.cap(1);
|
|
|
|
if (wms.contains(name))
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
|
|
|
WmData data;
|
|
|
|
data.internalName = wm;
|
|
|
|
data.exec = file.desktopGroup().readEntry( "Exec" );
|
2022-12-10 14:26:38 +02:00
|
|
|
if (data.exec.isEmpty())
|
2014-11-15 03:14:34 +02:00
|
|
|
continue;
|
2022-12-10 14:26:38 +02:00
|
|
|
data.configureCommand = file.desktopGroup().readEntry("X-KDE-WindowManagerConfigure");
|
|
|
|
data.parentArgument = file.desktopGroup().readEntry("X-KDE-WindowManagerConfigureParentArgument");
|
|
|
|
wms[name] = data;
|
|
|
|
wmCombo->addItem(name);
|
|
|
|
if (wms[ name ].internalName == current) {
|
|
|
|
// make it selected
|
|
|
|
wmCombo->setCurrentIndex(wmCombo->count() - 1);
|
2014-11-15 03:14:34 +02:00
|
|
|
oldwm = wm;
|
2022-12-10 14:26:38 +02:00
|
|
|
differentRB->setChecked(true);
|
|
|
|
wmCombo->setEnabled(true);
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
}
|
2022-12-10 14:26:38 +02:00
|
|
|
differentRB->setEnabled(wmCombo->count() > 0);
|
2014-11-15 03:14:34 +02:00
|
|
|
checkConfigureWm();
|
|
|
|
}
|
|
|
|
|
|
|
|
CfgWm::WmData CfgWm::currentWmData() const
|
|
|
|
{
|
2022-12-10 14:26:38 +02:00
|
|
|
return kwinRB->isChecked() ? wms["KWin"] : wms[wmCombo->currentText()];
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QString CfgWm::currentWm() const
|
|
|
|
{
|
|
|
|
return currentWmData().internalName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CfgWm::checkConfigureWm()
|
|
|
|
{
|
2022-12-10 14:26:38 +02:00
|
|
|
configureButton->setEnabled(!currentWmData().configureCommand.isEmpty());
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CfgWm::configureWm()
|
|
|
|
{
|
2022-12-10 14:26:38 +02:00
|
|
|
if (oldwm != currentWm() && !saveAndConfirm()) {
|
|
|
|
// needs switching first
|
2014-11-15 03:14:34 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
QStringList args;
|
2022-12-10 14:26:38 +02:00
|
|
|
if (!currentWmData().parentArgument.isEmpty()) {
|
|
|
|
args << currentWmData().parentArgument << QString::number(window()->winId());
|
|
|
|
}
|
|
|
|
if (!QProcess::startDetached(currentWmData().configureCommand, args)) {
|
|
|
|
KMessageBox::sorry(window(), i18n("Running the configuration tool failed"));
|
|
|
|
}
|
2014-11-15 03:14:34 +02:00
|
|
|
}
|