parent
0f38bdced0
commit
33ff53ca29
11 changed files with 548 additions and 345 deletions
@ -1,9 +0,0 @@ |
||||
set(kcheckrunning_SRCS |
||||
kcheckrunning.cpp) |
||||
|
||||
add_executable( kcheckrunning ${kcheckrunning_SRCS}) |
||||
|
||||
target_link_libraries(kcheckrunning ${X11_LIBRARIES}) |
||||
target_include_directories(kcheckrunning PRIVATE ${X11_X11_INCLUDE_PATH}) |
||||
|
||||
install(TARGETS kcheckrunning ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) |
||||
@ -0,0 +1,31 @@ |
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2019 Aleix Pol Gonzalez <aleixpol@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. |
||||
*/ |
||||
|
||||
#ifndef KCHECKRUNNING_H |
||||
#define KCHECKRUNNING_H |
||||
|
||||
enum CheckRunningState { |
||||
PlasmaRunning, |
||||
NoPlasmaRunning, |
||||
NoX11 |
||||
}; |
||||
|
||||
CheckRunningState kCheckRunning(); |
||||
|
||||
#endif |
||||
@ -0,0 +1,31 @@ |
||||
/****************************************************************************
|
||||
|
||||
Copyright (C) 2019 Aleix Pol Gonzalez <aleixpol@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 OR COPYRIGHT HOLDERS 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 KSTARTUPCONFIG_H |
||||
#define KSTARTUPCONFIG_H |
||||
|
||||
/// returns 0 if successful
|
||||
int kStartupConfig(); |
||||
|
||||
#endif |
||||
@ -0,0 +1,6 @@ |
||||
for i in $@ |
||||
do |
||||
. $i >/dev/null |
||||
done |
||||
|
||||
env |
||||
@ -1,310 +0,0 @@ |
||||
#!/bin/sh |
||||
# |
||||
# DEFAULT Plasma STARTUP SCRIPT ( @PROJECT_VERSION@ ) |
||||
# |
||||
|
||||
# When the X server dies we get a HUP signal from xinit. We must ignore it |
||||
# because we still need to do some cleanup. |
||||
trap 'echo GOT SIGHUP' HUP |
||||
|
||||
# Check if a Plasma session already is running and whether it's possible to connect to X |
||||
kcheckrunning |
||||
kcheckrunning_result=$? |
||||
if test $kcheckrunning_result -eq 0 ; then |
||||
echo "Plasma seems to be already running on this display." |
||||
xmessage -geometry 500x100 "Plasma 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 |
||||
|
||||
# Boot sequence: |
||||
# |
||||
# kdeinit is used to fork off processes which improves memory usage |
||||
# and startup time. |
||||
# |
||||
# * kdeinit starts klauncher first. |
||||
# * Then kded is started. kded is responsible for keeping the sycoca |
||||
# database up to date. When an up to date database is present it goes |
||||
# into the background and the startup continues. |
||||
# * Then kdeinit starts kcminit. kcminit performs initialisation of |
||||
# certain devices according to the user's settings |
||||
# |
||||
# * Then ksmserver is started which takes control of the rest of the startup sequence |
||||
|
||||
if [ ${XDG_CONFIG_HOME} ]; then |
||||
configDir=$XDG_CONFIG_HOME; |
||||
else |
||||
configDir=${HOME}/.config; #this is the default, http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
||||
fi |
||||
sysConfigDirs=${XDG_CONFIG_DIRS:-/etc/xdg} |
||||
|
||||
# We need to create config folder so we can write startupconfigkeys |
||||
mkdir -p $configDir |
||||
|
||||
#This is basically setting defaults so we can use them with kstartupconfig5 |
||||
cat >$configDir/startupconfigkeys <<EOF |
||||
kcminputrc Mouse cursorTheme 'breeze_cursors' |
||||
kcminputrc Mouse cursorSize '' |
||||
ksplashrc KSplash Theme Breeze |
||||
ksplashrc KSplash Engine KSplashQML |
||||
kdeglobals KScreen ScaleFactor '' |
||||
kdeglobals KScreen ScreenScaleFactors '' |
||||
kcmfonts General forceFontDPI 0 |
||||
EOF |
||||
|
||||
# preload the user's locale on first start |
||||
plasmalocalerc=$configDir/plasma-localerc |
||||
test -f $plasmalocalerc || { |
||||
cat >$plasmalocalerc <<EOF |
||||
[Formats] |
||||
LANG=$LANG |
||||
EOF |
||||
} |
||||
|
||||
# export LC_* variables set by kcmshell5 formats into environment |
||||
# so it can be picked up by QLocale and friends. |
||||
exportformatssettings=$configDir/plasma-locale-settings.sh |
||||
test -f $exportformatssettings && { |
||||
. $exportformatssettings |
||||
} |
||||
|
||||
kstartupconfig5 |
||||
returncode=$? |
||||
if test $returncode -ne 0; then |
||||
xmessage -geometry 500x100 "kstartupconfig5 does not exist or fails. The error code is $returncode. Check your installation." |
||||
exit 1 |
||||
fi |
||||
[ -r $configDir/startupconfig ] && . $configDir/startupconfig |
||||
|
||||
|
||||
#Do not sync any of this section with the wayland versions as there scale factors are |
||||
#sent properly over wl_output |
||||
|
||||
if [ "$kdeglobals_kscreen_screenscalefactors" ]; then |
||||
export QT_SCREEN_SCALE_FACTORS="$kdeglobals_kscreen_screenscalefactors" |
||||
if [ "$kdeglobals_kscreen_scalefactor" -eq "2" ] || [ "$kdeglobals_kscreen_scalefactor" -eq "3" ]; then |
||||
export GDK_SCALE=$kdeglobals_kscreen_scalefactor |
||||
export GDK_DPI_SCALE=`awk "BEGIN {print 1/$kdeglobals_kscreen_scalefactor}"` |
||||
fi |
||||
fi |
||||
#Manually disable auto scaling because we are scaling above |
||||
#otherwise apps that manually opt in for high DPI get auto scaled by the developer AND manually scaled by us |
||||
export QT_AUTO_SCREEN_SCALE_FACTOR=0 |
||||
|
||||
# XCursor mouse theme needs to be applied here to work even for kded or ksmserver |
||||
if test -n "$kcminputrc_mouse_cursortheme" -o -n "$kcminputrc_mouse_cursorsize" ; then |
||||
@EXPORT_XCURSOR_PATH@ |
||||
|
||||
kapplymousetheme "$kcminputrc_mouse_cursortheme" "$kcminputrc_mouse_cursorsize" |
||||
if test $? -eq 10; then |
||||
XCURSOR_THEME=breeze_cursors |
||||
export XCURSOR_THEME |
||||
elif test -n "$kcminputrc_mouse_cursortheme"; then |
||||
XCURSOR_THEME="$kcminputrc_mouse_cursortheme" |
||||
export XCURSOR_THEME |
||||
fi |
||||
if test -n "$kcminputrc_mouse_cursorsize"; then |
||||
XCURSOR_SIZE="$kcminputrc_mouse_cursorsize" |
||||
export XCURSOR_SIZE |
||||
fi |
||||
fi |
||||
|
||||
if test "$kcmfonts_general_forcefontdpi" -ne 0; then |
||||
xrdb -quiet -merge -nocpp <<EOF |
||||
Xft.dpi: $kcmfonts_general_forcefontdpi |
||||
EOF |
||||
fi |
||||
|
||||
dl=$DESKTOP_LOCKED |
||||
unset DESKTOP_LOCKED # Don't want it in the environment |
||||
|
||||
ksplash_pid= |
||||
if test -z "$dl"; then |
||||
# the splashscreen and progress indicator |
||||
case "$ksplashrc_ksplash_engine" in |
||||
KSplashQML) |
||||
ksplash_pid=`ksplashqml "${ksplashrc_ksplash_theme}" --pid` |
||||
;; |
||||
None) |
||||
;; |
||||
*) |
||||
;; |
||||
esac |
||||
fi |
||||
|
||||
# Source scripts found in <config locations>/plasma-workspace/env/*.sh |
||||
# (where <config locations> correspond to the system and user's configuration |
||||
# directory. |
||||
# |
||||
# This is where you can define environment variables that will be available to |
||||
# all KDE programs, so this is where you can run agents using e.g. eval `ssh-agent` |
||||
# or eval `gpg-agent --daemon`. |
||||
# Note: if you do that, you should also put "ssh-agent -k" as a shutdown script |
||||
# |
||||
# (see end of this file). |
||||
# For anything else (that doesn't set env vars, or that needs a window manager), |
||||
# better use the Autostart folder. |
||||
|
||||
scriptpath=`echo "$configDir:$sysConfigDirs" | tr ':' '\n'` |
||||
|
||||
for prefix in `echo $scriptpath`; do |
||||
for file in "$prefix"/plasma-workspace/env/*.sh; do |
||||
test -r "$file" && . "$file" || true |
||||
done |
||||
done |
||||
|
||||
# Set a left cursor instead of the standard X11 "X" cursor, since I've heard |
||||
# from some users that they're confused and don't know what to do. This is |
||||
# especially necessary on slow machines, where starting KDE takes one or two |
||||
# minutes until anything appears on the screen. |
||||
# |
||||
# If the user has overwritten fonts, the cursor font may be different now |
||||
# so don't move this up. |
||||
# |
||||
xsetroot -cursor_name left_ptr |
||||
|
||||
# Get Ghostscript to look into user's KDE fonts dir for additional Fontmap |
||||
usr_fdir=$HOME/.fonts |
||||
if test -n "$GS_LIB" ; then |
||||
GS_LIB=$usr_fdir:$GS_LIB |
||||
export GS_LIB |
||||
else |
||||
GS_LIB=$usr_fdir |
||||
export GS_LIB |
||||
fi |
||||
|
||||
echo 'startkde: Starting up...' 1>&2 |
||||
|
||||
# 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 |
||||
# /usr/local. |
||||
if test -z "$XDG_DATA_DIRS"; then |
||||
XDG_DATA_DIRS="@KDE_INSTALL_FULL_DATAROOTDIR@:/usr/share:/usr/local/share" |
||||
fi |
||||
export XDG_DATA_DIRS |
||||
|
||||
# Mark that full KDE session is running (e.g. Konqueror preloading works only |
||||
# with full KDE running). The KDE_FULL_SESSION property can be detected by |
||||
# any X client connected to the same X session, even if not launched |
||||
# directly from the KDE session but e.g. using "ssh -X", kdesu. $KDE_FULL_SESSION |
||||
# however guarantees that the application is launched in the same environment |
||||
# like the KDE session and that e.g. KDE utilities/libraries are available. |
||||
# KDE_FULL_SESSION property is also only available since KDE 3.5.5. |
||||
# The matching tests are: |
||||
# For $KDE_FULL_SESSION: |
||||
# if test -n "$KDE_FULL_SESSION"; then ... whatever |
||||
# For KDE_FULL_SESSION property: |
||||
# xprop -root | grep "^KDE_FULL_SESSION" >/dev/null 2>/dev/null |
||||
# if test $? -eq 0; then ... whatever |
||||
# |
||||
# Additionally there is (since KDE 3.5.7) $KDE_SESSION_UID with the uid |
||||
# of the user running the KDE session. It should be rarely needed (e.g. |
||||
# after sudo to prevent desktop-wide functionality in the new user's kded). |
||||
# |
||||
# Since KDE4 there is also KDE_SESSION_VERSION, containing the major version number. |
||||
# Note that this didn't exist in KDE3, which can be detected by its absense and |
||||
# the presence of KDE_FULL_SESSION. |
||||
# |
||||
KDE_FULL_SESSION=true |
||||
export KDE_FULL_SESSION |
||||
xprop -root -f KDE_FULL_SESSION 8t -set KDE_FULL_SESSION true |
||||
|
||||
KDE_SESSION_VERSION=5 |
||||
export KDE_SESSION_VERSION |
||||
xprop -root -f KDE_SESSION_VERSION 32c -set KDE_SESSION_VERSION 5 |
||||
|
||||
KDE_SESSION_UID=`id -ru` |
||||
export KDE_SESSION_UID |
||||
|
||||
XDG_CURRENT_DESKTOP=KDE |
||||
export XDG_CURRENT_DESKTOP |
||||
|
||||
# At this point all environment variables are set, let's send it to the DBus session server to update the activation environment |
||||
if which dbus-update-activation-environment >/dev/null 2>/dev/null ; then |
||||
dbus-update-activation-environment --systemd --all |
||||
else |
||||
@CMAKE_INSTALL_FULL_LIBEXECDIR@/ksyncdbusenv |
||||
fi |
||||
if test $? -ne 0; then |
||||
# Startup error |
||||
echo 'startkde: Could not sync environment to dbus.' 1>&2 |
||||
test -n "$ksplash_pid" && kill "$ksplash_pid" 2>/dev/null |
||||
xmessage -geometry 500x100 "Could not sync environment to dbus." |
||||
exit 1 |
||||
fi |
||||
|
||||
# We set LD_BIND_NOW to increase the efficiency of kdeinit. |
||||
# kdeinit unsets this variable before loading applications. |
||||
LD_BIND_NOW=true @CMAKE_INSTALL_FULL_LIBEXECDIR_KF5@/start_kdeinit_wrapper --kded +kcminit_startup |
||||
if test $? -ne 0; then |
||||
# Startup error |
||||
echo 'startkde: Could not start kdeinit5. Check your installation.' 1>&2 |
||||
test -n "$ksplash_pid" && kill "$ksplash_pid" 2>/dev/null |
||||
xmessage -geometry 500x100 "Could not start kdeinit5. Check your installation." |
||||
exit 1 |
||||
fi |
||||
|
||||
qdbus org.kde.KSplash /KSplash org.kde.KSplash.setStage kinit & |
||||
|
||||
# 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. |
||||
# kwrapper5 is used to reduce startup time and memory usage |
||||
# kwrapper5 does not return useful error codes such as the exit code of ksmserver. |
||||
# We only check for 255 which means that the ksmserver process could not be |
||||
# started, any problems thereafter, e.g. ksmserver failing to initialize, |
||||
# will remain undetected. |
||||
test -n "$KDEWM" && KDEWM="--windowmanager $KDEWM" |
||||
# If the session should be locked from the start (locked autologin), |
||||
# lock now and do the rest of the KDE startup underneath the locker. |
||||
KSMSERVEROPTIONS="" |
||||
test -n "$dl" && KSMSERVEROPTIONS=" --lockscreen" |
||||
kwrapper5 @CMAKE_INSTALL_FULL_BINDIR@/ksmserver $KDEWM $KSMSERVEROPTIONS |
||||
if test $? -eq 255; then |
||||
# Startup error |
||||
echo 'startkde: Could not start ksmserver. Check your installation.' 1>&2 |
||||
test -n "$ksplash_pid" && kill "$ksplash_pid" 2>/dev/null |
||||
xmessage -geometry 500x100 "Could not start ksmserver. Check your installation." |
||||
fi |
||||
|
||||
#Anything after here is logout |
||||
#It is not called after shutdown/restart |
||||
|
||||
wait_drkonqi=`kreadconfig5 --file startkderc --group WaitForDrKonqi --key Enabled --default true` |
||||
|
||||
if test x"$wait_drkonqi"x = x"true"x ; then |
||||
# wait for remaining drkonqi instances with timeout (in seconds) |
||||
wait_drkonqi_timeout=`kreadconfig5 --file startkderc --group WaitForDrKonqi --key Timeout --default 900` |
||||
wait_drkonqi_counter=0 |
||||
while qdbus | grep "^[^w]*org.kde.drkonqi" > /dev/null ; do |
||||
sleep 5 |
||||
wait_drkonqi_counter=$((wait_drkonqi_counter+5)) |
||||
if test "$wait_drkonqi_counter" -ge "$wait_drkonqi_timeout" ; then |
||||
# ask remaining drkonqis to die in a graceful way |
||||
qdbus | grep 'org.kde.drkonqi-' | while read address ; do |
||||
qdbus "$address" "/MainApplication" "quit" |
||||
done |
||||
break |
||||
fi |
||||
done |
||||
fi |
||||
|
||||
echo 'startkde: Shutting down...' 1>&2 |
||||
# just in case |
||||
test -n "$ksplash_pid" && kill "$ksplash_pid" 2>/dev/null |
||||
|
||||
# Clean up |
||||
kdeinit5_shutdown |
||||
|
||||
unset KDE_FULL_SESSION |
||||
xprop -root -remove KDE_FULL_SESSION |
||||
unset KDE_SESSION_VERSION |
||||
xprop -root -remove KDE_SESSION_VERSION |
||||
unset KDE_SESSION_UID |
||||
|
||||
echo 'startkde: Done.' 1>&2 |
||||
@ -0,0 +1,440 @@ |
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2019 Aleix Pol Gonzalez <aleixpol@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 "kcheckrunning/kcheckrunning.h" |
||||
#include "kstartupconfig/kstartupconfig.h" |
||||
#include <ksplashinterface.h> |
||||
|
||||
#include <QDir> |
||||
#include <QProcess> |
||||
#include <QStandardPaths> |
||||
#include <QTextStream> |
||||
#include <KSharedConfig> |
||||
#include <KConfigGroup> |
||||
|
||||
#include <signal.h> |
||||
#include <unistd.h> |
||||
|
||||
QTextStream out(stderr); |
||||
|
||||
QStringList allServices(const QLatin1String& prefix) |
||||
{ |
||||
QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface(); |
||||
const QStringList services = bus->registeredServiceNames(); |
||||
QMap<QString, QStringList> servicesWithAliases; |
||||
|
||||
for (const QString &serviceName : services) { |
||||
QDBusReply<QString> reply = bus->serviceOwner(serviceName); |
||||
QString owner = reply; |
||||
if (owner.isEmpty()) |
||||
owner = serviceName; |
||||
servicesWithAliases[owner].append(serviceName); |
||||
} |
||||
|
||||
QStringList names; |
||||
for (auto it = servicesWithAliases.constBegin(); it != servicesWithAliases.constEnd(); ++it) { |
||||
if (it.value().startsWith(prefix)) |
||||
names << it.value(); |
||||
} |
||||
names.removeDuplicates(); |
||||
names.sort(); |
||||
return names; |
||||
} |
||||
|
||||
int runSync(const QString& program, const QStringList &args, const QStringList &env = {}) |
||||
{ |
||||
QProcess p; |
||||
p.setEnvironment(env); |
||||
p.start(program, args); |
||||
p.setProcessChannelMode(QProcess::ForwardedChannels); |
||||
p.waitForFinished(); |
||||
return p.exitCode(); |
||||
} |
||||
|
||||
void messageBox(const QString &text) |
||||
{ |
||||
out << text; |
||||
runSync("xmessage", {"-geometry" "500x100", text}); |
||||
} |
||||
|
||||
void writeFile(const QString& path, const QByteArray& contents) |
||||
{ |
||||
QFile f(path); |
||||
if (!f.open(QIODevice::WriteOnly)) { |
||||
out << "Could not write into " << f.fileName() <<".\n"; |
||||
exit(1); |
||||
} |
||||
f.write(contents); |
||||
} |
||||
|
||||
void sourceFiles(const QStringList &files) |
||||
{ |
||||
QStringList filteredFiles; |
||||
std::copy_if(files.begin(), files.end(), std::back_inserter(filteredFiles), [](const QString& i){ return QFileInfo(i).isReadable(); } ); |
||||
|
||||
if (filteredFiles.isEmpty()) |
||||
return; |
||||
|
||||
const QStringList args = QStringList(CMAKE_INSTALL_FULL_LIBEXECDIR "/plasma-sourceenv.sh") << filteredFiles; |
||||
|
||||
QProcess p; |
||||
p.start("/bin/sh", args); |
||||
p.waitForFinished(); |
||||
|
||||
const auto fullEnv = p.readAllStandardOutput(); |
||||
auto envs = fullEnv.split('\n'); |
||||
for (auto &env: envs) { |
||||
putenv(env.data()); |
||||
} |
||||
} |
||||
|
||||
void sighupHandler(int) |
||||
{ |
||||
out << "GOT SIGHUP\n"; |
||||
} |
||||
|
||||
int main(int /*argc*/, char** /*argv*/) |
||||
{ |
||||
// When the X server dies we get a HUP signal from xinit. We must ignore it
|
||||
// because we still need to do some cleanup.
|
||||
signal(SIGHUP, sighupHandler); |
||||
|
||||
// Boot sequence:
|
||||
//
|
||||
// kdeinit is used to fork off processes which improves memory usage
|
||||
// and startup time.
|
||||
//
|
||||
// * kdeinit starts klauncher first.
|
||||
// * Then kded is started. kded is responsible for keeping the sycoca
|
||||
// database up to date. When an up to date database is present it goes
|
||||
// into the background and the startup continues.
|
||||
// * Then kdeinit starts kcminit. kcminit performs initialisation of
|
||||
// certain devices according to the user's settings
|
||||
//
|
||||
// * Then ksmserver is started which takes control of the rest of the startup sequence
|
||||
|
||||
// Check if a Plasma session already is running and whether it's possible to connect to X
|
||||
switch (kCheckRunning()) { |
||||
case NoX11: |
||||
out << "$DISPLAY is not set or cannot connect to the X server.\n"; |
||||
return 1; |
||||
case PlasmaRunning: |
||||
messageBox("Plasma seems to be already running on this display.\n"); |
||||
return 1; |
||||
case NoPlasmaRunning: |
||||
break; |
||||
} |
||||
|
||||
const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); |
||||
if (!QDir().mkpath(configDir)) |
||||
out << "Could not create config directory XDG_CONFIG_HOME: " << configDir << '\n'; |
||||
|
||||
//This is basically setting defaults so we can use them with kStartupConfig()
|
||||
//TODO: see into passing them as an argument
|
||||
writeFile(configDir + "/startupconfigkeys", |
||||
"kcminputrc Mouse cursorTheme 'breeze_cursors'\n" |
||||
"kcminputrc Mouse cursorSize ''\n" |
||||
"ksplashrc KSplash Theme Breeze\n" |
||||
"ksplashrc KSplash Engine KSplashQML\n" |
||||
"kdeglobals KScreen ScaleFactor ''\n" |
||||
"kdeglobals KScreen ScreenScaleFactors ''\n" |
||||
"kcmfonts General forceFontDPI 0\n" |
||||
); |
||||
|
||||
//preload the user's locale on first start
|
||||
const QString localeFile = configDir + "/plasma-localerc"; |
||||
if (!QFile::exists(localeFile)) { |
||||
writeFile(localeFile, |
||||
QByteArray("[Formats]\n" |
||||
"LANG=" +qgetenv("LANG")+ "\n")); |
||||
} |
||||
|
||||
if (int code = kStartupConfig()) { |
||||
messageBox("kStartupConfig() does not exist or fails. The error code is " + QByteArray::number(code) + ". Check your installation.\n"); |
||||
return 1; |
||||
} |
||||
|
||||
//export LC_* variables set by kcmshell5 formats into environment
|
||||
//so it can be picked up by QLocale and friends.
|
||||
sourceFiles({configDir + "/startupconfig", configDir + "/plasma-locale-settings.sh"}); |
||||
|
||||
#if !defined(WAYLAND) |
||||
//Do not sync any of this section with the wayland versions as there scale factors are
|
||||
//sent properly over wl_output
|
||||
|
||||
{ |
||||
const auto screenScaleFactors = qgetenv("kdeglobals_kscreen_screenscalefactors"); |
||||
if (!screenScaleFactors.isEmpty()) { |
||||
qputenv("QT_SCREEN_SCALE_FACTORS", screenScaleFactors); |
||||
if (screenScaleFactors == "2" || screenScaleFactors == "3") { |
||||
qputenv("GDK_SCALE", screenScaleFactors); |
||||
qputenv("GDK_DPI_SCALE", QByteArray::number(1/screenScaleFactors.toInt(), 'g', 3)); |
||||
} |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
//Manually disable auto scaling because we are scaling above
|
||||
//otherwise apps that manually opt in for high DPI get auto scaled by the developer AND manually scaled by us
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0"); |
||||
|
||||
//XCursor mouse theme needs to be applied here to work even for kded or ksmserver
|
||||
{ |
||||
const auto kcminputrc_mouse_cursorsize = qgetenv("kcminputrc_mouse_cursorsize"); |
||||
const auto kcminputrc_mouse_cursortheme = qgetenv("kcminputrc_mouse_cursortheme"); |
||||
if (!kcminputrc_mouse_cursortheme.isEmpty() || !kcminputrc_mouse_cursorsize.isEmpty()) { |
||||
#ifdef XCURSOR_PATH |
||||
QByteArray path(XCURSOR_PATH); |
||||
path.replace("$XCURSOR_PATH", qgetenv("XCURSOR_PATH")); |
||||
qputenv("XCURSOR_PATH", path); |
||||
#endif |
||||
|
||||
//TODO: consider linking directly
|
||||
if (runSync("kapplymousetheme", { "kcminputrc_mouse_cursortheme", "kcminputrc_mouse_cursorsize" }) == 10) { |
||||
qputenv("XCURSOR_THEME", "breeze_cursors"); |
||||
} else if (!kcminputrc_mouse_cursortheme.isEmpty()) { |
||||
qputenv("XCURSOR_THEME", kcminputrc_mouse_cursortheme); |
||||
} |
||||
if (!kcminputrc_mouse_cursorsize.isEmpty()) { |
||||
qputenv("XCURSOR_SIZE", kcminputrc_mouse_cursorsize); |
||||
} |
||||
} |
||||
} |
||||
|
||||
{ |
||||
const auto kcmfonts_general_forcefontdpi = qgetenv("kcmfonts_general_forcefontdpi"); |
||||
if (kcmfonts_general_forcefontdpi != "0") { |
||||
const QByteArray input = "Xft.dpi: kcmfonts_general_forcefontdpi"; |
||||
runSync("xrdb", { "-quiet", "-merge", "-nocpp" }); |
||||
} |
||||
} |
||||
|
||||
QScopedPointer<QProcess> ksplash; |
||||
const int dl = qEnvironmentVariableIntValue("DESKTOP_LOCKED"); |
||||
{ |
||||
qunsetenv("DESKTOP_LOCKED"); // Don't want it in the environment
|
||||
|
||||
if (dl) { |
||||
const auto ksplashrc_ksplash_engine = qgetenv("ksplashrc_ksplash_engine"); |
||||
// the splashscreen and progress indicator
|
||||
if (ksplashrc_ksplash_engine == "KSplashQML") { |
||||
ksplash.reset(new QProcess()); |
||||
ksplash->start("ksplashqml", {QString::fromUtf8(qgetenv("ksplashrc_ksplash_theme"))}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
// Source scripts found in <config locations>/plasma-workspace/env/*.sh
|
||||
// (where <config locations> correspond to the system and user's configuration
|
||||
// directory.
|
||||
//
|
||||
// This is where you can define environment variables that will be available to
|
||||
// all KDE programs, so this is where you can run agents using e.g. eval `ssh-agent`
|
||||
// or eval `gpg-agent --daemon`.
|
||||
// Note: if you do that, you should also put "ssh-agent -k" as a shutdown script
|
||||
//
|
||||
// (see end of this file).
|
||||
// For anything else (that doesn't set env vars, or that needs a window manager),
|
||||
// better use the Autostart folder.
|
||||
|
||||
{ |
||||
QStringList scripts; |
||||
const auto locations = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QStringLiteral("plasma-workspace/env"), QStandardPaths::LocateDirectory); |
||||
for (const QString & location : locations) { |
||||
QDir dir(location); |
||||
const auto dirScripts = dir.entryInfoList({QStringLiteral("*.sh")}); |
||||
for (const auto script : dirScripts) { |
||||
scripts << script.absoluteFilePath(); |
||||
} |
||||
} |
||||
sourceFiles(scripts); |
||||
} |
||||
|
||||
// Set a left cursor instead of the standard X11 "X" cursor, since I've heard
|
||||
// from some users that they're confused and don't know what to do. This is
|
||||
// especially necessary on slow machines, where starting KDE takes one or two
|
||||
// minutes until anything appears on the screen.
|
||||
//
|
||||
// If the user has overwritten fonts, the cursor font may be different now
|
||||
// so don't move this up.
|
||||
|
||||
runSync("xsetroot", {"-cursor_name", "left_ptr"}); |
||||
|
||||
// Get Ghostscript to look into user's KDE fonts dir for additional Fontmap
|
||||
{ |
||||
const QByteArray usr_fdir = QFile::encodeName(QDir::home().absoluteFilePath(".fonts")); |
||||
if (qEnvironmentVariableIsSet("GS_LIB")) { |
||||
qputenv("GS_LIB", usr_fdir + ':' + qgetenv("GS_LIB")); |
||||
} else { |
||||
qputenv("GS_LIB", usr_fdir); |
||||
} |
||||
} |
||||
|
||||
out << "startkde: Starting up...\n"; |
||||
|
||||
// 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
|
||||
// /usr/local.
|
||||
if (!qEnvironmentVariableIsSet("XDG_DATA_DIRS")) { |
||||
qputenv("XDG_DATA_DIRS", KDE_INSTALL_FULL_DATAROOTDIR ":/usr/share:/usr/local/share"); |
||||
} |
||||
|
||||
// Mark that full KDE session is running (e.g. Konqueror preloading works only
|
||||
// with full KDE running). The KDE_FULL_SESSION property can be detected by
|
||||
// any X client connected to the same X session, even if not launched
|
||||
// directly from the KDE session but e.g. using "ssh -X", kdesu. $KDE_FULL_SESSION
|
||||
// however guarantees that the application is launched in the same environment
|
||||
// like the KDE session and that e.g. KDE utilities/libraries are available.
|
||||
// KDE_FULL_SESSION property is also only available since KDE 3.5.5.
|
||||
// The matching tests are:
|
||||
// For $KDE_FULL_SESSION:
|
||||
// if test -n "$KDE_FULL_SESSION"; then ... whatever
|
||||
// For KDE_FULL_SESSION property:
|
||||
// xprop -root | grep "^KDE_FULL_SESSION" >/dev/null 2>/dev/null
|
||||
// if test $? -eq 0; then ... whatever
|
||||
//
|
||||
// Additionally there is (since KDE 3.5.7) $KDE_SESSION_UID with the uid
|
||||
// of the user running the KDE session. It should be rarely needed (e.g.
|
||||
// after sudo to prevent desktop-wide functionality in the new user's kded).
|
||||
//
|
||||
// Since KDE4 there is also KDE_SESSION_VERSION, containing the major version number.
|
||||
// Note that this didn't exist in KDE3, which can be detected by its absense and
|
||||
// the presence of KDE_FULL_SESSION.
|
||||
|
||||
qputenv("KDE_FULL_SESSION", "true"); |
||||
runSync("xprop", {"-root", "-f", "KDE_FULL_SESSION", "8t", "-set", "KDE_FULL_SESSION", "true"}); |
||||
|
||||
qputenv("KDE_SESSION_VERSION", "5"); |
||||
runSync("xprop", {"-root", "-f", "KDE_SESSION_VERSION", "32c", "-set", "KDE_SESSION_VERSION", "5"}); |
||||
|
||||
qputenv("KDE_SESSION_UID", QByteArray::number(getuid())); |
||||
qputenv("XDG_CURRENT_DESKTOP", "KDE"); |
||||
|
||||
{ |
||||
int exitCode; |
||||
// At this point all environment variables are set, let's send it to the DBus session server to update the activation environment
|
||||
if (!QStandardPaths::findExecutable("dbus-update-activation-environment").isEmpty()) |
||||
exitCode = runSync("dbus-update-activation-environment", { "--systemd", "--all" }); |
||||
else |
||||
exitCode = runSync(CMAKE_INSTALL_FULL_LIBEXECDIR "/ksyncdbusenv", {}); |
||||
|
||||
if (exitCode != 0) { |
||||
// Startup error
|
||||
if (ksplash) |
||||
ksplash->kill(); |
||||
messageBox("Could not sync environment to dbus.\n"); |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
{ |
||||
// We set LD_BIND_NOW to increase the efficiency of kdeinit.
|
||||
// kdeinit unsets this variable before loading applications.
|
||||
const int exitCode = runSync(CMAKE_INSTALL_FULL_LIBEXECDIR_KF5 "/start_kdeinit_wrapper", { "--kded", "+kcminit_startup" }, { "LD_BIND_NOW=true" }); |
||||
if (exitCode != 0) { |
||||
if (ksplash) |
||||
ksplash->kill(); |
||||
messageBox("startkde: Could not start kdeinit5. Check your installation."); |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
{ |
||||
OrgKdeKSplashInterface iface("org.kde.KSplash", "/KSplash", QDBusConnection::sessionBus()); |
||||
iface.setStage("kinit"); |
||||
} |
||||
|
||||
// finally, give the session control to the session manager
|
||||
// see plasma-workspace/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.
|
||||
// kwrapper5 is used to reduce startup time and memory usage
|
||||
// kwrapper5 does not return useful error codes such as the exit code of ksmserver.
|
||||
// We only check for 255 which means that the ksmserver process could not be
|
||||
// started, any problems thereafter, e.g. ksmserver failing to initialize,
|
||||
// will remain undetected.
|
||||
// st -n "$KDEWM" && KDEWM="--windowmanager $KDEWM"
|
||||
// If the session should be locked from the start (locked autologin),
|
||||
// lock now and do the rest of the KDE startup underneath the locker.
|
||||
QStringList ksmserverOptions(CMAKE_INSTALL_FULL_BINDIR "/ksmserver"); |
||||
if (qEnvironmentVariableIsSet("KDEWM")) |
||||
ksmserverOptions << qEnvironmentVariable("KDEWM"); |
||||
|
||||
if (dl) { |
||||
ksmserverOptions << "--lockscreen"; |
||||
} |
||||
const auto exitCode = runSync("kwrapper5", ksmserverOptions); |
||||
|
||||
if (exitCode == 255) { |
||||
// Startup error
|
||||
if (ksplash) |
||||
ksplash->kill(); |
||||
messageBox("startkde: Could not start ksmserver. Check your installation.\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Anything after here is logout
|
||||
// It is not called after shutdown/restart
|
||||
|
||||
{ |
||||
const auto cfg = KSharedConfig::openConfig("startkderc"); |
||||
KConfigGroup grp(cfg, "WaitForDrKonqi"); |
||||
bool wait_drkonqi = grp.readEntry("Enabled", true); |
||||
if (wait_drkonqi) { |
||||
// wait for remaining drkonqi instances with timeout (in seconds)
|
||||
const int wait_drkonqi_timeout = grp.readEntry("Timeout", 900) * 1000; |
||||
QElapsedTimer wait_drkonqi_counter; |
||||
wait_drkonqi_counter.start(); |
||||
QStringList services = allServices(QLatin1String("org.kde.drkonqi-")); |
||||
while (!services.isEmpty()) { |
||||
sleep(5); |
||||
services = allServices(QLatin1String("org.kde.drkonqi-")); |
||||
if (wait_drkonqi_counter.elapsed() >= wait_drkonqi_timeout) { |
||||
// ask remaining drkonqis to die in a graceful way
|
||||
for (const auto &service: services) { |
||||
QDBusInterface iface(service, "/MainApplication"); |
||||
iface.call("quit"); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
out << "startkde: Shutting down...\n"; |
||||
|
||||
// just in case
|
||||
if (ksplash) |
||||
ksplash->kill(); |
||||
|
||||
runSync("kdeinit5_shutdown", {}); |
||||
|
||||
qunsetenv("KDE_FULL_SESSION"); |
||||
runSync("xprop", { "-root", "-remove", "KDE_FULL_SESSION" }); |
||||
qunsetenv("KDE_SESSION_VERSION"); |
||||
runSync("xprop", { "-root", "-remove", "KDE_SESSION_VERSION" }); |
||||
qunsetenv("KDE_SESSION_UID"); |
||||
|
||||
out << "startkde: Done.\n"; |
||||
|
||||
return 0; |
||||
} |
||||
Loading…
Reference in new issue