kdeui: move session management to KApplicaiton

every comment about X11 and session management in general claims it was
broken, not going to claim otherwise. everything that does not use
KApplication shall not be involved into session management now and gets
the middle finger (SIGTERM or SIGKILL) after 5 sec by klauncher when the
session is done

also session management has to be explicitly enabled by applications
now, disabled by default

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-05-09 00:55:08 +03:00
parent 8ce0f2ec3f
commit 0e0db0b815
27 changed files with 469 additions and 711 deletions

View file

@ -213,7 +213,6 @@ install(
KServiceGroup KServiceGroup
KServiceType KServiceType
KServiceTypeTrader KServiceTypeTrader
KSessionManager
KSharedConfig KSharedConfig
KSharedPtr KSharedPtr
KShell KShell

View file

@ -1 +0,0 @@
#include "../ksessionmanager.h"

View file

@ -262,7 +262,6 @@ KCmdLineArgsStatic::KCmdLineArgsStatic () {
#ifdef Q_WS_X11 #ifdef Q_WS_X11
qt_options.add("display <displayname>", ki18n("Use the X-server display 'displayname'")); qt_options.add("display <displayname>", ki18n("Use the X-server display 'displayname'"));
#endif #endif
qt_options.add("session <sessionId>", ki18n("Restore the application for the given 'sessionId'"));
qt_options.add("nograb", ki18n("tells Katie to never grab the mouse or the keyboard")); qt_options.add("nograb", ki18n("tells Katie to never grab the mouse or the keyboard"));
qt_options.add("dograb", ki18n("running under a debugger can cause an implicit\n-nograb, use -dograb to override")); qt_options.add("dograb", ki18n("running under a debugger can cause an implicit\n-nograb, use -dograb to override"));
qt_options.add("sync", ki18n("switches to synchronous mode for debugging")); qt_options.add("sync", ki18n("switches to synchronous mode for debugging"));
@ -278,7 +277,7 @@ KCmdLineArgsStatic::KCmdLineArgsStatic () {
kde_options.add("waitforwm", ki18n("Waits for a WM_NET compatible windowmanager")); kde_options.add("waitforwm", ki18n("Waits for a WM_NET compatible windowmanager"));
#endif #endif
kde_options.add("geometry <geometry>", ki18n("sets the client geometry of the main widget - see man X for the argument format (usually WidthxHeight+XPos+YPos)")); kde_options.add("geometry <geometry>", ki18n("sets the client geometry of the main widget - see man X for the argument format (usually WidthxHeight+XPos+YPos)"));
kde_options.add("smkey <sessionKey>"); // this option is obsolete and exists only to allow smooth upgrades from sessions kde_options.add("session <sessionId>", ki18n("Restore the application for the given 'sessionId'"));
kde_options.add("debugger", ki18n("Show debugger")); kde_options.add("debugger", ki18n("Show debugger"));
} }

View file

@ -521,13 +521,8 @@ int main(int argc, char *argv[])
KComponentData componentData(&aboutData); KComponentData componentData(&aboutData);
KSharedConfig::Ptr config = componentData.config(); // Enable translations. KSharedConfig::Ptr config = componentData.config(); // Enable translations.
// NOTE: disables session manager entirely, for reference:
// https://www.x.org/releases/X11R7.7/doc/libSM/xsmp.html
::unsetenv("SESSION_MANAGER");
KApplication app; KApplication app;
app.setQuitOnLastWindowClosed(false); app.setQuitOnLastWindowClosed(false);
app.disableSessionManagement();
QDBusConnection session = QDBusConnection::sessionBus(); QDBusConnection session = QDBusConnection::sessionBus();
if (!session.isConnected()) { if (!session.isConnected()) {

View file

@ -128,7 +128,6 @@ set(kdeui_LIB_SRCS
jobs/kdynamicjobtracker.cpp jobs/kdynamicjobtracker.cpp
kernel/kapplication.cpp kernel/kapplication.cpp
kernel/kuniqueapplication.cpp kernel/kuniqueapplication.cpp
kernel/ksessionmanager.cpp
kernel/kstyle.cpp kernel/kstyle.cpp
kernel/kstartupinfo.cpp kernel/kstartupinfo.cpp
kernel/kglobalsettings.cpp kernel/kglobalsettings.cpp
@ -219,6 +218,9 @@ set(kdeui_LIB_SRCS
windowmanagement/kwindowsystem_x11.cpp windowmanagement/kwindowsystem_x11.cpp
windowmanagement/kwindowinfo_x11.cpp windowmanagement/kwindowinfo_x11.cpp
windowmanagement/netwm.cpp windowmanagement/netwm.cpp
kernel/kapplication_adaptor.cpp
# just so that it gets generated
${CMAKE_CURRENT_BINARY_DIR}/org.kde.KApplication.xml
) )
if (X11_Xkb_FOUND AND X11_Xkbfile_FOUND) if (X11_Xkb_FOUND AND X11_Xkbfile_FOUND)
@ -233,6 +235,8 @@ if (X11_Xkb_FOUND AND X11_Xkbfile_FOUND)
) )
endif() endif()
qt4_generate_dbus_interface(kernel/kapplication_adaptor.h org.kde.KApplication.xml)
set_source_files_properties( set_source_files_properties(
${CMAKE_SOURCE_DIR}/kdeui/kernel/kapplication.cpp ${CMAKE_SOURCE_DIR}/kdeui/kernel/kapplication.cpp
${CMAKE_SOURCE_DIR}/kdeui/kernel/kglobalsettings.cpp ${CMAKE_SOURCE_DIR}/kdeui/kernel/kglobalsettings.cpp
@ -373,7 +377,6 @@ install(
jobs/kdynamicjobtracker.h jobs/kdynamicjobtracker.h
kernel/kapplication.h kernel/kapplication.h
kernel/kuniqueapplication.h kernel/kuniqueapplication.h
kernel/ksessionmanager.h
kernel/kstyle.h kernel/kstyle.h
kernel/kstartupinfo.h kernel/kstartupinfo.h
kernel/kglobalsettings.h kernel/kglobalsettings.h
@ -460,7 +463,6 @@ install(
DESTINATION ${KDE4_INCLUDE_INSTALL_DIR} DESTINATION ${KDE4_INCLUDE_INSTALL_DIR}
) )
# KDE 5 remove this
install( install(
FILES FILES
widgets/kratingpainter.h widgets/kratingpainter.h
@ -472,3 +474,8 @@ install(
PROGRAMS preparetips PROGRAMS preparetips
DESTINATION ${KDE4_BIN_INSTALL_DIR} DESTINATION ${KDE4_BIN_INSTALL_DIR}
) )
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KApplication.xml
DESTINATION ${KDE4_DBUS_INTERFACES_INSTALL_DIR}
)

View file

@ -141,9 +141,9 @@ void KAboutApplicationPersonListDelegate::launchUrl( QAction *action ) const
QString url = action->data().toString(); QString url = action->data().toString();
if( !url.isEmpty() ) { if( !url.isEmpty() ) {
if( url.startsWith( "mailto:" ) ) if( url.startsWith( "mailto:" ) )
KToolInvocation::invokeMailer( KUrl( url ) ); KToolInvocation::self()->invokeMailer( KUrl( url ) );
else else
KToolInvocation::invokeBrowser( url ); KToolInvocation::self()->invokeBrowser( url );
} }
} }

View file

@ -929,7 +929,7 @@ void KDialog::slotButtonClicked(int button)
case KDialog::Help: { case KDialog::Help: {
emit helpClicked(); emit helpClicked();
if (!d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty()) { if (!d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty()) {
KToolInvocation::invokeHelp( d->mAnchor, d->mHelpApp); KToolInvocation::self()->invokeHelp( d->mAnchor, d->mHelpApp);
} }
break; break;
} }

View file

@ -28,7 +28,6 @@
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
#include <QtGui/QSessionManager>
#include <QtGui/QStyleFactory> #include <QtGui/QStyleFactory>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QtGui/QCloseEvent> #include <QtGui/QCloseEvent>
@ -46,7 +45,6 @@
#include "kicon.h" #include "kicon.h"
#include "kiconloader.h" #include "kiconloader.h"
#include "klocale.h" #include "klocale.h"
#include "ksessionmanager.h"
#include "kstandarddirs.h" #include "kstandarddirs.h"
#include "kstandardshortcut.h" #include "kstandardshortcut.h"
#include "kurl.h" #include "kurl.h"
@ -59,6 +57,7 @@
#include "kconfiggroup.h" #include "kconfiggroup.h"
#include "kactioncollection.h" #include "kactioncollection.h"
#include "kdebugger.h" #include "kdebugger.h"
#include "kapplication_adaptor.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -114,58 +113,78 @@ static void quit_handler(int sig)
qApp->quit(); qApp->quit();
} }
static void kRegisterSessionClient(const bool enable, const QString &serviceName)
{
if (serviceName.isEmpty()) {
return;
}
QDBusInterface sessionManager(
"org.kde.plasma-desktop", "/App", "local.PlasmaApp",
QDBusConnection::sessionBus()
);
if (sessionManager.isValid()) {
sessionManager.call(enable ? "registerClient" : "unregisterClient", serviceName);
} else {
kWarning() << "org.kde.plasma-desktop is not valid interface";
}
}
/* /*
Private data to make keeping binary compatibility easier Private data
*/ */
class KApplicationPrivate class KApplicationPrivate
{ {
public: public:
KApplicationPrivate(KApplication* q, const QByteArray &cName) KApplicationPrivate(KApplication* q, const QByteArray &cName)
: q(q) : q(q)
, adaptor(nullptr)
, componentData(cName) , componentData(cName)
, startup_id("0") , startup_id("0")
, app_started_timer(nullptr) , app_started_timer(nullptr)
, session_save(false) , session_save(false)
, pSessionConfig(nullptr) , pSessionConfig(nullptr)
, bSessionManagement(true) , bSessionManagement(false)
, debugger(nullptr) , debugger(nullptr)
{ {
} }
KApplicationPrivate(KApplication* q, const KComponentData &cData) KApplicationPrivate(KApplication* q, const KComponentData &cData)
: q(q) : q(q)
, adaptor(nullptr)
, componentData(cData) , componentData(cData)
, startup_id("0") , startup_id("0")
, app_started_timer(nullptr) , app_started_timer(nullptr)
, session_save(false) , session_save(false)
, pSessionConfig(nullptr) , pSessionConfig(nullptr)
, bSessionManagement(true) , bSessionManagement(false)
, debugger(nullptr) , debugger(nullptr)
{ {
} }
KApplicationPrivate(KApplication *q) KApplicationPrivate(KApplication *q)
: q(q) : q(q)
, adaptor(nullptr)
, componentData(KCmdLineArgs::aboutData()) , componentData(KCmdLineArgs::aboutData())
, startup_id("0") , startup_id("0")
, app_started_timer(nullptr) , app_started_timer(nullptr)
, session_save(false) , session_save(false)
, pSessionConfig(nullptr) , pSessionConfig(nullptr)
, bSessionManagement(true) , bSessionManagement(false)
, debugger(nullptr) , debugger(nullptr)
{ {
} }
void _k_x11FilterDestroyed(); void _k_x11FilterDestroyed();
void _k_checkAppStartedSlot(); void _k_checkAppStartedSlot();
void _k_disableAutorestartSlot(); void _k_aboutToQuitSlot();
QString sessionConfigName() const;
void init(); void init();
void parseCommandLine( ); // Handle KDE arguments (Using KCmdLineArgs) void parseCommandLine( ); // Handle KDE arguments (Using KCmdLineArgs)
KApplication *q; KApplication *q;
KApplicationAdaptor* adaptor;
QString serviceName;
KComponentData componentData; KComponentData componentData;
QByteArray startup_id; QByteArray startup_id;
QTimer* app_started_timer; QTimer* app_started_timer;
@ -271,29 +290,6 @@ void KApplicationPrivate::_k_checkAppStartedSlot()
} }
} }
/*
Auxiliary function to calculate a a session config name used for the
instance specific config object.
Syntax: "session/<appname>_<sessionId>"
*/
QString KApplicationPrivate::sessionConfigName() const
{
#ifdef QT_NO_SESSIONMANAGER
#error QT_NO_SESSIONMANAGER was set, this will not compile. Reconfigure Qt with Session management support.
#endif
QString sessKey = q->sessionKey();
if ( sessKey.isEmpty() && !sessionKey.isEmpty() )
sessKey = sessionKey;
return QString::fromLatin1("session/%1_%2_%3").arg(QCoreApplication::applicationName()).arg(q->sessionId()).arg(sessKey);
}
#ifdef Q_WS_X11
static SmcConn mySmcConnection = 0;
#else
// FIXME(E): Implement for Qt Embedded
// Possibly "steal" XFree86's libSM?
#endif
KApplication::KApplication() KApplication::KApplication()
: QApplication(KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv()), : QApplication(KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv()),
d(new KApplicationPrivate(this)) d(new KApplicationPrivate(this))
@ -398,12 +394,13 @@ void KApplicationPrivate::init()
reversedDomain.prepend(s); reversedDomain.prepend(s);
} }
const QString pidSuffix = QString::number( getpid() ).prepend( QLatin1String("-") ); const QString pidSuffix = QString::number( getpid() ).prepend( QLatin1String("-") );
const QString serviceName = reversedDomain + QCoreApplication::applicationName() + pidSuffix; serviceName = reversedDomain + QCoreApplication::applicationName() + pidSuffix;
if ( bus->registerService(serviceName) == QDBusConnectionInterface::ServiceNotRegistered ) { if ( bus->registerService(serviceName) == QDBusConnectionInterface::ServiceNotRegistered ) {
kError() << "Couldn't register name '" << serviceName << "' with DBUS - another process owns it already!"; kError() << "Couldn't register name '" << serviceName << "' with DBUS - another process owns it already!";
::exit(126); ::exit(126);
} }
} }
adaptor = new KApplicationAdaptor(q);
sessionBus.registerObject(QLatin1String("/MainApplication"), q, sessionBus.registerObject(QLatin1String("/MainApplication"), q,
QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSlots |
QDBusConnection::ExportScriptableProperties | QDBusConnection::ExportScriptableProperties |
@ -434,7 +431,7 @@ void KApplicationPrivate::init()
// too late to restart if the application is about to quit (e.g. if QApplication::quit() was // too late to restart if the application is about to quit (e.g. if QApplication::quit() was
// called or SIGTERM was received) // called or SIGTERM was received)
q->connect(q, SIGNAL(aboutToQuit()), SLOT(_k_disableAutorestartSlot())); q->connect(q, SIGNAL(aboutToQuit()), SLOT(_k_aboutToQuitSlot()));
KApplication::quitOnSignal(); KApplication::quitOnSignal();
KApplication::quitOnDisconnected(); KApplication::quitOnDisconnected();
@ -450,11 +447,63 @@ KApplication* KApplication::kApplication()
KConfig* KApplication::sessionConfig() KConfig* KApplication::sessionConfig()
{ {
if (!d->pSessionConfig) // create an instance specific config object if (!d->pSessionConfig) {
d->pSessionConfig = new KConfig( d->sessionConfigName(), KConfig::SimpleConfig ); // create an instance specific config object
QString configName = d->sessionKey;
if (configName.isEmpty()) {
configName = QString::fromLatin1("%1_%2").arg(QCoreApplication::applicationName()).arg(QCoreApplication::applicationPid());
}
d->pSessionConfig = new KConfig(
QString::fromLatin1("session/%1").arg(configName),
KConfig::SimpleConfig
);
}
return d->pSessionConfig; return d->pSessionConfig;
} }
bool KApplication::saveSession()
{
foreach (KMainWindow *window, KMainWindow::memberList()) {
if (!window->testAttribute(Qt::WA_WState_Hidden)) {
QCloseEvent e;
QApplication::sendEvent(window, &e);
if (!e.isAccepted()) {
return false;
}
}
}
foreach (QWidget* widget, QApplication::topLevelWidgets()) {
if (!widget || widget->isHidden() || widget->inherits("QMainWindow")) {
continue;
}
QCloseEvent e;
QApplication::sendEvent(widget, &e);
if (!e.isAccepted()) {
return false;
}
}
d->session_save = true;
KConfig* config = KApplication::kApplication()->sessionConfig();
if ( KMainWindow::memberList().count() ){
// According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
// hook is useful for better document orientation
KMainWindow::memberList().first()->saveGlobalProperties(config);
}
int n = 0;
foreach (KMainWindow* mw, KMainWindow::memberList()) {
n++;
mw->savePropertiesInternal(config, n);
}
KConfigGroup group( config, "Number" );
group.writeEntry("NumberOfWindows", n );
if ( d->pSessionConfig ) {
d->pSessionConfig->sync();
}
d->session_save = false;
return true;
}
void KApplication::reparseConfiguration() void KApplication::reparseConfiguration()
{ {
KGlobal::config()->reparseConfiguration(); KGlobal::config()->reparseConfiguration();
@ -465,133 +514,18 @@ void KApplication::quit()
QApplication::quit(); QApplication::quit();
} }
void KApplication::disableSessionManagement() { void KApplication::disableSessionManagement()
d->bSessionManagement = false;
}
void KApplication::enableSessionManagement() {
d->bSessionManagement = true;
#ifdef Q_WS_X11
// Session management support in Qt/KDE is awfully broken.
// If konqueror disables session management right after its startup,
// and enables it later (preloading stuff), it won't be properly
// saved on session shutdown.
// I'm not actually sure why it doesn't work, but saveState()
// doesn't seem to be called on session shutdown, possibly
// because disabling session management after konqueror startup
// disabled it somehow. Forcing saveState() here for this application
// seems to fix it.
if( mySmcConnection ) {
SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
SmInteractStyleAny,
False, False );
// flush the request
IceFlush(SmcGetIceConnection(mySmcConnection));
}
#endif
}
void KApplication::commitData( QSessionManager& sm )
{ {
d->session_save = true; if (d->bSessionManagement) {
bool canceled = false; kRegisterSessionClient(false, d->serviceName);
foreach (KSessionManager *it, KSessionManager::sessionClients()) {
if ( ( canceled = !it->commitData( sm ) ) )
break;
} }
d->bSessionManagement = false;
if ( canceled )
sm.cancel();
if ( sm.allowsInteraction() ) {
QWidgetList donelist, todolist;
QWidget* w;
commitDataRestart:
todolist = QApplication::topLevelWidgets();
for ( int i = 0; i < todolist.size(); ++i ) {
w = todolist.at( i );
if( !w )
break;
if ( donelist.contains( w ) )
continue;
if ( !w->isHidden() && !w->inherits( "KMainWindow" ) ) {
QCloseEvent e;
sendEvent( w, &e );
if ( !e.isAccepted() )
break; //canceled
donelist.append( w );
//grab the new list that was just modified by our closeevent
goto commitDataRestart;
}
}
}
if ( !d->bSessionManagement )
sm.setRestartHint( QSessionManager::RestartNever );
else
sm.setRestartHint( QSessionManager::RestartIfRunning );
d->session_save = false;
} }
void KApplication::saveState( QSessionManager& sm ) void KApplication::enableSessionManagement()
{ {
d->session_save = true; kRegisterSessionClient(true, d->serviceName);
#ifdef Q_WS_X11 d->bSessionManagement = true;
static bool firstTime = true;
mySmcConnection = (SmcConn) sm.handle();
if ( !d->bSessionManagement ) {
sm.setRestartHint( QSessionManager::RestartNever );
d->session_save = false;
return;
} else {
sm.setRestartHint( QSessionManager::RestartIfRunning );
}
if ( firstTime ) {
firstTime = false;
d->session_save = false;
return; // no need to save the state.
}
// remove former session config if still existing, we want a new
// and fresh one. Note that we do not delete the config file here,
// this is done by the session manager when it executes the
// discard commands. In fact it would be harmful to remove the
// file here, as the session might be stored under a different
// name, meaning the user still might need it eventually.
delete d->pSessionConfig;
d->pSessionConfig = 0;
// finally: do session management
bool canceled = false;
foreach(KSessionManager* it, KSessionManager::sessionClients()) {
if(canceled) break;
canceled = !it->saveState( sm );
}
// if we created a new session config object, register a proper discard command
if ( d->pSessionConfig ) {
d->pSessionConfig->sync();
QStringList discard;
discard << QLatin1String("rm") << KStandardDirs::locateLocal("config", d->sessionConfigName());
sm.setDiscardCommand( discard );
} else {
sm.setDiscardCommand( QStringList( QLatin1String("") ) );
}
if ( canceled )
sm.cancel();
#endif
d->session_save = false;
} }
bool KApplication::sessionSaving() const bool KApplication::sessionSaving() const
@ -599,6 +533,11 @@ bool KApplication::sessionSaving() const
return d->session_save; return d->session_save;
} }
bool KApplication::isSessionRestored() const
{
return !d->sessionKey.isEmpty();
}
void KApplicationPrivate::parseCommandLine( ) void KApplicationPrivate::parseCommandLine( )
{ {
KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde"); KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
@ -655,8 +594,8 @@ void KApplicationPrivate::parseCommandLine( )
} }
#endif #endif
if (args->isSet("smkey")) { if (args->isSet("session")) {
sessionKey = args->getOption("smkey"); sessionKey = args->getOption("session");
} }
if (args->isSet("debugger")) { if (args->isSet("debugger")) {
@ -671,12 +610,12 @@ KApplication::~KApplication()
delete d->debugger; delete d->debugger;
} }
if (d->pSessionConfig) {
delete d->pSessionConfig;
}
delete d; delete d;
KApp = 0; KApp = 0;
#ifdef Q_WS_X11
mySmcConnection = 0;
#endif
} }
@ -740,18 +679,6 @@ unsigned long KApplication::userTimestamp() const
#endif #endif
} }
void KApplication::updateRemoteUserTimestamp( const QString& service, int time )
{
#if defined Q_WS_X11
Q_ASSERT(service.contains('.'));
if( time == 0 )
time = QX11Info::appUserTime();
QDBusInterface(service, QLatin1String("/MainApplication"),
QString(QLatin1String("org.kde.KApplication")))
.call(QLatin1String("updateUserTimestamp"), time);
#endif
}
void KApplication::quitOnSignal() void KApplication::quitOnSignal()
{ {
sigset_t handlermask; sigset_t handlermask;
@ -829,9 +756,12 @@ void KApplication::clearStartupId()
d->startup_id = "0"; d->startup_id = "0";
} }
void KApplicationPrivate::_k_disableAutorestartSlot() void KApplicationPrivate::_k_aboutToQuitSlot()
{ {
KCrash::setFlags(KCrash::flags() & ~KCrash::AutoRestart); KCrash::setFlags(KCrash::flags() & ~KCrash::AutoRestart);
if (bSessionManagement) {
kRegisterSessionClient(false, serviceName);
}
} }
#include "moc_kapplication.cpp" #include "moc_kapplication.cpp"

