ksmserver: drop it and move session initialization to plasma-desktop

everything except the actual session management, second time ksmserver
starts crashing as I work on something for no reason and is time for it
to be done anew as there were quite some unsafe bits in it

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-05-07 02:08:57 +03:00
parent bb574694b1
commit 3e5dfaa22b
46 changed files with 322 additions and 4297 deletions

View file

@ -263,7 +263,6 @@ add_subdirectory(systemsettings)
# core apps
add_subdirectory(kwin)
add_subdirectory(ksmserver)
add_subdirectory(kscreensaver)
add_subdirectory(qguiplatformplugin_kde)

View file

@ -107,7 +107,6 @@ void KCMInit::runModules( int phase )
continue; // Skip
}
// see ksmserver's README for the description of the phases
QVariant vphase = service->property("X-KDE-Init-Phase", QVariant::Int );
int libphase = 1;
if( vphase.isValid() )

View file

@ -91,7 +91,7 @@ CfgWm::CfgWm(QWidget *parent)
connect(wmCombo,SIGNAL(activated(int)),this,SLOT(checkConfigureWm()));
connect(configureButton,SIGNAL(clicked()),this,SLOT(configureWm()));
KGlobal::dirs()->addResourceType( "windowmanagers", "data", "ksmserver/windowmanagers" );
KGlobal::dirs()->addResourceType("windowmanagers", "data", "plasma/windowmanagers");
}
CfgWm::~CfgWm()
@ -111,7 +111,7 @@ void CfgWm::defaults()
void CfgWm::load(KConfig *)
{
KConfig cfg("ksmserverrc", KConfig::NoGlobals);
KConfig cfg("plasmarc", KConfig::NoGlobals);
KConfigGroup c( &cfg, "General");
loadWMs(c.readEntry("windowManager", "kwin"));
emit changed(false);
@ -124,7 +124,7 @@ void CfgWm::save(KConfig *)
bool CfgWm::saveAndConfirm()
{
KConfig cfg("ksmserverrc", KConfig::NoGlobals);
KConfig cfg("plasmarc", KConfig::NoGlobals);
KConfigGroup c( &cfg, "General");
c.writeEntry("windowManager", currentWm());
emit changed(false);
@ -134,8 +134,8 @@ bool CfgWm::saveAndConfirm()
if (tryWmLaunch()) {
oldwm = currentWm();
cfg.sync();
QDBusInterface ksmserver("org.kde.ksmserver", "/KSMServer");
ksmserver.call(QDBus::NoBlock, "wmChanged");
QDBusInterface plasma("org.kde.plasma-desktop", "/App", "local.PlasmaApp");
plasma.call(QDBus::NoBlock, "wmChanged");
KMessageBox::information(
window(),
i18n("A new window manager is running.\n"
@ -269,12 +269,6 @@ void CfgWm::loadWMs(const QString &current)
continue;
if (!file.tryExec())
continue;
QString testexec = file.desktopGroup().readEntry("X-KDE-WindowManagerTestExec");
if (!testexec.isEmpty()) {
if (QProcess::execute(testexec) != 0) {
continue;
}
}
QString name = file.readName();
if (name.isEmpty())
continue;

View file

@ -7,5 +7,5 @@ install(
metacity.desktop
openbox.desktop
xfwm4.desktop
DESTINATION ${KDE4_DATA_INSTALL_DIR}/ksmserver/windowmanagers
DESTINATION ${KDE4_DATA_INSTALL_DIR}/plasma/windowmanagers
)

View file

@ -10,15 +10,6 @@ Exec - required, the command to execute to launch the window manager.
TryExec - optional.
X-KDE-WindowManagerTestExec - optional, a command that will be run and if
the exit code is not 0, the window manager won't be used (can be used
e.g. to detect that a window manager which requires compositing support
cannot be run on systems without such support).
X-KDE-WindowManagerId - optional, the name under which the window manager
registers with the session manager (if different from the name
of the .desktop file)
X-KDE-WindowManagerConfigure - optional, the command to run to configure
the window manager

View file

@ -1,79 +0,0 @@
project(ksmserver)
add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1218)
include_directories(
${CMAKE_SOURCE_DIR}/libs
# for kworkspace_export.h
${CMAKE_BINARY_DIR}/libs/kworkspace
)
add_subdirectory(kcm)
check_library_exists(ICE _IceTransNoListen "" HAVE__ICETRANSNOLISTEN)
configure_file(config-ksmserver.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ksmserver.h)
########### next target ###############
set(ksmserver_SRCS
main.cpp
server.cpp
shutdowndlg.cpp
startup.cpp
shutdown.cpp
client.cpp
)
set(kcminit_adaptor ${CMAKE_SOURCE_DIR}/kcminit/main.h)
set(kcminit_xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KCMinit.xml)
qt4_generate_dbus_interface(${kcminit_adaptor} ${kcminit_xml})
qt4_add_dbus_interface( ksmserver_SRCS ${kcminit_xml} kcminit_interface )
# This is actually now disabled, because OrgKDEKlauncherInterface is also provided
# by kdecore, it is not autogenerated and is not binary compatible with a currently
# generated version, thus at certain circumstances leading to strange crashes.
# This should be fixed for KDE5.
# KLauchner.xml is installed by kdelibs, so it is in KDE4_DBUS_INTERFACES_INSTALL_DIR
# set(klauncher_xml ${KDE4_DBUS_INTERFACES_INSTALL_DIR}/org.kde.KLauncher.xml)
# qt4_add_dbus_interface( ksmserver_SRCS ${klauncher_xml} klauncher_interface )
qt4_add_dbus_adaptor(ksmserver_SRCS org.kde.KSMServerInterface.xml server.h KSMServer)
add_executable(ksmserver ${ksmserver_SRCS})
target_link_libraries(ksmserver
KDE4::plasma
KDE4::kdeui
KDE4::kio
KDE4::solid
${QT_QTDECLARATIVE_LIBRARY}
${X11_LIBRARIES}
kworkspace
)
install(
TARGETS ksmserver
DESTINATION ${KDE4_BIN_INSTALL_DIR}
)
########### next target ###############
set(kcheckrunning_SRCS
kcheckrunning.cpp
)
add_executable(kcheckrunning ${kcheckrunning_SRCS})
target_link_libraries(kcheckrunning ${X11_LIBRARIES})
install(
TARGETS kcheckrunning
DESTINATION ${KDE4_BIN_INSTALL_DIR}
)
########### install files ###############
install(
FILES org.kde.KSMServerInterface.xml
DESTINATION ${KDE4_DBUS_INTERFACES_INSTALL_DIR}
)

View file

@ -1,48 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
******************************************************************/
#ifndef KSMSERVER_INTERFACE_H
#define KSMSERVER_INTERFACE_H
#include <dcopobject.h>
class KSMServerInterface : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.KSMServerInterface")
public Q_SLOTS:
Q_SCRIPTABLE void logout(int, int );
Q_SCRIPTABLE QStringList sessionList();
Q_SCRIPTABLE QString currentSession();
Q_SCRIPTABLE void saveCurrentSession();
Q_SCRIPTABLE void saveCurrentSessionAs( QString );
Q_SCRIPTABLE void suspendStartup( QString );
Q_SCRIPTABLE void resumeStartup( QString );
Q_SCRIPTABLE void wmChanged();
};
#endif

View file

@ -1,16 +0,0 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,2 +0,0 @@
#!/bin/bash
$XGETTEXT *.cpp -o $podir/ksmserver.pot

View file

@ -1,159 +0,0 @@
KDE session manager (ksmserver)
--------------------------------
Matthias Ettrich <ettrich@kde.org>
Lubos Lunak <l.lunak@kde.org>
ksmserver is KDE's session management server. It talks the
standard X11R6 session management protocol (XSMP). Thus, in theory,
it should be compatible with all session managment compliant X11R6
applications. Unfortunately, there aren't that many of them. To be
precise, I have never seen a single commercial application that
supports it and even within the official X11R6 distribution, 'xclock'
is the only exception. Nevertheless we've chosen to support XSMP
despites the complexity of the protocol in order to provide KDE users
more interoperability with applications that were not explicitely
written with KDE in mind. XSMP, as an official X standard, promised to
be more likely to be supported by third parties than even a superior
KDE-specific protocol. Let's see whether we were right and more
applications will actually talk XSMP. At least all KDE applications do
now.
Here's a short overview on how session management works.
Contents
--------
Starting the server
KDE startup sequence
Establishing the connection
Authorization
Requesting a shutdown
Starting the server
-------------------
The server is usually started from the 'startkde' script. It supports the following options:
-r, --restore Restores the previous session if available
-w, --windowmanager <wm> Starts 'wm' in case no other window manager is
participating in the session. Default is 'kwin'
The default 'startkde' launches 'ksmserver --restore'. The
'windowmanager' option is useful for users that prefer a window
manager other than kwin. Since the window manager has to participate
in the session (it has to remember window positions and states), it is
usually restarted when the session is restored. To be *really* sure
that this happens, even if the wm might have crashed during the
previous session, ksmserver ensures that. The option specifies, which
windowmanager shall be launched for sure. But again: if the stored
session contains a window manager, the restored one will be used, not
the specified one. As a special feature, ksmserver always starts the
specified window manager first, which results in a much nicer startup
sequence (less flashy).
KDE startup sequence
--------------------
Ksmserver controls the second part of the KDE startup sequence,
after it gets control from the startkde script, which controls
the first part of the startup sequence. All code related to startup
should be in startup.cpp and going down in that source file should
follow the startup order (but note that this is just a documentation
which may get outdated, so in case of doubts the source wins ;) ).
The startkde script launches kcminit, which performs initialization done by
kcontrol modules. There are three kcminit phases, 0, 1 and 2, controlled
by X-KDE-Init-Phase= in the .desktop file, which defaults to 1. Phase 0 kcminit
modules should be only those that really need to be run early in the startup
process. After executing phase 0 modules kcminit returns and waits.
When ksmserver is launched, the first thing it does is launching
the window manager, as the WM is necessary before any windows are possibly
shown. When the WM is ready, ksmserver launchers kded. Kded loads autoloaded
kded modules, i.e. those that have X-KDE-Kded-autoload=true in .desktop
files. The exact way autoloading works is controlled by X-KDE-Kded-phase=,
which may be 0, 1 or 2 (the default). Kded phase 0 means the module is
always loaded by kded, even outside of KDE session. It should used only
by kded modules which must be always running. Kded phase 1 modules are
loaded right after kded startup, but only during KDE startup, i.e. it is
for modules that are always needed by the KDE session. Phase 2 modules
will be loaded later. [More information about kded modules could be
found in kdelibs/kded/HOWTO]
The next thing ksmserver does is to tell klauncher to perform autostart
phase 0 ($KDEHOME/share/autostart). There are 3 autostart phases, 0, 1 and 2,
defined by X-KDE-autostart-phase, defaulting to 2. Phase 0 is reserved only
for the actual visible base components of KDE, i.e. Plasma, in order to make
the startup appear visually faster. Plasma uses D-Bus calls suspendStartup()
and resumeStartup() to make ksmserver stay waiting for autostart phase 0
until Plasma is ready (note: suspendStartup() needs to be called before
the application registers with ksmserver, i.e. before KApplication ctor is called).
Next step is telling the waiting kcminit to perform phase 1 - all kcminit
modules that should be executed before KDE startup is considered done.
After that ksmserver tells klauncher to perform autostart phase 1,
i.e. launching normal components of KDE that should be available right
after KDE startup, and after this session restore is performed,
i.e. launching all applications that were running during last session
saving (usually logout).
By this time KDE session is considered to be more or less ready and
ksmserver does the knotify startkde event (i.e. plays the login sound).
It also tells klauncher to perform autostart phase 2, kded to load all
remaining autoload (i.e. kded phase 2) modules, kcminit to execute
kcminit phase 2 (kcontrol modules that do initialization that can wait,
like launching daemons) and it itself executes the user Autostart folder.
Technical note: There's a reason why kded modules and items in autostart
default to the latest phase. Before you explicitly use a different phase,
read and understand what's above. You should also consider whether something
really needs to be launched during KDE startup and can't be loaded on-demand
when really needed. Abusing the phases will result in public spanking
for making KDE startup slower.
Establishing the connection
---------------------------
As required by the XSMP specification, the session management server
propagates its network address in the SESSION_MANAGER environment
variable. Probably not the best way to do it, but it's the way it
is. All KDE (and plain Qt) applications simply read this variable and
try to establish a connection to an XSMP server at this address. If
the variable is undefined, nothing happens.
This means, if you want to start a program that should not participate
in the session, simply undefine SESSION_MANAGER in your terminal
window and launch the application. If you want to see an application
desparately trying to connect to something, try setting it to some
bogus value.
In addition, ksmserver propagates both its network address and its
process id in /run/user/<uid>/KSMserver_$DISPLAY. A utility function
KWorkSpace::propagateSessionManager() reads this setting and sets
SESSION_MANAGER accordingly, so that child processes can pick it up.
The function is called by clients that are started outside the session
(i.e. before ksmserver is started), but want to launch other processes
that should participate in the session.
Authorization
-------------
XSMP is built on top of the Inter Client Exchange (ICE) protocol,
which comes standard as a part of X11R6 and later.
Authorization is done using 'iceauth', with MIT-MAGIC-COOKIE as used
by X. In order to be able to access the session management server, you
need to be able to read ~/.ICEauthority. For security reasons, we do
not provide any host-based authorization.
Requesting a shutdown
---------------------
If an application wants to request a shutdown (i.e. a logout), it does
this via an SmcRequestSaveYourself message to the server. In KDE, a
utility function KWorkSpace::requestShutDown() does exactly
this. It's for example called by KDE's panel or by the context menu of
the desktop.

View file

@ -1,185 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Copyright 2005 Lubos Lunak <l.lunak@kde.org>
relatively small extensions by Oswald Buddenhagen <ob6@inf.tu-dresden.de>
some code taken from the dcopserver (part of the KDE libraries), which is
Copyright 1999 Matthias Ettrich <ettrich@kde.org>
Copyright 1999 Preston Brown <pbrown@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#include "config-unix.h"
#include "client.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <kglobal.h>
#include <krandom.h>
#include "server.h"
extern KSMServer* the_server;
KSMClient::KSMClient( SmsConn conn)
{
smsConn = conn;
id = 0;
resetState();
}
KSMClient::~KSMClient()
{
foreach( SmProp *prop, properties )
SmFreeProperty( prop );
if (id) free((void*)id);
}
SmProp* KSMClient::property( const char* name ) const
{
foreach ( SmProp *prop, properties ) {
if ( qstrcmp( prop->name, name ) == 0)
return prop;
}
return 0;
}
void KSMClient::resetState()
{
saveYourselfDone = false;
pendingInteraction = false;
waitForPhase2 = false;
wasPhase2 = false;
}
/*
* This fakes SmsGenerateClientID() in case we can't read our own hostname.
* In this case SmsGenerateClientID() returns NULL, but we really want a
* client ID, so we fake one.
*/
K_GLOBAL_STATIC(QString, my_addr)
char * safeSmsGenerateClientID( SmsConn /*c*/ )
{
// Causes delays with misconfigured network :-/.
// char *ret = SmsGenerateClientID(c);
char* ret = NULL;
if (!ret) {
if (my_addr->isEmpty()) {
// qWarning("Can't get own host name. Your system is severely misconfigured\n");
/* Faking our IP address, the 0 below is "unknown" address format
(1 would be IP, 2 would be DEC-NET format) */
char hostname[ 256 ];
::memset(hostname, '\0', sizeof(hostname));
if( ::gethostname( hostname, 255 ) != 0 )
my_addr->sprintf("0%.8x", KRandom::random());
else {
// create some kind of hash for the hostname
int addr[ 4 ] = { 0, 0, 0, 0 };
int pos = 0;
for( unsigned int i = 0;
i < strlen( hostname );
++i, ++pos )
addr[ pos % 4 ] += hostname[ i ];
*my_addr = "0";
for( int i = 0;
i < 4;
++i )
*my_addr += QString::number( addr[ i ], 16 );
}
}
/* Needs to be malloc(), to look the same as libSM */
ret = (char *)malloc(1+my_addr->length()+13+10+4+1 + /*safeness*/ 10);
static int sequence = 0;
if (ret == NULL)
return NULL;
sprintf(ret, "1%s%.13ld%.10d%.4d", my_addr->toLatin1().constData(), (long)time(NULL),
getpid(), sequence);
sequence = (sequence + 1) % 10000;
}
return ret;
}
void KSMClient::registerClient( const char* previousId )
{
id = previousId;
if ( !id )
id = safeSmsGenerateClientID( smsConn );
SmsRegisterClientReply( smsConn, (char*) id );
SmsSaveYourself( smsConn, SmSaveLocal, false, SmInteractStyleNone, false );
SmsSaveComplete( smsConn );
the_server->clientRegistered( previousId );
}
QString KSMClient::program() const
{
SmProp* p = property( SmProgram );
if ( !p || qstrcmp( p->type, SmARRAY8) != 0 || p->num_vals < 1)
return QString();
return QLatin1String( (const char*) p->vals[0].value );
}
QStringList KSMClient::restartCommand() const
{
QStringList result;
SmProp* p = property( SmRestartCommand );
if ( !p || qstrcmp( p->type, SmLISTofARRAY8) != 0 || p->num_vals < 1)
return result;
for ( int i = 0; i < p->num_vals; i++ )
result +=QLatin1String( (const char*) p->vals[i].value );
return result;
}
QStringList KSMClient::discardCommand() const
{
QStringList result;
SmProp* p = property( SmDiscardCommand );
if ( !p || qstrcmp( p->type, SmLISTofARRAY8) != 0 || p->num_vals < 1)
return result;
for ( int i = 0; i < p->num_vals; i++ )
result +=QLatin1String( (const char*) p->vals[i].value );
return result;
}
int KSMClient::restartStyleHint() const
{
SmProp* p = property( SmRestartStyleHint );
if ( !p || qstrcmp( p->type, SmCARD8) != 0 || p->num_vals < 1)
return SmRestartIfRunning;
return *((unsigned char*)p->vals[0].value);
}
QString KSMClient::userId() const
{
SmProp* p = property( SmUserID );
if ( !p || qstrcmp( p->type, SmARRAY8) != 0 || p->num_vals < 1)
return QString();
return QLatin1String( (const char*) p->vals[0].value );
}

View file

@ -1,64 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#ifndef CLIENT_H
#define CLIENT_H
#include <kapplication.h>
#include <kworkspace/kworkspace.h>
#include "server.h"
class KSMClient
{
public:
explicit KSMClient( SmsConn );
~KSMClient();
void registerClient( const char* previousId = 0 );
SmsConn connection() const { return smsConn; }
void resetState();
bool saveYourselfDone;
bool pendingInteraction;
bool waitForPhase2;
bool wasPhase2;
QList<SmProp*> properties;
SmProp* property( const char* name ) const;
QString program() const;
QStringList restartCommand() const;
QStringList discardCommand() const;
int restartStyleHint() const;
QString userId() const;
const char* clientId() { return id ? id : ""; }
private:
const char* id;
SmsConn smsConn;
};
#endif

View file

@ -1,2 +0,0 @@
/* Define to 1 if you have the `_IceTransNoListen' function. */
#cmakedefine HAVE__ICETRANSNOLISTEN 1

View file

@ -1,31 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#ifndef GLOBAL_H
#define GLOBAL_H
#define KSMVendorString "KDE"
#define KSMReleaseString "1.0"
#endif

View file

@ -1,52 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2005 Lubos Lunak <l.lunak@kde.org>
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 <X11/Xlib.h>
/*
Return 0 when KDE is running, 1 when KDE is not running but it is possible
to connect to X, 2 when it's not possible to connect to X.
*/
int main()
{
Display* dpy = XOpenDisplay(NULL);
if (dpy == NULL) {
return 2;
}
// if ksmserver is not started yet check for the X11 atom that startkde sets
Atom type = None;
int format = 0;
unsigned long nitems = 0;
unsigned long after = 0;
unsigned char* data = NULL;
const int kde_full_session_status = XGetWindowProperty(
dpy, RootWindow(dpy, 0),
XInternAtom(dpy, "KDE_FULL_SESSION", False),
0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data
);
const bool kde_running = (kde_full_session_status == Success && data);
if (data) {
XFree(data);
}
XCloseDisplay(dpy);
if (kde_running) {
return 0;
}
return 1;
}

View file

@ -1,19 +0,0 @@
set(kcm_smserver_PART_SRCS
kcmsmserver.cpp
smserverconfigimpl.cpp
smserverconfigdlg.ui
)
kde4_add_plugin(kcm_smserver ${kcm_smserver_PART_SRCS})
target_link_libraries(kcm_smserver KDE4::kdeui)
install(TARGETS kcm_smserver DESTINATION ${KDE4_PLUGIN_INSTALL_DIR})
########### install files ###############
install(FILES kcmsmserver.desktop DESTINATION ${KDE4_SERVICES_INSTALL_DIR})

View file

@ -1,5 +0,0 @@
#!/bin/bash
$EXTRACTRC *.ui >> rc.cpp
$XGETTEXT *.cpp -o $podir/kcmsmserver.pot
rm -f rc.cpp

View file

@ -1,135 +0,0 @@
/*
* kcmsmserver.cpp
* Copyright (c) 2000,2002 Oswald Buddenhagen <ossi@kde.org>
*
* based on kcmtaskbar.cpp
* Copyright (c) 2000 Kurt Granroth <granroth@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
*/
#include <QCheckBox>
#include <QVBoxLayout>
#include <QtDBus/QtDBus>
#include <qregexp.h>
#include <kapplication.h>
#include <kconfiggroup.h>
#include <klineedit.h>
#include <kworkspace/kworkspace.h>
#include <kstandarddirs.h>
#include <kdesktopfile.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <klocale.h>
#include "kcmsmserver.h"
#include "smserverconfigimpl.h"
K_PLUGIN_FACTORY(SMSFactory,
registerPlugin<SMServerConfig>();
)
K_EXPORT_PLUGIN(SMSFactory("kcmsmserver"))
SMServerConfig::SMServerConfig( QWidget *parent, const QVariantList & )
: KCModule (SMSFactory::componentData(), parent)
{
setQuickHelp( i18n("<h1>Session Manager</h1>"
" You can configure the session manager here."
" This includes options such as whether or not the session exit (logout)"
" should be confirmed, whether the session should be restored again when logging in"
" and whether the computer should be automatically shut down after session"
" exit by default."));
QVBoxLayout *topLayout = new QVBoxLayout(this);
topLayout->setMargin(0);
dialog = new SMServerConfigImpl(this);
connect(dialog, SIGNAL(changed()), SLOT(changed()));
topLayout->addWidget(dialog);
}
void SMServerConfig::load()
{
KConfigGroup c(KSharedConfig::openConfig("ksmserverrc", KConfig::NoGlobals), "General");
dialog->confirmLogoutCheck->setChecked(c.readEntry("confirmLogout", true));
bool en = c.readEntry("offerShutdown", true);
dialog->offerShutdownCheck->setChecked(en);
dialog->sdGroup->setEnabled(en);
QString s = c.readEntry( "loginMode" );
if ( s == "default" )
dialog->emptySessionRadio->setChecked(true);
else if ( s == "restoreSavedSession" )
dialog->savedSessionRadio->setChecked(true);
else // "restorePreviousLogout"
dialog->previousSessionRadio->setChecked(true);
switch (c.readEntry("shutdownType", int(KWorkSpace::ShutdownTypeNone))) {
case int(KWorkSpace::ShutdownTypeHalt):
dialog->haltRadio->setChecked(true);
break;
case int(KWorkSpace::ShutdownTypeReboot):
dialog->rebootRadio->setChecked(true);
break;
default:
dialog->logoutRadio->setChecked(true);
break;
}
dialog->excludeLineedit->setText( c.readEntry("excludeApps"));
emit changed(false);
}
void SMServerConfig::save()
{
KConfig c("ksmserverrc", KConfig::NoGlobals);
KConfigGroup group = c.group("General");
group.writeEntry( "confirmLogout", dialog->confirmLogoutCheck->isChecked());
group.writeEntry( "offerShutdown", dialog->offerShutdownCheck->isChecked());
QString s = "restorePreviousLogout";
if ( dialog->emptySessionRadio->isChecked() )
s = "default";
else if ( dialog->savedSessionRadio->isChecked() )
s = "restoreSavedSession";
group.writeEntry( "loginMode", s );
group.writeEntry( "shutdownType",
dialog->haltRadio->isChecked() ?
int(KWorkSpace::ShutdownTypeHalt) :
dialog->rebootRadio->isChecked() ?
int(KWorkSpace::ShutdownTypeReboot) :
int(KWorkSpace::ShutdownTypeNone));
group.writeEntry("excludeApps", dialog->excludeLineedit->text());
c.sync();
# if 0
// update the k menu if necessary
QDBusInterface kicker("org.kde.kicker", "/kicker", "org.kde.kicker");
kicker.call("configure");
#endif
}
void SMServerConfig::defaults()
{
dialog->previousSessionRadio->setChecked(true);
dialog->confirmLogoutCheck->setChecked(true);
dialog->offerShutdownCheck->setChecked(true);
dialog->sdGroup->setEnabled(true);
dialog->logoutRadio->setChecked(true);
dialog->excludeLineedit->clear();
}
#include "moc_kcmsmserver.cpp"

View file

@ -1,205 +0,0 @@
[Desktop Entry]
Exec=kcmshell4 kcmsmserver
Icon=preferences-system-session
Type=Service
X-KDE-ServiceTypes=KCModule
X-DocPath=kcontrol/kcmsmserver/index.html
X-KDE-Library=kcm_smserver
X-KDE-ParentApp=kcontrol
X-KDE-System-Settings-Parent-Category=startup-and-shutdown
Name=Session Management
Name[ar]=إدارة الجلسات
Name[ast]=Xestión de sesiones
Name[bg]=Управление на сесии
Name[bs]=Upravljanje sesijama
Name[ca]=Gestió de sessions
Name[ca@valencia]=Gestió de sessions
Name[cs]=Správa sezení
Name[da]=Sessionshåndtering
Name[de]=Sitzungsverwaltung
Name[el]=Διαχείριση συνεδριών
Name[en_GB]=Session Management
Name[es]=Gestión de sesiones
Name[et]=Seansihaldus
Name[eu]=Saio-kudeaketa
Name[fa]=مدیریت نشست
Name[fi]=Istunnonhallinta
Name[ga]=Bainistíocht Seisiún
Name[gl]=Xestión de sesións
Name[gu]=
Name[he]=ניהול הפעלות
Name[hi]=
Name[hr]=Upravljanje sesijama
Name[hu]=Munkamenetkezelés
Name[ia]=Gestion de session
Name[id]=Manajemen Sesi
Name[is]=Setustjórn
Name[kk]=Сеансты басқаруы
Name[km]=
Name[kn]=ಿ ()
Name[ko]=
Name[lt]=Sesijų tvarkymas
Name[lv]=Sesiju pārvaldnieks
Name[mr]=
Name[nb]=Øktbehandling
Name[nds]=Törnpleeg
Name[nl]=Sessiebeheer
Name[nn]=Økthandsamar
Name[pa]=
Name[pl]=Zarządzanie sesją
Name[pt]=Gestão de Sessões
Name[pt_BR]=Gerenciamento de sessões
Name[ro]=Administrarea sesiunilor
Name[ru]=Управление сеансами
Name[si]=
Name[sk]=Správa sedenia
Name[sl]=Upravljanje s sejami
Name[sr]=Управљање сесијама
Name[sr@ijekavian]=Управљање сесијама
Name[sr@ijekavianlatin]=Upravljanje sesijama
Name[sr@latin]=Upravljanje sesijama
Name[sv]=Sessionshantering
Name[tg]=Мудири амалҳо
Name[th]=
Name[tr]=Oturum Yönetimi
Name[ug]=ئەڭگىمە باشقۇرۇش
Name[uk]=Керування сеансами
Name[wa]=Manaedjmint des sessions
Name[x-test]=xxSession Managementxx
Name[zh_CN]=
Name[zh_TW]=
Comment=Configure the session manager and logout settings
Comment[af]=Konfigureer die sessie bestuurder en teken af instellings
Comment[ar]=اضبط مدير الجلسات وإعدادات تسجيل الخروج
Comment[ast]=Configurar el xestor de sesiones y les preferencies de zarru de sesión
Comment[be]=Настаўленні кіраўніка сеансаў і параметраў выхаду
Comment[be@latin]=Nałady kiraŭnika sesijaŭ i vychadu z systemy
Comment[bg]=Настройване сесиите на системата и поведението при изход
Comment[bn]= - ি ি
Comment[bn_IN]= ি - ি ি
Comment[br]=Kefluniañ ar merour an dalc'hioù hag an doare mont kuit
Comment[bs]=Podešavanje menadžera sesija i odjavljivanja
Comment[ca]=Aquí podeu configurar el gestor de la sessió i la sortida
Comment[ca@valencia]=Ací podeu configurar el gestor de la sessió i l'eixida
Comment[cs]=Nastavení správce sezení a odhlašování
Comment[csb]=Kònfigùracëjô menedżera sesëji ë nastôwów wëlogòwaniô
Comment[cy]=Ffurfweddu'r rheolydd sesiwn a gosodiadau allgofnodi
Comment[da]=Indstil sessionshåndterig og log ud-indstillinger
Comment[de]=Einstellungen für Sitzungsverwaltung und Abmeldung vornehmen
Comment[el]=Διαμορφώστε το διαχειριστή συνεδρίας και τις επιλογές αποσύνδεσης
Comment[en_GB]=Configure the session manager and logout settings
Comment[eo]=Agordi la seancan administrilon kaj la elsaluton
Comment[es]=Configurar el gestor de sesiones y las preferencias de cierre de sesión
Comment[et]=Seansihalduri ja väljalogimise seadistamine
Comment[eu]=Konfiguratu saio-kudeatzailea eta saio-bukaeraren ezarpenak
Comment[fa]=پیکربندی مدیر نشست و تنظیمات خروج
Comment[fi]=Istunnonhallinnan ja uloskirjautumisen asetukset
Comment[fy]=Hjir kinne jo it sesjebehear en ôfmeld-ynstellings fêststelle
Comment[ga]=Cumraigh bainisteoir an tseisiúin agus socruithe logála amach
Comment[gl]=Configura o xestor de sesións e as opcións de saída
Comment[gu]= િ
Comment[he]=הגדרת מנהל ההפעלות והגדרות היציאה
Comment[hi]= ि ि
Comment[hne]= ि ि
Comment[hr]=Konfiguriranje upravitelja sesijama i postavkama odjavljivanja
Comment[hsb]=Rjadowar posedźenjow a nastajenjow za wotzjewjenje připrawić
Comment[hu]=A KDE munkafolyamat és a kijelentkezési mód beállításai
Comment[ia]=Configura le gerente de session e preferentias de exito (logout)
Comment[id]=Atur manajer sesi dan pengaturan log keluar
Comment[is]=Stilla setustjóra og aðgerðir við útstimplun
Comment[ka]=
Comment[kk]=Сеанс менеджерді және жүйеден шығу параметрлерін баптау
Comment[km]=
Comment[kn]=ಿ () ಿ () ಿ
Comment[ko]=
Comment[lt]=Čia galite konfigūruoti sesijos tvarkytuvę ir išsiregistravimo nustatymus
Comment[lv]=Šeit jūs varat konfigurēt sesiju pārvaldnieku un pieslēgšanās parametrus
Comment[mai]= ि ि
Comment[mk]=Конфигурирајте го менаџерот на сесии и поставувањата за одјавување
Comment[ml]= ി ിി ി
Comment[mr]=
Comment[ms]=Konfigur seting pengurus sesi dan bentangan
Comment[nb]=Tilpass øktbehandleren og utlogginga
Comment[nds]=Dat Afmellen un den Törnpleger instellen
Comment[ne]= ि ि
Comment[nl]=Hier kunt u het sessiebeheer en de afmeld-instellingen bepalen
Comment[nn]=Oppsett av økthandsamar og utlogging
Comment[pa]= ਿ
Comment[pl]=Ustawienia sesji i wylogowania
Comment[pt]=Configuração do gestor de sessões e das opções de encerramento
Comment[pt_BR]=Configura o gerenciador de sessões e as opções de encerramento
Comment[ro]=Configurează managerul de sesiune și setările de ieșire
Comment[ru]=Настройка диспетчера сеансов
Comment[se]=Heivet bargovuorrogieđahalli ja olggosčáliheami
Comment[si]=
Comment[sk]=Nastavenie správcu sedení a odhlásenia
Comment[sl]=Nastavi upravljalnik sej in nastavitve odjav
Comment[sr]=Поставке менаџера сесија и одјављивања
Comment[sr@ijekavian]=Поставке менаџера сесија и одјављивања
Comment[sr@ijekavianlatin]=Postavke menadžera sesija i odjavljivanja
Comment[sr@latin]=Postavke menadžera sesija i odjavljivanja
Comment[sv]=Anpassa sessionshanteraren och utloggningsinställningar
Comment[ta]= ி ி
Comment[te]= ిిి ి ి
Comment[tg]=Танзимоти мудири сассияҳо ва хуруҷкунӣ
Comment[th]=
Comment[tr]=Oturum yöneticisi ve çıkış ayarlarını yapılandır
Comment[ug]=ئەڭگىمە باشقۇرغۇچ ۋە چىقىش تەڭشىكىنى سەپلەيدۇ
Comment[uk]=Налаштування керування сеансами та параметрів виходу з системи
Comment[uz]=Seans boshqaruvchisini va chiqish moslamalarini moslash
Comment[uz@cyrillic]=Сеанс бошқарувчисини ва чиқиш мосламаларини мослаш
Comment[vi]=Cu hình trình qun lý phiên chy và thiết lp đăng xut
Comment[wa]=Apontiaedje do manaedjeu di sessions eyet apontiaedjes do dislodjaedje
Comment[xh]=Qwalasela umphathi wesiqendu nezicwangciso zokuphuma ngaphandle
Comment[x-test]=xxConfigure the session manager and logout settingsxx
Comment[zh_CN]=
Comment[zh_TW]=
X-KDE-Keywords=ksmserver,session,logout,confirmation,save,restore
X-KDE-Keywords[bs]=ksmserver,sesija,odjava,potvrda,snimanje,restore
X-KDE-Keywords[ca]=ksmserver,sessió,sortida,confirmació,desa,restaura
X-KDE-Keywords[ca@valencia]=ksmserver,sessió,eixida,confirmació,guarda,restaura
X-KDE-Keywords[da]=ksmserver,session,log ud,bekræftelse,gem,genskab
X-KDE-Keywords[de]=Ksmserver,Sitzung,Abmelden,Logout,Bestätigung,Speichern,Wiederherstellen
X-KDE-Keywords[el]=ksmserver,συνεδρία,έξοδος,επιβεβαίωση,αποθήκευση,επαναφορά
X-KDE-Keywords[en_GB]=ksmserver,session,logout,confirmation,save,restore
X-KDE-Keywords[es]=ksmserver,sesión,cierre de sesión,confirmación,guardado,restauración
X-KDE-Keywords[et]=ksmserver,seanss,väljalogimine,kinnitus,salvestamine,taastamine
X-KDE-Keywords[eu]=ksmserver,saioa,saio-bukaera,berretsi,gorde,leheneratu
X-KDE-Keywords[fi]=ksmserver,istunto,uloskirjautuminen,kirjaudu,ulos,varmistus,varmista,tallennus,tallentaminen,tallenna,palautus,palautuminen,palauta
X-KDE-Keywords[fr]=ksmserver, session, déconnexion, confirmation, enregistrer, restaurer
X-KDE-Keywords[ga]=ksmserver,seisiún,logáil amach,dearbhú,sábháil,athchóiriú
X-KDE-Keywords[gl]=ksmserver,sesión,saír,confirmación,gardar,restaurar
X-KDE-Keywords[hu]=ksmserver,munkamenet,kijelentkezés,megerősítés,mentés,visszaállítás
X-KDE-Keywords[ia]=ksmserver,session,claude session,confirmation,salveguarda,restabili
X-KDE-Keywords[it]=ksmserver,sessione,uscita,conferma,salva,ripristina
X-KDE-Keywords[kk]=ksmserver,session,logout,confirmation,save,restore
X-KDE-Keywords[km]=ksmserver,session,logout,confirmation,save,restore
X-KDE-Keywords[ko]=ksmserver,session,logout,confirmation,save,restore,,,,,
X-KDE-Keywords[mr]=ksm, , , , , ि
X-KDE-Keywords[nb]=ksmserver,økt,logg ut,bekreft,lagre,tilbakestill
X-KDE-Keywords[nds]=KSM-Server,Törn,Afmellen,Nafragen,Sekern,Wedderherstellen
X-KDE-Keywords[nl]=ksmserver,sessie,afmelden,bevestiging,opslaan,herstellen
X-KDE-Keywords[pl]=ksmserver,sesja,wylogowanie,potwierdzenie,zapis,przywracanie
X-KDE-Keywords[pt]=ksmserver,sessão,encerrar,confirmação,gravar,repor
X-KDE-Keywords[pt_BR]=ksmserver,sessão,encerrar,confirmação,salvar,restaurar
X-KDE-Keywords[ro]=ksmserver,sesiune,logout,confirmare,salvare,restabilire,ieșire
X-KDE-Keywords[ru]=ksmserver,session,logout,confirmation,save,restore,сессия,выход,выход из системы,подтверждение,сохранить,восстановить
X-KDE-Keywords[sk]=ksmserver,sedenie,odhlásenie,potvrdenie,uložiť,obnoviť
X-KDE-Keywords[sl]=ksmserver,seja,seje,odjava,prijava,izklop,zaustavitev,potrditev,shranjevanje,obnavljanje
X-KDE-Keywords[sr]=ksmserver;session;logout;confirmation;save;restore;КСМсервер;сесија;одјављивање;потврда;сачувати;обновити;
X-KDE-Keywords[sr@ijekavian]=ksmserver;session;logout;confirmation;save;restore;КСМсервер;сесија;одјављивање;потврда;сачувати;обновити;
X-KDE-Keywords[sr@ijekavianlatin]=ksmserver;session;logout;confirmation;save;restore;KSMServer;sesija;odjavljivanje;potvrda;sačuvati;obnoviti;
X-KDE-Keywords[sr@latin]=ksmserver;session;logout;confirmation;save;restore;KSMServer;sesija;odjavljivanje;potvrda;sačuvati;obnoviti;
X-KDE-Keywords[sv]=ksmserver,session,utloggning,bekräftelse,spara,återställ
X-KDE-Keywords[tr]=ksmserver,oturum,çıkış,doğrulama,onaylama,kaydet,yeniden yükle
X-KDE-Keywords[uk]=ksmserver,session,logout,confirmation,save,restore,сеанс,вихід,підтвердження,зберегти,збереження,відновити,відновлення
X-KDE-Keywords[x-test]=xxksmserver,session,logout,confirmation,save,restorexx
X-KDE-Keywords[zh_CN]=ksmserver,session,logout,confirmation,save,restore,,,,,
X-KDE-Keywords[zh_TW]=ksmserver,session,logout,confirmation,save,restore
Categories=Qt;KDE;X-KDE-settings-components;

View file

@ -1,44 +0,0 @@
/*
* kcmsmserver.h
* Copyright (c) 2000 Oswald Buddenhagen <ob6@inf.tu-dresden.de>
*
* based on kcmtaskbar.h
* Copyright (c) 2000 Kurt Granroth <granroth@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
*/
#ifndef __kcmsmserver_h__
#define __kcmsmserver_h__
#include <kcmodule.h>
class SMServerConfigImpl;
class SMServerConfig : public KCModule
{
Q_OBJECT
public:
explicit SMServerConfig( QWidget *parent=0, const QVariantList &list=QVariantList() );
void load();
void save();
void defaults();
private:
SMServerConfigImpl* dialog;
};
#endif

View file

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SMServerConfigDlg</class>
<widget class="QWidget" name="SMServerConfigDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>477</width>
<height>398</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="topBox">
<property name="title">
<string>General</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="confirmLogoutCheck">
<property name="whatsThis">
<string>Check this option if you want the session manager to display a logout confirmation dialog box.</string>
</property>
<property name="text">
<string>Conf&amp;irm logout</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="offerShutdownCheck">
<property name="text">
<string>O&amp;ffer shutdown options</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="sdGroup">
<property name="whatsThis">
<string>Here you can choose what should happen by default when you log out. This only has meaning, if you logged in through KDM.</string>
</property>
<property name="title">
<string>Default Leave Option</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QRadioButton" name="logoutRadio">
<property name="text">
<string>&amp;End current session</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="haltRadio">
<property name="text">
<string>&amp;Turn off computer</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rebootRadio">
<property name="text">
<string>&amp;Restart computer</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="loginGroup">
<property name="whatsThis">
<string>&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Restore previous session:&lt;/b&gt; Will save all applications running on exit and restore them when they next start up&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Restore manually saved session: &lt;/b&gt; Allows the session to be saved at any time via &quot;Save Session&quot; in the K-Menu. This means the currently started applications will reappear when they next start up.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Start with an empty session:&lt;/b&gt; Do not save anything. Will come up with an empty desktop on next start.&lt;/li&gt;
&lt;/ul&gt;</string>
</property>
<property name="title">
<string>On Login</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="previousSessionRadio">
<property name="text">
<string>Restore &amp;previous session</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="savedSessionRadio">
<property name="text">
<string>Restore &amp;manually saved session</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="emptySessionRadio">
<property name="text">
<string>Start with an empty &amp;session</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="textLabel1">
<property name="text">
<string>Applications to be e&amp;xcluded from sessions:</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="buddy">
<cstring>excludeLineedit</cstring>
</property>
</widget>
</item>
<item>
<widget class="KLineEdit" name="excludeLineedit">
<property name="whatsThis">
<string>Here you can enter a colon or comma separated list of applications that should not be saved in sessions, and therefore will not be started when restoring a session. For example 'xterm:konsole' or 'xterm,konsole'.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
</customwidgets>
<connections>
<connection>
<sender>offerShutdownCheck</sender>
<signal>toggled(bool)</signal>
<receiver>sdGroup</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>20</x>
<y>20</y>
</hint>
<hint type="destinationlabel">
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -1,39 +0,0 @@
/***************************************************************************
smserverconfigimpl.cpp - description
-------------------
begin : Thu May 17 2001
copyright : (C) 2001 by stulle
email : stulle@tux
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "smserverconfigimpl.h"
#include "moc_smserverconfigimpl.cpp"
SMServerConfigImpl::SMServerConfigImpl(QWidget *parent ) : SMServerConfigDlg(parent) {
connect(confirmLogoutCheck,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(previousSessionRadio,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(savedSessionRadio,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(emptySessionRadio,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(logoutRadio,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(haltRadio,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(rebootRadio,SIGNAL(toggled(bool)), SLOT(configChanged()));
connect(excludeLineedit,SIGNAL(textChanged(QString)),SLOT(configChanged()));
connect(offerShutdownCheck,SIGNAL(toggled(bool)),SLOT(configChanged()));
}
SMServerConfigImpl::~SMServerConfigImpl(){
}
/** No descriptions */
void SMServerConfigImpl::configChanged(){
emit changed();
}

View file

@ -1,50 +0,0 @@
/***************************************************************************
smserverconfigimpl.h - description
-------------------
begin : Thu May 17 2001
copyright : (C) 2001 by stulle
email : stulle@tux
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef SMSERVERCONFIGIMPL_H
#define SMSERVERCONFIGIMPL_H
#include <QWidget>
#include "ui_smserverconfigdlg.h"
/**
*@author stulle
*/
class SMServerConfigDlg : public QWidget, public Ui::SMServerConfigDlg
{
public:
SMServerConfigDlg( QWidget *parent ) : QWidget( parent ) {
setupUi( this );
}
};
class SMServerConfigImpl : public SMServerConfigDlg {
Q_OBJECT
public:
SMServerConfigImpl(QWidget *parent=0);
~SMServerConfigImpl();
public Q_SLOTS: // Public slots
/** No descriptions */
void configChanged();
Q_SIGNALS: // Signals
/** No descriptions */
void changed();
};
#endif

View file

@ -1,253 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#include "config-ksmserver.h"
#include "server.h"
#include <fixx11h.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <KMessageBox>
#include <QtDBus/QtDBus>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kconfiggroup.h>
#include <kaboutdata.h>
#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kwindowsystem.h>
#include <kcrash.h>
#include <QtGui/qx11info_x11.h>
#include <QtCore/qfile.h>
#include <X11/Xlib.h>
static const char version[] = "0.4";
static const char description[] = I18N_NOOP( "The reliable KDE session manager that talks the standard X11R6 \nsession management protocol (XSMP)." );
extern KSMServer* the_server;
void IoErrorHandler ( IceConn iceConn)
{
the_server->ioError( iceConn );
}
bool writeTest(QByteArray path)
{
path += "/XXXXXX";
int fd = mkstemp(path.data());
if (fd == -1)
return false;
if (write(fd, "Hello World\n", 12) == -1)
{
int save_errno = errno;
close(fd);
unlink(path.data());
errno = save_errno;
return false;
}
close(fd);
unlink(path.data());
return true;
}
void sanity_check( int argc, char* argv[], KAboutData* aboutDataPtr )
{
QString msg;
QByteArray path = getenv("HOME");
QByteArray readOnly = getenv("KDE_HOME_READONLY");
if (path.isEmpty())
{
msg = QLatin1String("$HOME not set!");
}
if (msg.isEmpty() && access(path.data(), W_OK))
{
if (errno == ENOENT)
msg = QLatin1String("$HOME directory (%1) does not exist.");
else if (readOnly.isEmpty())
msg = QLatin1String("No write access to $HOME directory (%1).");
}
if (msg.isEmpty() && access(path.data(), R_OK))
{
if (errno == ENOENT)
msg = "$HOME directory (%1) does not exist.";
else
msg = "No read access to $HOME directory (%1).";
}
if (msg.isEmpty() && readOnly.isEmpty() && !writeTest(path))
{
if (errno == ENOSPC)
msg = "$HOME directory (%1) is out of disk space.";
else
msg = QByteArray("Writing to the $HOME directory (%1) failed with\n "
"the error '")+QByteArray(strerror(errno))+QByteArray("'");
}
if (msg.isEmpty())
{
path = getenv("ICEAUTHORITY");
if (path.isEmpty())
{
path = getenv("HOME");
path += "/.ICEauthority";
}
if (access(path.data(), W_OK) && (errno != ENOENT))
msg = "No write access to '%1'.";
else if (access(path.data(), R_OK) && (errno != ENOENT))
msg = "No read access to '%1'.";
}
if (msg.isEmpty())
{
path = getenv("TMPDIR");
if (path.isEmpty())
path = "/tmp";
if (!writeTest(path))
{
if (errno == ENOSPC)
msg = "Temp directory (%1) is out of disk space.";
else
msg = "Writing to the temp directory (%1) failed with\n "
"the error '"+QByteArray(strerror(errno))+QByteArray("'");
}
}
if (msg.isEmpty() && (path != "/tmp"))
{
path = "/tmp";
if (!writeTest(path))
{
if (errno == ENOSPC)
msg = "Temp directory (%1) is out of disk space.";
else
msg = "Writing to the temp directory (%1) failed with\n "
"the error '"+QByteArray(strerror(errno))+QByteArray("'");
}
}
if (msg.isEmpty())
{
path += "/.ICE-unix";
if (access(path.data(), W_OK) && (errno != ENOENT))
msg = "No write access to '%1'.";
else if (access(path.data(), R_OK) && (errno != ENOENT))
msg = "No read access to '%1'.";
}
if (!msg.isEmpty())
{
const char *msg_pre =
"The following installation problem was detected\n"
"while trying to start KDE:"
"\n\n ";
const char *msg_post = "\n\nKDE is unable to start.\n";
fputs(msg_pre, stderr);
fprintf(stderr, "%s", qPrintable(msg.arg(QFile::decodeName(path))));
fputs(msg_post, stderr);
QApplication a(argc, argv);
KComponentData i(aboutDataPtr);
QString qmsg = msg_pre+msg.arg(QFile::decodeName(path))+msg_post;
KMessageBox::error(0, qmsg, "KDE Installation Problem!");
exit(255);
}
}
int main( int argc, char* argv[] )
{
KAboutData aboutData( "ksmserver", 0, ki18n("The KDE Session Manager"),
version, ki18n(description), KAboutData::License_BSD,
ki18n("(C) 2000, The KDE Developers"));
aboutData.addAuthor(ki18n("Matthias Ettrich"),KLocalizedString(), "ettrich@kde.org");
aboutData.addAuthor(ki18n("Luboš Luňák"), ki18n( "Maintainer" ), "l.lunak@kde.org" );
sanity_check(argc, argv, &aboutData);
KCmdLineArgs::init(argc, argv, &aboutData);
KCmdLineOptions options;
options.add("r");
options.add("restore", ki18n("Restores the saved user session if available"));
options.add("w");
options.add("windowmanager <wm>", ki18n("Starts 'wm' in case no other window manager is \nparticipating in the session. Default is 'kwin'"));
options.add("nolocal", ki18n("Also allow remote connections"));
KCmdLineArgs::addCmdLineOptions( options );
::unsetenv("SESSION_MANAGER");
KApplication app;
fcntl(ConnectionNumber(QX11Info::display()), F_SETFD, 1);
app.setQuitOnLastWindowClosed(false); // #169486
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
if( !QDBusConnection::sessionBus().interface()->registerService( "org.kde.ksmserver", QDBusConnectionInterface::DontQueueService ) )
{
qWarning("Could not register with D-BUS. Aborting.");
return 1;
}
QString wm = args->getOption("windowmanager");
bool only_local = args->isSet("local");
#ifndef HAVE__ICETRANSNOLISTEN
/* this seems strange, but the default is only_local, so if !only_local
* the option --nolocal was given, and we warn (the option --nolocal
* does nothing on this platform, as here the default is reversed)
*/
if (!only_local) {
qWarning("--[no]local is not supported on your platform. Sorry.");
}
only_local = false;
#endif
KSMServer *server = new KSMServer( wm, only_local );
KCrash::setFlags(KCrash::Log);
IceSetIOErrorHandler( IoErrorHandler );
KConfigGroup config(KGlobal::config(), "General");
int realScreenCount = ScreenCount( QX11Info::display() );
bool screenCountChanged =
( config.readEntry( "screenCount", realScreenCount ) != realScreenCount );
QString loginMode = config.readEntry( "loginMode", "restorePreviousLogout" );
if ( args->isSet("restore") && ! screenCountChanged )
server->restoreSession( SESSION_BY_USER );
else if ( loginMode == "default" || screenCountChanged )
server->startDefaultSession();
else if ( loginMode == "restorePreviousLogout" )
server->restoreSession( SESSION_PREVIOUS_LOGOUT );
else if ( loginMode == "restoreSavedSession" )
server->restoreSession( SESSION_BY_USER );
else
server->startDefaultSession();
return app.exec();
}

View file

@ -1,41 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.KSMServerInterface">
<method name="logout">
<arg type="i" direction="in"/>
<arg type="i" direction="in"/>
</method>
<method name="canShutdown">
<arg type="b" direction="out"/>
</method>
<method name="sessionList">
<arg type="as" direction="out"/>
</method>
<method name="currentSession">
<arg type="s" direction="out"/>
</method>
<method name="saveCurrentSession">
</method>
<method name="saveCurrentSessionAs">
<arg type="s" direction="in"/>
</method>
<method name="suspendStartup">
<arg type="s" direction="in"/>
</method>
<method name="resumeStartup">
<arg type="s" direction="in"/>
</method>
<method name="wmChanged"/>
<method name="saveSubSession">
<arg type="s" direction="in"/>
<arg type="as" direction="in"/>
<arg type="as" direction="in"/>
</method>
<method name="restoreSubSession">
<arg type="s" direction="in"/>
</method>
<signal name="subSessionClosed"/>
<signal name="subSessionCloseCanceled"/>
<signal name="subSessionOpened"/>
</interface>
</node>

File diff suppressed because it is too large Load diff

View file

@ -1,243 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#ifndef SERVER_H
#define SERVER_H
#include <QStringList>
#include <QObject>
#include <QProcess>
#include <QTimer>
#include <QDateTime>
#include <QDBusInterface>
#include <QMap>
#include <kapplication.h>
#include <kworkspace/kworkspace.h>
#include <kmessagebox.h>
#define INT32 QINT32
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include <X11/ICE/ICElib.h>
extern "C" {
#include <X11/ICE/ICEutil.h>
#include <X11/ICE/ICEmsg.h>
#include <X11/ICE/ICEproto.h>
#include <X11/SM/SM.h>
#include <X11/SM/SMlib.h>
}
#include <fixx11h.h>
#define SESSION_PREVIOUS_LOGOUT "saved at previous logout"
#define SESSION_BY_USER "saved by user"
class KSMListener;
class KSMConnection;
class KSMClient;
class KSMServer : public QObject
{
Q_OBJECT
public:
KSMServer( const QString& windowManager, bool only_local );
~KSMServer();
static KSMServer* self();
void* watchConnection( IceConn iceConn );
void removeConnection( KSMConnection* conn );
KSMClient* newClient( SmsConn );
void deleteClient( KSMClient* client );
// callbacks
void saveYourselfDone( KSMClient* client, bool success );
void interactRequest( KSMClient* client, int dialogType );
void interactDone( KSMClient* client, bool cancelShutdown );
void phase2Request( KSMClient* client );
// error handling
void ioError( IceConn iceConn );
// notification
void clientSetProgram( KSMClient* client );
void clientRegistered( const char* previousId );
// public API
void restoreSession( const QString &sessionName );
void startDefaultSession();
void shutdown( KWorkSpace::ShutdownConfirm confirm,
KWorkSpace::ShutdownType sdtype );
virtual void suspendStartup( const QString &app );
virtual void resumeStartup( const QString &app );
void launchWM( const QList< QStringList >& wmStartCommands );
public Q_SLOTS:
void cleanUp();
private Q_SLOTS:
void newConnection( int socket );
void processData( int socket );
void protectionTimeout();
void timeoutQuit();
void timeoutWMQuit();
void kcmPhase1Timeout();
void kcmPhase2Timeout();
void pendingShutdownTimeout();
void logoutSoundTimeout();
void autoStart0();
void autoStart1();
void autoStart2();
void tryRestoreNext();
void startupSuspendTimeout();
void wmProcessChange();
void logoutSoundFinished();
void autoStart0Done();
void autoStart1Done();
void autoStart2Done();
void kcmPhase1Done();
void kcmPhase2Done();
void defaultLogout();
void logoutWithoutConfirmation();
void haltWithoutConfirmation();
void rebootWithoutConfirmation();
private:
void handlePendingInteractions();
void completeShutdownOrCheckpoint();
void startKilling();
void startKillingSubSession();
void performStandardKilling();
void completeKilling();
void completeKillingSubSession();
void killWM();
void signalSubSessionClosed();
void completeKillingWM();
void cancelShutdown( KSMClient* c );
void killingCompleted();
void createLogoutEffectWidget();
void discardSession();
void storeSession();
void startProtection();
void endProtection();
bool startApplication( const QStringList& command,
const QString& clientMachine = QString(),
const QString& userId = QString());
void executeCommand( const QStringList& command );
bool isWM( const KSMClient* client ) const;
bool isWM( const QString& command ) const;
void selectWm( const QString& kdewm );
bool defaultSession() const; // empty session
void setupXIOErrorHandler();
bool checkStartupSuspend();
void finishStartup();
void resumeStartupInternal();
void setupShortcuts();
// public dcop interface
public Q_SLOTS: //public dcop interface
void logout( int, int );
bool canShutdown();
QString currentSession();
void saveCurrentSession();
void saveCurrentSessionAs( const QString & );
QStringList sessionList();
void wmChanged();
void saveSubSession( const QString &name, QStringList saveAndClose,
QStringList saveOnly = QStringList() );
void restoreSubSession( const QString &name );
Q_SIGNALS:
void subSessionClosed();
void subSessionCloseCanceled();
void subSessionOpened();
private:
QList<KSMListener*> listener;
QList<KSMClient*> clients;
enum State {
Idle,
LaunchingWM, AutoStart0, KcmInitPhase1, AutoStart1, Restoring, FinishingStartup, // startup
Shutdown, Checkpoint, Killing, KillingWM, WaitingForKNotify, // shutdown
ClosingSubSession, KillingSubSession, RestoringSubSession
};
State state;
bool dialogActive;
bool saveSession;
int wmPhase1WaitingCount;
int saveType;
QMap< QString, int > startupSuspendCount;
KWorkSpace::ShutdownType shutdownType;
bool clean;
KSMClient* clientInteracting;
QString wm;
QStringList wmCommands;
QProcess* wmProcess;
QString sessionGroup;
QString sessionName;
QTimer protectionTimer;
QTimer restoreTimer;
QString xonCommand;
QTimer startupSuspendTimeoutTimer;
bool waitAutoStart2;
bool waitKcmInit2;
QTimer pendingShutdown;
QWidget* logoutEffectWidget;
KWorkSpace::ShutdownConfirm pendingShutdown_confirm;
KWorkSpace::ShutdownType pendingShutdown_sdtype;
// sequential startup
int appsToStart;
int lastAppStarted;
QString lastIdStarted;
QStringList excludeApps;
QDBusInterface* klauncherSignals;
QDBusInterface* kcminitSignals;
uint inhibitCookie;
//subSession stuff
QList<KSMClient*> clientsToKill;
QList<KSMClient*> clientsToSave;
};
#endif

View file

@ -1,670 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
relatively small extensions by Oswald Buddenhagen <ob6@inf.tu-dresden.de>
some code taken from the dcopserver (part of the KDE libraries), which is
Copyright 1999 Matthias Ettrich <ettrich@kde.org>
Copyright 1999 Preston Brown <pbrown@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#include <config-unix.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <QPushButton>
#include <QTimer>
#include <QtDBus/QtDBus>
#include <KApplication>
#include <KConfig>
#include <KConfigGroup>
#include <KGlobal>
#include <KLocale>
#include <KNotification>
#include <KStandardDirs>
#include <KTemporaryFile>
#include <kworkspace/kdisplaymanager.h>
#include "server.h"
#include "global.h"
#include "client.h"
#include "shutdowndlg.h"
#include <solid/powermanagement.h>
#include <kdebug.h>
#include <QDesktopWidget>
#include <QtGui/qx11info_x11.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
void KSMServer::logout( int confirm, int sdtype )
{
shutdown( (KWorkSpace::ShutdownConfirm)confirm,
(KWorkSpace::ShutdownType)sdtype);
}
bool KSMServer::canShutdown()
{
KSharedConfig::Ptr config = KGlobal::config();
config->reparseConfiguration(); // config may have changed in the KControl module
KConfigGroup cg( config, "General");
return cg.readEntry( "offerShutdown", true ) && KDisplayManager().canShutdown();
}
void KSMServer::shutdown( KWorkSpace::ShutdownConfirm confirm,
KWorkSpace::ShutdownType sdtype )
{
pendingShutdown.stop();
if( dialogActive )
return;
if( state >= Shutdown ) // already performing shutdown
return;
if( state != Idle ) // performing startup
{
// perform shutdown as soon as startup is finished, in order to avoid saving partial session
if( !pendingShutdown.isActive())
{
pendingShutdown.start( 1000 );
pendingShutdown_confirm = confirm;
pendingShutdown_sdtype = sdtype;
}
return;
}
KSharedConfig::Ptr config = KGlobal::config();
config->reparseConfiguration(); // config may have changed in the KControl module
KConfigGroup cg( config, "General");
bool logoutConfirmed =
(confirm == KWorkSpace::ShutdownConfirmYes) ? false :
(confirm == KWorkSpace::ShutdownConfirmNo) ? true :
!cg.readEntry( "confirmLogout", true );
bool choose = false;
bool maysd = false;
if (cg.readEntry( "offerShutdown", true ) && KDisplayManager().canShutdown())
maysd = true;
if (!maysd) {
if (sdtype != KWorkSpace::ShutdownTypeNone &&
sdtype != KWorkSpace::ShutdownTypeDefault &&
logoutConfirmed)
return; /* unsupported fast shutdown */
sdtype = KWorkSpace::ShutdownTypeNone;
} else if (sdtype == KWorkSpace::ShutdownTypeDefault) {
sdtype = (KWorkSpace::ShutdownType)
cg.readEntry( "shutdownType", (int)KWorkSpace::ShutdownTypeNone );
choose = true;
}
dialogActive = true;
if ( !logoutConfirmed ) {
KApplication::kApplication()->updateUserTimestamp();
logoutConfirmed = KSMShutdownDlg::confirmShutdown( maysd, choose, sdtype);
// ###### We can't make the screen remain gray while talking to the apps,
// because this prevents interaction ("do you want to save", etc.)
// TODO: turn the feedback widget into a list of apps to be closed,
// with an indicator of the current status for each.
KSMShutdownFeedback::stop(); // make the screen become normal again
}
if ( logoutConfirmed ) {
// If the logout was confirmed, let's start a powermanagement inhibition.
// We store the cookie so we can interrupt it if the logout will be canceled
inhibitCookie = Solid::PowerManagement::beginSuppressingSleep();
shutdownType = sdtype;
// shall we save the session on logout?
saveSession = ( cg.readEntry( "loginMode", "restorePreviousLogout" ) == "restorePreviousLogout" );
if ( saveSession )
sessionGroup = QString("Session: ") + SESSION_PREVIOUS_LOGOUT;
// Set the real desktop background to black so that exit looks
// clean regardless of what was on "our" desktop.
QPalette palette;
palette.setColor( kapp->desktop()->backgroundRole(), Qt::black );
kapp->desktop()->setPalette(palette);
state = Shutdown;
wmPhase1WaitingCount = 0;
saveType = saveSession?SmSaveBoth:SmSaveGlobal;
startProtection();
foreach( KSMClient* c, clients ) {
c->resetState();
// Whoever came with the idea of phase 2 got it backwards
// unfortunately. Window manager should be the very first
// one saving session data, not the last one, as possible
// user interaction during session save may alter
// window positions etc.
// Moreover, KWin's focus stealing prevention would lead
// to undesired effects while session saving (dialogs
// wouldn't be activated), so it needs be assured that
// KWin will turn it off temporarily before any other
// user interaction takes place.
// Therefore, make sure the WM finishes its phase 1
// before others a chance to change anything.
// KWin will check if the session manager is ksmserver,
// and if yes it will save in phase 1 instead of phase 2.
if( isWM( c ) )
++wmPhase1WaitingCount;
}
if (wmPhase1WaitingCount > 0) {
foreach( KSMClient* c, clients ) {
if( isWM( c ) )
SmsSaveYourself( c->connection(), saveType,
true, SmInteractStyleAny, false );
}
} else { // no WM, simply start them all
foreach( KSMClient* c, clients )
SmsSaveYourself( c->connection(), saveType,
true, SmInteractStyleAny, false );
}
if ( clients.isEmpty() )
completeShutdownOrCheckpoint();
}
dialogActive = false;
}
void KSMServer::pendingShutdownTimeout()
{
shutdown( pendingShutdown_confirm, pendingShutdown_sdtype );
}
void KSMServer::saveCurrentSession()
{
if ( state != Idle || dialogActive )
return;
if ( currentSession().isEmpty() || currentSession() == SESSION_PREVIOUS_LOGOUT )
sessionGroup = QString("Session: ") + SESSION_BY_USER;
state = Checkpoint;
wmPhase1WaitingCount = 0;
saveType = SmSaveLocal;
saveSession = true;
foreach( KSMClient* c, clients ) {
c->resetState();
if( isWM( c ) )
++wmPhase1WaitingCount;
}
if (wmPhase1WaitingCount > 0) {
foreach( KSMClient* c, clients ) {
if( isWM( c ) )
SmsSaveYourself( c->connection(), saveType, false, SmInteractStyleNone, false );
}
} else {
foreach( KSMClient* c, clients )
SmsSaveYourself( c->connection(), saveType, false, SmInteractStyleNone, false );
}
if ( clients.isEmpty() )
completeShutdownOrCheckpoint();
}
void KSMServer::saveCurrentSessionAs( const QString &session )
{
if ( state != Idle || dialogActive )
return;
sessionGroup = "Session: " + session;
saveCurrentSession();
}
// callbacks
void KSMServer::saveYourselfDone( KSMClient* client, bool success )
{
if ( state == Idle ) {
// State saving when it's not shutdown or checkpoint. Probably
// a shutdown was canceled and the client is finished saving
// only now. Discard the saved state in order to avoid
// the saved data building up.
QStringList discard = client->discardCommand();
if( !discard.isEmpty())
executeCommand( discard );
return;
}
if ( success ) {
client->saveYourselfDone = true;
completeShutdownOrCheckpoint();
} else {
// fake success to make KDE's logout not block with broken
// apps. A perfect ksmserver would display a warning box at
// the very end.
client->saveYourselfDone = true;
completeShutdownOrCheckpoint();
}
startProtection();
if( isWM( client ) && !client->wasPhase2 && wmPhase1WaitingCount > 0 ) {
--wmPhase1WaitingCount;
// WM finished its phase1, save the rest
if( wmPhase1WaitingCount == 0 ) {
foreach( KSMClient* c, clients )
if( !isWM( c ))
SmsSaveYourself( c->connection(), saveType, saveType != SmSaveLocal,
saveType != SmSaveLocal ? SmInteractStyleAny : SmInteractStyleNone,
false );
}
}
}
void KSMServer::interactRequest( KSMClient* client, int /*dialogType*/ )
{
if ( state == Shutdown || state == ClosingSubSession )
client->pendingInteraction = true;
else
SmsInteract( client->connection() );
handlePendingInteractions();
}
void KSMServer::interactDone( KSMClient* client, bool cancelShutdown_ )
{
if ( client != clientInteracting )
return; // should not happen
clientInteracting = 0;
if ( cancelShutdown_ )
cancelShutdown( client );
else
handlePendingInteractions();
}
void KSMServer::phase2Request( KSMClient* client )
{
client->waitForPhase2 = true;
client->wasPhase2 = true;
completeShutdownOrCheckpoint();
if( isWM( client ) && wmPhase1WaitingCount > 0 ) {
--wmPhase1WaitingCount;
// WM finished its phase1 and requests phase2, save the rest
if( wmPhase1WaitingCount == 0 ) {
foreach( KSMClient* c, clients )
if( !isWM( c ))
SmsSaveYourself( c->connection(), saveType, saveType != SmSaveLocal,
saveType != SmSaveLocal ? SmInteractStyleAny : SmInteractStyleNone,
false );
}
}
}
void KSMServer::handlePendingInteractions()
{
if ( clientInteracting )
return;
foreach( KSMClient* c, clients ) {
if ( c->pendingInteraction ) {
clientInteracting = c;
c->pendingInteraction = false;
break;
}
}
if ( clientInteracting ) {
endProtection();
SmsInteract( clientInteracting->connection() );
} else {
startProtection();
}
}
void KSMServer::cancelShutdown( KSMClient* c )
{
clientInteracting = 0;
kDebug() << state;
if ( state == ClosingSubSession ) {
clientsToKill.clear();
clientsToSave.clear();
emit subSessionCloseCanceled();
} else {
Solid::PowerManagement::stopSuppressingSleep(inhibitCookie);
kDebug() << "Client " << c->program() << " (" << c->clientId() << ") canceled shutdown.";
KSMShutdownFeedback::stop(); // make the screen become normal again
KNotification::event(
"kde/cancellogout" , QString(),
i18n("Logout canceled by '%1'", c->program())
);
foreach( KSMClient* c, clients ) {
SmsShutdownCancelled( c->connection() );
if( c->saveYourselfDone ) {
// Discard also saved state.
QStringList discard = c->discardCommand();
if( !discard.isEmpty())
executeCommand( discard );
}
}
}
state = Idle;
}
void KSMServer::startProtection()
{
KSharedConfig::Ptr config = KGlobal::config();
config->reparseConfiguration(); // config may have changed in the KControl module
KConfigGroup cg( config, "General" );
int timeout = cg.readEntry( "clientShutdownTimeoutSecs", 15 ) * 1000;
protectionTimer.setSingleShot( true );
protectionTimer.start( timeout );
}
void KSMServer::endProtection()
{
protectionTimer.stop();
}
/*
Internal protection slot, invoked when clients do not react during
shutdown.
*/
void KSMServer::protectionTimeout()
{
if ( ( state != Shutdown && state != Checkpoint && state != ClosingSubSession ) || clientInteracting )
return;
foreach( KSMClient* c, clients ) {
if ( !c->saveYourselfDone && !c->waitForPhase2 ) {
kDebug() << "protectionTimeout: client " << c->program() << "(" << c->clientId() << ")";
c->saveYourselfDone = true;
}
}
completeShutdownOrCheckpoint();
startProtection();
}
void KSMServer::completeShutdownOrCheckpoint()
{
if ( state != Shutdown && state != Checkpoint && state != ClosingSubSession )
return;
QList<KSMClient*> pendingClients;
if (state == ClosingSubSession)
pendingClients = clientsToSave;
else
pendingClients = clients;
foreach( KSMClient* c, pendingClients ) {
if ( !c->saveYourselfDone && !c->waitForPhase2 )
return; // not done yet
}
// do phase 2
bool waitForPhase2 = false;
foreach( KSMClient* c, pendingClients ) {
if ( !c->saveYourselfDone && c->waitForPhase2 ) {
c->waitForPhase2 = false;
SmsSaveYourselfPhase2( c->connection() );
waitForPhase2 = true;
}
}
if ( waitForPhase2 )
return;
if ( saveSession )
storeSession();
else
discardSession();
if ( state == Shutdown ) {
// KDE says good bye
KNotification *n = new KNotification(this);
n->setEventID("kde/exitkde");
connect(n, SIGNAL(closed()) , this, SLOT(logoutSoundFinished()) );
// https://bugs.kde.org/show_bug.cgi?id=228005
// if sound is not working for some reason the closed() signal never happens
// and logoutSoundFinished() never gets called. Add this timer to make
// sure the shutdown procedure continues even if sound system is broken.
QTimer::singleShot(10000, this, SLOT(logoutSoundTimeout()));
kDebug() << "Starting logout event";
state = WaitingForKNotify;
createLogoutEffectWidget();
n->send();
} else if ( state == Checkpoint ) {
foreach( KSMClient* c, clients ) {
SmsSaveComplete( c->connection());
}
state = Idle;
} else { //ClosingSubSession
startKillingSubSession();
}
}
void KSMServer::logoutSoundTimeout()
{
if (state != WaitingForKNotify) {
return;
}
kDebug() << "logout sound timeout";
logoutSoundFinished();
}
void KSMServer::startKilling()
{
kDebug() << "Starting killing clients";
// kill all clients
state = Killing;
foreach( KSMClient* c, clients ) {
if( isWM( c )) // kill the WM as the last one in order to reduce flicker
continue;
kDebug() << "completeShutdown: client " << c->program() << "(" << c->clientId() << ")";
SmsDie( c->connection() );
}
kDebug() << " We killed all clients. We have now clients.count()=" << clients.count();
completeKilling();
QTimer::singleShot( 10000, this, SLOT(timeoutQuit()) );
}
void KSMServer::completeKilling()
{
kDebug() << "KSMServer::completeKilling clients.count()=" << clients.count();
if( state == Killing ) {
bool wait = false;
foreach( KSMClient* c, clients ) {
if( isWM( c ))
continue;
wait = true; // still waiting for clients to go away
}
if( wait )
return;
killWM();
}
}
void KSMServer::killWM()
{
if( state != Killing )
return;
delete logoutEffectWidget;
kDebug() << "Starting killing WM";
state = KillingWM;
bool iswm = false;
foreach( KSMClient* c, clients ) {
if( isWM( c )) {
iswm = true;
kDebug() << "killWM: client " << c->program() << "(" << c->clientId() << ")";
SmsDie( c->connection() );
}
}
if( iswm ) {
completeKillingWM();
QTimer::singleShot( 5000, this, SLOT(timeoutWMQuit()) );
}
else
killingCompleted();
}
void KSMServer::completeKillingWM()
{
kDebug() << "KSMServer::completeKillingWM clients.count()=" << clients.count();
if( state == KillingWM ) {
if( clients.isEmpty())
killingCompleted();
}
}
// shutdown is fully complete
void KSMServer::killingCompleted()
{
kapp->quit();
}
void KSMServer::logoutSoundFinished( )
{
if( state != WaitingForKNotify )
return;
kDebug() << "Logout event finished";
startKilling();
}
void KSMServer::timeoutQuit()
{
foreach( KSMClient* c, clients ) {
kWarning() << "SmsDie timeout, client " << c->program() << "(" << c->clientId() << ")" ;
}
killWM();
}
void KSMServer::timeoutWMQuit()
{
if( state == KillingWM ) {
kWarning() << "SmsDie WM timeout" ;
}
killingCompleted();
}
void KSMServer::createLogoutEffectWidget()
{
// Ok, this is rather a hack. In order to fade the whole desktop when playing the logout
// sound, killing applications and leaving KDE, create a dummy window that triggers
// the logout fade effect again.
logoutEffectWidget = new QWidget( NULL, Qt::X11BypassWindowManagerHint );
logoutEffectWidget->winId(); // workaround for Qt4.3 setWindowRole() assert
logoutEffectWidget->setWindowRole( "logouteffect" );
// Qt doesn't set this on unmanaged windows
QByteArray appName = QApplication::applicationName().toLatin1();
QByteArray appClass = QX11Info::appClass();
XClassHint class_hint;
class_hint.res_name = appName.data(); // application name
class_hint.res_class = appClass.data(); // application class
XSetWMProperties( QX11Info::display(), logoutEffectWidget->winId(),
NULL, NULL, NULL, 0, NULL, NULL, &class_hint );
XChangeProperty( QX11Info::display(), logoutEffectWidget->winId(),
XInternAtom( QX11Info::display(), "WM_WINDOW_ROLE", False ), XA_STRING, 8, PropModeReplace,
(unsigned char *)"logouteffect", strlen( "logouteffect" ));
logoutEffectWidget->setGeometry( -100, -100, 1, 1 );
logoutEffectWidget->show();
}
void KSMServer::saveSubSession(const QString &name, QStringList saveAndClose, QStringList saveOnly)
{
if( state != Idle ) { // performing startup
kDebug() << "not idle!" << state;
return;
}
kDebug() << name << saveAndClose << saveOnly;
state = ClosingSubSession;
saveType = SmSaveBoth; //both or local? what oes it mean?
saveSession = true;
sessionGroup = "SubSession: " + name;
startProtection();
foreach( KSMClient* c, clients ) {
if (saveAndClose.contains(c->clientId())) {
c->resetState();
SmsSaveYourself( c->connection(), saveType,
true, SmInteractStyleAny, false );
clientsToSave << c;
clientsToKill << c;
} else if (saveOnly.contains(c->clientId())) {
c->resetState();
SmsSaveYourself( c->connection(), saveType,
true, SmInteractStyleAny, false );
clientsToSave << c;
}
}
completeShutdownOrCheckpoint();
}
void KSMServer::startKillingSubSession()
{
kDebug() << "Starting killing clients";
// kill all clients
state = KillingSubSession;
foreach( KSMClient* c, clientsToKill ) {
kDebug() << "completeShutdown: client " << c->program() << "(" << c->clientId() << ")";
SmsDie( c->connection() );
}
kDebug() << " We killed some clients. We have now clients.count()=" << clients.count();
completeKillingSubSession();
QTimer::singleShot( 10000, this, SLOT(signalSubSessionClosed()) );
}
void KSMServer::completeKillingSubSession()
{
kDebug() << "KSMServer::completeKillingSubSession clients.count()=" << clients.count();
if( state == KillingSubSession ) {
bool wait = false;
foreach( KSMClient* c, clientsToKill ) {
if( isWM( c ))
continue;
wait = true; // still waiting for clients to go away
}
if( wait )
return;
signalSubSessionClosed();
}
}
void KSMServer::signalSubSessionClosed()
{
if( state != KillingSubSession )
return;
clientsToKill.clear();
clientsToSave.clear();
//TODO tell the subSession manager the close request was carried out
//so that plasma can close its stuff
state = Idle;
kDebug() << state;
emit subSessionClosed();
}

View file

@ -1,499 +0,0 @@
/*****************************************************************
ksmserver - the KDE session management server
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Copyright 2005 Lubos Lunak <l.lunak@kde.org>
relatively small extensions by Oswald Buddenhagen <ob6@inf.tu-dresden.de>
some code taken from the dcopserver (part of the KDE libraries), which is
Copyright 1999 Matthias Ettrich <ettrich@kde.org>
Copyright 1999 Preston Brown <pbrown@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
#include "config-unix.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <QPushButton>
#include <QTimer>
#include <QtDBus/QtDBus>
#include <klocale.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kstandarddirs.h>
#include <kapplication.h>
#include <ktemporaryfile.h>
#include <knotification.h>
#include <kconfiggroup.h>
#include <kdebug.h>
#include "global.h"
#include "server.h"
#include "client.h"
#include <QtGui/qx11info_x11.h>
#include "kcminit_interface.h"
//#define KSMSERVER_STARTUP_DEBUG1
#ifdef KSMSERVER_STARTUP_DEBUG1
static QTime t;
#endif
/*! Restores the previous session. Ensures the window manager is
running (if specified).
*/
void KSMServer::restoreSession( const QString &sessionName )
{
if( state != Idle )
return;
#ifdef KSMSERVER_STARTUP_DEBUG1
t.start();
#endif
state = LaunchingWM;
kDebug() << "KSMServer::restoreSession " << sessionName;
KSharedConfig::Ptr config = KGlobal::config();
sessionGroup = "Session: " + sessionName;
KConfigGroup configSessionGroup( config, sessionGroup);
int count = configSessionGroup.readEntry( "count", 0 );
appsToStart = count;
connect( klauncherSignals, SIGNAL(autoStart0Done()), SLOT(autoStart0Done()));
connect( klauncherSignals, SIGNAL(autoStart1Done()), SLOT(autoStart1Done()));
connect( klauncherSignals, SIGNAL(autoStart2Done()), SLOT(autoStart2Done()));
// find all commands to launch the wm in the session
QList<QStringList> wmStartCommands;
if ( !wm.isEmpty() ) {
for ( int i = 1; i <= count; i++ ) {
QString n = QString::number(i);
if ( isWM( configSessionGroup.readEntry( QString("program")+n, QString() ) ) ) {
wmStartCommands << configSessionGroup.readEntry( QString("restartCommand")+n, QStringList() );
}
}
}
if( wmStartCommands.isEmpty()) // otherwise use the configured default
wmStartCommands << wmCommands;
launchWM( wmStartCommands );
}
/*!
Starts the default session.
Currently, that's the window manager only (if specified).
*/
void KSMServer::startDefaultSession()
{
if( state != Idle )
return;
state = LaunchingWM;
#ifdef KSMSERVER_STARTUP_DEBUG1
t.start();
#endif
sessionGroup = "";
connect( klauncherSignals, SIGNAL(autoStart0Done()), SLOT(autoStart0Done()));
connect( klauncherSignals, SIGNAL(autoStart1Done()), SLOT(autoStart1Done()));
connect( klauncherSignals, SIGNAL(autoStart2Done()), SLOT(autoStart2Done()));
launchWM( QList< QStringList >() << wmCommands );
}
void KSMServer::launchWM( const QList< QStringList >& wmStartCommands )
{
assert( state == LaunchingWM );
// when we have a window manager, we start it first and give
// it some time before launching other processes. Results in a
// visually more appealing startup.
QStringList wmCommand = wmStartCommands[0];
QString program = wmCommand.takeAt(0);
connect( wmProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(wmProcessChange()));
connect( wmProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(wmProcessChange()));
wmProcess->start(program, wmCommand);
wmProcess->waitForStarted(4000);
QMetaObject::invokeMethod(this, "autoStart0", Qt::QueuedConnection);
}
void KSMServer::clientSetProgram( KSMClient* client )
{
if( client->program() == wm )
autoStart0();
}
void KSMServer::wmProcessChange()
{
if( state != LaunchingWM ) {
// don't care about the process when not in the wm-launching state anymore
disconnect(wmProcess, 0, this, 0);
return;
}
if( wmProcess->state() == QProcess::NotRunning ) {
// wm failed to launch for some reason, go with kwin instead
kWarning() << "Window manager" << wm << "failed to launch";
if( wm == "kwin" )
return; // uhoh, kwin itself failed
kDebug() << "Launching KWin";
wm = "kwin";
wmCommands = ( QStringList() << "kwin" );
// launch it
launchWM( QList< QStringList >() << wmCommands );
return;
}
}
void KSMServer::autoStart0()
{
if( state != LaunchingWM )
return;
if( !checkStartupSuspend())
return;
state = AutoStart0;
static const QString kdedInterface = QString::fromLatin1("org.kde.kded");
QDBusConnectionInterface* sessionInterface = QDBusConnection::sessionBus().interface();
if (!sessionInterface->isServiceRegistered(kdedInterface)) {
sessionInterface->startService(kdedInterface);
}
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << t.elapsed();
#endif
klauncherSignals->asyncCall("autoStart", int(0));
}
void KSMServer::autoStart0Done()
{
if( state != AutoStart0 )
return;
disconnect( klauncherSignals, SIGNAL(autoStart0Done()), this, SLOT(autoStart0Done()));
if( !checkStartupSuspend())
return;
kDebug() << "Autostart 0 done";
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << t.elapsed();
#endif
state = KcmInitPhase1;
kcminitSignals = new QDBusInterface("org.kde.kcminit", "/kcminit", "org.kde.KCMInit", QDBusConnection::sessionBus(), this );
if( !kcminitSignals->isValid()) {
kWarning() << "kcminit not running? If we are running with mobile profile or in another platform other than X11 this is normal.";
delete kcminitSignals;
kcminitSignals = 0;
QMetaObject::invokeMethod(this, "kcmPhase1Done", Qt::QueuedConnection);
return;
}
connect( kcminitSignals, SIGNAL(phase1Done()), SLOT(kcmPhase1Done()));
QTimer::singleShot( 10000, this, SLOT(kcmPhase1Timeout())); // protection
org::kde::KCMInit kcminit("org.kde.kcminit", "/kcminit" , QDBusConnection::sessionBus());
kcminit.runPhase1();
}
void KSMServer::kcmPhase1Done()
{
if( state != KcmInitPhase1 )
return;
kDebug() << "Kcminit phase 1 done";
if (kcminitSignals) {
disconnect( kcminitSignals, SIGNAL(phase1Done()), this, SLOT(kcmPhase1Done()));
}
autoStart1();
}
void KSMServer::kcmPhase1Timeout()
{
if( state != KcmInitPhase1 )
return;
kDebug() << "Kcminit phase 1 timeout";
kcmPhase1Done();
}
void KSMServer::autoStart1()
{
if( state != KcmInitPhase1 )
return;
state = AutoStart1;
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << t.elapsed();
#endif
klauncherSignals->asyncCall("autoStart", int(1));
}
void KSMServer::autoStart1Done()
{
if( state != AutoStart1 )
return;
disconnect( klauncherSignals, SIGNAL(autoStart1Done()), this, SLOT(autoStart1Done()));
if( !checkStartupSuspend())
return;
kDebug() << "Autostart 1 done";
setupShortcuts(); // done only here, because it needs kglobalaccel :-/
lastAppStarted = 0;
lastIdStarted.clear();
state = Restoring;
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << t.elapsed();
#endif
if( defaultSession()) {
autoStart2();
return;
}
tryRestoreNext();
}
void KSMServer::clientRegistered( const char* previousId )
{
if ( previousId && lastIdStarted == previousId )
tryRestoreNext();
}
void KSMServer::tryRestoreNext()
{
if( state != Restoring && state != RestoringSubSession )
return;
restoreTimer.stop();
startupSuspendTimeoutTimer.stop();
KConfigGroup config(KGlobal::config(), sessionGroup );
while ( lastAppStarted < appsToStart ) {
lastAppStarted++;
QString n = QString::number(lastAppStarted);
QString clientId = config.readEntry( QString("clientId")+n, QString() );
bool alreadyStarted = false;
foreach ( KSMClient *c, clients ) {
if ( c->clientId() == clientId ) {
alreadyStarted = true;
break;
}
}
if ( alreadyStarted )
continue;
QStringList restartCommand = config.readEntry( QString("restartCommand")+n, QStringList() );
if ( restartCommand.isEmpty() ||
(config.readEntry( QString("restartStyleHint")+n, 0 ) == SmRestartNever)) {
continue;
}
if ( isWM( config.readEntry( QString("program")+n, QString() ) ) )
continue; // wm already started
if( config.readEntry( QString( "wasWm" )+n, false ))
continue; // it was wm before, but not now, don't run it (some have --replace in command :( )
startApplication( restartCommand,
config.readEntry( QString("clientMachine")+n, QString() ),
config.readEntry( QString("userId")+n, QString() ));
lastIdStarted = clientId;
if ( !lastIdStarted.isEmpty() ) {
restoreTimer.setSingleShot( true );
restoreTimer.start( 2000 );
return; // we get called again from the clientRegistered handler
}
}
//all done
appsToStart = 0;
lastIdStarted.clear();
if (state == Restoring)
autoStart2();
else { //subsession
state = Idle;
emit subSessionOpened();
}
}
void KSMServer::autoStart2()
{
if( state != Restoring )
return;
if( !checkStartupSuspend())
return;
state = FinishingStartup;
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << t.elapsed();
#endif
waitAutoStart2 = true;
waitKcmInit2 = true;
klauncherSignals->asyncCall("autoStart", int(2));
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << "klauncher" << t.elapsed();
#endif
QDBusInterface kded( "org.kde.kded", "/kded", "org.kde.kded" );
QDBusPendingCall pendingcall = kded.asyncCall( "loadSecondPhase" );
while (!pendingcall.isFinished()) {
QApplication::processEvents();
}
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << "kded" << t.elapsed();
#endif
if (kcminitSignals) {
connect( kcminitSignals, SIGNAL(phase2Done()), SLOT(kcmPhase2Done()));
QTimer::singleShot( 10000, this, SLOT(kcmPhase2Timeout())); // protection
org::kde::KCMInit kcminit("org.kde.kcminit", "/kcminit" , QDBusConnection::sessionBus());
kcminit.runPhase2();
} else {
QMetaObject::invokeMethod(this, "kcmPhase2Done", Qt::QueuedConnection);
}
KNotification::event("kde/startkde"); // this is the time KDE is up, more or less
}
void KSMServer::autoStart2Done()
{
if( state != FinishingStartup )
return;
disconnect( klauncherSignals, SIGNAL(autoStart2Done()), this, SLOT(autoStart2Done()));
kDebug() << "Autostart 2 done";
waitAutoStart2 = false;
finishStartup();
}
void KSMServer::kcmPhase2Done()
{
if( state != FinishingStartup )
return;
kDebug() << "Kcminit phase 2 done";
if (kcminitSignals) {
disconnect( kcminitSignals, SIGNAL(phase2Done()), this, SLOT(kcmPhase2Done()));
delete kcminitSignals;
kcminitSignals = 0;
}
waitKcmInit2 = false;
finishStartup();
}
void KSMServer::kcmPhase2Timeout()
{
if( !waitKcmInit2 )
return;
kDebug() << "Kcminit phase 2 timeout";
kcmPhase2Done();
}
void KSMServer::finishStartup()
{
if( state != FinishingStartup )
return;
if( waitAutoStart2 || waitKcmInit2 )
return;
#ifdef KSMSERVER_STARTUP_DEBUG1
kDebug() << t.elapsed();
#endif
state = Idle;
setupXIOErrorHandler(); // From now on handle X errors as normal shutdown.
}
bool KSMServer::checkStartupSuspend()
{
if( startupSuspendCount.isEmpty())
return true;
// wait for the phase to finish
if( !startupSuspendTimeoutTimer.isActive())
{
startupSuspendTimeoutTimer.setSingleShot( true );
startupSuspendTimeoutTimer.start( 10000 );
}
return false;
}
void KSMServer::suspendStartup( const QString &app )
{
if( !startupSuspendCount.contains( app ))
startupSuspendCount[ app ] = 0;
++startupSuspendCount[ app ];
}
void KSMServer::resumeStartup( const QString &app )
{
if( !startupSuspendCount.contains( app ))
return;
if( --startupSuspendCount[ app ] == 0 ) {
startupSuspendCount.remove( app );
if( startupSuspendCount.isEmpty() && startupSuspendTimeoutTimer.isActive()) {
startupSuspendTimeoutTimer.stop();
resumeStartupInternal();
}
}
}
void KSMServer::startupSuspendTimeout()
{
kDebug() << "Startup suspend timeout:" << state;
resumeStartupInternal();
}
void KSMServer::resumeStartupInternal()
{
startupSuspendCount.clear();
switch( state ) {
case LaunchingWM:
autoStart0();
break;
case AutoStart0:
autoStart0Done();
break;
case AutoStart1:
autoStart1Done();
break;
case Restoring:
autoStart2();
break;
default:
kWarning() << "Unknown resume startup state" ;
break;
}
}
void KSMServer::restoreSubSession( const QString& name )
{
sessionGroup = "SubSession: " + name;
KConfigGroup configSessionGroup( KGlobal::config(), sessionGroup);
int count = configSessionGroup.readEntry( "count", 0 );
appsToStart = count;
lastAppStarted = 0;
lastIdStarted.clear();
state = RestoringSubSession;
tryRestoreNext();
}

View file

@ -130,11 +130,6 @@ qt4_add_dbus_adaptor(kwin_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterf
qt4_add_dbus_adaptor(kwin_SRCS org.kde.kwin.Compositing.xml composite.h KWin::Compositor)
qt4_add_dbus_adaptor(kwin_SRCS org.kde.kwin.Effects.xml effects.h KWin::EffectsHandlerImpl)
qt4_add_dbus_interface(kwin_SRCS
${CMAKE_SOURCE_DIR}/ksmserver/org.kde.KSMServerInterface.xml
ksmserver_interface
)
########### target link libraries ###############
if (NOT X11_xf86vmode_FOUND)

View file

@ -147,7 +147,7 @@ void LogoutEffect::slotWindowDeleted(EffectWindow* w)
bool LogoutEffect::isLogoutDialog(EffectWindow* w)
{
// TODO there should be probably a better way (window type?)
if (w->windowClass() == "ksmserver ksmserver"
if (w->windowClass() == "plasma-desktop plasma-desktop"
&& (w->windowRole() == "logoutdialog" || w->windowRole() == "logouteffect")) {
return true;
}
@ -166,7 +166,7 @@ void LogoutEffect::slotPropertyNotify(EffectWindow* w, long a)
return;
}
// We are using a compatible KSMServer therefore only terminate the effect when the
// using a compatible session manager therefore only terminate the effect when the
// atom is deleted, not when the dialog is closed.
canDoPersistent = true;
effects->addRepaintFull();

View file

@ -32,6 +32,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif // HAVE_MALLOC_H
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QMessageBox>
#include <QEvent>
#include <QVBoxLayout>
@ -53,8 +55,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QtGui/qx11info_x11.h>
#include <fixx11h.h>
#include <ksmserver_interface.h>
#include "atoms.h"
#include "options.h"
#include "sm.h"
@ -335,10 +335,14 @@ int main(int argc, char * argv[])
KCmdLineArgs::addCmdLineOptions(args);
KWin::Application a;
org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
ksmserver.suspendStartup("kwin");
QDBusInterface plasma("org.kde.plasma-desktop", "/App", "local.PlasmaApp", QDBusConnection::sessionBus());
if (plasma.isValid()) {
plasma.call("suspendStartup", "kwin");
}
if (!a.setup()) {
ksmserver.resumeStartup("kwin");
if (plasma.isValid()) {
plasma.call("resumeStartup", "kwin");
}
a.exit(1);
return 1;
}
@ -354,7 +358,9 @@ int main(int argc, char * argv[])
// and one more iteration just in case
a.processEvents();
ksmserver.resumeStartup("kwin");
if (plasma.isValid()) {
plasma.call("resumeStartup", "kwin");
}
KWin::SessionManager weAreIndeed;
KWin::SessionSaveDoneHelper helper;
KGlobal::locale()->insertCatalog("kwin_effects");

View file

@ -39,24 +39,24 @@ namespace KWin
bool SessionManager::saveState(QSessionManager& sm)
{
// If the session manager is ksmserver, save stacking
// If the session manager is plasma-desktop, save stacking
// order, active window, active desktop etc. in phase 1,
// as ksmserver assures no interaction will be done
// as plasma-desktop assures no interaction will be done
// before the WM finishes phase 1. Saving in phase 2 is
// too late, as possible user interaction may change some things.
// Phase2 is still needed though (ICCCM 5.2)
char* sm_vendor = SmcVendor(static_cast< SmcConn >(sm.handle()));
bool ksmserver = qstrcmp(sm_vendor, "KDE") == 0;
bool kde = qstrcmp(sm_vendor, "KDE") == 0;
free(sm_vendor);
if (!sm.isPhase2()) {
Workspace::self()->sessionSaveStarted();
if (ksmserver) // save stacking order etc. before "save file?" etc. dialogs change it
if (kde) // save stacking order etc. before "save file?" etc. dialogs change it
Workspace::self()->storeSession(kapp->sessionConfig(), SMSavePhase0);
sm.release(); // Qt doesn't automatically release in this case (bug?)
sm.requestPhase2();
return true;
}
Workspace::self()->storeSession(kapp->sessionConfig(), ksmserver ? SMSavePhase2 : SMSavePhase2Full);
Workspace::self()->storeSession(kapp->sessionConfig(), kde ? SMSavePhase2 : SMSavePhase2Full);
kapp->sessionConfig()->sync();
return true;
}

View file

@ -6,8 +6,8 @@ set(kworkspace_LIB_SRCS
)
set(ksmserver_xml ${CMAKE_SOURCE_DIR}/ksmserver/org.kde.KSMServerInterface.xml)
qt4_add_dbus_interface(kworkspace_LIB_SRCS ${ksmserver_xml} ksmserver_interface)
set(plasma_xml ${CMAKE_SOURCE_DIR}/plasma/shells/plasma-desktop/dbus/org.kde.plasma.App.xml)
qt4_add_dbus_interface(kworkspace_LIB_SRCS ${plasma_xml} plasma_interface)
set(kwin_xml ${CMAKE_SOURCE_DIR}/kwin/org.kde.KWin.xml)

View file

@ -18,6 +18,7 @@
*/
#include "kworkspace.h"
#include "kdisplaymanager.h"
#include <QApplication>
#include <QDataStream>
@ -31,7 +32,7 @@
#include <klocale.h>
#include <kstandarddirs.h>
#include <kuser.h>
#include <ksmserver_interface.h>
#include <plasma_interface.h>
#include <stdlib.h> // getenv()
#include <sys/types.h>
@ -167,12 +168,12 @@ static void cleanup_sm()
void requestShutDown(ShutdownConfirm confirm, ShutdownType sdtype)
{
#ifdef Q_WS_X11
/* use ksmserver's dcop interface if necessary */
/* use plasma's dcop interface if necessary */
if ( confirm == ShutdownConfirmYes ||
sdtype != ShutdownTypeDefault )
{
org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
ksmserver.logout((int)confirm, (int)sdtype);
local::PlasmaApp plasma("org.kde.plasma-desktop", "/App", QDBusConnection::sessionBus());
plasma.logout((int)confirm, (int)sdtype);
return;
}
@ -191,12 +192,7 @@ bool canShutDown( ShutdownConfirm confirm, ShutdownType sdtype )
if ( confirm == ShutdownConfirmYes ||
sdtype != ShutdownTypeDefault )
{
org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
QDBusReply<bool> reply = ksmserver.canShutdown();
if (!reply.isValid()) {
return false;
}
return reply;
return KDisplayManager().canShutdown();
}
return true;

View file

@ -69,7 +69,7 @@ namespace KWorkSpace
* Asks the session manager to shut the session down.
*
* Using @p confirm == ShutdownConfirmYes or @p sdtype != ShutdownTypeDefault
* causes the use of ksmserver's D-Bus interface. The remaining two
* causes the use of plasma's D-Bus interface. The remaining two
* combinations use the standard XSMP and will work with any session manager
* compliant with it.
*

View file

@ -28,7 +28,7 @@
namespace KWorkSpace
{
// A class that creates another connection to ksmserver and handles it properly.
// A class that creates another connection to plasma and handles it properly.
class KRequestShutdownHelper
: public QObject
{

View file

@ -36,7 +36,7 @@ public:
enum DoWhat {
DoNothing = 0,
DoSwitch = 1,
// shutdown is asked for by ksmserver
// shutdown is asked for by plasma-desktop
DoToRam = 2,
DoToDisk = 3,
DoHybrid = 4

View file

@ -15,6 +15,7 @@ set(plasma_SRCS
panelappletoverlay.cpp
plasmaapp.cpp
positioningruler.cpp
shutdowndlg.cpp
)
set(plasmaapp_dbusXML dbus/org.kde.plasma.App.xml)
@ -37,11 +38,6 @@ install(
DESTINATION ${KDE4_BIN_INSTALL_DIR}
)
install(
FILES data/plasma-desktop.desktop
DESTINATION ${KDE4_AUTOSTART_INSTALL_DIR}
)
install(
FILES data/plasma-desktoprc
DESTINATION ${KDE4_CONFIG_INSTALL_DIR}

View file

@ -1,77 +0,0 @@
[Desktop Entry]
Exec=plasma-desktop
Name=Plasma Desktop Workspace
Name[ar]=مساحة عمل بلازما
Name[ast]=Espaciu de trabayu del escritoriu Plasma
Name[be@latin]=Rabočy abšar stała Plasma
Name[bg]=Работно пространство Plasma
Name[bs]=Plazma radni prostor površi
Name[ca]=Espai de treball de l'escriptori Plasma
Name[ca@valencia]=Espai de treball de l'escriptori Plasma
Name[cs]=Pracovní plocha Plasma
Name[da]=Plasma Desktop Workspace
Name[de]=Plasma-Arbeitsflächenbereiche
Name[el]=Χώρος επιφάνειας εργασίας Plasma
Name[en_GB]=Plasma Desktop Workspace
Name[eo]=Plasma Labortabla laborspaco
Name[es]=Espacio de trabajo del escritorio Plasma
Name[et]=Plasma töölaua töötsoon
Name[eu]=Plasma mahaigainaren laneko eremua
Name[fi]=Plasma-työpöytä
Name[fr]=Espace de travail Plasma
Name[fy]=Plasma buroblêd wurkromte
Name[ga]=Spás Oibre Deisce Plasma
Name[gl]=Espazo de traballo do escritorio Plasma
Name[gu]=
Name[he]=סביבת העבודה של Plasma
Name[hi]=
Name[hne]=
Name[hr]=Plasma radno okruženje
Name[hu]=Plazma munkaterület
Name[ia]=Spatio de labor de scriptorio de Plasma
Name[id]=Ruang Kerja Desktop Plasma
Name[is]=Vinnurýmd Plasma skjáborðs
Name[it]=Spazio di lavoro del desktop di Plasma
Name[kk]=Plasma үстел жұмыс орны
Name[km]=
Name[kn]= ( )
Name[ko]=Plasma
Name[lt]=Plasma darbastalio erdvė
Name[lv]=Plasma darbvirsma
Name[ml]= ിി
Name[mr]=Plasma
Name[nb]=Arbeidsrom for Plasma skrivebord
Name[nds]=Plasma-Schriefdischarbeitrebeet
Name[nl]=Plasma Bureaublad Werkplek
Name[nn]=Arbeidsområde for Plasma-skrivebord
Name[or]=
Name[pa]=
Name[pl]=Przestrzeń pulpitu Plazmy
Name[pt]=Área de Trabalho do Plasma
Name[pt_BR]=Espaço de Trabalho Plasma
Name[ro]=Spațiu de lucru Plasma al biroului
Name[ru]=Рабочий стол Plasma
Name[si]=
Name[sk]=Pracovná plocha Plasma
Name[sl]=Delovni prostor Plasma Desktop
Name[sr]=Плазма, радни простор површи
Name[sr@ijekavian]=Плазма, радни простор површи
Name[sr@ijekavianlatin]=Plasma, radni prostor površi
Name[sr@latin]=Plasma, radni prostor površi
Name[sv]=Plasma arbetsområde för skrivbordet
Name[ta]=Plasma Desktop Workspace
Name[te]= ి
Name[tg]=Муҳити мизи кории Plasma
Name[th]=
Name[tr]=Plasma Masaüstü Çalışma Alanı
Name[ug]=پلازما ئۈستەلئۈستى خىزمەت بوشلۇقى
Name[uk]=Робочий простір стільниці Плазми
Name[wa]=Espåce di boutaedje Sicribanne di Plasma
Name[x-test]=xxPlasma Desktop Workspacexx
Name[zh_CN]=Plasma
Name[zh_TW]=Plasma
Type=Service
StartupNotify=false
OnlyShowIn=KDE;
X-KDE-autostart-phase=0

View file

@ -10,5 +10,16 @@
<method name="supportInformation">
<arg type="s" direction="out"/>
</method>
<method name="suspendStartup">
<arg type="s" direction="in"/>
</method>
<method name="resumeStartup">
<arg type="s" direction="in"/>
</method>
<method name="logout">
<arg type="i" direction="in"/>
<arg type="i" direction="in"/>
</method>
<method name="wmChanged"/>
</interface>
</node>

View file

@ -42,6 +42,8 @@
#include <KActionCollection>
#include <KToolInvocation>
#include <KConfigSkeleton>
#include <KDesktopFile>
#include <KShell>
#include <Plasma/AbstractToolBox>
#include <Plasma/Containment>
@ -59,12 +61,17 @@
#include "panelshadows.h"
#include "panelview.h"
#include "toolbutton.h"
#include "shutdowndlg.h"
#include "kworkspace/kdisplaymanager.h"
#ifdef Q_WS_X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
static const QString s_defaultwm = QString::fromLatin1("kwin");
static const QStringList s_defaultwmcommands = QStringList() << s_defaultwm;
static void addInformationForApplet(QTextStream &stream, Plasma::Applet *applet)
{
if (applet->isContainment()) {
@ -100,7 +107,14 @@ PlasmaApp* PlasmaApp::self()
PlasmaApp::PlasmaApp()
: KUniqueApplication(),
m_corona(nullptr),
m_panelHidden(0)
m_panelHidden(0),
m_phase(0),
m_klauncher(nullptr),
m_kcminit(nullptr),
m_wmproc(nullptr),
m_startupsuspend(0),
m_dialogActive(false),
m_sdtype(KWorkSpace::ShutdownTypeNone)
{
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "plasma app ctor start" << "(line:" << __LINE__ << ")";
@ -131,12 +145,76 @@ PlasmaApp::PlasmaApp()
action->setGlobalShortcut(QKeySequence(Qt::CTRL+Qt::Key_Print));
connect(action, SIGNAL(triggered(bool)), SLOT(captureCurrentWindow()));
action = actionCollection->addAction("Log Out");
action->setText(i18n("Log Out"));
action->setGlobalShortcut(QKeySequence(Qt::ALT+Qt::CTRL+Qt::Key_Delete));
connect(action, SIGNAL(triggered(bool)), SLOT(defaultLogout()));
action = actionCollection->addAction("Log Out Without Confirmation");
action->setText(i18n("Log Out Without Confirmation"));
action->setGlobalShortcut(QKeySequence(Qt::ALT+Qt::CTRL+Qt::SHIFT+Qt::Key_Delete));
connect(action, SIGNAL(triggered(bool)), SLOT(logoutWithoutConfirmation()));
action = actionCollection->addAction("Halt Without Confirmation");
action->setText(i18n("Halt Without Confirmation"));
action->setGlobalShortcut(QKeySequence(Qt::ALT+Qt::CTRL+Qt::SHIFT+Qt::Key_PageDown));
connect(action, SIGNAL(triggered(bool)), SLOT(haltWithoutConfirmation()));
action = actionCollection->addAction("Reboot Without Confirmation");
action->setText(i18n("Reboot Without Confirmation"));
action->setGlobalShortcut(QKeySequence(Qt::ALT+Qt::CTRL+Qt::SHIFT+Qt::Key_PageUp));
connect(action, SIGNAL(triggered(bool)), SLOT(rebootWithoutConfirmation()));
QTimer::singleShot(0, this, SLOT(setupDesktop()));
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "plasma app ctor end" << "(line:" << __LINE__ << ")";
m_klauncher = new QDBusInterface(
QLatin1String("org.kde.klauncher"),
QLatin1String("/KLauncher"),
QLatin1String("org.kde.KLauncher"),
QDBusConnection::sessionBus(),
this
);
// TODO: m_klauncher->call("setLaunchEnv", "SESSION_MANAGER", "TODO");
m_kcminit = new QDBusInterface(
QLatin1String("org.kde.kcminit"),
QLatin1String("/kcminit"),
QLatin1String("org.kde.KCMInit"),
QDBusConnection::sessionBus(),
this
);
KGlobal::dirs()->addResourceType("windowmanagers", "data", "plasma/windowmanagers");
QStringList wmcommands;
if (qgetenv("KDE_FAILSAFE").toInt() != 1) {
KConfig cfg("plasmarc", KConfig::NoGlobals);
KConfigGroup config(&cfg, "General");
const QString wmname = config.readEntry("windowManager", s_defaultwm);
if (wmname != s_defaultwm) {
KDesktopFile wmfile("windowmanagers", wmname + ".desktop");
if (!wmfile.noDisplay() && wmfile.tryExec()) {
wmcommands = KShell::splitArgs(wmfile.desktopGroup().readEntry("Exec"));
}
}
}
if (wmcommands.isEmpty()) {
wmcommands = s_defaultwmcommands;
}
const QString wmprog = wmcommands.takeFirst();
m_wmproc = new QProcess(this);
m_wmproc->start(wmprog, wmcommands);
m_wmproc->waitForStarted(4000);
QTimer::singleShot(100, this, SLOT(nextPhase()));
}
PlasmaApp::~PlasmaApp()
{
cleanup();
if (m_corona) {
m_corona->saveLayout(KStandardDirs::locateLocal("config", "plasma-desktoprc"));
@ -876,6 +954,44 @@ QString PlasmaApp::supportInformation() const
return streambuffer;
}
void PlasmaApp::suspendStartup(const QString &app)
{
// TODO: timeout for suspending
m_startupsuspend++;
}
void PlasmaApp::resumeStartup(const QString &app)
{
m_startupsuspend--;
}
void PlasmaApp::logout(int confirm, int sdtype)
{
// TODO: prevent logout while initializing
m_sdtype = static_cast<KWorkSpace::ShutdownType>(sdtype);
if (confirm == KWorkSpace::ShutdownConfirmNo) {
QTimer::singleShot(500, this, SLOT(doLogout()));
return;
}
if (m_dialogActive) {
return;
}
m_dialogActive = true;
KApplication::kApplication()->updateUserTimestamp();
const bool maysd = KDisplayManager().canShutdown();
const bool choose = (m_sdtype == KWorkSpace::ShutdownTypeDefault);
const bool logoutConfirmed = KSMShutdownDlg::confirmShutdown(maysd, choose, m_sdtype);
if (logoutConfirmed) {
QTimer::singleShot(500, this, SLOT(doLogout()));
}
m_dialogActive = false;
}
void PlasmaApp::wmChanged()
{
// changing the window manager happens from the KCM, currently nothing to do when that happens
}
void PlasmaApp::captureDesktop()
{
KToolInvocation::kdeinitExec("ksnapshot", QStringList() << "--fullscreen");
@ -886,4 +1002,79 @@ void PlasmaApp::captureCurrentWindow()
KToolInvocation::kdeinitExec("ksnapshot", QStringList() << "--current");
}
void PlasmaApp::cleanup()
{
if (m_klauncher) {
m_klauncher->call("cleanup");
m_klauncher->deleteLater();
m_klauncher = nullptr;
}
if (m_wmproc && m_wmproc->state() != QProcess::NotRunning) {
m_wmproc->kill();
m_wmproc->waitForFinished();
m_wmproc->deleteLater();
m_wmproc = nullptr;
}
}
void PlasmaApp::nextPhase()
{
if (m_startupsuspend <= 0){
switch (m_phase) {
case 0: {
static const QString kdedInterface = QString::fromLatin1("org.kde.kded");
QDBusConnectionInterface* sessionInterface = QDBusConnection::sessionBus().interface();
if (!sessionInterface->isServiceRegistered(kdedInterface)) {
sessionInterface->startService(kdedInterface);
}
m_klauncher->call("autoStart", int(0));
m_kcminit->call("runPhase1");
break;
}
case 1: {
m_klauncher->call("autoStart", int(1));
m_kcminit->call("runPhase2");
break;
}
case 2: {
m_klauncher->call("autoStart", int(2));
break;
}
}
m_phase++;
}
QTimer::singleShot(100, this, SLOT(nextPhase()));
}
void PlasmaApp::defaultLogout()
{
logout(KWorkSpace::ShutdownConfirmYes, KWorkSpace::ShutdownTypeDefault);
}
void PlasmaApp::logoutWithoutConfirmation()
{
logout(KWorkSpace::ShutdownConfirmNo, KWorkSpace::ShutdownTypeNone);
}
void PlasmaApp::haltWithoutConfirmation()
{
logout(KWorkSpace::ShutdownConfirmNo, KWorkSpace::ShutdownTypeHalt);
}
void PlasmaApp::rebootWithoutConfirmation()
{
logout(KWorkSpace::ShutdownConfirmNo, KWorkSpace::ShutdownTypeReboot);
}
void PlasmaApp::doLogout()
{
cleanup();
if (m_sdtype == KWorkSpace::ShutdownTypeDefault || m_sdtype == KWorkSpace::ShutdownTypeNone) {
quit();
} else {
KDisplayManager().shutdown(m_sdtype);
}
}
#include "moc_plasmaapp.cpp"

View file

@ -21,8 +21,10 @@
#ifndef PLASMA_APP_H
#define PLASMA_APP_H
#include <QtCore/qtimer.h>
#include <QtCore/qsharedpointer.h>
#include <QTimer>
#include <QWeakPointer>
#include <QDBusInterface>
#include <QProcess>
#include <KUniqueApplication>
#include <Plasma/Plasma>
@ -35,6 +37,7 @@
#endif
#include "desktoptracker.h"
#include "kworkspace/kworkspace.h"
namespace Plasma
{
@ -95,6 +98,11 @@ public Q_SLOTS:
QString supportInformation() const;
void suspendStartup(const QString &app);
void resumeStartup(const QString &app);
void logout(int confirm, int sdtype);
void wmChanged();
protected:
#ifdef Q_WS_X11
PanelView *findPanelForTrigger(WId trigger) const;
@ -123,6 +131,14 @@ private Q_SLOTS:
void captureDesktop();
void captureCurrentWindow();
void cleanup();
void nextPhase();
void defaultLogout();
void logoutWithoutConfirmation();
void haltWithoutConfirmation();
void rebootWithoutConfirmation();
void doLogout();
private:
DesktopCorona *m_corona;
PanelShadows *m_panelShadows;
@ -138,6 +154,13 @@ private:
QTimer m_desktopViewCreationTimer;
int m_panelHidden;
QHash<int, QWeakPointer<ControllerWindow> > m_widgetExplorers;
int m_phase;
QDBusInterface* m_klauncher;
QDBusInterface* m_kcminit;
QProcess* m_wmproc;
int m_startupsuspend;
bool m_dialogActive;
KWorkSpace::ShutdownType m_sdtype;
};
#endif // multiple inclusion guard

View file

@ -1,27 +1,21 @@
/*****************************************************************
ksmserver - the KDE session management server
/*
This file is part of the KDE project
Copyright (C) 2023 Ivailo Monev <xakepa10@gmail.com>
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
Copyright 2007 Urs Wolfer <uwolfer @ kde.org>
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.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
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.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
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 "shutdowndlg.h"
#include "kworkspace/kdisplaymanager.h"
@ -53,27 +47,6 @@ static bool kSwitchTitleEvent(QEvent *event)
Q_UNREACHABLE();
}
void KSMShutdownFeedback::start()
{
if (KWindowSystem::compositingActive()) {
// Announce that the user MAY be logging out (Intended for the compositor)
Display* dpy = QX11Info::display();
Atom announce = XInternAtom(dpy, "_KDE_LOGGING_OUT", False);
unsigned char dummy = 0;
XChangeProperty(dpy, QX11Info::appRootWindow(), announce, announce, 8, PropModeReplace, &dummy, 1);
}
}
void KSMShutdownFeedback::stop()
{
if (KWindowSystem::compositingActive()) {
// No longer logging out, announce (Intended for the compositor)
Display* dpy = QX11Info::display();
Atom announce = XInternAtom(dpy, "_KDE_LOGGING_OUT", False);
XDeleteProperty(QX11Info::display(), QX11Info::appRootWindow(), announce);
}
}
KSMShutdownDlg::KSMShutdownDlg(QWidget* parent,
bool maysd, bool choose, KWorkSpace::ShutdownType sdtype)
: Plasma::Dialog(parent, Qt::Dialog | Qt::WindowStaysOnTopHint),
@ -92,8 +65,13 @@ KSMShutdownDlg::KSMShutdownDlg(QWidget* parent,
m_second(s_timeout),
m_shutdownType(sdtype)
{
// make the screen gray
KSMShutdownFeedback::start();
if (KWindowSystem::compositingActive()) {
// Announce that the user MAY be logging out (Intended for the compositor)
Display* dpy = QX11Info::display();
Atom announce = XInternAtom(dpy, "_KDE_LOGGING_OUT", False);
unsigned char dummy = 0;
XChangeProperty(dpy, QX11Info::appRootWindow(), announce, announce, 8, PropModeReplace, &dummy, 1);
}
m_scene = new QGraphicsScene(this);
m_widget = new QGraphicsWidget();
@ -247,8 +225,12 @@ KSMShutdownDlg::KSMShutdownDlg(QWidget* parent,
KSMShutdownDlg::~KSMShutdownDlg()
{
// make the screen become normal again
KSMShutdownFeedback::stop();
if (KWindowSystem::compositingActive()) {
// No longer logging out, announce (Intended for the compositor)
Display* dpy = QX11Info::display();
Atom announce = XInternAtom(dpy, "_KDE_LOGGING_OUT", False);
XDeleteProperty(QX11Info::display(), QX11Info::appRootWindow(), announce);
}
// delete m_widget;
}
@ -363,10 +345,10 @@ bool KSMShutdownDlg::confirmShutdown(bool maysd, bool choose, KWorkSpace::Shutdo
{
KSMShutdownDlg* dialog = new KSMShutdownDlg(nullptr, maysd, choose, sdtype);
// NOTE: KWin logout effect expects class hint values to be ksmserver
// NOTE: KWin logout effect expects class hint values to be plasma-desktop
XClassHint classHint;
classHint.res_name = const_cast<char*>("ksmserver");
classHint.res_class = const_cast<char*>("ksmserver");
classHint.res_name = const_cast<char*>("plasma-desktop");
classHint.res_class = const_cast<char*>("plasma-desktop");
XSetClassHint(QX11Info::display(), dialog->winId(), &classHint);
dialog->setWindowRole("logoutdialog");

View file

@ -1,26 +1,21 @@
/*****************************************************************
ksmserver - the KDE session management server
/*
This file is part of the KDE project
Copyright (C) 2023 Ivailo Monev <xakepa10@gmail.com>
Copyright 2000 Matthias Ettrich <ettrich@kde.org>
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.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
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.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
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 SHUTDOWNDLG_H
#define SHUTDOWNDLG_H
@ -35,15 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <Plasma/Separator>
#include <Plasma/IconWidget>
#include <Plasma/PushButton>
#include <kworkspace/kworkspace.h>
// The methods that make the desktop gray if compositor is active.
class KSMShutdownFeedback
{
public:
static void start();
static void stop();
};
#include "kworkspace/kworkspace.h"
// The confirmation dialog
class KSMShutdownDlg : public Plasma::Dialog

View file

@ -13,19 +13,6 @@ fi
# because we still need to do some cleanup.
trap 'echo GOT SIGHUP' HUP
# Check if a KDE session already is running and whether it's possible to connect to X
kcheckrunning
kcheckrunning_result=$?
if test $kcheckrunning_result -eq 0 ; then
echo "KDE seems to be already running on this display."
xmessage -geometry 500x100 "KDE seems to be already running on this display." > /dev/null 2>/dev/null
exit 1
elif test $kcheckrunning_result -eq 2 ; then
echo "\$DISPLAY is not set or cannot connect to the X server."
exit 1
fi
unset kcheckrunning_result
# Make sure that the KDE prefix is first in XDG_DATA_DIRS and that it's set at all.
# The spec allows XDG_DATA_DIRS to be not set, but X session startup scripts tend
# to set it to a list of paths *not* including the KDE prefix if it's not /usr or
@ -44,7 +31,7 @@ test -n "$KDEHOME" && kdehome=`echo "$KDEHOME"|sed "s,^~/,$HOME/,"`
kcminputrc_mouse_cursortheme=`kreadconfig --file kcminputrc --group Mouse --key cursorTheme --default Oxygen_White`
kcminputrc_mouse_cursorsize=`kreadconfig --file kcminputrc --group Mouse --key cursorSize`
# XCursor mouse theme needs to be applied here to work even for kded or ksmserver
# XCursor mouse theme needs to be applied here to work even for kded
if test -n "$kcminputrc_mouse_cursortheme" -o -n "$kcminputrc_mouse_cursorsize" ; then
@EXPORT_XCURSOR_PATH@
@ -131,24 +118,21 @@ kbuildsycoca4
# Start kcminit_startup
kcminit_startup
kcminit_result=$?
if test $? -ne 0; then
# Startup error
echo 'startkde: Could not start kcminit_startup. Check your installation.' 1>&2
xmessage -geometry 500x100 "Could not start kcminit_startup. Check your installation."
echo "startkde: Could not start kcminit_startup ($kcminit_result). Check your installation." 1>&2
xmessage -geometry 500x100 "Could not start kcminit_startup ($kcminit_result). Check your installation."
exit 1
fi
# finally, give the session control to the session manager
# see kdebase/ksmserver for the description of the rest of the startup sequence
# if the KDEWM environment variable has been set, then it will be used as KDE's
# window manager instead of kwin.
# if KDEWM is not set, ksmserver will ensure kwin is started.
test -n "$KDEWM" && KDEWM="--windowmanager $KDEWM"
ksmserver $KDEWM
if test $? -ne 0; then
# finally, give the session control to plasma-desktop
plasma-desktop
plasma_result=$?
if test $plasma_result -ne 0; then
# Startup error
echo 'startkde: Could not start ksmserver. Check your installation.' 1>&2
xmessage -geometry 500x100 "Could not start ksmserver. Check your installation."
echo "startkde: Could not start plasma-desktop ($plasma_result). Check your installation." 1>&2
xmessage -geometry 500x100 "Could not start plasma-desktop ($plasma_result). Check your installation."
fi
echo 'startkde: Shutting down...' 1>&2