Commit 77e319e8 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧

Initial import from the monolithic kde-workspace.

This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
techbase wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:

http://community.kde.org/Frameworks/GitOldHistory

If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.

Branched from the monolithic repo kde-workspace, frameworks  branch, at commit
049113e719dd2fc4446d054fa1a3aada330094f0
parents
add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1223)
add_subdirectory(kcheckpass)
add_subdirectory(data)
add_subdirectory(greeter)
set(screensaver_dbusXML dbus/org.freedesktop.ScreenSaver.xml)
set(kscreensaver_dbusXML dbus/org.kde.screensaver.xml)
set(ksmserver_xml ${ksmserver_SOURCE_DIR}/org.kde.KSMServerInterface.xml)
set(powerdevilpolicyagent_xml ${SOLID_DBUS_INTERFACES_DIR}/kf5_org.kde.Solid.PowerManagement.PolicyAgent.xml)
set(ksld_SRCS
ksldapp.cpp
autologout.cpp
interface.cpp
lockwindow.cpp)
qt5_add_dbus_adaptor(ksld_SRCS ${screensaver_dbusXML} interface.h ScreenLocker::Interface)
qt5_add_dbus_adaptor(ksld_SRCS ${kscreensaver_dbusXML} interface.h ScreenLocker::Interface kscreensaveradaptor KScreenSaverAdaptor)
kconfig_add_kcfg_files(ksld_SRCS kcfg/kscreensaversettings.kcfgc)
qt5_add_dbus_interface(ksld_SRCS ${ksmserver_xml} ksmserver_interface)
qt5_add_dbus_interface(ksld_SRCS ${powerdevilpolicyagent_xml} powerdevilpolicyagent)
add_library(screenlocker_static STATIC ${ksld_SRCS})
target_link_libraries(screenlocker_static
PW::KWorkspace
Qt5::X11Extras
KF5::IdleTime
KF5::GlobalAccel
KF5::XmlGui
KF5::Crash
KF5::KDE4Support
${X11_LIBRARIES}
${X11_Xcursor_LIB}
${XCB_XCB_LIBRARY}
)
# Needed to compile on Arm target.
set_target_properties(screenlocker_static PROPERTIES COMPILE_FLAGS "-fPIC")
set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/ScreenSaverDBusInterface")
ecm_configure_package_config_file(ScreenSaverDBusInterfaceConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/ScreenSaverDBusInterfaceConfig.cmake
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR})
install(FILES kscreenlocker.notifyrc DESTINATION ${DATA_INSTALL_DIR}/ksmserver/ RENAME ksmserver.notifyrc)
install(FILES ${screensaver_dbusXML}
DESTINATION ${DBUS_INTERFACES_INSTALL_DIR}
RENAME kf5_org.freedesktop.ScreenSaver.xml)
The screenlocker is statically built into ksmserver, it gets instantiated by the main class KSldApp.
It provides 3 main things:
* Shows a fullscreen window (LockWindow class), that spawns into all screens, eats the input events and is black to hide everything.
* Provides the usual org.freedesktop.ScreenSaver interface
* starts the process that will actually show the unlock screen
Security considerations.
* greeter windows are marked with the _KDE_SCREEN_LOCKER atom, no windows of other processes can go over them
* the screen locker is managed by ksmserver: in case of crash of a greeter or an X screen saver, the global lock window that spawns between all monitors will still be there. In case of crash of ksmserver, being the session manager, the whole session will be brought down.
KSldApp may launch one of two possible unlock screen binaries, decided by the PlasmaEnable bool key in kscreensaverrc:
1) Simple
The one in the greeter subdirectory, built in the kscreenlocker_greet binary.
It uses a series of QML files organized in a Plasma Package to display the actual unlocker ui, one for each screen in case of multimonitor.
This greeter can optionally support legacy X screensavers, for doing so creates another fullscreen window per screen on top of the greeter one, and xembends a screensaver window.
The X screensaver goes away after mouse move and gets back after a minute (or user pressing esc)
2) Plasma based
The source lives in kde-workspace/plasma/screensaver/shell/ and the binary is plasma-overlay.
It instances a Plasma scene, a View and a Containment for each screen in case of multimonitor.
Uses the same QML package to display the unlocker as kscreenlocker_greet.
Does not support X screensavers.
\ No newline at end of file
#!bin/sh
$EXTRACTRC kcfg/*.kcfg >> rc.cpp
# do not include subdirectory as it has an own Messages.sh
$XGETTEXT *.h *.cpp -o $podir/kscreenlocker.pot
@PACKAGE_INIT@
set(SCREENSAVER_DBUS_INTERFACE "${PACKAGE_PREFIX_DIR}/@DBUS_INTERFACES_INSTALL_DIR@/kf5_org.freedesktop.ScreenSaver.xml")
//===========================================================================
//
// This file is part of the KDE project
//
// Copyright 2004 Chris Howells <howells@kde.org>
#include "autologout.h"
#include "lockwindow.h"
#include <kconfig.h>
#include <kmessagebox.h>
#include <KLocalizedString>
#include <kdialog.h>
#include <KIconLoader>
#include <ksmserver_interface.h>
#include <QLayout>
#include <QMessageBox>
#include <QLabel>
#include <QStyle>
#include <QApplication>
#include <QDialog>
#include <QAbstractEventDispatcher>
#include <QProgressBar>
#include <QtDBus>
#define COUNTDOWN 30
AutoLogout::AutoLogout(ScreenLocker::LockWindow *parent) : QDialog(NULL, Qt::X11BypassWindowManagerHint)
{
QLabel *pixLabel = new QLabel( this );
pixLabel->setObjectName( QLatin1String( "pixlabel" ) );
pixLabel->setPixmap(DesktopIcon(QLatin1String( "application-exit" )));
QLabel *greetLabel = new QLabel(i18n("<qt><nobr><b>Automatic Log Out</b></nobr></qt>"), this);
QLabel *infoLabel = new QLabel(i18n("<qt>To prevent being logged out, resume using this session by moving the mouse or pressing a key.</qt>"), this);
mStatusLabel = new QLabel(QLatin1String( "<b> </b>" ), this);
mStatusLabel->setAlignment(Qt::AlignCenter);
QLabel *mProgressLabel = new QLabel(i18n("Time Remaining:"), this);
mProgressRemaining = new QProgressBar(this);
mProgressRemaining->setTextVisible(false);
frameLayout = new QGridLayout(this);
frameLayout->setSpacing(KDialog::spacingHint());
frameLayout->setMargin(KDialog::marginHint() * 2);
frameLayout->addWidget(pixLabel, 0, 0, 3, 1, Qt::AlignCenter | Qt::AlignTop);
frameLayout->addWidget(greetLabel, 0, 1);
frameLayout->addWidget(mStatusLabel, 1, 1);
frameLayout->addWidget(infoLabel, 2, 1);
frameLayout->addWidget(mProgressLabel, 3, 1);
frameLayout->addWidget(mProgressRemaining, 4, 1);
// get the time remaining in seconds for the status label
mRemaining = COUNTDOWN * 25;
mProgressRemaining->setMaximum(COUNTDOWN * 25);
updateInfo(mRemaining);
mCountdownTimerId = startTimer(1000/25);
connect(parent, SIGNAL(userActivity()), SLOT(slotActivity()));
}
AutoLogout::~AutoLogout()
{
hide();
}
void AutoLogout::updateInfo(int timeout)
{
mStatusLabel->setText(i18np("<qt><nobr>You will be automatically logged out in 1 second</nobr></qt>",
"<qt><nobr>You will be automatically logged out in %1 seconds</nobr></qt>",
timeout / 25) );
mProgressRemaining->setValue(timeout);
}
void AutoLogout::timerEvent(QTimerEvent *ev)
{
if (ev->timerId() == mCountdownTimerId)
{
updateInfo(mRemaining);
--mRemaining;
if (mRemaining < 0)
{
killTimer(mCountdownTimerId);
logout();
}
}
}
void AutoLogout::slotActivity()
{
if (mRemaining >= 0)
accept();
}
void AutoLogout::logout()
{
QAbstractEventDispatcher::instance()->unregisterTimers(this);
org::kde::KSMServerInterface ksmserver(QLatin1String( "org.kde.ksmserver" ), QLatin1String( "/KSMServer" ), QDBusConnection::sessionBus());
ksmserver.logout( 0, 0, 0 );
}
void AutoLogout::setVisible(bool visible)
{
QDialog::setVisible(visible);
if (visible)
QApplication::flush();
}
#include "autologout.moc"
//===========================================================================
//
// This file is part of the KDE project
//
// Copyright 1999 Martin R. Jones <mjones@kde.org>
// Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
// Copyright 2004 Chris Howells <howells@kde.org>
#ifndef AUTOLOGOUT_H
#define AUTOLOGOUT_H
#include <QTimer>
#include <QDialog>
#include <QLayout>
namespace ScreenLocker
{
class LockWindow;
}
class LockProcess;
class QGridLayout;
class QLabel;
class QDialog;
class QProgressBar;
class AutoLogout : public QDialog
{
Q_OBJECT
public:
AutoLogout(ScreenLocker::LockWindow *parent);
~AutoLogout();
virtual void setVisible(bool visible);
protected:
virtual void timerEvent(QTimerEvent *);
private Q_SLOTS:
void slotActivity();
private:
void updateInfo(int);
QGridLayout *frameLayout;
QLabel *mStatusLabel;
int mCountdownTimerId;
int mRemaining;
QTimer countDownTimer;
QProgressBar *mProgressRemaining;
void logout();
};
#endif // AUTOLOGOUT_H
set( force_krunner_lock_shortcut_unreg_SRCS force_krunner_lock_shortcut_unreg.cpp )
add_executable( force_krunner_lock_shortcut_unreg ${force_krunner_lock_shortcut_unreg_SRCS} )
target_link_libraries( force_krunner_lock_shortcut_unreg Qt5::Core Qt5::DBus )
install( TARGETS force_krunner_lock_shortcut_unreg DESTINATION ${LIB_INSTALL_DIR}/kconf_update_bin/ )
install( FILES kscreenlocker_locksession-shortcut.upd DESTINATION ${KCONF_UPDATE_INSTALL_DIR} )
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2011 Alex Merry <kde@randomguy3.me.uk>
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
// see kscreenlocker_locksession-shortcut.upd
#include <QtDBus/QtDBus>
int main( int argc, char* argv[] )
{
QDBusInterface accelIface(QStringLiteral("org.kde.kglobalaccel"), QStringLiteral("/kglobalaccel"), QStringLiteral("org.kde.KGlobalAccel"));
QStringList krunnerShortcutId;
krunnerShortcutId << QLatin1String("krunner") << QLatin1String("Lock Session") << QString() << QString();
/*
QDBusReply<QList<int> > reply = accelIface.call("shortcut", krunnerShortcutId);
int shortcut = -1;
if (reply.isValid() && reply.value().size() == 1) {
shortcut = reply.value().at(0);
}
*/
accelIface.call(QDBus::NoBlock, QStringLiteral("unRegister"), krunnerShortcutId);
}
Id=4.9-locksession-shortcut
File=kglobalshortcutsrc
Group=krunner,kscreenlocker
Key=Lock Session
# If this update script is run from within an existing KDE session
# (if the user updates the kde-workspace package while KDE is running)
# then we need to make sure the shortcut we just stole from krunner
# isn't written back to the file at logout
Script=force_krunner_lock_shortcut_unreg
<!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.freedesktop.ScreenSaver">
<signal name="ActiveChanged">
<arg type="b"/>
</signal>
<method name="Lock">
</method>
<method name="SimulateUserActivity">
</method>
<method name="GetActive">
<arg type="b" direction="out"/>
</method>
<method name="GetActiveTime">
<arg name="seconds" type="u" direction="out"/>
</method>
<method name="GetSessionIdleTime">
<arg name="seconds" type="u" direction="out"/>
</method>
<method name="SetActive">
<arg type="b" direction="out"/>
<arg name="e" type="b" direction="in"/>
</method>
<method name="Inhibit">
<arg name="application_name" type="s" direction="in"/>
<arg name="reason_for_inhibit" type="s" direction="in"/>
<arg name="cookie" type="u" direction="out"/>
</method>
<method name="UnInhibit">
<arg name="cookie" type="u" direction="in"/>
</method>
<method name="Throttle">
<arg name="application_name" type="s" direction="in"/>
<arg name="reason_for_inhibit" type="s" direction="in"/>
<arg name="cookie" type="u" direction="out"/>
</method>
<method name="UnThrottle">
<arg name="cookie" type="u" direction="in"/>
</method>
</interface>
</node>
<!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.screensaver">
<!-- start in plasma setup mode -->
<method name="setupPlasma" />
<!-- Re-read configuration -->
<method name="configure" />
<!-- Private API. Don't use. -->
<method name="saverLockReady" />
</interface>
</node>
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${KCheckPass_SOURCE_DIR}/kcheckpass
)
set(kscreenlocker_greet_SRCS
sessions.cpp
greeterapp.cpp
screensaverwindow.cpp
main.cpp )
kconfig_add_kcfg_files(kscreenlocker_greet_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../kcfg/kscreensaversettings.kcfgc)
add_executable(kscreenlocker_greet ${kscreenlocker_greet_SRCS})
target_link_libraries(kscreenlocker_greet
PW::KWorkspace
KF5::Solid
KF5::Plasma
KF5::Service
KF5::Declarative
KF5::Crash
Qt5::Quick
Qt5::Qml
Qt5::X11Extras
${X11_LIBRARIES}
KF5::KDE4Support
)
install(TARGETS kscreenlocker_greet DESTINATION ${LIBEXEC_INSTALL_DIR})
install(DIRECTORY themes/org.kde.passworddialog DESTINATION ${DATA_INSTALL_DIR}/ksmserver/screenlocker)
#!bin/sh
$XGETTEXT `find . -name \*.cc -o -name \*.cpp -o -name \*.h` -o $podir/kscreenlocker_greet.pot
$XGETTEXT `find . -name '*.qml'` -j -L Java -o $podir/kscreenlocker_greet.pot
/********************************************************************
KSld - the KDE Screenlocker Daemon
This file is part of the KDE project.
Copyright (C) 1999 Martin R. Jones <mjones@kde.org>
Copyright (C) 2002 Luboš Luňák <l.lunak@kde.org>
Copyright (C) 2003 Oswald Buddenhagen <ossi@kde.org>
Copyright (C) 2011 Martin Gräßlin <mgraesslin@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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "greeter.h"
#include "kscreensaversettings.h"
// workspace
#include <kcheckpass-enums.h>
// KDE
#include <KDebug>
#include <KLibrary>
#include <KLocale>
#include <KPluginFactory>
#include <KPluginLoader>
#include <KStandardDirs>
#include <KLocalizedString>
// Qt
#include <QtCore/QFile>
#include <QtCore/QSocketNotifier>
#include <QtCore/QTimer>
#include <QGraphicsProxyWidget>
#include <QLineEdit>
// kscreenlocker stuff
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <QPalette>
namespace ScreenLocker
{
Greeter::Greeter(QObject *parent)
: QObject(parent)
, m_greeterWidget(new QWidget())
, m_greet(0)
, m_valid(false)
, m_pid(0)
, m_fd(0)
, m_notifier(NULL)
, m_failedLock(false)
{
m_pluginHandle.library = 0;
initialize();
m_valid = loadGreetPlugin();
if (m_valid) {
m_greet = m_pluginHandle.info->create(this, m_greeterWidget, QString(),
KGreeterPlugin::Authenticate,
KGreeterPlugin::ExUnlock);
m_greet->start();
}
}
Greeter::~Greeter()
{
if (m_pluginHandle.library) {
if (m_pluginHandle.info->done) {
m_pluginHandle.info->done();
}
m_pluginHandle.library->unload();
}
}
void Greeter::initialize()
{
KScreenSaverSettings::self()->readConfig();
m_plugins = KScreenSaverSettings::pluginsUnlock();
if (m_plugins.isEmpty()) {
m_plugins << QLatin1String( "classic" ) << QLatin1String( "generic" );
}
m_pluginOptions = KScreenSaverSettings::pluginOptions();
const QStringList dmopt =
QString::fromLatin1( ::getenv( "XDM_MANAGED" )).split(QLatin1Char(','), QString::SkipEmptyParts);
for (QStringList::ConstIterator it = dmopt.constBegin(); it != dmopt.constEnd(); ++it) {
if ((*it).startsWith(QLatin1String( "method=" ))) {
m_method = (*it).mid(7);
}
}
}
// standard greeter stuff
// private static
QVariant Greeter::getConf(void *ctx, const char *key, const QVariant &dflt)
{
Greeter *that = (Greeter *)ctx;
QString fkey = QLatin1String( key ) % QLatin1Char( '=' );
for (QStringList::ConstIterator it = that->m_pluginOptions.constBegin();
it != that->m_pluginOptions.constEnd(); ++it)
if ((*it).startsWith( fkey ))
return (*it).mid( fkey.length() );
return dflt;
}
bool Greeter::loadGreetPlugin()
{
if (m_pluginHandle.library) {
//we were locked once before, so all the plugin loading's done already
//FIXME should I be unloading the plugin on unlock instead?
return true;
}
for (QStringList::ConstIterator it = m_plugins.constBegin(); it != m_plugins.constEnd(); ++it) {
GreeterPluginHandle plugin;
KLibrary *lib = new KLibrary( (*it)[0] == QLatin1Char( '/' ) ? *it : QLatin1String( "kgreet_" ) + *it );
if (lib->fileName().isEmpty()) {
kWarning() << "GreeterPlugin " << *it << " does not exist" ;
delete lib;
continue;
}
if (!lib->load()) {
kWarning() << "Cannot load GreeterPlugin " << *it << " (" << lib->fileName() << ")" ;
delete lib;
continue;
}
plugin.library = lib;
plugin.info = (KGreeterPluginInfo *)lib->resolveFunction( "kgreeterplugin_info" );
if (!plugin.info ) {
kWarning() << "GreeterPlugin " << *it << " (" << lib->fileName() << ") is no valid greet widget plugin" ;
lib->unload();
delete lib;
continue;
}
if (plugin.info->method && !m_method.isEmpty() && m_method != QLatin1String( plugin.info->method )) {
kDebug() << "GreeterPlugin " << *it << " (" << lib->fileName() << ") serves " << plugin.info->method << ", not " << m_method;
lib->unload();
delete lib;
continue;
}
if (!plugin.info->init( m_method, getConf, this )) {
kDebug() << "GreeterPlugin " << *it << " (" << lib->fileName() << ") refuses to serve " << m_method;
lib->unload();
delete lib;
continue;
}
kDebug() << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded";
m_pluginHandle = plugin;
return true;
}
return false;
}
void Greeter::verify()
{
if (m_failedLock) {
// greeter blocked due to failed unlock attempt
return;
}
m_greet->next();
}
void Greeter::clear()
{
m_greet->clear();
}
void Greeter::failedTimer()
{
emit greeterReady();
m_greet->revive();
m_greet->start();
m_failedLock = false;
}
////// kckeckpass interface code
int Greeter::Reader(void *buf, int count)
{
int ret, rlen;
for (rlen = 0; rlen < count; ) {
dord:
ret = ::read(m_fd, (void *)((char *)buf + rlen), count - rlen);
if (ret < 0) {
if (errno == EINTR)
goto dord;
if (errno == EAGAIN)
break;
return -1;
}
if (!ret)
break;
rlen += ret;
}
return rlen;
}
bool Greeter::GRead(void *buf, int count)
{
return Reader(buf, count) == count;
}
bool Greeter::GWrite(const void *buf, int count)
{
return ::write(m_fd, buf, count) == count;
}
bool Greeter::GSendInt(int val)
{
return GWrite(&val, sizeof(val));
}