summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2017-11-14 12:39:18 +0100
committerSimon Rettberg2017-11-14 12:39:18 +0100
commit073dee6c0b93b531b9567ec44ecdc6209a841c22 (patch)
treed99b148cfc4351a4e3666b58d3e3f48078ec2461
parentImprove style a bit: Pull b-l-logo down, a bit smaller, better dropdown style (diff)
downloadslxgreeter-073dee6c0b93b531b9567ec44ecdc6209a841c22.tar.gz
slxgreeter-073dee6c0b93b531b9567ec44ecdc6209a841c22.tar.xz
slxgreeter-073dee6c0b93b531b9567ec44ecdc6209a841c22.zip
Support autologin via guest session
-rw-r--r--CMakeLists.txt28
-rw-r--r--src/global.cpp51
-rw-r--r--src/global.h72
-rw-r--r--src/loginform.cpp65
-rw-r--r--src/loginform.h11
-rw-r--r--src/main.cpp46
-rw-r--r--src/mainwindow.cpp7
-rw-r--r--src/mainwindow.h2
-rw-r--r--src/settings.h1
9 files changed, 209 insertions, 74 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8f7a2e..e33c334 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
+# Since some distro (debian) doesn't have a qt5 version of liblightdm-qt5, let's just ship it
+OPTION(USE_INCLUDED_LDMQT "Use included liblightdm-qt" OFF)
+
PROJECT(qt-lightdm-greeter)
set(CMAKE_CXX_STANDARD 11)
@@ -8,9 +11,8 @@ set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
-file(GLOB_RECURSE SRCS src/*.cpp)
-file(GLOB_RECURSE UIS src/*.ui)
-#message(STATUS "SRCS ${SRCS}")
+file(GLOB SRCS src/*.cpp)
+file(GLOB UIS src/*.ui)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Svg REQUIRED)
@@ -23,11 +25,21 @@ QT5_WRAP_UI(UI_HEADERS ${UIS})
# Some cmake versions can't understand the CMAKE_CXX_STANDARD option above?
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
-include(FindPkgConfig)
-pkg_check_modules(LIGHTDM_QT liblightdm-qt5-3)
-if (NOT LIGHTDM_QT_INCLUDE_DIRS)
- MESSAGE( FATAL_ERROR "Cannot find liblightdm-qt" )
-endif()
+IF (USE_INCLUDED_LDMQT)
+ message( FATAL_ERROR "Using included liblightdm-qt is not implemented" )
+ SET( LIGHTDM_QT_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/liblightdm-qt" )
+ SET( LIGHTDM_QT_LIBRARIES "" )
+ FILE(GLOB LQT_SRCS src/liblightdm-qt/*.cpp)
+ SET( SRCS ${SRCS} ${LQT_SRCS} )
+ # TODO
+ # pkg check modules liblightdm-gobject(-1)-dev
+ELSE()
+ include(FindPkgConfig)
+ pkg_check_modules(LIGHTDM_QT liblightdm-qt5-3)
+ if (NOT LIGHTDM_QT_INCLUDE_DIRS)
+ MESSAGE( FATAL_ERROR "Cannot find liblightdm-qt" )
+ endif()
+ENDIF()
include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
diff --git a/src/global.cpp b/src/global.cpp
new file mode 100644
index 0000000..7039bc1
--- /dev/null
+++ b/src/global.cpp
@@ -0,0 +1,51 @@
+#include "global.h"
+#include <QTimer>
+#include <QModelIndex>
+#include <QString>
+#include <QEventLoop>
+#include <QDebug>
+#include <QCoreApplication>
+
+bool Global::m_testMode = false;
+
+QLightDM::Greeter* Global::m_Greeter = nullptr;
+QLightDM::PowerInterface* Global::m_Power = nullptr;
+QLightDM::SessionsModel* Global::m_Sessions = nullptr;
+
+void Global::initGreeter()
+{
+ m_Greeter = new QLightDM::Greeter();
+ if (!m_Greeter->connectSync()) {
+ m_Greeter->deleteLater();
+ m_Greeter = nullptr;
+ }
+}
+
+bool Global::autoLoginGuest()
+{
+ GreeterCb *cb = new GreeterCb();
+ GreeterCb::connect(greeter(), SIGNAL(authenticationComplete()), cb, SLOT(authenticationComplete()));
+ GreeterCb::connect(greeter(), SIGNAL(autologinTimerExpired()), cb, SLOT(autologinTimerExpired()));
+ GreeterCb::connect(greeter(), SIGNAL(reset()), cb, SLOT(reset()));
+ qWarning() << "Trying to auth as guest";
+ greeter()->authenticateAsGuest();
+ QTimer::singleShot(3000, cb, SLOT(customTimeout()));
+ while (!cb->authComplete && !cb->authError && greeter()->inAuthentication()) {
+ QCoreApplication::instance()->processEvents(QEventLoop::AllEvents);
+ }
+ qWarning() << "Complete:" << cb->authComplete << "Error:"
+ << cb->authError << "InAuth:" << greeter()->inAuthentication() << "isAuthenticated" << greeter()->isAuthenticated();
+ if (cb->authComplete && greeter()->isAuthenticated()) {
+ cb->deleteLater();
+ return startSession();
+ }
+ cb->deleteLater();
+ return false;
+}
+
+bool Global::startSession()
+{
+ QModelIndex i = sessions()->index(0, 0);
+ QString s = m_Sessions->data(i, QLightDM::SessionsModel::KeyRole).toString();
+ return m_Greeter->startSessionSync(s);
+}
diff --git a/src/global.h b/src/global.h
new file mode 100644
index 0000000..bdfda89
--- /dev/null
+++ b/src/global.h
@@ -0,0 +1,72 @@
+#ifndef GLOBAL_H_
+#define GLOBAL_H_
+
+#include <QLightDM/Power>
+#include <QLightDM/Greeter>
+#include <QLightDM/SessionsModel>
+
+class Global {
+public:
+ static inline QLightDM::Greeter* greeter()
+ {
+ if (!m_testMode && m_Greeter == nullptr) {
+ initGreeter();
+ }
+ return m_Greeter;
+ }
+
+ static inline QLightDM::PowerInterface* power()
+ {
+ if (!m_testMode && m_Power == nullptr) {
+ m_Power = new QLightDM::PowerInterface();
+ }
+ return m_Power;
+ }
+
+ static inline QLightDM::SessionsModel* sessions()
+ {
+ if (!m_testMode && m_Sessions == nullptr) {
+ m_Sessions = new QLightDM::SessionsModel();
+ }
+ return m_Sessions;
+ }
+
+ static inline void enableTestMode()
+ {
+ m_testMode = true;
+ }
+
+ static inline bool testMode()
+ {
+ return m_testMode;
+ }
+
+ static bool autoLoginGuest();
+
+ static bool startSession();
+
+private:
+ static bool m_testMode;
+ static QLightDM::Greeter *m_Greeter;
+ static QLightDM::PowerInterface *m_Power;
+ static QLightDM::SessionsModel *m_Sessions;
+
+ static void initGreeter();
+
+ Global() {};
+};
+
+class GreeterCb : public QObject
+{
+ Q_OBJECT
+public slots:
+ void authenticationComplete() { authComplete = true; }
+ void autologinTimerExpired() { authError = true; }
+ void reset() { authError = true; }
+ void customTimeout() { authError = true; }
+public:
+ GreeterCb() : authComplete(false), authError(false) {}
+ bool authComplete, authError;
+};
+
+#endif /* GLOBAL_H_ */
diff --git a/src/loginform.cpp b/src/loginform.cpp
index 2fb09df..c070f92 100644
--- a/src/loginform.cpp
+++ b/src/loginform.cpp
@@ -19,26 +19,13 @@
#include "loginform.h"
#include "ui_loginform.h"
#include "settings.h"
+#include "global.h"
-LoginForm::LoginForm(bool testMode, QWidget *parent) :
+LoginForm::LoginForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::LoginForm),
- m_Greeter(nullptr),
- power(nullptr),
- sessionsModel(nullptr),
clearMsg(false)
{
- if (!testMode) {
- m_Greeter = new QLightDM::Greeter(this);
- power = new QLightDM::PowerInterface(this);
- sessionsModel = new QLightDM::SessionsModel(this);
- }
-
- if (m_Greeter != nullptr && !m_Greeter->connectSync()) {
- exit(0);
- return;
- }
-
ui->setupUi(this);
initialize();
}
@@ -64,9 +51,7 @@ void LoginForm::initialize()
QPixmap icon(":/resources/bwlp.svg"); // This project came from Razor-qt
ui->iconLabel->setPixmap(icon.scaled(ui->iconLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
- ui->leaveComboBox->setView(new QListView());
- //addLeaveEntry(power->canHibernate(), "system-suspend-hibernate", tr("Hibernate"), "hibernate");
- //addLeaveEntry(power->canSuspend(), "system-suspend", tr("Suspend"), "suspend");
+ ui->leaveComboBox->setView(new QListView()); // This is required to get the stylesheet to apply
cancelLoginTimer.setInterval(10000);
cancelLoginTimer.setSingleShot(true);
@@ -76,17 +61,16 @@ void LoginForm::initialize()
hideMessageTimer.setSingleShot(true);
connect(&hideMessageTimer, SIGNAL(timeout()), this, SLOT(hideMessage()));
- if (m_Greeter != nullptr) {
- ui->hostnameLabel->setText(m_Greeter->hostname());
+ if (!Global::testMode()) {
+ ui->hostnameLabel->setText(Global::greeter()->hostname());
- addLeaveEntry(power->canShutdown(), "system-shutdown", tr("Shutdown"), "shutdown");
- addLeaveEntry(power->canRestart(), "system-reboot", tr("Restart"), "restart");
+ addLeaveEntry(Global::power()->canShutdown(), "system-shutdown", tr("Shutdown"), "shutdown");
+ addLeaveEntry(Global::power()->canRestart(), "system-reboot", tr("Restart"), "restart");
- //connect(ui->userInput, SIGNAL(editingFinished()), this, SLOT(userChanged()));
connect(ui->leaveComboBox, SIGNAL(activated(int)), this, SLOT(leaveDropDownActivated(int)));
- connect(m_Greeter, SIGNAL(showPrompt(QString, QLightDM::Greeter::PromptType)), this, SLOT(onPrompt(QString, QLightDM::Greeter::PromptType)));
- connect(m_Greeter, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)), this, SLOT(onMessage(QString, QLightDM::Greeter::MessageType)));
- connect(m_Greeter, SIGNAL(authenticationComplete()), this, SLOT(onAuthenticationComplete()));
+ connect(Global::greeter(), SIGNAL(showPrompt(QString, QLightDM::Greeter::PromptType)), this, SLOT(onPrompt(QString, QLightDM::Greeter::PromptType)));
+ connect(Global::greeter(), SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)), this, SLOT(onMessage(QString, QLightDM::Greeter::MessageType)));
+ connect(Global::greeter(), SIGNAL(authenticationComplete()), this, SLOT(onAuthenticationComplete()));
}
ui->leaveComboBox->setDisabled(ui->leaveComboBox->count() <= 1);
@@ -95,11 +79,11 @@ void LoginForm::initialize()
void LoginForm::startAuthentication()
{
- if (m_Greeter == nullptr) {
+ if (Global::testMode()) {
return;
}
- if (m_Greeter->inAuthentication()) {
- m_Greeter->cancelAuthentication();
+ if (Global::greeter()->inAuthentication()) {
+ Global::greeter()->cancelAuthentication();
}
if (ui->userInput->text().isEmpty()) {
ui->userInput->setFocus();
@@ -115,23 +99,23 @@ void LoginForm::startAuthentication()
ui->userInput->setEnabled(false);
ui->passwordInput->setEnabled(false);
cancelLoginTimer.start();
- m_Greeter->authenticate(ui->userInput->text());
+ Global::greeter()->authenticate(ui->userInput->text());
}
void LoginForm::onPrompt(QString prompt, QLightDM::Greeter::PromptType promptType)
{
std::cerr << "Prompt: " << prompt.toStdString() << std::endl;
- m_Greeter->respond(ui->passwordInput->text());
+ Global::greeter()->respond(ui->passwordInput->text());
ui->passwordInput->clear();
}
void LoginForm::leaveDropDownActivated(int index)
{
QString actionName = ui->leaveComboBox->itemData(index).toString();
- if (actionName == "shutdown") power->shutdown();
- else if (actionName == "restart") power->restart();
- else if (actionName == "hibernate") power->hibernate();
- else if (actionName == "suspend") power->suspend();
+ if (actionName == "shutdown") Global::power()->shutdown();
+ else if (actionName == "restart") Global::power()->restart();
+ else if (actionName == "hibernate") Global::power()->hibernate();
+ else if (actionName == "suspend") Global::power()->suspend();
}
void LoginForm::onMessage(QString message, QLightDM::Greeter::MessageType type)
@@ -150,13 +134,10 @@ void LoginForm::addLeaveEntry(bool canDo, QString iconName, QString text, QStrin
void LoginForm::onAuthenticationComplete()
{
- if (m_Greeter->isAuthenticated()) {
+ if (Global::greeter()->isAuthenticated()) {
std::cerr << "Auth complete, start session" << std::endl;
showMessage(tr("Starting session..."), false);
- QModelIndex i = sessionsModel->index(0, 0);
- QString s = sessionsModel->data(i, QLightDM::SessionsModel::KeyRole).toString();
- std::cerr << s.toStdString() << std::endl;
- if (m_Greeter->startSessionSync(s)) {
+ if (Global::startSession()) {
cancelLoginTimer.stop();
} else {
showMessage(tr("Cannot open session"), true);
@@ -171,9 +152,9 @@ void LoginForm::onAuthenticationComplete()
void LoginForm::cancelLogin()
{
std::cerr << "Cancel login" << std::endl;
- if (m_Greeter->inAuthentication()) {
+ if (Global::greeter()->inAuthentication()) {
std::cerr << "Was in authentication" << std::endl;
- m_Greeter->cancelAuthentication();
+ Global::greeter()->cancelAuthentication();
}
cancelLoginTimer.stop();
ui->passwordInput->clear();
diff --git a/src/loginform.h b/src/loginform.h
index 5e6f870..e414d2b 100644
--- a/src/loginform.h
+++ b/src/loginform.h
@@ -16,10 +16,11 @@
#include <QMap>
#include <QTimer>
-#include <QLightDM/Power>
#include <QLightDM/Greeter>
-#include <QLightDM/SessionsModel>
+namespace QLightDM {
+class PowerInterface;
+}
namespace Ui
{
@@ -31,7 +32,7 @@ class LoginForm : public QWidget
Q_OBJECT
public:
- explicit LoginForm(bool testMode, QWidget *parent = 0);
+ explicit LoginForm(QWidget *parent = nullptr);
~LoginForm();
virtual void setFocus(Qt::FocusReason reason);
@@ -56,10 +57,6 @@ private:
Ui::LoginForm *ui;
- QLightDM::Greeter *m_Greeter;
- QLightDM::PowerInterface *power;
- QLightDM::SessionsModel *sessionsModel;
-
QMap<int, void (QLightDM::PowerInterface::*)()> powerSlots;
QTimer cancelLoginTimer;
diff --git a/src/main.cpp b/src/main.cpp
index ece6b87..8eee16f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -22,6 +22,7 @@
#include "settings.h"
#include "mainwindow.h"
#include "x11util.h"
+#include "global.h"
static void messageHandler(QtMsgType type, const QMessageLogContext&, const QString& msg)
{
@@ -35,34 +36,49 @@ static inline int size(const QRect& r)
int main(int argc, char *argv[])
{
- //dup2(2, 1)
+ if (argc > 1 && QString(argv[1]) == QString("--test")) {
+ Global::enableTestMode();
+ }
+
+ QApplication a(argc, argv);
+
// I have no idea why, but Qt's stock qWarning() output never makes it
// to /var/log/lightdm/x-0-greeter.log, so we use std::cerr instead..
qInstallMessageHandler(messageHandler);
- QApplication a(argc, argv);
-
if (! Settings().iconThemeName().isEmpty()) {
QIcon::setThemeName(Settings().iconThemeName());
}
- // Build background for X server, in case we start a session that
- // doesn't set one on its own this will make sure it's not simply
- // black
- QImage entire;
- QSize desktopSize = QApplication::desktop()->size();
- qWarning() << "Desktop full size is " << desktopSize;
- entire = QImage(desktopSize, QImage::Format_RGB32);
- QPainter painter(&entire);
+ if (!Global::testMode() && !Settings().autoLoginCheckCmd().isEmpty()) {
+ QProcess p;
+ int ret = QProcess::execute(Settings().autoLoginCheckCmd());
+ if (ret == 0) {
+ if (Global::autoLoginGuest()) {
+ qWarning() << "Guest login ok";
+ return a.exec();
+ // TODO: Background?
+ } else {
+ qWarning() << "Guest login failed";
+ // TODO: Set error message, display somewhere
+ }
+ }
+ }
- const bool testMode = argc > 1 && QString(argv[1]) == QString("--test");
+ // Build background for X server, in case we start a session that
+ // doesn't set one on its own this will make sure it's not simply
+ // black
+ QImage entire;
// Get a list of non-overlapping screens, as this might lead to a broken
// greeter with main windows covering other login forms
QMap<int, QRect> screens;
- if (testMode) {
+ if (Global::testMode()) {
screens.insert(0, QRect(0, 0, 1024, 768));
} else {
+ QSize desktopSize = QApplication::desktop()->size();
+ qWarning() << "Desktop full size is " << desktopSize;
+ entire = QImage(desktopSize, QImage::Format_RGB32);
for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) {
QRect r = QApplication::desktop()->screenGeometry(i);
QMutableMapIterator<int, QRect>it(screens);
@@ -83,6 +99,7 @@ int main(int argc, char *argv[])
skip_rect: ; // Do nothing
}
}
+
// Determine primary screen
int primary;
if (screens.contains(QApplication::desktop()->primaryScreen())) {
@@ -94,11 +111,12 @@ int main(int argc, char *argv[])
}
// Now set up all the screens
+ QPainter painter(&entire);
MainWindow *focusWindow = 0;
QMapIterator<int, QRect> it(screens);
while (it.hasNext()) {
it.next();
- MainWindow *w = new MainWindow(primary == it.key(), it.key(), it.value(), testMode);
+ MainWindow *w = new MainWindow(primary == it.key(), it.key(), it.value());
w->show();
if (w->showLoginForm()) {
focusWindow = w;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 3307ef8..2eb84c9 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -23,7 +23,7 @@
static const Settings _settings;
-MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, bool testMode, QWidget *parent) :
+MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, QWidget *parent) :
QWidget(parent),
m_ScreenRect(screenRect),
m_Primary(primary),
@@ -35,12 +35,15 @@ MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, bool t
setBackground();
+ // TODO: Check if testMode == false and greeter == NULL, if so display big error message
+ // instead of exiting/crashing
+
// display login dialog only in the main screen
int spaceY = screenRect.height() / 2;
if (showLoginForm()) {
- m_LoginForm = new LoginForm(testMode, this);
+ m_LoginForm = new LoginForm(this);
spaceY -= m_LoginForm->height() / 2;
int maxX = screenRect.width() - m_LoginForm->width();
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 42d494e..ccaa073 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -27,7 +27,7 @@ class MainWindow : public QWidget
Q_OBJECT
public:
- explicit MainWindow(bool primary, int screen, const QRect &rect, bool testMode, QWidget *parent = 0);
+ explicit MainWindow(bool primary, int screen, const QRect &rect, QWidget *parent = 0);
~MainWindow();
void setFocus(Qt::FocusReason reason);
diff --git a/src/settings.h b/src/settings.h
index 81b1381..0a03567 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -18,6 +18,7 @@ public:
QString bottomLeftLogoPath() const { return value("greeter-bottom-left-logo-path").toString(); }
QStringList gradientColors() const { return value("greeter-background-gradient").toString().split(QRegExp("\\s"), QString::SkipEmptyParts); }
QString logMessageFile() const { return value("greeter-message-file").toString(); }
+ QString autoLoginCheckCmd() const { return value("auto-login-check-cmd").toString(); }
};