View file

@ -63,7 +63,6 @@ class KApplicationPrivate;
class KDEUI_EXPORT KApplication : public QApplication class KDEUI_EXPORT KApplication : public QApplication
{ {
Q_OBJECT Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.KApplication")
public: public:
/** /**
* This constructor is the one you should use. * This constructor is the one you should use.
@ -138,7 +137,6 @@ public:
*/ */
KConfig* sessionConfig(); KConfig* sessionConfig();
/** /**
* Disables session management for this application. * Disables session management for this application.
* *
@ -155,20 +153,6 @@ public:
*/ */
void enableSessionManagement(); void enableSessionManagement();
/**
* Reimplemented for internal purposes, mainly the highlevel
* handling of session management with KSessionManager.
* @internal
*/
void commitData( QSessionManager& sm );
/**
* Reimplemented for internal purposes, mainly the highlevel
* handling of session management with KSessionManager.
* @internal
*/
void saveState( QSessionManager& sm );
/** /**
* Returns true if the application is currently saving its session * Returns true if the application is currently saving its session
* data (most probably before KDE logout). This is intended for use * data (most probably before KDE logout). This is intended for use
@ -178,6 +162,12 @@ public:
*/ */
bool sessionSaving() const; bool sessionSaving() const;
/**
* Returns true if the application is currently restoring its session
*
* @see KMainWindow::queryClose
*/
bool isSessionRestored() const;
/** /**
* Sets the top widget of the application. * Sets the top widget of the application.
@ -236,15 +226,6 @@ public:
*/ */
unsigned long userTimestamp() const; unsigned long userTimestamp() const;
/**
* Updates the last user action timestamp in the application registered to DBUS with id service
* to the given time, or to this application's user time, if 0 is given.
* Use before causing user interaction in the remote application, e.g. invoking a dialog
* in the application using a DCOP call.
* Consult focus stealing prevention section in kdebase/kwin/README.
*/
void updateRemoteUserTimestamp( const QString& service, int time = 0 );
/** /**
* Setups signal handler for SIGTERM, SIGHUP and SIGINT to call QApplication::quit() when such * Setups signal handler for SIGTERM, SIGHUP and SIGINT to call QApplication::quit() when such
* signal is received. * signal is received.
@ -270,15 +251,18 @@ public:
public Q_SLOTS: public Q_SLOTS:
/** /**
* Updates the last user action timestamp to the given time, or to the current time, * Updates the last user action timestamp to the given time, or to the current time, if 0 is
* if 0 is given. Do not use unless you're really sure what you're doing. * given. Do not use unless you're really sure what you're doing. Consult focus stealing
* Consult focus stealing prevention section in kdebase/kwin/README. * prevention section in kdebase/kwin/README.
*/ */
Q_SCRIPTABLE void updateUserTimestamp( int time = 0 ); void updateUserTimestamp(int time = 0);
/**
// D-Bus slots: * Saves the state of the application for the current session, the state will be restored on the
Q_SCRIPTABLE void reparseConfiguration(); * next login
Q_SCRIPTABLE void quit(); */
virtual bool saveSession();
void reparseConfiguration();
void quit();
protected: protected:
/** /**
@ -290,8 +274,7 @@ protected:
/** /**
* @internal Used by KUniqueApplication * @internal Used by KUniqueApplication
*/ */
KApplication(Display *display, Qt::HANDLE visual, Qt::HANDLE colormap, KApplication(Display *display, Qt::HANDLE visual, Qt::HANDLE colormap, const KComponentData &cData);
const KComponentData &cData);
/** /**
* Used to catch X11 events * Used to catch X11 events
@ -313,7 +296,7 @@ private:
Q_PRIVATE_SLOT(d, void _k_x11FilterDestroyed()) Q_PRIVATE_SLOT(d, void _k_x11FilterDestroyed())
Q_PRIVATE_SLOT(d, void _k_checkAppStartedSlot()) Q_PRIVATE_SLOT(d, void _k_checkAppStartedSlot())
Q_PRIVATE_SLOT(d, void _k_disableAutorestartSlot()) Q_PRIVATE_SLOT(d, void _k_aboutToQuitSlot())
}; };
#endif #endif

View file

@ -0,0 +1,71 @@
/*
This file is part of the KDE libraries
Copyright (C) 2024 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kapplication_adaptor.h"
#include "kapplication.h"
KApplicationAdaptor::KApplicationAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
}
QStringList KApplicationAdaptor::restartCommand() const
{
QStringList result;
result.append(QCoreApplication::applicationFilePath());
result.append("--session");
result.append(QString::fromLatin1("%1_%2").arg(QCoreApplication::applicationName()).arg(QCoreApplication::applicationPid()));
return result;
}
void KApplicationAdaptor::updateUserTimestamp(int time)
{
if (kapp) {
kapp->updateUserTimestamp(time);
}
}
void KApplicationAdaptor::saveSession()
{
if (kapp) {
if (kapp->saveSession()) {
emit sessionSaved();
} else {
emit sessionSaveCanceled();
}
return;
}
emit sessionSaved();
}
void KApplicationAdaptor::reparseConfiguration()
{
if (kapp) {
kapp->reparseConfiguration();
}
}
void KApplicationAdaptor::quit()
{
if (kapp) {
kapp->quit();
}
}
#include "moc_kapplication_adaptor.cpp"

View file

@ -0,0 +1,48 @@
/*
This file is part of the KDE libraries
Copyright (C) 2024 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KAPPLICATION_ADAPTOR_H
#define KAPPLICATION_ADAPTOR_H
#include <QDBusAbstractAdaptor>
class KApplicationAdaptor : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.KApplication")
public:
KApplicationAdaptor(QObject *parent);
Q_SIGNALS:
void sessionSaved();
void sessionSaveCanceled();
public Q_SLOTS:
QStringList restartCommand() const;
void updateUserTimestamp(int time = 0);
void saveSession();
void reparseConfiguration();
void quit();
private:
Q_DISABLE_COPY(KApplicationAdaptor);
};
#endif // KAPPLICATION_ADAPTOR_H

View file

@ -1,50 +0,0 @@
/* This file is part of the KDE libraries
Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
Copyright (c) 1998, 1999 KDE Team
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "ksessionmanager.h"
KSessionManager::KSessionManager()
{
sessionClients().removeAll( this );
sessionClients().append( this );
}
KSessionManager::~KSessionManager()
{
sessionClients().removeAll( this );
}
bool KSessionManager::saveState(QSessionManager&)
{
return true;
}
bool KSessionManager::commitData(QSessionManager&)
{
return true;
}
QList<KSessionManager *>& KSessionManager::sessionClients()
{
static QList<KSessionManager*> session_clients;
return session_clients;
}

View file

@ -1,78 +0,0 @@
/* This file is part of the KDE libraries
Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
Copyright (c) 1998, 1999 KDE Team
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KSESSIONMANAGER_H
#define KSESSIONMANAGER_H
#include <kdeui_export.h>
#include <QtGui/QSessionManager>
/**
Provides highlevel access to session management on a per-object
base.
KSessionManager makes it possible to provide implementations for
QApplication::commitData() and QApplication::saveState(), without
subclassing KApplication. KMainWindow internally makes use of this.
You don't need to do anything with this class when using
KMainWindow. Instead, use KMainWindow::saveProperties(),
KMainWindow::readProperties(), KMainWindow::queryClose(),
and friends.
@short Highlevel access to session management.
@author Matthias Ettrich <ettrich@kde.org>
*/
class KDEUI_EXPORT KSessionManager
{
public:
KSessionManager();
virtual ~KSessionManager();
/**
See QApplication::saveState() for documentation.
This function is just a convenience version to avoid subclassing KApplication.
Return true to indicate a successful state save or false to
indicate a problem and to halt the shutdown process (will
implicitly call sm.cancel() ).
*/
virtual bool saveState( QSessionManager& sm );
/**
See QApplication::commitData() for documentation.
This function is just a convenience version to avoid subclassing KApplication.
Return true to indicate a successful commit of data or false to
indicate a problem and to halt the shutdown process (will
implicitly call sm.cancel() ).
*/
virtual bool commitData( QSessionManager& sm );
static QList<KSessionManager*>& sessionClients();
private:
Q_DISABLE_COPY(KSessionManager)
};
#endif // KSESSIONMANAGER_H

View file

@ -66,20 +66,22 @@ static inline QString getKLauncherError(const int result, const QString &app)
static inline void printError(const QString &text, QString *error) static inline void printError(const QString &text, QString *error)
{ {
if (error) if (error) {
*error = text; *error = text;
else } else {
kError() << text; kError() << text;
}
} }
KToolInvocation *KToolInvocation::self() K_GLOBAL_STATIC(KToolInvocation, kToolInvocation)
KToolInvocation* KToolInvocation::self()
{ {
K_GLOBAL_STATIC(KToolInvocation, s_self) return kToolInvocation;
return s_self;
} }
KToolInvocation::KToolInvocation() KToolInvocation::KToolInvocation(QObject *parent)
: QObject(0), : QObject(parent),
klauncherIface(nullptr) klauncherIface(nullptr)
{ {
klauncherIface = new QDBusInterface( klauncherIface = new QDBusInterface(
@ -89,16 +91,17 @@ KToolInvocation::KToolInvocation()
QDBusConnection::sessionBus(), QDBusConnection::sessionBus(),
this this
); );
qAddPostRoutine(kToolInvocation.destroy);
} }
KToolInvocation::~KToolInvocation() KToolInvocation::~KToolInvocation()
{ {
delete klauncherIface; qRemovePostRoutine(kToolInvocation.destroy);
} }
void KToolInvocation::setLaunchEnv(const QString &name, const QString &value) void KToolInvocation::setLaunchEnv(const QString &name, const QString &value)
{ {
self()->klauncherIface->asyncCall(QString::fromLatin1("setLaunchEnv"), name, value); klauncherIface->asyncCall(QString::fromLatin1("setLaunchEnv"), name, value);
} }
int KToolInvocation::startServiceInternal(const char *_function, int KToolInvocation::startServiceInternal(const char *_function,
@ -161,58 +164,48 @@ int KToolInvocation::startServiceInternal(const char *_function,
} }
int KToolInvocation::startServiceByDesktopPath(const QString &name, const QString &URL, int KToolInvocation::startServiceByDesktopPath(const QString &name, const QString &URL,
QString *error, QString *error, const QByteArray &startup_id)
const QByteArray &startup_id)
{ {
QStringList URLs; QStringList URLs;
if (!URL.isEmpty()) if (!URL.isEmpty()) {
URLs.append(URL); URLs.append(URL);
return self()->startServiceInternal("start_service_by_desktop_path", }
name, URLs, error, startup_id); return startServiceInternal("start_service_by_desktop_path", name, URLs, error, startup_id);
} }
int KToolInvocation::startServiceByDesktopPath(const QString &name, const QStringList &URLs, int KToolInvocation::startServiceByDesktopPath(const QString &name, const QStringList &URLs,
QString *error, QString *error, const QByteArray &startup_id)
const QByteArray &startup_id)
{ {
return self()->startServiceInternal("start_service_by_desktop_path", return startServiceInternal("start_service_by_desktop_path", name, URLs, error, startup_id);
name, URLs, error, startup_id);
} }
int KToolInvocation::startServiceByDesktopName(const QString &name, const QString &URL, int KToolInvocation::startServiceByDesktopName(const QString &name, const QString &URL,
QString *error, QString *error, const QByteArray &startup_id)
const QByteArray &startup_id)
{ {
QStringList URLs; QStringList URLs;
if (!URL.isEmpty()) if (!URL.isEmpty()) {
URLs.append(URL); URLs.append(URL);
return self()->startServiceInternal("start_service_by_desktop_name", }
name, URLs, error, startup_id); return startServiceInternal("start_service_by_desktop_name", name, URLs, error, startup_id);
} }
int KToolInvocation::startServiceByDesktopName(const QString &name, const QStringList &URLs, int KToolInvocation::startServiceByDesktopName(const QString &name, const QStringList &URLs,
QString *error, QString *error, const QByteArray &startup_id)
const QByteArray &startup_id)
{ {
return self()->startServiceInternal("start_service_by_desktop_name", return startServiceInternal("start_service_by_desktop_name", name, URLs, error, startup_id);
name, URLs, error, startup_id);
} }
int KToolInvocation::kdeinitExec(const QString &name, const QStringList &args, int KToolInvocation::kdeinitExec(const QString &name, const QStringList &args, QString *error,
QString *error,
const QByteArray &startup_id) const QByteArray &startup_id)
{ {
return self()->startServiceInternal("kdeinit_exec", return startServiceInternal("kdeinit_exec", name, args, error, startup_id);
name, args, error, startup_id);
} }
int KToolInvocation::kdeinitExecWait(const QString &name, const QStringList &args, int KToolInvocation::kdeinitExecWait(const QString &name, const QStringList &args, QString *error,
QString *error,
const QByteArray &startup_id) const QByteArray &startup_id)
{ {
return self()->startServiceInternal("kdeinit_exec_wait", return startServiceInternal("kdeinit_exec_wait", name, args, error, startup_id);
name, args, error, startup_id);
} }
void KToolInvocation::invokeHelp(const QString &anchor, void KToolInvocation::invokeHelp(const QString &anchor,
@ -227,31 +220,29 @@ void KToolInvocation::invokeHelp(const QString &anchor,
} else { } else {
appname = _appname; appname = _appname;
} }
KService::Ptr service(KService::serviceByDesktopName(appname)); KService::Ptr service(KService::serviceByDesktopName(appname));
if (service) { if (service) {
docPath = service->docPath(); docPath = service->docPath();
} }
if (!docPath.isEmpty()) { if (!docPath.isEmpty()) {
url = KUrl(KUrl(QString::fromLatin1(KDE_HELP_URL)), docPath); url = KUrl(KUrl(QString::fromLatin1(KDE_HELP_URL)), docPath);
} else { } else {
url = QString::fromLatin1(KDE_HELP_URL); url = QString::fromLatin1(KDE_HELP_URL);
} }
if (!anchor.isEmpty()) { if (!anchor.isEmpty()) {
url.addQueryItem(QString::fromLatin1("anchor"), anchor); url.addQueryItem(QString::fromLatin1("anchor"), anchor);
} }
invokeBrowser(url.url()); invokeBrowser(url.url());
} }
void KToolInvocation::invokeMailer(const QString &address, const QString &subject, const QByteArray &startup_id) void KToolInvocation::invokeMailer(const QString &address, const QString &subject,
const QByteArray &startup_id)
{ {
invokeMailer(address, QString(), subject, QString(), QStringList(), startup_id ); invokeMailer(address, QString(), subject, QString(), QStringList(), startup_id);
} }
void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray& startup_id, bool allowAttachments) void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray &startup_id,
bool allowAttachments)
{ {
QString address = mailtoURL.path(); QString address = mailtoURL.path();
QString subject; QString subject;

View file

@ -37,230 +37,193 @@ class KUrl;
*/ */
class KDECORE_EXPORT KToolInvocation : public QObject class KDECORE_EXPORT KToolInvocation : public QObject
{ {
Q_OBJECT
Q_OBJECT
private: private:
KToolInvocation();
public: public:
// @internal KToolInvocation(QObject *parent = nullptr);
~KToolInvocation(); ~KToolInvocation();
static KToolInvocation *self(); static KToolInvocation *self();
public Q_SLOTS: public Q_SLOTS:
/** /**
* Invokes the KHelpCenter HTML help viewer from docbook sources. * Invokes the KHelpCenter HTML help viewer from docbook sources.
* *
* @param anchor This has to be a defined anchor in your * @param anchor This has to be a defined anchor in your docbook sources. If empty the
* docbook sources. If empty the main index * main index is loaded
* is loaded * @param appname This allows you to show the help of another application. If empty the
* @param appname This allows you to show the help of another * current name() is used
* application. If empty the current name() is * @param startup_id For app startup notification, "0" for none
* used */
* @param startup_id for app startup notification, "0" for none, void invokeHelp(const QString &anchor = QString(), const QString &appname = QString(),
* "" ( empty string ) is the default const QByteArray &startup_id = QByteArray());
*/
static void invokeHelp(const QString &anchor = QString(), /**
const QString &appname = QString(), * Convenience method; invokes the standard email application.
const QByteArray &startup_id = QByteArray()); *
* @param address The destination address
* @param subject Subject string. Can be QString().
* @param startup_id Ffor app startup notification, "0" for none
*/
void invokeMailer(const QString &address, const QString &subject,
const QByteArray &startup_id = QByteArray());
/** /**
* Convenience method; invokes the standard email application. * Invokes the standard email application.
* *
* @param address The destination address * @param mailtoURL A mailto URL.
* @param subject Subject string. Can be QString(). * @param startup_id For app startup notification, "0" for none
* @param startup_id for app startup notification, "0" for none, * @param allowAttachments Whether attachments specified in mailtoURL should be honoured. The
* "" ( empty string ) is the default * default is false; do not honor requests for attachments.
*/ */
static void invokeMailer(const QString &address, const QString &subject, void invokeMailer(const KUrl &mailtoURL, const QByteArray &startup_id = QByteArray(),
const QByteArray &startup_id = QByteArray()); bool allowAttachments = false);
/** /**
* Invokes the standard email application. * Convenience method; invokes the standard email application.
* *
* @param mailtoURL A mailto URL. * All parameters are optional.
* @param startup_id for app startup notification, "0" for none, *
* "" ( empty string ) is the default * @param to The destination address.
* @param allowAttachments whether attachments specified in mailtoURL should be honoured. * @param cc The Cc field
The default is false; do not honor requests for attachments. * @param subject Subject string
*/ * @param body A string containing the body of the mail
static void invokeMailer(const KUrl &mailtoURL, const QByteArray &startup_id = QByteArray(), * @param attachURLs List of URLs to be attached to the mail.
bool allowAttachments = false); * @param startup_id For app startup notification, "0" for none
*/
void invokeMailer(const QString &to, const QString &cc, const QString &subject,
const QString &body, const QStringList &attachURLs = QStringList(),
const QByteArray &startup_id = QByteArray());
/** /**
* Convenience method; invokes the standard email application. * Invokes the user's preferred browser. Note that you should only do this when you know for
* * sure that the browser can handle the URL (i.e. its mimetype). In doubt, if the URL can point
* All parameters are optional. * to an image or anything else than HTML, prefer to use KRun.
* *
* @param to The destination address. * @param url The destination address
* @param cc The Cc field * @param startup_id For app startup notification, "0" for none
* @param subject Subject string */
* @param body A string containing the body of the mail void invokeBrowser(const QString &url, const QByteArray &startup_id = QByteArray());
* @param attachURLs List of URLs to be attached to the mail.
* @param startup_id for app startup notification, "0" for none,
* "" ( empty string ) is the default
*/
static void invokeMailer(const QString &to, const QString &cc,
const QString &subject, const QString &body,
const QStringList &attachURLs = QStringList(),
const QByteArray &startup_id = QByteArray());
/** /**
* Invokes the user's preferred browser. * Invokes the standard terminal application.
* Note that you should only do this when you know for sure that the browser can *
* handle the URL (i.e. its mimetype). In doubt, if the URL can point to an image * @param command The command to execute, can be empty.
* or anything else than HTML, prefer to use new KRun( url ). * @param workdir The initial working directory, can be empty.
* * @param startup_id For app startup notification, "0" for none
* See also <a *
* href="http://techbase.kde.org/Development/Architecture/KDE4/Starting_Other_Programs#KToolInvocation::invokeBrowser>techbase</a> * @since 4.1
* for a discussion of invokeBrowser vs KRun. */
* void invokeTerminal(const QString &command, const QString &workdir = QString(),
* @param url The destination address const QByteArray &startup_id = QByteArray());
* @param startup_id for app startup notification, "0" for none,
* "" ( empty string ) is the default
*/
static void invokeBrowser(const QString &url,
const QByteArray &startup_id = QByteArray());
/**
* Invokes the standard terminal application.
*
* @param command the command to execute, can be empty.
* @param workdir the initial working directory, can be empty.
* @param startup_id for app startup notification, "0" for none,
* "" ( empty string ) is the default
*
* @since 4.1
*/
static void invokeTerminal(const QString &command,
const QString &workdir = QString(),
const QByteArray &startup_id = "");
public: public:
/** /**
* Set environment variable of the launcher. * Set environment variable of the launcher, e.g. "SESSION_MANAGER"
* E.g. "SESSION_MANAGER" *
* * @param name The environment variable name
* @param name the environment variable name * @param value The environment variable value
* @param value the environment variable value */
*/ void setLaunchEnv(const QString &name, const QString &value);
static void setLaunchEnv(const QString &name, const QString &value);
/**
* Starts a service based on the desktop path of the service, e.g.
* "Applications/konqueror.desktop" or "/home/user/bla/myfile.desktop"
*
* @param name The path of the desktop file
* @param URL If not empty this URL is passed to the service
* @param error On failure, @p error contains a description of the error that occurred.
* If the pointer is null, the argument will be ignored
* @param startup_id For app startup notification, "0" for none
* @return an error code indicating success (== 0) or failure (> 0).
*/
int startServiceByDesktopPath(const QString &name, const QString &URL,
QString *error = nullptr,
const QByteArray &startup_id = QByteArray());
/**
* Starts a service based on the desktop path of the service, e..g.
* "Applications/konqueror.desktop" or "/home/user/bla/myfile.desktop"
*
* @param name The path of the desktop file
* @param URLs If not empty these URLs will be passed to the service
* @param error On failure, @p error contains a description of the error that occurred.
* If the pointer is null, the argument will be ignored
* @param startup_id For app startup notification, "0" for none
* @return an error code indicating success (== 0) or failure (> 0).
*/
int startServiceByDesktopPath(const QString &name, const QStringList &URLs = QStringList(),
QString *error = nullptr,
const QByteArray &startup_id = QByteArray());
/** /**
* Starts a service based on the desktop path of the service. * Starts a service based on the desktop name of the service, e.g. "konqueror"
* E.g. "Applications/konqueror.desktop" or "/home/user/bla/myfile.desktop"
* *
* @param name the path of the desktop file * @param name The desktop name of the service
* @param URL if not empty this URL is passed to the service * @param URL If not empty this URL is passed to the service
* @param error On failure, @p error contains a description of the error * @param error On failure, @p error contains a description of the error that occurred.
* that occurred. If the pointer is 0, the argument will be * If the pointer is null, the argument will be ignored
* ignored * @param startup_id For app startup notification, "0" for none
* @param startup_id for app startup notification, "0" for none, * @return an error code indicating success (== 0) or failure (> 0)
* "" ( empty string ) is the default
* @return an error code indicating success (== 0) or failure (> 0).
*/ */
static int startServiceByDesktopPath(const QString &name, const QString &URL, int startServiceByDesktopName(const QString &name, const QString &URL,
QString *error = 0, QString *error = nullptr,
const QByteArray &startup_id = QByteArray()); const QByteArray &startup_id = QByteArray());
/** /**
* Starts a service based on the desktop path of the service. * Starts a service based on the desktop name of the service, e.g. "konqueror"
* E.g. "Applications/konqueror.desktop" or "/home/user/bla/myfile.desktop" *
* * @param name The desktop name of the service
* @param name the path of the desktop file * @param URLs If not empty these URLs will be passed to the service
* @param URLs if not empty these URLs will be passed to the service * @param error On failure, @p error contains a description of the error that occurred.
* @param error On failure, @p error contains a description of the error * If the pointer is null, the argument will be ignored
* that occurred. If the pointer is 0, the argument will be * @param startup_id For app startup notification, "0" for none
* ignored * @return an error code indicating success (== 0) or failure (> 0)
* @param startup_id for app startup notification, "0" for none, */
* "" ( empty string ) is the default int startServiceByDesktopName(const QString &name, const QStringList &URLs = QStringList(),
* @return an error code indicating success (== 0) or failure (> 0). QString *error = nullptr,
*/ const QByteArray &startup_id = QByteArray());
static int startServiceByDesktopPath(const QString &name, const QStringList &URLs = QStringList(),
QString *error = 0,
const QByteArray &startup_id = QByteArray());
/** /**
* Starts a service based on the desktop name of the service. * Starts a program via kdeinit.
* E.g. "konqueror" *
* * @param name Name of the program to start
* @param name the desktop name of the service * @param args Arguments to pass to the program
* @param URL if not empty this URL is passed to the service * @param error On failure, @p error contains a description of the error that occurred
* @param error On failure, @p error contains a description of the error * If the pointer is null, the argument will be ignored
* that occurred. If the pointer is 0, the argument will be * @param startup_id For app startup notification, "0" for none
* ignored * @return an error code indicating success (== 0) or failure (> 0)
* @param startup_id for app startup notification, "0" for none, */
* "" ( empty string ) is the default int kdeinitExec(const QString &name, const QStringList &args = QStringList(),
* @return an error code indicating success (== 0) or failure (> 0). QString *error = nullptr, const QByteArray &startup_id = QByteArray());
*/
static int startServiceByDesktopName(const QString &name, const QString &URL,
QString *error = 0,
const QByteArray &startup_id = QByteArray());
/** /**
* Starts a service based on the desktop name of the service. * Starts a program via kdeinit and wait for it to finish, it behaves similar to the system()
* E.g. "konqueror" * function.
* *
* @param name the desktop name of the service * @param name Name of the program to start
* @param URLs if not empty these URLs will be passed to the service * @param args Arguments to pass to the program
* @param error On failure, @p error contains a description of the error * @param error On failure, @p error contains a description of the error that occurred
* that occurred. If the pointer is 0, the argument will be * If the pointer is null, the argument will be ignored
* ignored * @param startup_id For app startup notification, "0" for none
* @param startup_id for app startup notification, "0" for none, * @return an error code indicating success (== 0) or failure (> 0)
* "" ( empty string ) is the default */
* @return an error code indicating success (== 0) or failure (> 0). int kdeinitExecWait(const QString &name, const QStringList &args = QStringList(),
*/ QString *error = nullptr, const QByteArray &startup_id = QByteArray());
static int startServiceByDesktopName(const QString &name, const QStringList &URLs = QStringList(),
QString *error = 0,
const QByteArray &startup_id = QByteArray());
/**
* Starts a program via kdeinit.
*
* program name and arguments are converted to according to the
* local encoding and passed as is to kdeinit.
*
* @param name Name of the program to start
* @param args Arguments to pass to the program
* @param error On failure, @p error contains a description of the error
* that occurred. If the pointer is 0, the argument will be
* ignored
* @param startup_id for app startup notification, "0" for none,
* "" ( empty string ) is the default
* @return an error code indicating success (== 0) or failure (> 0).
*/
static int kdeinitExec(const QString &name, const QStringList &args = QStringList(),
QString *error = 0, const QByteArray &startup_id = QByteArray());
/**
* Starts a program via kdeinit and wait for it to finish.
*
* Like kdeinitExec(), but it waits till the program is finished.
* As such it behaves similar to the system(...) function.
*
* @param name Name of the program to start
* @param args Arguments to pass to the program
* @param error On failure, @p error contains a description of the error
* that occurred. If the pointer is 0, the argument will be
* ignored
* @param startup_id for app startup notification, "0" for none,
* "" ( empty string ) is the default
* @return an error code indicating success (== 0) or failure (> 0).
*/
static int kdeinitExecWait(const QString &name, const QStringList &args = QStringList(),
QString *error = 0, const QByteArray &startup_id = QByteArray());
private: private:
/** Q_DISABLE_COPY(KToolInvocation);
* @internal
*/
int startServiceInternal(const char *_function,
const QString &name, const QStringList &URLs,
QString *error,
const QByteArray &startup_id,
const QString &workdir = QString());
QDBusInterface *klauncherIface; /**
* @internal
*/
int startServiceInternal(const char *_function,
const QString &name, const QStringList &URLs,
QString *error,
const QByteArray &startup_id,
const QString &workdir = QString());
QDBusInterface *klauncherIface;
}; };
#endif #endif

View file

@ -236,7 +236,7 @@ QAction *KHelpMenu::action(MenuId id) const
void KHelpMenu::appHelpActivated() void KHelpMenu::appHelpActivated()
{ {
KToolInvocation::invokeHelp(); KToolInvocation::self()->invokeHelp();
} }
void KHelpMenu::aboutApplication() void KHelpMenu::aboutApplication()
@ -288,7 +288,7 @@ void KHelpMenu::aboutKDE()
void KHelpMenu::reportBug() void KHelpMenu::reportBug()
{ {
KToolInvocation::invokeBrowser(KDE_BUG_REPORT_URL); KToolInvocation::self()->invokeBrowser(KDE_BUG_REPORT_URL);
} }

View file

@ -30,7 +30,6 @@
#include "ktoolbarhandler_p.h" #include "ktoolbarhandler_p.h"
#include "kcmdlineargs.h" #include "kcmdlineargs.h"
#include "ktoggleaction.h" #include "ktoggleaction.h"
#include "ksessionmanager.h"
#include "kstandardaction.h" #include "kstandardaction.h"
#include <QtCore/QList> #include <QtCore/QList>
@ -40,7 +39,6 @@
#include <QtGui/QDesktopWidget> #include <QtGui/QDesktopWidget>
#include <QtGui/QDockWidget> #include <QtGui/QDockWidget>
#include <QtGui/QLayout> #include <QtGui/QLayout>
#include <QtGui/QSessionManager>
#include <QtGui/QStyle> #include <QtGui/QStyle>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QtGui/QMenuBar> #include <QtGui/QMenuBar>
@ -101,76 +99,6 @@ bool DockResizeListener::eventFilter(QObject *watched, QEvent *event)
return QObject::eventFilter(watched, event); return QObject::eventFilter(watched, event);
} }
class KMWSessionManager : public KSessionManager
{
public:
KMWSessionManager()
{
}
bool dummyInit() { return true; }
bool saveState( QSessionManager& )
{
KConfig* config = KApplication::kApplication()->sessionConfig();
if ( KMainWindow::memberList().count() ){
// According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
// hook is useful for better document orientation
KMainWindow::memberList().first()->saveGlobalProperties(config);
}
int n = 0;
foreach (KMainWindow* mw, KMainWindow::memberList()) {
n++;
mw->savePropertiesInternal(config, n);
}
KConfigGroup group( config, "Number" );
group.writeEntry("NumberOfWindows", n );
return true;
}
bool commitData( QSessionManager& sm )
{
// not really a fast method but the only compatible one
if ( sm.allowsInteraction() ) {
bool canceled = false;
foreach (KMainWindow *window, KMainWindow::memberList()) {
if ( !window->testAttribute( Qt::WA_WState_Hidden ) ) {
QCloseEvent e;
QApplication::sendEvent( window, &e );
canceled = !e.isAccepted();
if (canceled)
break;
/* Don't even think_about deleting widgets with
Qt::WDestructiveClose flag set at this point. We
are faking a close event, but we are *not*_
closing the window. The purpose of the faked
close event is to prepare the application so it
can safely be quit without the user losing data
(possibly showing a message box "do you want to
save this or that?"). It is possible that the
session manager quits the application later
(emitting QApplication::aboutToQuit() when this
happens), but it is also possible that the user
cancels the shutdown, so the application will
continue to run.
*/
}
}
if (canceled)
return false;
// else
return true;
}
// the user wants it, the user gets it
return true;
}
};
K_GLOBAL_STATIC(KMWSessionManager, ksm)
K_GLOBAL_STATIC(QList<KMainWindow*>, sMemberList) K_GLOBAL_STATIC(QList<KMainWindow*>, sMemberList)
static bool being_first = true; static bool being_first = true;
@ -207,8 +135,8 @@ void KMainWindowPrivate::init(KMainWindow *_q)
// So don't let the default Qt mechanism allow any toplevel widget to just quit the app on us. // So don't let the default Qt mechanism allow any toplevel widget to just quit the app on us.
// Setting WA_QuitOnClose to false for all KMainWindows is not enough, any progress widget // Setting WA_QuitOnClose to false for all KMainWindows is not enough, any progress widget
// or dialog box would still quit the app... // or dialog box would still quit the app...
if (qApp) if (kapp)
qApp->setQuitOnLastWindowClosed(false); kapp->setQuitOnLastWindowClosed(false);
helpMenu = 0; helpMenu = 0;
@ -216,9 +144,6 @@ void KMainWindowPrivate::init(KMainWindow *_q)
QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayStyleChanged()), QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayStyleChanged()),
q, SLOT(_k_slotStyleChanged())); q, SLOT(_k_slotStyleChanged()));
// force KMWSessionManager creation - someone a better idea?
ksm->dummyInit();
sMemberList->append( q ); sMemberList->append( q );
settingsDirty = false; settingsDirty = false;
@ -460,7 +385,7 @@ KMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
bool KMainWindow::canBeRestored( int number ) bool KMainWindow::canBeRestored( int number )
{ {
if ( !qApp->isSessionRestored() ) if ( !kapp->isSessionRestored() )
return false; return false;
KConfig *config = kapp->sessionConfig(); KConfig *config = kapp->sessionConfig();
if ( !config ) if ( !config )
@ -473,7 +398,7 @@ bool KMainWindow::canBeRestored( int number )
const QString KMainWindow::classNameOfToplevel( int number ) const QString KMainWindow::classNameOfToplevel( int number )
{ {
if ( !qApp->isSessionRestored() ) if ( !kapp->isSessionRestored() )
return QString(); return QString();
KConfig *config = kapp->sessionConfig(); KConfig *config = kapp->sessionConfig();
if ( !config ) if ( !config )

View file

@ -101,7 +101,7 @@ class KToolBar;
class KDEUI_EXPORT KMainWindow : public QMainWindow class KDEUI_EXPORT KMainWindow : public QMainWindow
{ {
friend class KMWSessionManager; friend class KApplication;
friend class DockResizeListener; friend class DockResizeListener;
KDEUI_DECLARE_PRIVATE(KMainWindow) KDEUI_DECLARE_PRIVATE(KMainWindow)
Q_OBJECT Q_OBJECT

View file

@ -31,7 +31,6 @@
#include "kxmlguifactory.h" #include "kxmlguifactory.h"
#include "kcmdlineargs.h" #include "kcmdlineargs.h"
#include "ktoggleaction.h" #include "ktoggleaction.h"
#include "ksessionmanager.h"
#include "kstandardaction.h" #include "kstandardaction.h"
#include <config.h> #include <config.h>

View file

@ -32,7 +32,6 @@ int main(int argc, char **argv)
} }
::setlocale(LC_ALL, ""); ::setlocale(LC_ALL, "");
::unsetenv("SESSION_MANAGER");
if (!argv[1]) if (!argv[1])
{ {

View file

@ -45,17 +45,6 @@ KLauncher::~KLauncher()
session.unregisterService("org.kde.klauncher"); session.unregisterService("org.kde.klauncher");
} }
void KLauncher::setSessionManager(const QByteArray &sessionmanager)
{
const int equalindex = sessionmanager.indexOf('=');
kDebug() << "SESSION_MANAGER" << sessionmanager;
if (equalindex > 0) {
const QByteArray sessionmanagervalue = sessionmanager.mid(equalindex + 1, sessionmanager.size() - equalindex - 1);
kDebug() << "SESSION_MANAGER" << sessionmanager << sessionmanagervalue;
m_adaptor->setLaunchEnv(QString::fromLatin1("SESSION_MANAGER"), sessionmanagervalue);
}
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
KAboutData aboutData( KAboutData aboutData(
@ -66,15 +55,8 @@ int main(int argc, char *argv[])
KCmdLineArgs::init(argc, argv, &aboutData); KCmdLineArgs::init(argc, argv, &aboutData);
const QByteArray sessionmanager = qgetenv("SESSION_MANAGER");
// NOTE: disables session manager entirely, for reference:
// https://www.x.org/releases/X11R7.7/doc/libSM/xsmp.html
::unsetenv("SESSION_MANAGER");
KApplication app; KApplication app;
app.setQuitOnLastWindowClosed(false); app.setQuitOnLastWindowClosed(false);
app.disableSessionManagement();
QDBusConnection session = QDBusConnection::sessionBus(); QDBusConnection session = QDBusConnection::sessionBus();
if (!session.isConnected()) { if (!session.isConnected()) {
@ -88,8 +70,6 @@ int main(int argc, char *argv[])
} }
KLauncher klauncher(&app); KLauncher klauncher(&app);
klauncher.setSessionManager(sessionmanager);
return app.exec(); // keep running return app.exec(); // keep running
} }

View file

@ -30,8 +30,6 @@ public:
KLauncher(QObject *parent = nullptr); KLauncher(QObject *parent = nullptr);
~KLauncher(); ~KLauncher();
void setSessionManager(const QByteArray &sessionmanager);
private: private:
KLauncherAdaptor* m_adaptor; KLauncherAdaptor* m_adaptor;
}; };

View file

@ -74,10 +74,10 @@ public:
public: public:
public Q_SLOTS: public Q_SLOTS:
// used by ksmserver // used by plasma-desktop
void autoStart(int phase); void autoStart(int phase);
// used by ksmserver and klauncher itself // used by plasma-desktop and klauncher itself
void exec_blind(const QString &name, const QStringList &arg_list); void exec_blind(const QString &name, const QStringList &arg_list);
void cleanup(); void cleanup();

View file

@ -941,7 +941,7 @@ bool KRun::run(const KService& _service, const KUrl::List& _urls, QWidget* windo
QString error; QString error;
int i = KToolInvocation::startServiceByDesktopPath( int i = KToolInvocation::self()->startServiceByDesktopPath(
_service.entryPath(), urls.toStringList(), &error, asn _service.entryPath(), urls.toStringList(), &error, asn
); );
@ -1100,7 +1100,7 @@ void KRun::init()
if (service) { if (service) {
kDebug(7010) << "Helper protocol service is" << service->name() << service->entryPath(); kDebug(7010) << "Helper protocol service is" << service->name() << service->entryPath();
QString errorstr; QString errorstr;
if (KToolInvocation::startServiceByDesktopPath(service->entryPath(), d->m_strURL.url(), &errorstr, d->m_asn) == 0) { if (KToolInvocation::self()->startServiceByDesktopPath(service->entryPath(), d->m_strURL.url(), &errorstr, d->m_asn) == 0) {
d->m_bFinished = true; d->m_bFinished = true;
d->startTimer(); d->startTimer();
return; return;

View file

@ -38,7 +38,7 @@ int main( int argc, char **argv )
if ( args->count() != 1 ) if ( args->count() != 1 )
return 1; return 1;
KToolInvocation::invokeMailer(KUrl(args->arg(0)), QByteArray(), true); KToolInvocation::self()->invokeMailer(KUrl(args->arg(0)), QByteArray(), true);
return 0; return 0;
} }

View file

@ -94,7 +94,7 @@ int main(int argc, char **argv)
cmd << QString::number(url.port()); cmd << QString::number(url.port());
} }
KToolInvocation::kdeinitExec(terminal, cmd); KToolInvocation::self()->kdeinitExec(terminal, cmd);
return 0; return 0;
} }

View file

@ -327,7 +327,7 @@ void KCMultiDialog::slotHelpClicked()
} }
moduleService = moduleService.replace(QLatin1String(".desktop"), QString()); moduleService = moduleService.replace(QLatin1String(".desktop"), QString());
KToolInvocation::invokeHelp(QString(), moduleService); KToolInvocation::self()->invokeHelp(QString(), moduleService);
} }