diff --git a/.gitmodules b/.gitmodules index 80625a0..1348776 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "src/VirtualKeyboard"] path = src/VirtualKeyboard url = git@github.com:nackee/VirtualKeyboard.git +[submodule "VirtualKeyboard"] + path = VirtualKeyboard + url = git@github.com:nackee/VirtualKeyboard.git diff --git a/BiometricAuth/BiometricAuth.pri b/BiometricAuth/BiometricAuth.pri new file mode 100644 index 0000000..cbb2ea1 --- /dev/null +++ b/BiometricAuth/BiometricAuth.pri @@ -0,0 +1,9 @@ +SOURCES += \ + $$PWD/biometricproxy.cpp \ + $$PWD/biometricauthwidget.cpp \ + $$PWD/biometricdeviceswidget.cpp + +HEADERS += \ + $$PWD/biometricproxy.h \ + $$PWD/biometricauthwidget.h \ + $$PWD/biometricdeviceswidget.h diff --git a/backend/ukui-screensaver-backend.pro b/BiometricAuth/BiometricAuth.pro similarity index 50% rename from backend/ukui-screensaver-backend.pro rename to BiometricAuth/BiometricAuth.pro index 61a2764..00bc543 100644 --- a/backend/ukui-screensaver-backend.pro +++ b/BiometricAuth/BiometricAuth.pro @@ -1,11 +1,18 @@ -QT -= gui -QT += core dbus +#------------------------------------------------- +# +# Project created by QtCreator 2018-12-06T09:17:41 +# +#------------------------------------------------- -CONFIG += c++11 console -CONFIG -= app_bundle +QT += core gui dbus + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = BiometricAuth +TEMPLATE = app # The following define makes your compiler emit warnings if you use -# any feature of Qt which as been marked deprecated (the exact warnings +# any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS @@ -15,17 +22,16 @@ DEFINES += QT_DEPRECATED_WARNINGS # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 -SOURCES += src/backend_main.cpp \ - src/interface.cpp \ - src/sessionwatcher.cpp \ - src/interfaceAdaptor.cpp -HEADERS += \ - src/interface.h \ - src/sessionwatcher.h \ - src/types.h \ - src/interfaceAdaptor.h +SOURCES += \ + main.cpp \ + biometricauthwidget.cpp \ + biometricproxy.cpp \ + biometricdeviceswidget.cpp -target.path = /usr/bin/ +HEADERS += \ + biometricauthwidget.h \ + biometricproxy.h \ + biometricdeviceswidget.h -INSTALLS += target +FORMS += diff --git a/BiometricAuth/CMakeLists.txt b/BiometricAuth/CMakeLists.txt new file mode 100644 index 0000000..28604a2 --- /dev/null +++ b/BiometricAuth/CMakeLists.txt @@ -0,0 +1,24 @@ +qt5_wrap_cpp(BiometricAuth_SRC + biometricdeviceinfo.h + biometricproxy.h + biometricauthwidget.h + biometricdeviceswidget.h + ) + +set(BiometricAuth_SRC + ${BiometricAuth_SRC} + biometricdeviceinfo.cpp + biometricproxy.cpp + biometricauthwidget.cpp + biometricdeviceswidget.cpp + ) + +include_directories( + ${Qt5Core_INCLUDE_DIRS} + ${Qt5Widgets_INCLUDE_DIRS} + ${Qt5DBus_INCLUDE_DIRS} + ) + + +add_library(BiometricAuth STATIC ${BiometricAuth_SRC}) +target_link_libraries(BiometricAuth Qt5::Core Qt5::DBus Qt5::Widgets) diff --git a/BiometricAuth/biometricauthwidget.cpp b/BiometricAuth/biometricauthwidget.cpp new file mode 100644 index 0000000..d79f45c --- /dev/null +++ b/BiometricAuth/biometricauthwidget.cpp @@ -0,0 +1,249 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include "biometricauthwidget.h" +#include +#include +#include + +BiometricAuthWidget::BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent) : + QWidget(parent), + proxy(proxy), + isInAuth(false), + movieTimer(nullptr), + failedCount(0), + timeoutCount(0), + beStopped(false) +{ + initUI(); + resize(400, 300); + + if(this->proxy) + { + connect(this->proxy, &BiometricProxy::StatusChanged, + this, &BiometricAuthWidget::onStatusChanged); + } +} + +void BiometricAuthWidget::initUI() +{ + //显示提示信息 + lblNotify = new QLabel(this); + lblNotify->setWordWrap(true); + lblNotify->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); + + //显示当前设备 + lblDevice = new QLabel(this); + lblDevice->setWordWrap(true); + lblDevice->setAlignment(Qt::AlignCenter); + + //显示图片 + lblImage = new QLabel(this); + lblImage->setFixedSize(100, 100); +} + + +void BiometricAuthWidget::resizeEvent(QResizeEvent */*event*/) +{ + lblNotify->setGeometry(0, 0, width(), 40); + lblDevice->setGeometry(0, lblNotify->geometry().bottom()+5, width(), 30); + lblImage->setGeometry((width() - lblImage->width()) / 2, + lblDevice->geometry().bottom() + 10, + lblImage->width(), lblImage->height()); +} + +void BiometricAuthWidget::startAuth(DeviceInfoPtr device, int uid) +{ + if(!proxy) + { + qWarning() << "BiometricProxy doesn't exist."; + return; + } + + if(isInAuth) + { + qDebug() << "Identification is currently under way, stop it"; + stopAuth(); + } + + this->device = device; + this->uid = uid; + this->userName = getpwuid(uid)->pw_name; + this->failedCount = 0; + this->timeoutCount = 0; + this->beStopped = false; + + startAuth_(); +} + +void BiometricAuthWidget::startAuth_() +{ + lblDevice->setText(tr("Current device: ") + device->shortName); + + qDebug().noquote() << QString("Identify:[drvid: %1, uid: %2]").arg(1).arg(2); + + isInAuth = true; + + QDBusPendingCall call = proxy->Identify(device->id, uid); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &BiometricAuthWidget::onIdentifyComplete); + + updateImage(1); +} + +void BiometricAuthWidget::stopAuth() +{ + beStopped = true; + if(!isInAuth) + { + return; + } + proxy->StopOps(device->id); + isInAuth = false; + updateImage(0); +} + +void BiometricAuthWidget::onIdentifyComplete(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply reply = *watcher; + if(reply.isError()) + { + qWarning() << "Identify error: " << reply.error().message(); + Q_EMIT authComplete(false); + updateImage(0); + return; + } + int result = reply.argumentAt(0).toInt(); + int authUid = reply.argumentAt(1).toInt(); + + // 特征识别成功,而且用户id匹配 + if(result == DBUS_RESULT_SUCCESS && authUid == uid) + { + qDebug() << "Identify success"; + Q_EMIT authComplete(true); + } + // 特征识别不匹配 + else if(result == DBUS_RESULT_NOTMATCH) + { + qDebug() << "Identify failed"; + failedCount++; + if(failedCount >= GetMaxFailedAutoRetry(userName)) + { + Q_EMIT authComplete(false); + } + else + { + lblNotify->setText(tr("Identify failed, Please retry.")); + QTimer::singleShot(1000, this, &BiometricAuthWidget::startAuth_); + } + } + //识别发生错误 + else if(result == DBUS_RESULT_ERROR) + { + StatusReslut ret = proxy->UpdateStatus(device->id); + //识别操作超时 + if(ret.result == 0 && ret.opsStatus == IDENTIFY_TIMEOUT) + { + timeoutCount++; + if(timeoutCount >= GetMaxTimeoutAutoRetry(userName)) + { + Q_EMIT authComplete(false); + } + else + { + QTimer::singleShot(1000, [&]{ + if(!beStopped) + { + startAuth_(); + } + }); + } + } + } + updateImage(0); +} + +void BiometricAuthWidget::onStatusChanged(int drvid, int status) +{ + if(!isInAuth) + { + return; + } + if(drvid != device->id) + { + return; + } + + // 显示来自服务的提示信息 + if(status == STATUS_NOTIFY) + { + QString notifyMsg = proxy->GetNotifyMesg(drvid); + lblNotify->setText(notifyMsg); + } +} + +static int count = 0; +void BiometricAuthWidget::updateImage(int type) +{ + if(type == 0) + { + if(movieTimer && movieTimer->isActive()) + { + movieTimer->stop(); + } + + QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/01.png") + .arg(DeviceType::getDeviceType(device->deviceType)); + setImage(imagePath); + } + else + { + if(!movieTimer) + { + movieTimer = new QTimer(this); + movieTimer->setInterval(100); + connect(movieTimer, &QTimer::timeout, + this, &BiometricAuthWidget::onMoviePixmapUpdate); + } + count = 0; + movieTimer->start(); + } +} + +void BiometricAuthWidget::onMoviePixmapUpdate() +{ + if(count >= 18) + { + count = 0; + } + count++; + QString fileName = (count < 10 ? "0" : "") + QString::number(count); + QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/%2.png") + .arg(DeviceType::getDeviceType(device->deviceType)) + .arg(fileName); + setImage(imagePath); +} + +void BiometricAuthWidget::setImage(const QString &path) +{ + QPixmap image(path); + image = image.scaled(lblImage->width(), lblImage->height(), + Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + lblImage->setPixmap(image); +} diff --git a/BiometricAuth/biometricauthwidget.h b/BiometricAuth/biometricauthwidget.h new file mode 100644 index 0000000..4350be7 --- /dev/null +++ b/BiometricAuth/biometricauthwidget.h @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#ifndef BIOMETRICAUTHWIDGET_H +#define BIOMETRICAUTHWIDGET_H + +#include +#include "biometricproxy.h" + +class QLabel; +//class QDBusPendingCallWatcher; +//class BiometricProxy; +//class DeviceIdentityPtr; +class BiometricAuthWidget : public QWidget +{ + Q_OBJECT +public: + explicit BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent = 0); + + /** + * @brief 进行生物识别认证 + * @param deviceInfo 使用的设备 + * @param uid 待认证的用户id + */ + void startAuth(DeviceInfoPtr device, int uid); + + /** + * @brief 终止生物识别认证 + */ + void stopAuth(); + + bool isAuthenticating() { return isInAuth; } + +protected: + void resizeEvent(QResizeEvent *event); + +Q_SIGNALS: + /** + * @brief 认证完成 + * @param result 认证结果 + */ + void authComplete(bool result); + +private Q_SLOTS: + void onIdentifyComplete(QDBusPendingCallWatcher *watcher); + void onStatusChanged(int drvid, int status); + void onMoviePixmapUpdate(); + void startAuth_(); + +private: + void initUI(); + void updateImage(int type = 0); + void setImage(const QString &path); + +private: + QLabel *lblNotify; + QLabel *lblDevice; + QLabel *lblImage; + + BiometricProxy *proxy; + int uid; + QString userName; + DeviceInfoPtr device; + bool isInAuth; + QTimer *movieTimer; + int failedCount; + int timeoutCount; + bool beStopped; +}; + +#endif // BIOMETRICAUTHWIDGET_H diff --git a/BiometricAuth/biometricdeviceinfo.cpp b/BiometricAuth/biometricdeviceinfo.cpp new file mode 100644 index 0000000..9100010 --- /dev/null +++ b/BiometricAuth/biometricdeviceinfo.cpp @@ -0,0 +1,161 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include "biometricdeviceinfo.h" + +#include +#include +//#include + +QString DeviceType::getDeviceType(int deviceType) +{ + if(deviceType >= __MAX_NR_TYPES) + { + return ""; + } + QMetaEnum meta = QMetaEnum::fromType(); + const char *typeString = meta.valueToKey(deviceType); + return QString(typeString); +} + +QString DeviceType::getDeviceType_tr(int deviceType) +{ + switch(deviceType) + { + case FingerPrint: + return tr("FingerPrint"); + case FingerVein: + return tr("FingerVein"); + case Iris: + return tr("Iris"); + case Face: + return tr("Face"); + case VoicePrint: + return tr("VoicePrint"); + default: + return ""; + } +} + +QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo) +{ + stream << "[" + << deviceInfo.id + << deviceInfo.shortName + << deviceInfo.fullName + << deviceInfo.deviceType + << deviceInfo.driverEnable + << deviceInfo.deviceNum + << "]"; + return stream; +} + +QDBusArgument &operator <<(QDBusArgument &arg, const DeviceInfo &deviceInfo) +{ + arg.beginStructure(); + arg << deviceInfo.id + << deviceInfo.shortName + << deviceInfo.fullName + << deviceInfo.driverEnable + << deviceInfo.deviceNum + << deviceInfo.deviceType + << deviceInfo.storageType + << deviceInfo.eigType + << deviceInfo.verifyType + << deviceInfo.identifyType + << deviceInfo.busType + << deviceInfo.deviceStatus + << deviceInfo.OpsStatus; + arg.endStructure(); + return arg; +} +const QDBusArgument &operator >>(const QDBusArgument &arg, DeviceInfo &deviceInfo) +{ + arg.beginStructure(); + arg >> deviceInfo.id + >> deviceInfo.shortName + >> deviceInfo.fullName + >> deviceInfo.driverEnable + >> deviceInfo.deviceNum + >> deviceInfo.deviceType + >> deviceInfo.storageType + >> deviceInfo.eigType + >> deviceInfo.verifyType + >> deviceInfo.identifyType + >> deviceInfo.busType + >> deviceInfo.deviceStatus + >> deviceInfo.OpsStatus; + arg.endStructure(); + return arg; +} + +void registerMetaType() +{ + qRegisterMetaType("DeviceInfo"); + qDBusRegisterMetaType(); +} + + +QString GetDefaultDevice(const QString &userName) +{ + QString configPath = QString("/home/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName); + QSettings settings(configPath, QSettings::IniFormat); + qDebug() << "configure path: " << settings.fileName(); + + QString defaultDevice = settings.value("DefaultDevice").toString(); + if(defaultDevice.isEmpty()) + { + QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat); + defaultDevice = sysSettings.value("DefaultDevice").toString(); + } + + return defaultDevice; +} + +static int getValueFromSettings(const QString &userName, const QString &key, int defaultValue = 3) +{ + //从家目录下的配置文件中获取 + QString configPath = QString("/home/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName); + QSettings settings(configPath, QSettings::IniFormat); + QString valueStr = settings.value(key).toString(); + + //如果没有获取到,则从系统配置文件中获取 + if(valueStr.isEmpty()) + { + QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat); + valueStr = sysSettings.value(key).toString(); + } + + bool ok; + int value = valueStr.toInt(&ok); + if( (value == 0 && !ok) || valueStr.isEmpty() ) + { + value = defaultValue; + } + return value; +} + +int GetMaxFailedAutoRetry(const QString &userName) +{ + return getValueFromSettings(userName, "MaxFailedAutoRetry"); +} + +int GetMaxTimeoutAutoRetry(const QString &userName) +{ + return getValueFromSettings(userName, "MaxTimeoutAutoRetry"); +} diff --git a/BiometricAuth/biometricdeviceinfo.h b/BiometricAuth/biometricdeviceinfo.h new file mode 100644 index 0000000..7f77f73 --- /dev/null +++ b/BiometricAuth/biometricdeviceinfo.h @@ -0,0 +1,157 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#ifndef BIOMETRICDEVICEINFO_H +#define BIOMETRICDEVICEINFO_H + +#include +#include + +#define BIOMETRIC_DBUS_SERVICE "org.ukui.Biometric" +#define BIOMETRIC_DBUS_PATH "/org/ukui/Biometric" +#define BIOMETRIC_DBUS_INTERFACE "org.ukui.Biometric" + +#define UKUI_BIOMETRIC_IMAGES_PATH "/usr/share/ukui-biometric/images/" +#define UKUI_BIOMETRIC_CONFIG_PATH ".biometric_auth/ukui_biometric.conf" +#define UKUI_BIOMETRIC_SYS_CONFIG_PATH "/etc/biometric-auth/ukui-biometric.conf" + +#define BIOMETRIC_PAM "BIOMETRIC_PAM" +#define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" +#define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS" + +/** + * @brief 设备类型 + */ +class DeviceType : public QObject +{ + Q_OBJECT +public: + DeviceType(); + enum Type { + FingerPrint, + FingerVein, + Iris, + Face, + VoicePrint, + __MAX_NR_TYPES + }; + Q_ENUM(Type) + /** + * @brief 获取设备类型的字符串表现形式 + * @param deviceType 设备类型 + * @return + */ + static QString getDeviceType(int deviceType); + + /** + * @brief 获取设备类型的国际化字符串 + * @param deviceType 设备类型 + * @return + */ + static QString getDeviceType_tr(int deviceType); +}; + +/** + * @brief StatusChanged D-Bus 信号触发时的状态变化类型 + */ +enum StatusType { + STATUS_DEVICE, + STATUS_OPERATION, + STATUS_NOTIFY +}; + +/** + * @brief 识别、终止操作等DBus调用的结果,即返回值里的 result + */ +enum DBusResult { + DBUS_RESULT_SUCCESS = 0, + DBUS_RESULT_NOTMATCH = -1, + DBUS_RESULT_ERROR = -2, + DBUS_RESULT_DEVICEBUSY = -3, + DBUS_RESULT_NOSUCHDEVICE = -4, + DBUS_RESULT_PERMISSIONDENIED = -5 +}; + +/** + * @brief 识别操作(Identify)的ops状态 + */ +enum IdentifyOpsStatus { + IDENTIFY_MATCH = 400, + IDENTIFY_NOTMATCH, + IDENTIFY_ERROR, + IDENTIFY_STOPBYUSER, + IDENTIFY_TIMEOUT, + IDENTIFY_MAX +}; + +/** + * @brief 设备的信息 + */ +struct DeviceInfo +{ + int id; + QString shortName; + QString fullName; + int driverEnable; + int deviceNum; + int deviceType; + int storageType; + int eigType; + int verifyType; + int identifyType; + int busType; + int deviceStatus; + int OpsStatus; +}; + +class QDBusArgument; + +QDBusArgument &operator <<(QDBusArgument &arg, const DeviceInfo &deviceInfo); +const QDBusArgument &operator >>(const QDBusArgument &arg, DeviceInfo &deviceInfo); + +void registerMetaType(); + +typedef std::shared_ptr DeviceInfoPtr; +typedef QList DeviceList; +typedef QMap DeviceMap; + +QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo); + +Q_DECLARE_METATYPE(DeviceInfo) + +/** + * @brief 获取默认设备 + * @return + */ +QString GetDefaultDevice(const QString &userName); + +/** + * @brief 获取失败后自动重新开始的最大次数 + * @param userName + * @return + */ +int GetMaxFailedAutoRetry(const QString &userName); + +/** + * @brief 获取超时后自动重新开始的最大次数 + * @param userName + * @return + */ +int GetMaxTimeoutAutoRetry(const QString &userName); + +#endif // BIOMETRICDEVICEINFO_H diff --git a/BiometricAuth/biometricdeviceswidget.cpp b/BiometricAuth/biometricdeviceswidget.cpp new file mode 100644 index 0000000..00285c5 --- /dev/null +++ b/BiometricAuth/biometricdeviceswidget.cpp @@ -0,0 +1,268 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include "biometricdeviceswidget.h" +#include +#include +#include +#include +#include +#include + + +BiometricDevicesWidget::BiometricDevicesWidget(BiometricProxy *proxy, QWidget *parent) + : QWidget(parent), + proxy(proxy) +{ + initUI(); + if(proxy && proxy->isValid()) + { + connect(proxy, &BiometricProxy::USBDeviceHotPlug, + this, &BiometricDevicesWidget::onUSBDeviceHotPlug); + updateDevice(); + } + + resize(500, 500); +} + +void BiometricDevicesWidget::initUI() +{ + lblPrompt = new QLabel(this); + lblPrompt->setObjectName(QStringLiteral("lblBioetricDevicesPrompt")); + lblPrompt->setText(tr("Please select the biometric device")); + lblPrompt->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + + lblDeviceType = new QLabel(this); + lblDeviceType->setObjectName(QStringLiteral("lblDeviceType")); + lblDeviceType->setText(tr("Device type:")); + lblDeviceType->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + + QStyledItemDelegate* itemDelegate = new QStyledItemDelegate(); + + cmbDeviceType = new QComboBox(this); + cmbDeviceType->setObjectName(QStringLiteral("cmbDeviceType")); + cmbDeviceType->setMaxVisibleItems(5); + cmbDeviceType->setItemDelegate(itemDelegate); + connect(cmbDeviceType, SIGNAL(currentIndexChanged(int)), + this, SLOT(onCmbDeviceTypeCurrentIndexChanged(int))); + + lblDeviceName = new QLabel(this); + lblDeviceName->setObjectName(QStringLiteral("lblDeviceName")); + lblDeviceName->setText(tr("Device name:")); + lblDeviceName->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + + cmbDeviceName = new QComboBox(this); + cmbDeviceName->setObjectName(QStringLiteral("cmbDeviceName")); + cmbDeviceName->setMaxVisibleItems(5); + cmbDeviceName->setItemDelegate(itemDelegate); + + btnOK = new QPushButton(tr("OK"), this); + btnOK->setObjectName(QStringLiteral("OKButton")); + btnOK->setCursor(Qt::PointingHandCursor); + connect(btnOK, &QPushButton::clicked, + this, &BiometricDevicesWidget::onOKButtonClicked); +} + +void BiometricDevicesWidget::resizeEvent(QResizeEvent */*event*/) +{ + lblPrompt->setGeometry(0, 0, width(), 40); + lblDeviceType->setGeometry(0, lblPrompt->geometry().bottom() + 40, + 120, 20); + cmbDeviceType->setGeometry(0, lblDeviceType->geometry().bottom() + 15, + 300, 40); + lblDeviceName->setGeometry(0, cmbDeviceType->geometry().bottom() + 80, + 120, 20); + cmbDeviceName->setGeometry(0, lblDeviceName->geometry().bottom() + 15, + 300, 40); + btnOK->setGeometry(0, cmbDeviceName->geometry().bottom() + 80, 140, 38); + +} + +void BiometricDevicesWidget::updateDevice() +{ + deviceMap.clear(); + DeviceList deviceList = proxy->GetDevList(); + for(auto pDeviceInfo : deviceList) + { + qDebug() << *pDeviceInfo; + deviceMap[pDeviceInfo->deviceType].push_back(pDeviceInfo); + } + cmbDeviceType->clear(); + for(int type : deviceMap.keys()) + { + QString iconPath = QString(UKUI_BIOMETRIC_IMAGES_PATH"icon/%1.png") + .arg(DeviceType::getDeviceType(type)); + qDebug() << iconPath; + cmbDeviceType->addItem(QIcon(iconPath), DeviceType::getDeviceType_tr(type), type); + } + if(deviceMap.size() > 0) + { + int index = deviceMap.keys().at(0); + setCurrentDevice(deviceMap[index].at(0)); + } +} + + +void BiometricDevicesWidget::setCurrentDevice(int drvid) +{ + DeviceInfoPtr pDeviceInfo = findDeviceById(drvid); + if(pDeviceInfo) + { + setCurrentDevice(pDeviceInfo); + } +} + +void BiometricDevicesWidget::setCurrentDevice(const QString &deviceName) +{ + DeviceInfoPtr pDeviceInfo = findDeviceByName(deviceName); + if(pDeviceInfo) + { + setCurrentDevice(pDeviceInfo); + } +} + +void BiometricDevicesWidget::setCurrentDevice(const DeviceInfoPtr &pDeviceInfo) +{ + this->currentDevice = pDeviceInfo; + cmbDeviceType->setCurrentText(DeviceType::getDeviceType_tr(pDeviceInfo->deviceType)); + cmbDeviceName->setCurrentText(pDeviceInfo->shortName); +} + +bool BiometricDevicesWidget::deviceExists(int drvid) +{ + return (findDeviceById(drvid) != nullptr); +} + +bool BiometricDevicesWidget::deviceExists(const QString &deviceName) +{ + return (findDeviceByName(deviceName) != nullptr); +} + +DeviceInfoPtr BiometricDevicesWidget::findDeviceById(int drvid) +{ + for(int type : deviceMap.keys()) + { + DeviceList &deviceList = deviceMap[type]; + auto iter = std::find_if(deviceList.begin(), deviceList.end(), + [&](DeviceInfoPtr ptr){ + return ptr->id == drvid; + }); + if(iter != deviceList.end()) + { + return *iter; + } + } + return DeviceInfoPtr(); +} + +DeviceInfoPtr BiometricDevicesWidget::findDeviceByName(const QString &name) +{ + for(int type : deviceMap.keys()) + { + DeviceList &deviceList = deviceMap[type]; + auto iter = std::find_if(deviceList.begin(), deviceList.end(), + [&](DeviceInfoPtr ptr){ + return ptr->shortName == name; + }); + if(iter != deviceList.end()) + { + return *iter; + } + } + return DeviceInfoPtr(); +} + +void BiometricDevicesWidget::onCmbDeviceTypeCurrentIndexChanged(int index) +{ + if(index < 0 || index >= deviceMap.keys().size()) + { + return; + } + int type = cmbDeviceType->itemData(index).toInt(); + cmbDeviceName->clear(); + for(auto &deviceInfo : deviceMap.value(type)) + { + cmbDeviceName->addItem(deviceInfo->shortName); + } +} + +void BiometricDevicesWidget::onOKButtonClicked() +{ + int type = cmbDeviceType->currentData().toInt(); + int index = cmbDeviceName->currentIndex(); + qDebug() << type << index; + DeviceInfoPtr deviceInfo = deviceMap.value(type).at(index); + Q_EMIT deviceChanged(deviceInfo); + hide(); +} + +void BiometricDevicesWidget::onUSBDeviceHotPlug(int drvid, int action, int /*devNum*/) +{ + int savedDeviceId = currentDevice->id; + int savedCount = 0; + for(int type : deviceMap.keys()) + savedCount += deviceMap.value(type).count(); + + switch(action) + { + case ACTION_ATTACHED: + { + //插入设备后,需要更新设备列表 + deviceMap.clear(); + updateDevice(); + setCurrentDevice(savedDeviceId); + break; + } + case ACTION_DETACHED: + { + DeviceInfoPtr pDeviceInfo = findDeviceById(drvid); + if(pDeviceInfo) + { + int type = pDeviceInfo->deviceType; + deviceMap[type].removeOne(pDeviceInfo); + int index = cmbDeviceName->findText(pDeviceInfo->shortName); + cmbDeviceName->removeItem(index); + + //如果该类型的设备全被移除,删除该类型相关的列表 + if(deviceMap[type].isEmpty()) + { + deviceMap.remove(type); + index = cmbDeviceType->findData(type); + cmbDeviceType->removeItem(index); + } + } + if(savedDeviceId != drvid) + { + setCurrentDevice(savedDeviceId); + } + break; + } + } + + int count = 0; + for(int type : deviceMap.keys()) + count += deviceMap.value(type).count(); + + //设备数量发生了变化 + if(count != savedCount) + { + Q_EMIT deviceCountChanged(count); + } +} + + diff --git a/BiometricAuth/biometricdeviceswidget.h b/BiometricAuth/biometricdeviceswidget.h new file mode 100644 index 0000000..7fde6fd --- /dev/null +++ b/BiometricAuth/biometricdeviceswidget.h @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#ifndef BIOMETRICDEVICESWIDGET_H +#define BIOMETRICDEVICESWIDGET_H + +#include +#include "biometricproxy.h" + +class QLabel; +class QPushButton; +class QComboBox; + + +class BiometricDevicesWidget : public QWidget +{ + Q_OBJECT +public: + explicit BiometricDevicesWidget(BiometricProxy *proxy, QWidget *parent = nullptr); + void setCurrentDevice(int drvid); + void setCurrentDevice(const QString &deviceName); + void setCurrentDevice(const DeviceInfoPtr &pDeviceInfo); + DeviceInfoPtr findDeviceById(int drvid); + DeviceInfoPtr findDeviceByName(const QString &name); + bool deviceExists(int drvid); + bool deviceExists(const QString &deviceName); + +protected: + void resizeEvent(QResizeEvent *event); + +Q_SIGNALS: + void deviceChanged(const DeviceInfoPtr &pDeviceInfo); + void deviceCountChanged(int newCount); + +private Q_SLOTS: + void onCmbDeviceTypeCurrentIndexChanged(int index); + void onOKButtonClicked(); + void onUSBDeviceHotPlug(int drvid, int action, int devNum); + +private: + void initUI(); + void updateDevice(); + +private: + typedef QMap QButtonMap; + + QLabel *lblPrompt; + QLabel *lblDeviceType; + QLabel *lblDeviceName; + QComboBox *cmbDeviceType; + QComboBox *cmbDeviceName; + QPushButton *btnOK; + QPushButton *btnCancel; + + BiometricProxy *proxy; + DeviceMap deviceMap; + DeviceInfoPtr currentDevice; +}; + +#endif // BIOMETRICDEVICESWIDGET_H diff --git a/BiometricAuth/biometricproxy.cpp b/BiometricAuth/biometricproxy.cpp new file mode 100644 index 0000000..357efa2 --- /dev/null +++ b/BiometricAuth/biometricproxy.cpp @@ -0,0 +1,139 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include "biometricproxy.h" + + +BiometricProxy::BiometricProxy(QObject *parent) + : QDBusAbstractInterface(BIOMETRIC_DBUS_SERVICE, + BIOMETRIC_DBUS_PATH, + BIOMETRIC_DBUS_INTERFACE, + QDBusConnection::systemBus(), + parent) +{ + registerMetaType(); +} + +QDBusPendingCall BiometricProxy::Identify(int drvid, int uid, int indexStart, int indexEnd) +{ + QList argList; + argList << drvid << uid << indexStart << indexEnd; + return asyncCallWithArgumentList(QStringLiteral("Identify"), argList); +} + +int BiometricProxy::StopOps(int drvid, int waiting) +{ + QDBusReply reply = call(QStringLiteral("StopOps"), drvid, waiting); + if(!reply.isValid()) + { + qWarning() << "StopOps error:" << reply.error(); + return -1; + } + return reply.value(); +} + +DeviceList BiometricProxy::GetDevList() +{ + QDBusMessage result = call(QStringLiteral("GetDevList")); + if(result.type() == QDBusMessage::ErrorMessage) + { + qWarning() << "GetDevList error:" << result.errorMessage(); + return DeviceList(); + } + auto dbusArg = result.arguments().at(1).value(); + QList variantList; + DeviceList deviceList; + dbusArg >> variantList; + for(int i = 0; i < variantList.size(); i++) + { + DeviceInfoPtr pDeviceInfo = std::make_shared(); + + auto arg = variantList.at(i).value(); + arg >> *pDeviceInfo; + + deviceList.push_back(pDeviceInfo); + } + + return deviceList; +} + +int BiometricProxy::GetDevCount() +{ + QDBusMessage result = call(QStringLiteral("GetDevList")); + if(result.type() == QDBusMessage::ErrorMessage) + { + qWarning() << "GetDevList error:" << result.errorMessage(); + return 0; + } + int count = result.arguments().at(0).value(); + return count; +} + +QString BiometricProxy::GetDevMesg(int drvid) +{ + QDBusMessage result = call(QStringLiteral("GetDevMesg"), drvid); + if(result.type() == QDBusMessage::ErrorMessage) + { + qWarning() << "GetDevMesg error:" << result.errorMessage(); + return ""; + } + return result.arguments().at(0).toString(); +} + +QString BiometricProxy::GetNotifyMesg(int drvid) +{ + QDBusMessage result = call(QStringLiteral("GetNotifyMesg"), drvid); + if(result.type() == QDBusMessage::ErrorMessage) + { + qWarning() << "GetNotifyMesg error:" << result.errorMessage(); + return ""; + } + return result.arguments().at(0).toString(); +} + +QString BiometricProxy::GetOpsMesg(int drvid) +{ + QDBusMessage result = call(QStringLiteral("GetOpsMesg"), drvid); + if(result.type() == QDBusMessage::ErrorMessage) + { + qWarning() << "GetOpsMesg error:" << result.errorMessage(); + return ""; + } + return result.arguments().at(0).toString(); +} + +StatusReslut BiometricProxy::UpdateStatus(int drvid) +{ + StatusReslut status; + QDBusMessage result = call(QStringLiteral("UpdateStatus"), drvid); + if(result.type() == QDBusMessage::ErrorMessage) + { + qWarning() << "UpdateStatus error:" << result.errorMessage(); + status.result = -1; + return status; + } + + status.result = result.arguments().at(0).toInt(); + status.enable = result.arguments().at(1).toInt(); + status.devNum = result.arguments().at(2).toInt(); + status.devStatus = result.arguments().at(3).toInt(); + status.opsStatus = result.arguments().at(4).toInt(); + status.notifyMessageId = result.arguments().at(5).toInt(); + + return status; +} diff --git a/BiometricAuth/biometricproxy.h b/BiometricAuth/biometricproxy.h new file mode 100644 index 0000000..3c161ae --- /dev/null +++ b/BiometricAuth/biometricproxy.h @@ -0,0 +1,126 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#ifndef BIOMETRICPROXY_H +#define BIOMETRICPROXY_H + +#include +#include +#include "biometricdeviceinfo.h" + +/** + * @brief UpdateStauts调用返回的结果 + */ +struct StatusReslut +{ + int result; + int enable; + int devNum; + int devStatus; + int opsStatus; + int notifyMessageId; +}; + +/** + * @brief USB设备插拔动作 + */ +enum USBDeviceAction +{ + ACTION_ATTACHED = 1, + ACTION_DETACHED = -1 +}; + +/** + * @brief DBus代理类,负责调用对应的DBus接口 + */ +class BiometricProxy : public QDBusAbstractInterface +{ + Q_OBJECT +public: + explicit BiometricProxy(QObject *parent = nullptr); + +public Q_SLOTS: + /** + * @brief 使用指定id的设备进行用户认证 + * @param drvid 驱动(设备)id + * @param uid 用户id + * @param indexStart 用于认证的特征索引范围 + * @param indexEnd + * @return 结果: (结果,用户id) + */ + QDBusPendingCall Identify(int drvid, int uid, int indexStart = 0, int indexEnd = -1); + /** + * @brief 终止设备上正在进行的操作 + * @param drvid 设备id + * @param waiting 等待时间(秒) + * @return + */ + int StopOps(int drvid, int waiting = 5); + /** + * @brief 获取已连接的设备列表 + * @return + */ + DeviceList GetDevList(); + /** + * @brief 获取设备数量 + * @return + */ + int GetDevCount(); + /** + * @brief 获取设备消息 + * @param drvid 驱动id + * @return + */ + QString GetDevMesg(int drvid); + /** + * @brief GetNotifyMesg 获取通知消息 + * @param drvid 驱动id + * @return + */ + QString GetNotifyMesg(int drvid); + /** + * @brief GetOpsMesg 获取操作消息 + * @param drvid 驱动id + * @return + */ + QString GetOpsMesg(int drvid); + /** + * @brief UpdateStatus 获取更新的设备状态 + * @param drvid 驱动id + * @return 结果: + */ + StatusReslut UpdateStatus(int drvid); + +Q_SIGNALS: + /** + * @brief 设备状态发生变化 + * @param drvid 设备id + * @param status 设备状态 + */ + void StatusChanged(int drvid, int status); + /** + * @brief USB设备热插拔 + * @param drvid 设备id + * @param action 插拔动作(1:插入,-1:拔出) + * @param deviceNum 插拔动作后该驱动拥有的设备数量 + */ + void USBDeviceHotPlug(int drvid, int action, int deviceNum); +}; + +#endif // BIOMETRICPROXY_H diff --git a/BiometricAuth/main.cpp b/BiometricAuth/main.cpp new file mode 100644 index 0000000..6215ae1 --- /dev/null +++ b/BiometricAuth/main.cpp @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include +#include +#include "biometricproxy.h" +#include "biometricauthwidget.h" +#include "biometricdeviceswidget.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + BiometricProxy proxy; + BiometricAuthWidget biometricAuthWidget(&proxy); + biometricAuthWidget.hide(); + BiometricDevicesWidget biometricDeviceWidget(&proxy); + QObject::connect(&biometricDeviceWidget, &BiometricDevicesWidget::deviceChanged, + &a, [&](const DeviceInfoPtr &pDeviceInfo){ + biometricAuthWidget.startAuth(pDeviceInfo, 1000); + biometricAuthWidget.show(); + }); + QObject::connect(&biometricDeviceWidget, &BiometricDevicesWidget::deviceCountChanged, + &a, [&](int count){ + qDebug() << "device count changed: " << count; + }); + biometricDeviceWidget.show(); + + return a.exec(); +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0c66166 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 2.6) +project(ukui-screensaver) + +find_package(Qt5 COMPONENTS Core Widgets DBus X11Extras) +find_package(PkgConfig REQUIRED) + +set(TS_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/zh_CN.ts + ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/es.ts + ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/fr.ts + ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/pt.ts + ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/ru.ts + ) +add_custom_command( + OUTPUT ${TS_FILES} + COMMAND lupdate src/ -ts ${TS_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) +add_custom_target( + i18n_ts + DEPENDS ${TS_FILES} + ) +add_compile_options(-fPIC) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_INSTALL_PREFIX /usr) + +set(Debug ON) +if(Debug) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +#add_subdirectory(BioAuth) +add_subdirectory(BiometricAuth) +add_subdirectory(VirtualKeyboard) +add_subdirectory(src) +add_subdirectory(i18n_ts) +add_subdirectory(data) + +add_dependencies(ukui-screensaver-dialog BiometricAuth VirtualKeyboard) diff --git a/Makefile b/Makefile deleted file mode 100644 index 505e93e..0000000 --- a/Makefile +++ /dev/null @@ -1,116 +0,0 @@ -# The default options are compiling with debugging information -mode = debug - -CC = gcc -CXX = g++ - -# Source file directory -I18N_SRC = i18n_ts/ - -# bin file installation directory -BIN_DIR = /usr/bin - -# gsettings xml file -GSETTINGS_DIR = /usr/share/glib-2.0/schemas - -# desktop file -DESKTOP_DIR = /etc/xdg/autostart - -# directory file -DIRECTORY_DIR = /usr/share/desktop-directories - -# menus file -MENUS_DIR = /etc/xdg/menus - -# Set build options -ifeq ($(mode), debug) - # Compile with debugging information - QMAKE_OPTIONS = CONFIG+=debug -else - # Compile without debugging information - QMAKE_OPTIONS = -endif - -# Target -all: gui i18n command - -# -# Compilation -# - -# Compile GUI -gui: - qmake src/ $(QMAKE_OPTIONS) -o Saver_Makefile - $(MAKE) -f Saver_Makefile - qmake backend/ $(QMAKE_OPTIONS) -o Backend_Makefile - $(MAKE) -f Backend_Makefile - qmake command/ $(QMAKE_OPTIONS) -o Command_Makefile - $(MAKE) -f Command_Makefile - -# Generate Qt translation file -i18n: - $(MAKE) -C $(I18N_SRC) - -command: - $(CC) src/ukui-screensaver-command.c -o ukui-screensaver-command - - -# -# Installation -# - -install: install-target install-i18n install-data - -install-target: - # Install target - $(MAKE) -f Saver_Makefile install INSTALL_ROOT=$(DESTDIR)/ - $(MAKE) -f Backend_Makefile install INSTALL_ROOT=$(DESTDIR)/ - $(MAKE) -f Command_Makefile install INSTALL_ROOT=$(DESTDIR)/ - -install-i18n: - # Install i18n - $(MAKE) -C $(I18N_SRC) install - -install-data: - # Install gsettings file - install -D -m 644 data/org.ukui.screensaver.gschema.xml $(DESTDIR)$(GSETTINGS_DIR)/org.ukui.screensaver.gschema.xml - install -D -m 644 data/ukui-screensaver.desktop $(DESTDIR)$(DESKTOP_DIR)/ukui-screensaver.desktop - install -D -m 644 data/ukui-screensavers.menu $(DESTDIR)$(MENUS_DIR)/ukui-screensavers.menu - install -D -m 644 data/ukui-screensaver.directory $(DESTDIR)$(DIRECTORY_DIR)/ukui-screensaver.directory - - -# -# Uninstallation -# - -uninstall: uninstall-target uninstall-i18n uninstall-data - -uninstall-target: - # Uninstall target - $(MAKE) -f Saver_Makefile uninstall - $(MAKE) -f Backend_Makefile uninstall - $(MAKE) -f Command_Makefile uninstall - -uninstall-i18n: - # Uninstall i18n - $(MAKE) -C $(I18N_SRC) uninstall - -uninstall-data: - # Uninstall data - rm -rf $(DESTDIR)$(GSETTINGS_DIR)/org.ukui.screensaver.gschema.xml - rm -rf $(DESTDIR)$(DESKTOP_DIR)/ukui-screensaver.desktop - rm -rf $(DESTDIR)$(MENUS_DIR)/ukui-screensavers.menu - rm -rf $(DESTDIR)$(DIRECTORY_DIR)/ukui-screensaver.directory - -# -# Clean intermediate file -# - -clean: - # Clean GUI intermediate files - rm -f *.o moc_* ui_* qrc_*.cpp - rm -f Saver_Makefile Backend_Makefile Command_Makefile .qmake.stash - rm -f ukui-screensaver-dialog ukui-screensaver-command ukui-screensaver-backend - # Clean i18n intermediate files - $(MAKE) -C $(I18N_SRC) clean - diff --git a/VirtualKeyboard b/VirtualKeyboard new file mode 160000 index 0000000..5b620e1 --- /dev/null +++ b/VirtualKeyboard @@ -0,0 +1 @@ +Subproject commit 5b620e1437fa56738b00b635e0563de745b22c79 diff --git a/command/ukui-screensaver-command.pro b/command/ukui-screensaver-command.pro deleted file mode 100644 index aaabd5c..0000000 --- a/command/ukui-screensaver-command.pro +++ /dev/null @@ -1,23 +0,0 @@ -QT -= gui -QT += dbus - -CONFIG += c++11 console -CONFIG -= app_bundle - -# The following define makes your compiler emit warnings if you use -# any feature of Qt which as been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if you use deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -SOURCES += \ - command_main.cpp - -target.path = /usr/bin/ - -INSTALLS += target diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt new file mode 100644 index 0000000..3921cef --- /dev/null +++ b/data/CMakeLists.txt @@ -0,0 +1,4 @@ +install(FILES org.ukui.screensaver.gschema.xml DESTINATION /usr/share/glib-2.0/schemas) +install(FILES ukui-screensaver.desktop DESTINATION /etc/xdg/autostart) +install(FILES ukui-screensaver.directory DESTINATION /usr/share/desktop-directories) +install(FILES ukui-screensavers.menu DESTINATION /etc/xdg/menu) diff --git a/i18n_ts/CMakeLists.txt b/i18n_ts/CMakeLists.txt new file mode 100644 index 0000000..f4b0cef --- /dev/null +++ b/i18n_ts/CMakeLists.txt @@ -0,0 +1,12 @@ +find_package(Qt5LinguistTools) + +file(GLOB ts_files *.ts) +qt5_create_translation(qm_files ${ts_files}) +add_custom_target(i18n + DEPENDS ${qm_files} + SOURCES ${ts_files} + ) +# 让主目标依赖翻译文件,这样才会执行i18n +add_dependencies(ukui-screensaver-dialog i18n) + +install(FILES ${qm_files} DESTINATION /usr/share/ukui-screensaver/i18n_qm/) diff --git a/i18n_ts/Makefile b/i18n_ts/Makefile deleted file mode 100644 index c1b7c8e..0000000 --- a/i18n_ts/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -INSTALL_DIR_DATA = /usr/share/ukui-screensaver - -all: - lrelease *.ts - -clean: - rm -f *.qm - -install: - mkdir -p $(DESTDIR)$(INSTALL_DIR_DATA)/i18n_qm/ - install -m 666 -D *.qm $(DESTDIR)$(INSTALL_DIR_DATA)/i18n_qm/ - -uninstall: - rm -f $(DESTDIR)$(INSTALL_DIR_DATA)/i18n_qm/*.qm diff --git a/i18n_ts/es.ts b/i18n_ts/es.ts index 946cf94..1961923 100644 --- a/i18n_ts/es.ts +++ b/i18n_ts/es.ts @@ -1,287 +1,153 @@ - - - BioAuthentication - - authentication failed, restart after 2 seconds - autenticación fallida, reinicie después de 2 segundos - - - - BioDeviceView - - password login - contraseña de acceso - - - fingerprint - huella dactilar - - - fingerevin - fingerevin - - - iris - iris - - - - KeyboardWidget - - KeyboardWidget - TecladoWidget - - - q - q - - - w - w - - - e - mi - - - r - r - - - t - t - - - y - y - - - u - tu - - - i - yo - - - o - o - - - p - pag - - - a - una - - - s - s - - - d - re - - - f - F - - - g - sol - - - h - h - - - j - j - - - k - k - - - l - l - - - z - z - - - x - X - - - c - do - - - v - v - - - b - segundo - - - n - norte - - - m - metro - - - , - , - - - . - . - - - Ctrl - Ctrl - - - Alt - Alt - - - / - / - - - 9 - 9 - - - 5 - 5 - - - 8 - 8 - - - 4 - 4 - - - 2 - 2 - - - 7 - 7 - - - 1 - 1 - - - 0 - 0 - - - 6 - 6 - - - 3 - 3 - - - Delete - Borrar - - - End - Fin - - - Insert - Insertar - - - PgUp - PgUp - - - Home - Casa - - - PgDn - PgDn - - - Abc - A B C - - - @ - @ - - - 123 - 123 - - - - MainWindow - - MainWindow - Ventana principal - - - Username - Nombre de usuario - - - Unlock - desbloquear - - - Has Logged In - Ha iniciado sesión - - - Avatar - Avatar - - - Switch User - Cambiar de usuario - - - TextLabel - TextLabel - - - Password Incorrect - Contraseña incorrecta - - - - main - - Dialog for the ukui ScreenSaver. - Diálogo para el protector de pantalla de ukui. - - - lock the screen immediately - bloquea la pantalla inmediatamente - - - activated by session idle signal - activado por la señal de inactividad de la sesión - - - \ No newline at end of file + + + AuthDialog + + Form + Formar + + + More Devices + Más dispositivos + + + Biometric + Biometrico + + + Password + Contraseña + + + Retry + Procesar de nuevo + + + UnLock + Desbloquear + + + LoggedIn + Conectado + + + Password Incorrect, Please try again + Contraseña incorrecta, por favor intente de nuevo + + + + BioAuthWidget + + Form + Formar + + + TextLabel + TextLabel + + + More + Más + + + Retry + Procesar de nuevo + + + Password + Contraseña + + + + BioDevices + + FingerPrint + Huella dactilar + + + FingerVein + FingerVein + + + Iris + Iris + + + Face + Cara + + + VoicePrint + Impresión de voz + + + + BioDevicesWidget + + Form + Formar + + + Please select other biometric devices + Por favor seleccione otros dispositivos biométricos + + + Device Type: + Tipo de dispositivo: + + + Device Name: + Nombre del dispositivo: + + + + KeyboardWidget + + KeyboardWidget + TecladoWidget + + + + LockWidget + + Form + Formar + + + Date + Fecha + + + Time + Hora + + + Guest + Huésped + + + SwitchUser + Cambiar de usuario + + + + main + + Start command for the ukui ScreenSaver. + Comando de inicio para el protector de pantalla de ukui. + + + lock the screen immediately + bloquea la pantalla inmediatamente + + + Dialog for the ukui ScreenSaver. + Diálogo para el protector de pantalla de ukui. + + + activated by session idle signal + activado por la señal de inactividad de la sesión + + + diff --git a/i18n_ts/fr.ts b/i18n_ts/fr.ts index 0585356..2808658 100644 --- a/i18n_ts/fr.ts +++ b/i18n_ts/fr.ts @@ -2,76 +2,149 @@ - BioAuthentication + AuthDialog - authentication failed, restart after 2 seconds - L'authentification a échoué, redémarrez après 2 secondes + Form + Forme + + + More Devices + Plus d'appareils + + + Biometric + Biométrique + + + Password + Mot de passe + + + Retry + Réessayez + + + UnLock + Ouvrir + + + LoggedIn + Connecté + + + Password Incorrect, Please try again + Mot de passe incorrect, veuillez réessayer - BioDeviceView + BioAuthWidget + + Form + Forme + - password login - mot de passe login + TextLabel + TextLabel - fingerprint - empreinte digitale + More + Plus - fingerevin - fingerevin + Retry + Réessayez - iris - iris + Password + Mot de passe - MainWindow + BioDevices - MainWindow - Fenêtre principale + FingerPrint + Empreinte digitale - Username - Nom d'utilisateur + FingerVein + FingerVein - Unlock - Ouvrir + Iris + Iris - Has Logged In - S'est connecté + Face + Visage - Avatar - Avatar + VoicePrint + VoicePrint + + + BioDevicesWidget - Switch User - Changer d'utilisateur + Form + Forme - TextLabel - TextLabel + Please select other biometric devices + Veuillez sélectionner d'autres appareils biométriques - Password Incorrect - Mot de passe incorrect + Device Type: + Type d'appareil: + + + Device Name: + Nom de l'appareil: + + + + KeyboardWidget + + KeyboardWidget + KeyboardWidget + + + + LockWidget + + Form + Forme + + + Date + Rendez-vous amoureux + + + Time + Temps + + + Guest + Client + + + SwitchUser + Changer d'utilisateur main - Dialog for the ukui ScreenSaver. - Boîte de dialogue pour l'écran de veille ukui. + Start command for the ukui ScreenSaver. + Commande de démarrage pour l'ukui ScreenSaver. lock the screen immediately verrouiller l'écran immédiatement + + Dialog for the ukui ScreenSaver. + Boîte de dialogue pour l'écran de veille ukui. + activated by session idle signal activé par le signal d'inactivité de la session diff --git a/i18n_ts/pt.ts b/i18n_ts/pt.ts index 65d5975..a1b0965 100644 --- a/i18n_ts/pt.ts +++ b/i18n_ts/pt.ts @@ -2,76 +2,149 @@ - BioAuthentication + AuthDialog - authentication failed, restart after 2 seconds - autenticação falhou, reinicie após 2 segundos + Form + Formato + + + More Devices + Mais dispositivos + + + Biometric + Biométrico + + + Password + Senha + + + Retry + Tente novamente + + + UnLock + Desbloquear + + + LoggedIn + Logado + + + Password Incorrect, Please try again + Senha incorreta, por favor tente novamente - BioDeviceView + BioAuthWidget + + Form + Formato + - password login - senha de acesso + TextLabel + TextLabel - fingerprint - impressão digital + More + Mais - fingerevin - fingerevin + Retry + Tente novamente - iris - íris + Password + Senha - MainWindow + BioDevices - MainWindow - Janela principal + FingerPrint + Impressão digital - Username - Nome de usuário + FingerVein + FingerVein - Unlock - Desbloquear + Iris + Íris - Has Logged In - Fez o login + Face + Face - Avatar - Avatar + VoicePrint + VoicePrint + + + BioDevicesWidget - Switch User - Mudar de utilizador + Form + Formato - TextLabel - TextLabel + Please select other biometric devices + Por favor, selecione outros dispositivos biométricos - Password Incorrect - Senha incorreta + Device Type: + Tipo de dispositivo: + + + Device Name: + Nome do dispositivo: + + + + KeyboardWidget + + KeyboardWidget + KeyboardWidget + + + + LockWidget + + Form + Formato + + + Date + Encontro + + + Time + Tempo + + + Guest + Convidado + + + SwitchUser + Mudar de utilizador main - Dialog for the ukui ScreenSaver. - Diálogo para o ScreenSaver ukui. + Start command for the ukui ScreenSaver. + Inicie o comando para o ScreenSaver do ukui. lock the screen immediately bloquear a tela imediatamente + + Dialog for the ukui ScreenSaver. + Diálogo para o ScreenSaver ukui. + activated by session idle signal ativado por sinal ocioso de sessão diff --git a/i18n_ts/ru.ts b/i18n_ts/ru.ts index 609e177..8743fb4 100644 --- a/i18n_ts/ru.ts +++ b/i18n_ts/ru.ts @@ -2,76 +2,149 @@ - BioAuthentication + AuthDialog - authentication failed, restart after 2 seconds - Ошибка аутентификации, перезагрузка через 2 секунды + Form + форма + + + More Devices + Дополнительные устройства + + + Biometric + Биометрические + + + Password + пароль + + + Retry + Retry + + + UnLock + отпереть + + + LoggedIn + LoggedIn + + + Password Incorrect, Please try again + Пароль неверен, повторите попытку - BioDeviceView + BioAuthWidget + + Form + форма + + + TextLabel + TextLabel + + + More + Больше + + + Retry + Retry + - password login - логин паролей + Password + пароль + + + BioDevices - fingerprint - отпечаток пальца + FingerPrint + FingerPrint - fingerevin - fingerevin + FingerVein + FingerVein - iris + Iris Ирис + + Face + Лицо + + + VoicePrint + Voiceprint + - MainWindow + BioDevicesWidget - MainWindow - MainWindow + Form + форма - Username - имя пользователя + Please select other biometric devices + Выберите другие биометрические устройства - Unlock - отпереть + Device Type: + Тип устройства: - Has Logged In - Записан + Device Name: + Имя устройства: + + + KeyboardWidget - Avatar - Аватар + KeyboardWidget + KeyboardWidget + + + LockWidget - Switch User - Сменить пользователя + Form + форма - TextLabel - TextLabel + Date + Дата + + + Time + Время - Password Incorrect - Неверный пароль + Guest + гость + + + SwitchUser + Сменить пользователя main - Dialog for the ukui ScreenSaver. - Диалог для экранного экрана ukui. + Start command for the ukui ScreenSaver. + Начните команду для ukui ScreenSaver. lock the screen immediately немедленно заблокируйте экран + + Dialog for the ukui ScreenSaver. + Диалог для экранного экрана ukui. + activated by session idle signal активируется сигналом холостого хода diff --git a/i18n_ts/zh_CN.ts b/i18n_ts/zh_CN.ts index 4616653..c16bdab 100644 --- a/i18n_ts/zh_CN.ts +++ b/i18n_ts/zh_CN.ts @@ -2,94 +2,216 @@ - BioAuthentication + AuthDialog - - authentication failed, restart after 2 seconds - 认证失败,两秒后重新开始 + More Devices + 选择其他设备 + + + Biometric + 使用生物识别认证 + + + Password + 使用密码认证 + + + + Retry + 重试 + + + UnLock + 解锁 + + + LoggedIn + 已登录 + + + + Password: + 密码: + + + + Password Incorrect, Please try again + 密码错误,请重试 + + + + Biometric Authentication + 生物识别认证 + + + + Password Authentication + 密码认证 + + + + Other Devices + 其他设备 + + + + BioDevices + + FingerPrint + 指纹 + + + FingerVein + 指静脉 + + + Iris + 虹膜 + + + Face + 人脸 + + + VoicePrint + 声纹 - BioDeviceView + BioDevicesWidget - - password login - 密码 + Please select other biometric devices + 请选择其他生物识别设备 - - fingerprint + Device Type: + 设备类型: + + + Device Name: + 设备名称: + + + + BiometricAuthWidget + + + Current device: + 当前设备: + + + + Identify failed, Please retry. + 识别失败,请重试 + + + + BiometricDevicesWidget + + + Please select the biometric device + 请选择生物设备 + + + + Device type: + 设备类型: + + + + Device name: + 设备型号: + + + + OK + 确定 + + + + DeviceType + + + FingerPrint 指纹 - - fingerevin + + FingerVein 指静脉 - - iris + + Iris 虹膜 - - - MainWindow - - MainWindow - + + Face + 人脸 - - Avatar - + + VoicePrint + 声纹 + + + KeyboardWidget - - Switch User - 切换用户 + + KeyboardWidget + + + + LockWidget - - - TextLabel - + + Form + - - Username + + Date - - Has Logged In - 已登录 + + Time + - - Unlock - 解锁 + + Guest + 游客 - - Password Incorrect - 密码错误 + + SwitchUser + 切换用户 main - - Dialog for the ukui ScreenSaver. + + Start command for the ukui ScreenSaver. - + + lock the screen immediately - + + Dialog for the ukui ScreenSaver. + + + + activated by session idle signal diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..08b0fcb --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,113 @@ +pkg_check_modules(X11 REQUIRED x11) +pkg_check_modules(XTST REQUIRED xtst) +pkg_check_modules(XCB REQUIRED xcb) +pkg_check_modules(QGS REQUIRED gsettings-qt) + +find_library(PAM_LIBRARIES pam) + +include_directories(${PROJECT_SOURCE_DIR}/VirtualKeyboard/src) +include_directories(${PROJECT_SOURCE_DIR}/BiometricAuth) + +include_directories( + ${X11_INCLUDE_DIRS} + ${XTST_INCLUDE_DIRS} + ${XCB_INCLUDE_DIRS} + ${QGS_INCLUDE_DIRS} + ) + +set(EXTRA_LIBS + ${EXTRA_LIBS} + ${PAM_LIBRARIES} + ${X11_LIBRARIES} + ${XTST_LIBRARIES} + ${XCB_LIBRARIES} + ${QGS_LIBRARIES} + ) + +qt5_wrap_ui(dialog_SRC + lockwidget.ui + ) + +qt5_add_resources(dialog_SRC + assets.qrc + ) + +# 头文件中包含了Xlib.h,需要单独拿出来处理,不知道原因 +qt5_wrap_cpp(dialog_SRC + fullbackgroundwidget.h + lockwidget.h + authdialog.h + screensaverwidget.h + auth.h + auth-pam.h + screensaver.h + xeventmonitor.h + monitorwatcher.h + configuration.h + users.h + displaymanager.h + iconedit.h + ) + +set(dialog_SRC + ${dialog_SRC} + ukui-screensaver-dialog.cpp + fullbackgroundwidget.cpp + lockwidget.cpp + authdialog.cpp + screensaverwidget.cpp + auth-pam.cpp + xeventmonitor.cpp + monitorwatcher.cpp + grab-x11.cpp + configuration.cpp + screensaver.cpp + users.cpp + displaymanager.cpp + iconedit.cpp + ) +add_executable(ukui-screensaver-dialog ${dialog_SRC}) + +target_link_libraries(ukui-screensaver-dialog + Qt5::Core + Qt5::Widgets + Qt5::DBus + Qt5::X11Extras + ${EXTRA_LIBS} + BiometricAuth VirtualKeyboard + ) + +qt5_wrap_cpp(backend_SRC + interface.h + sessionwatcher.h + interfaceAdaptor.h + ) +set(backend_SRC + ${backend_SRC} + ukui-screensaver-backend.cpp + interface.cpp + sessionwatcher.cpp + interfaceAdaptor.cpp + ) +add_executable(ukui-screensaver-backend ${backend_SRC}) +target_link_libraries(ukui-screensaver-backend Qt5::Core Qt5::DBus) + +set(command_SRC + ukui-screensaver-command.cpp + ) +add_executable(ukui-screensaver-command ${command_SRC}) +target_link_libraries(ukui-screensaver-command Qt5::Core Qt5::DBus) + + +install(TARGETS + ukui-screensaver-dialog + ukui-screensaver-backend + ukui-screensaver-command + DESTINATION bin) + +#set(test-act_SRC +# users.cpp +# test-accounts.cpp +# ) +#add_executable(test-accounts ${test-act_SRC}) +#target_link_libraries(test-accounts Qt5::Core Qt5::DBus) diff --git a/src/VirtualKeyboard b/src/VirtualKeyboard deleted file mode 160000 index 77ca340..0000000 --- a/src/VirtualKeyboard +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 77ca340b355e6be669959791bc1a5ef921faf0f2 diff --git a/src/assets.qrc b/src/assets.qrc index b842ab6..18d4838 100644 --- a/src/assets.qrc +++ b/src/assets.qrc @@ -4,11 +4,18 @@ assets/show-password.png - assets/warn.png - assets/arrow_left.png - assets/arrow_left_prelight.png - assets/arrow_left_active.png assets/hide-password.png assets/keyboard.png + assets/avatar.png + assets/waiting.png + assets/capslock.png + assets/combobox_down.png + assets/scrollbar_down.png + assets/scrollbar_down_clicked.png + assets/scrollbar_down_hover.png + assets/scrollbar_up.png + assets/scrollbar_up_clicked.png + assets/scrollbar_up_hover.png + assets/unlock-button.png diff --git a/src/assets/arrow_left.png b/src/assets/arrow_left.png deleted file mode 100644 index abfd68f..0000000 Binary files a/src/assets/arrow_left.png and /dev/null differ diff --git a/src/assets/arrow_left_active.png b/src/assets/arrow_left_active.png deleted file mode 100644 index bc15583..0000000 Binary files a/src/assets/arrow_left_active.png and /dev/null differ diff --git a/src/assets/arrow_left_prelight.png b/src/assets/arrow_left_prelight.png deleted file mode 100644 index 65439de..0000000 Binary files a/src/assets/arrow_left_prelight.png and /dev/null differ diff --git a/src/assets/authdialog.qss b/src/assets/authdialog.qss index 6ef9574..f3b4785 100644 --- a/src/assets/authdialog.qss +++ b/src/assets/authdialog.qss @@ -1,77 +1,196 @@ QPushButton { border: none; outline: none; + color: white; +} +QPushButton::hover { + background: rgba(0, 0, 0, 50); +} +QPushButton::pressed { + background: rgba(0, 0, 0, 120); } QLabel { color: white; } -/* 解锁按钮 */ -#btnUnlock { - color: black; - background-color: #0078d7; +#userWidget{ +/* background: rgba(255, 0, 255, 30%);*/ } -#btnUnlock:hover { - background-color: #3f8de0; +/* 头像 */ +#faceLabel { + border:2px solid white; } -#btnUnlock:active { - background-color: #2367b9; + +/* 用户名 */ +#login_nameLabel{ + font-size: 28px; } -#btnUnlock:disabled { - background-color: #013C76; + +/* 密码输入框 */ +QLineEdit { + background: #FFFFFF; + border: 1px solid #FFFFFF; + font-size: 14px; + lineedit-password-character:9679; +} +QLineEdit::disabled { + background: lightgray; +} +QLineEdit::hover { + border: 1px solid #00FFFF; +} +QLineEdit::focus{ + background: #CDDDEC; + border: #CDDDEC; + +} +/* 大写提示 */ +#capsIconLabel{ + background: url(:/image/assets/capslock.png); + background-repeat: no-repeat; + background-position: center; + max-width: 22px; + max-height: 22px; + min-width: 22px; + min-height: 22px; } -/* 生物识别按钮*/ -#btnBiometric::hover{ - background-color:rgb(0, 0, 0, 50); +/* echo mode */ +#echoModeButton { + background: transparent; + image: url(:/image/assets/hide-password.png); + max-width: 22px; + max-height: 22px; + margin-right: 5px; +} +#echoModeButton::checked { + image: url(:/image/assets/show-password.png); +} +/* 登录按钮 */ +#loginButton{ + background: #559BE2; +/* image: url(:/image/assets/login-button.png);*/ + min-width: 26px; + max-width: 26px; + min-height: 26px; + max-height: 26px; + margin-right: 4px; + icon-size: 26px; +} +#loginButton::hover{ + background: #1172D5; +} +#loginButton::pressed{ + background: #0653A1; +} +/* PAM message提示*/ +#messageLabel { + font-size: 16px; + color: white; } -/* 密码框 */ -#lineEditPassword { - border:1px solid #026096; - font-size: 14px + +/* 切换用户 */ +QPushButton::menu-indicator{ + image:none; +} +QMenu{ + background-color: rgb(89,87,87); + border: 1px solid black; + color: white; + font-size: 14px; +} +QMenu::item:selected { + background-color:rgb(235,110,36); +} +QMenu::item:pressed { + background-color: rgb(220,80,6); } -/* 提示 */ -#lblLogged, #lblPrompt { - color: white; font-size: 13px; +/* 虚拟键盘开启按钮、用户切换按钮 */ +#btnSwitchUser, #btnKeyboard { + border: 1px solid gray; +} +#btnKeyboard, #btnSwitchUser { + border: 1px solid gray; +} +#btnKeyboard::hover, #btnSwitchUser::hover { + background-color: rgb(255, 255, 255, 20%); } +#btnKeyboard::pressed, #btnSwitchUser::pressed{ + background: rgba(0, 0, 0, 30%); +} + + -#lblUsername { - font-size: 20px; +/********************** 下拉选项 *************************/ + +QComboBox{ + background: rgba(255, 255, 255, 20); + border: 1px solid rgb(255, 255, 255, 30); + font-size:18px; color: white; + combobox-popup: 0; /* 配合setMaxVisibleItems设置下拉框显示的条数,超过的滚动显示 */ } -/* 头像 */ -#lblAvatar { - border:2px solid white; +QComboBox::down-arrow{ + image:url(:/image/assets/combobox_down.png); +} +QComboBox::drop-down{ + width: 30px; + border: none; } -/* 返回按钮 */ -#btnSwitchUser{ - background: url(:/image/assets/arrow_left.png); - background-repeat: no-repeat; - background-position: center; +QComboBox QListView{ + border: 1px solid #5187bd; + background: #4682B4; + background: rgba(255, 255, 255, 30%); + font-size: 18px; + color: white; } -#btnSwitchUser::hover{ - background: url(:/image/assets/arrow_left_prelight.png); - background-repeat: no-repeat; - background-position: center; +QComboBox QListView::item:hover{ + background: rgba(255, 255, 255, 20%); + +} +QComboBox QListView::item:selected{ + background-color: rgba(255, 255, 255, 30%); } -#btnKeyboard::hover, #btnPower::hover { - background-color: rgb(255, 255, 255, 50); +/********************** 生物识别切换按钮 **************************/ +#biometricButton, #passwordButton, +#otherDeviceButton, #retryButton, +#OKButton +{ + background: rgba(255, 255, 255, 20%); + font-size: 14px; + border: 1px solid rgba(255, 255, 255, 30%); + color: white; } -#btnKeyboard::pressed, #btnPower::pressed { - background: rgb(255, 255, 255, 150); +#biometricButton::hover, #passwordButton::hover, +#otherDeviceButton::hover, #retryButton::hover, +#OKButton::hover +{ + background: rgba(255, 255, 255, 35%); + border: 1px solid rgba(255, 255, 255, 50%); } -#btnKeyboard { - border: 1px solid gray; +#biometricButton::pressed, #passwordButton::pressed, +#otherDeviceButton::pressed, #retryButton::pressed, +#OKButton::pressed +{ + background: rgba(0, 0, 0, 15%); + border: 1px solid rgba(255, 255, 255, 20%); } -#btnKeyboard::pressed{ - background: rgba(0, 0, 0, 200); + + +/********************** 生物识别设备选择界面 ************************/ +#lblBioetricDevicesPrompt { + font-size: 30px; } +#lblDeviceType, #lblDeviceName, +#cmbDeviceType, #cmbDeviceName{ + font-size: 18px; +} diff --git a/src/assets/avatar.png b/src/assets/avatar.png new file mode 100644 index 0000000..cbb92d0 Binary files /dev/null and b/src/assets/avatar.png differ diff --git a/src/assets/capslock.png b/src/assets/capslock.png new file mode 100644 index 0000000..b4259ab Binary files /dev/null and b/src/assets/capslock.png differ diff --git a/src/assets/combobox_down.png b/src/assets/combobox_down.png new file mode 100644 index 0000000..e07de91 Binary files /dev/null and b/src/assets/combobox_down.png differ diff --git a/src/assets/hide-password.png b/src/assets/hide-password.png index d4e1bf7..bd85995 100644 Binary files a/src/assets/hide-password.png and b/src/assets/hide-password.png differ diff --git a/src/assets/scrollbar_down.png b/src/assets/scrollbar_down.png new file mode 100644 index 0000000..9dbebca Binary files /dev/null and b/src/assets/scrollbar_down.png differ diff --git a/src/assets/scrollbar_down_clicked.png b/src/assets/scrollbar_down_clicked.png new file mode 100644 index 0000000..fe8bc04 Binary files /dev/null and b/src/assets/scrollbar_down_clicked.png differ diff --git a/src/assets/scrollbar_down_hover.png b/src/assets/scrollbar_down_hover.png new file mode 100644 index 0000000..50da897 Binary files /dev/null and b/src/assets/scrollbar_down_hover.png differ diff --git a/src/assets/scrollbar_up.png b/src/assets/scrollbar_up.png new file mode 100644 index 0000000..8618cf9 Binary files /dev/null and b/src/assets/scrollbar_up.png differ diff --git a/src/assets/scrollbar_up_clicked.png b/src/assets/scrollbar_up_clicked.png new file mode 100644 index 0000000..20c6e3c Binary files /dev/null and b/src/assets/scrollbar_up_clicked.png differ diff --git a/src/assets/scrollbar_up_hover.png b/src/assets/scrollbar_up_hover.png new file mode 100644 index 0000000..9b2532c Binary files /dev/null and b/src/assets/scrollbar_up_hover.png differ diff --git a/src/assets/show-password.png b/src/assets/show-password.png index b4c5853..afaf744 100644 Binary files a/src/assets/show-password.png and b/src/assets/show-password.png differ diff --git a/src/assets/unlock-button.png b/src/assets/unlock-button.png new file mode 100644 index 0000000..6b7ed57 Binary files /dev/null and b/src/assets/unlock-button.png differ diff --git a/src/assets/waiting.png b/src/assets/waiting.png new file mode 100644 index 0000000..2136f8b Binary files /dev/null and b/src/assets/waiting.png differ diff --git a/src/assets/warn.png b/src/assets/warn.png deleted file mode 100644 index 2995db8..0000000 Binary files a/src/assets/warn.png and /dev/null differ diff --git a/src/auth-pam.cpp b/src/auth-pam.cpp new file mode 100644 index 0000000..45409f5 --- /dev/null +++ b/src/auth-pam.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include "auth-pam.h" + +#include + +#include +#include + + +#define PAM_SERVICE_NAME "ukui-screensaver-qt" + +//通信管道的文件描述符 +int toParent[2], toChild[2]; + +static void writeData(int fd, const void *buf, ssize_t count); +static void writeString(int fd, const char *data); +static int readData(int fd, void *buf, size_t count); +static char * readString(int fd); +static int pam_conversation(int msgLength, const struct pam_message **msg, + PAM_RESPONSE **resp, void *appData); +static void sigchld_handler(int signo); + +AuthPAM::AuthPAM(QObject *parent) + : Auth(parent), + pid(0), + nPrompts(0), + _isAuthenticated(false), + _isAuthenticating(false) +{ + signal(SIGCHLD, sigchld_handler); +} + +void AuthPAM::authenticate(const QString &userName) +{ + stopAuth(); + + if(pipe(toParent) || pipe(toChild)) + qDebug()<< "create pipe failed: " << strerror(errno); + if((pid = fork()) < 0) + { + qDebug() << "fork error: " << strerror(errno); + } + else if(pid == 0) + { + _authenticate(userName.toLocal8Bit().data()); + } + else + { + _isAuthenticating = true; + notifier = new QSocketNotifier(toParent[0], QSocketNotifier::Read); + connect(notifier, &QSocketNotifier::activated, this, &AuthPAM::onSockRead); + } +} + +void AuthPAM::stopAuth() +{ + if(pid != 0) + { + messageList.clear(); + responseList.clear(); + _isAuthenticating = false; + _isAuthenticated = false; + nPrompts = 0; + + ::kill(pid, SIGKILL); + + pid = 0; + } +} + +void AuthPAM::respond(const QString &response) +{ + nPrompts--; + responseList.push_back(response); + +// for(auto msg : messageList) +// qDebug() << msg.msg; +// qDebug() << responseList; +// qDebug() << nPrompts; + + if(nPrompts == 0) + { + //发送响应到子进程 + int j = 0; + PAM_RESPONSE *resp = (PAM_RESPONSE*)calloc(messageList.size(), sizeof(PAM_RESPONSE)); + //响应的数量和消息的数量一致,如果消息类型不是PROMPT,则响应是空的 + for(int i = 0; i < messageList.size(); i++) + { + struct pam_message message = messageList[i]; + PAM_RESPONSE *r = &resp[i]; + if(message.msg_style == PAM_PROMPT_ECHO_OFF + || message.msg_style == PAM_PROMPT_ECHO_ON) + { + int respLength = responseList[j].length() + 1; + r->resp = (char *)malloc(sizeof(char) * respLength); + memcpy(r->resp, responseList[j].toLocal8Bit().data(), respLength); + j++; + } + } + _respond(resp); + free(resp); + messageList.clear(); + responseList.clear(); + } +} + +bool AuthPAM::isAuthenticated() +{ + return _isAuthenticated; +} + +bool AuthPAM::isAuthenticating() +{ + return _isAuthenticating; +} + + +void AuthPAM::onSockRead() +{ +// qDebug() << "has message"; + int msgLength; + int authComplete; + readData(toParent[0], &authComplete, sizeof(authComplete)); + + if(authComplete) + { + int authRet; + if(readData(toParent[0], (void*)&authRet, sizeof(authRet)) <= 0) + qDebug() << "get authentication result failed: " << strerror(errno); + qDebug() << "result: " << authRet; + _isAuthenticated = (authRet == PAM_SUCCESS); + _isAuthenticating = false; + Q_EMIT authenticateComplete(); + + } + else + { + readData(toParent[0], &msgLength, sizeof(msgLength)); +// qDebug() << "message length: " << msgLength; + + for(int i = 0; i < msgLength; i++) + { + //读取message + struct pam_message message; + readData(toParent[0], &message.msg_style, sizeof(message.msg_style)); + message.msg = readString(toParent[0]); + + qDebug() << message.msg; + + messageList.push_back(message); + + switch (message.msg_style) + { + case PAM_PROMPT_ECHO_OFF: + nPrompts++; + Q_EMIT showPrompt(message.msg, Auth::PromptTypeSecret); + break; + case PAM_PROMPT_ECHO_ON: + nPrompts++; + Q_EMIT showPrompt(message.msg, Auth::PromptTypeQuestion); + break; + case PAM_ERROR_MSG: + Q_EMIT showMessage(message.msg, Auth::MessageTypeInfo); + break; + case PAM_TEXT_INFO: + Q_EMIT showMessage(message.msg, Auth::MessageTypeError); + break; + } + } + + if(nPrompts == 0) + { + //不需要响应,发送一个空的 + PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(messageList.size(), sizeof(PAM_RESPONSE)); + _respond(response); + free(response); + messageList.clear(); + } + } +} + +static void +writeData(int fd, const void *buf, ssize_t count) +{ + if(write(fd, buf, count) != count) + qDebug() << "write to parent failed: " << strerror(errno); +} + +static void +writeString(int fd, const char *data) +{ + int length = data ? strlen(data) : -1; + writeData(fd, &length, sizeof(length)); + if(data) + writeData(fd, data, sizeof(char) * length); +} + +static int +readData(int fd, void *buf, size_t count) +{ + ssize_t nRead = read(fd, buf, count); + if(nRead < 0) + qDebug() << "read data failed: " << strerror(errno); + return nRead; +} + +static char * +readString(int fd) +{ + int length; + + if(readData(fd, &length, sizeof(length)) <= 0) + return NULL; + if(length <= 0) + return NULL; + + char *value = (char *)malloc(sizeof(char) * (length + 1)); + readData(fd, value, length); + value[length] = '\0'; + + return value; +} + +void AuthPAM::_authenticate(const char *userName) +{ + qDebug() << "authenticate " << userName; + + pam_handle_t *pamh = NULL; + char *newUser; + int ret; + int authRet; + struct pam_conv conv; + + conv.conv = pam_conversation; + conv.appdata_ptr = NULL; + + ret = pam_start(PAM_SERVICE_NAME, userName, &conv, &pamh); + if(ret != PAM_SUCCESS) + { + qDebug() << "failed to start PAM: " << pam_strerror(NULL, ret); + } + + authRet = pam_authenticate(pamh, 0); + + ret = pam_get_item(pamh, PAM_USER, (const void **)&newUser); + if(ret != PAM_SUCCESS) + { + pam_end(pamh, 0); + qDebug() << "failed to get username"; + } + free(newUser); + fprintf(stderr, "authentication result: %d\n", authRet); + + // 发送认证结果 + int authComplete = 1; + writeData(toParent[1], (const void*)&authComplete, sizeof(authComplete)); + writeData(toParent[1], (const void *)&authRet, sizeof(authRet)); + qDebug() << "--- 认证完成"; + _exit(EXIT_SUCCESS); +} + +void AuthPAM::_respond(const PAM_RESPONSE *response) +{ + for(int i = 0; i < messageList.size(); i++) + { + const PAM_RESPONSE *resp = &response[i]; + writeData(toChild[1], (const void *)&resp->resp_retcode, + sizeof(resp->resp_retcode)); + writeString(toChild[1], resp->resp); + } +} + + +static int +pam_conversation(int msgLength, const struct pam_message **msg, + PAM_RESPONSE **resp, void */*appData*/) +{ + PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(msgLength,sizeof(PAM_RESPONSE)); + + int authComplete = 0; + writeData(toParent[1], (const void*)&authComplete, sizeof(authComplete)); + writeData(toParent[1], (const void*)&msgLength, sizeof(msgLength)); + //发送pam消息 + for(int i = 0; i < msgLength; i++) + { + const struct pam_message *m = msg[i]; + writeData(toParent[1], (const void *)&m->msg_style, sizeof(m->msg_style)); + writeString(toParent[1], m->msg); + } + //读取响应 + for(int i = 0; i < msgLength; i++) + { + PAM_RESPONSE *r = &response[i]; + readData(toChild[0], &r->resp_retcode, sizeof(r->resp_retcode)); + r->resp = readString(toChild[0]); + } + *resp = response; + return PAM_SUCCESS; +} + +void sigchld_handler(int signo) +{ + if(signo == SIGCHLD) + { + ::waitpid(-1, NULL, WNOHANG); + } +} diff --git a/src/auth-pam.h b/src/auth-pam.h new file mode 100644 index 0000000..3fba36c --- /dev/null +++ b/src/auth-pam.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef AUTHPAM_H +#define AUTHPAM_H +#include "auth.h" +#include +#include + +#include + +typedef struct pam_message PAM_MESSAGE; +typedef struct pam_response PAM_RESPONSE; + +class AuthPAM : public Auth +{ + Q_OBJECT +public: + AuthPAM(QObject *parent = nullptr); + + void authenticate(const QString &userName); + void stopAuth(); + void respond(const QString &response); + bool isAuthenticated(); + bool isAuthenticating(); + +private: + void _authenticate(const char *userName); + void _respond(const struct pam_response *response); + +private Q_SLOTS: + void onSockRead(); + +private: + QString userName; + pid_t pid; + QSocketNotifier *notifier; + int nPrompts; + QStringList responseList; + QList messageList; + bool _isAuthenticated; //认证结果 + bool _isAuthenticating; +}; + +#endif // AUTHPAM_H diff --git a/src/gsettings.h b/src/auth.h similarity index 51% rename from src/gsettings.h rename to src/auth.h index 0f63a91..b2f8193 100644 --- a/src/gsettings.h +++ b/src/auth.h @@ -15,45 +15,48 @@ * along with this program; if not, see . * **/ -#ifndef GSETTINGS_H -#define GSETTINGS_H +#ifndef AUTH_H +#define AUTH_H -/* https://forum.qt.io/topic/7399 */ #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include -extern "C" { - #include -} -class QGSettings : public QObject +class Auth : public QObject { - Q_OBJECT + Q_OBJECT + Q_ENUMS(PromptType MessageType) public: - explicit QGSettings(QString schema, QObject *parent = nullptr); + explicit Auth(QObject *parent = nullptr) + : QObject(parent) + { + + } + + enum PromptType { + PromptTypeQuestion, + PromptTypeSecret + }; + enum MessageType { + MessageTypeInfo, + MessageTypeError + }; -public: - QString getString(QString key); - int getInt(QString key); - bool getBool(QString key); - QList getStringList(QString key); - int getEnum(QString key); - - bool setString(QString key, QString value); - bool setInt(QString key, int value); - bool setBool(QString key, bool value); - bool setStringList(QString key, QList value); - static void changedCallback(GSettings *gsettings, const gchar *key, - gpointer user_data); Q_SIGNALS: - void valueChanged(QString key); + void showPrompt(const QString &prompt, Auth::PromptType type); + void showMessage(const QString &message, Auth::MessageType type); + void authenticateComplete(); -private: - GSettings *gsettings; +public: + virtual void authenticate(const QString &userName) = 0; + virtual void stopAuth() = 0; + virtual void respond(const QString &response) = 0; + virtual bool isAuthenticating() = 0; + virtual bool isAuthenticated() = 0; }; -#endif // GSETTINGS_H +#endif // AUTH_H diff --git a/src/authdialog.cpp b/src/authdialog.cpp new file mode 100644 index 0000000..fc8de14 --- /dev/null +++ b/src/authdialog.cpp @@ -0,0 +1,580 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include "authdialog.h" + +#include +#include +#include + +#include +#include + +#include "users.h" +#include "iconedit.h" +#include "biometricproxy.h" +#include "biometricauthwidget.h" +#include "biometricdeviceswidget.h" + +AuthDialog::AuthDialog(const UserItem &user, QWidget *parent) : + QWidget(parent), + user(user), + auth(new AuthPAM(this)), + m_deviceCount(-1), + authMode(UNKNOWN), + m_biometricProxy(nullptr), + m_biometricAuthWidget(nullptr), + m_biometricDevicesWidget(nullptr), + m_buttonsWidget(nullptr) +{ + initUI(); + + connect(auth, &Auth::showMessage, this, &AuthDialog::onShowMessage); + connect(auth, &Auth::showPrompt, this, &AuthDialog::onShowPrompt); + connect(auth, &Auth::authenticateComplete, this, &AuthDialog::onAuthComplete); + +} + +void AuthDialog::startAuth() +{ + auth->authenticate(user.name); + + showPasswordAuthWidget(); + m_passwordEdit->clear(); + m_passwordEdit->setEnabled(false); +} + +void AuthDialog::stopAuth() +{ + //这里只是为了在显示屏幕保护程序时停止生物识别认证 + + if(m_biometricAuthWidget) + m_biometricAuthWidget->stopAuth(); +} + +void AuthDialog::initUI() +{ + setFixedWidth(500); + + m_userWidget = new QWidget(this); + m_userWidget->setObjectName(QStringLiteral("userWidget")); + + /* 头像 */ + m_faceLabel = new QLabel(m_userWidget); + m_faceLabel->setObjectName(QStringLiteral("faceLabel")); + m_faceLabel->setFocusPolicy(Qt::NoFocus); + QPixmap facePixmap(user.icon); + facePixmap = facePixmap.scaled(128, 128, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + m_faceLabel->setPixmap(facePixmap); + + /* 用户名 */ + m_nameLabel = new QLabel(m_userWidget); + m_nameLabel->setObjectName(QStringLiteral("login_nameLabel")); + m_nameLabel->setFocusPolicy(Qt::NoFocus); + m_nameLabel->setAlignment(Qt::AlignCenter); + m_nameLabel->setText(user.realName.isEmpty() ? user.name : user.realName); + + /* 密码框所在窗口 */ + m_passwdWidget = new QWidget(this); + m_passwdWidget->setObjectName(QStringLiteral("passwordWidget")); + + /* 密码框 */ + m_passwordEdit = new IconEdit(m_passwdWidget); + m_passwordEdit->setObjectName(QStringLiteral("passwordEdit")); + m_passwordEdit->setIcon(QIcon(":/image/assets/unlock-button.png")); + m_passwordEdit->setFocusPolicy(Qt::StrongFocus); + m_passwordEdit->installEventFilter(this); +// m_passwordEdit->hide(); //收到请求密码的prompt才显示出来 + m_passwordEdit->setEnabled(false); + connect(m_passwordEdit, SIGNAL(clicked(const QString&)), + this, SLOT(onRespond(const QString&))); + + /* 密码认证信息显示列表 */ + m_messageLabel = new QLabel(m_passwdWidget); + m_messageLabel->setObjectName(QStringLiteral("messageLabel")); + m_messageLabel->setAlignment(Qt::AlignCenter); +} + +void AuthDialog::resizeEvent(QResizeEvent *) +{ + setChildrenGeometry(); +} + +void AuthDialog::setChildrenGeometry() +{ + // 用户信息显示位置 + m_userWidget->setGeometry(0, (height() - 240 - 150) / 2, + width(), 240); + m_faceLabel->setGeometry((width() - 128) / 2, 0, 128, 128); + m_nameLabel->setGeometry(0, m_faceLabel->geometry().bottom() + 25, + width(), 40); + + // 密码框和提示信息显示位置 + m_passwdWidget->setGeometry(0, m_userWidget->geometry().bottom(), width(), 150); + m_passwordEdit->setGeometry((m_passwdWidget->width() - 400)/2, 0, 400, 40); + m_messageLabel->setGeometry((m_passwdWidget->width() - 300)/2, + m_passwordEdit->geometry().bottom() + 25, + 300, 20); + + + setBiometricWidgetGeometry(); + setBiometricButtonWidgetGeometry(); +} + + + +void AuthDialog::closeEvent(QCloseEvent *event) +{ + qDebug() << "AuthDialog::closeEvent"; + + if(auth && auth->isAuthenticating()) + { + auth->stopAuth(); + } + return QWidget::closeEvent(event); +} + + +void AuthDialog::onShowMessage(const QString &message, Auth::MessageType type) +{ + m_messageLabel->setText(message); + stopWaiting(); +} + +void AuthDialog::onShowPrompt(const QString &prompt, Auth::PromptType type) +{ + qDebug() << "prompt: " << prompt; + QString text = prompt; + if(text == BIOMETRIC_PAM) + { + if(authMode == PASSWORD) + { + skipBiometricAuth(); + } + else + { + performBiometricAuth(); + } + } + else + { + stopWaiting(); + if(!text.isEmpty()) + m_passwordEdit->setEnabled(true); + + m_passwordEdit->setFocus(); + if(type != Auth::PromptTypeSecret) + m_passwordEdit->setType(QLineEdit::Normal); + else + m_passwordEdit->setType(QLineEdit::Password); + + if(text == "Password: ") + text = tr("Password: "); + + m_passwordEdit->clear(); + m_passwordEdit->setPrompt(text); + } +} + +void AuthDialog::onAuthComplete() +{ + if(auth->isAuthenticated()) + { + Q_EMIT authenticateCompete(true); + } + else + { + onShowMessage(tr("Password Incorrect, Please try again"), + Auth::MessageTypeError); + //认证失败,重新认证 + authMode = PASSWORD; + startAuth(); + } +} + +void AuthDialog::onRespond(const QString &text) +{ + clearMessage(); + startWaiting(); + + auth->respond(text); +} + +void AuthDialog::onCapsLockChanged() +{ + m_passwordEdit->onCapsStateChanged(); +} + +void AuthDialog::startWaiting() +{ + if(m_buttonsWidget) + { + m_buttonsWidget->setEnabled(false); + } +} + +void AuthDialog::stopWaiting() +{ + m_passwordEdit->stopWaiting(); + if(m_buttonsWidget) + { + m_buttonsWidget->setEnabled(true); + } +} + +void AuthDialog::clearMessage() +{ + m_messageLabel->clear(); +} + +void AuthDialog::performBiometricAuth() +{ + if(!m_biometricProxy) + { + m_biometricProxy = new BiometricProxy(this); + } + + //服务没启动,或者打开DBus连接出错 + if(!m_biometricProxy->isValid()) + { + qWarning() << "An error occurs when connect to the biometric DBus"; + skipBiometricAuth(); + return; + } + + //初始化enableBiometriAuth + if(m_deviceCount < 0) + { + m_deviceCount = m_biometricProxy->GetDevCount(); + } + + //没有可用设备,不启用生物识别认证 + if(m_deviceCount < 1) + { + qWarning() << "No available devices"; + skipBiometricAuth(); + return; + } + + initBiometricButtonWidget(); + + //获取默认设备 + if(m_deviceName.isEmpty()) + { + m_deviceName = GetDefaultDevice(user.name); + } + qDebug() << m_deviceName; +// qDebug() << (m_deviceInfo ? m_deviceInfo->shortName : ""); + + //如果默认设备为空的话,第一次不启动生物识别认证 + if(m_deviceName.isEmpty() && !m_deviceInfo) + { + qDebug() << "No default device"; + skipBiometricAuth(); + return; + } + + //初始化生物识别认证UI + initBiometricWidget(); + clearMessage(); + + if(!m_deviceInfo) + { + m_deviceInfo = m_biometricDevicesWidget->findDeviceByName(m_deviceName); + } + if(!m_deviceInfo) + { + skipBiometricAuth(); + return; + } + + authMode = BIOMETRIC; + + m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); + + showBiometricAuthWidget(); +} + +void AuthDialog::skipBiometricAuth() +{ + auth->respond(BIOMETRIC_IGNORE); + + showPasswordAuthWidget(); +} + +void AuthDialog::initBiometricWidget() +{ + if(m_biometricAuthWidget) + { + return; + } + + m_biometricAuthWidget = new BiometricAuthWidget(m_biometricProxy, this); + connect(m_biometricAuthWidget, &BiometricAuthWidget::authComplete, + this, &AuthDialog::onBiometricAuthComplete); + m_biometricDevicesWidget = new BiometricDevicesWidget(m_biometricProxy, this); + connect(m_biometricDevicesWidget, &BiometricDevicesWidget::deviceChanged, + this, &AuthDialog::onDeviceChanged); + + setBiometricWidgetGeometry(); +} + +void AuthDialog::initBiometricButtonWidget() +{ + if(m_buttonsWidget) + { + return; + } + + m_buttonsWidget = new QWidget(this); + m_buttonsWidget->setObjectName(QStringLiteral("buttonsWidget")); + m_buttonsWidget->setFixedHeight(25); + + QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + + m_biometricButton = new QPushButton(m_buttonsWidget); + m_biometricButton->setObjectName(QStringLiteral("biometricButton")); + m_biometricButton->setText(tr("Biometric Authentication")); + m_biometricButton->setSizePolicy(sizePolicy); + m_biometricButton->setVisible(false); + m_biometricButton->setCursor(Qt::PointingHandCursor); + QFontMetrics fm(m_biometricButton->font(), m_biometricButton); + int width = fm.width(m_biometricButton->text()); + m_biometricButton->setMaximumWidth(width + 20); + connect(m_biometricButton, &QPushButton::clicked, + this, &AuthDialog::onBiometricButtonClicked); + + m_passwordButton = new QPushButton(m_buttonsWidget); + m_passwordButton->setObjectName(QStringLiteral("passwordButton")); + m_passwordButton->setText(tr("Password Authentication")); + fm = QFontMetrics(m_passwordButton->font(), m_passwordButton); + width = fm.width(m_passwordButton->text()); + m_passwordButton->setMaximumWidth(std::max(width + 20, 110)); + m_passwordButton->setSizePolicy(sizePolicy); + m_passwordButton->setVisible(false); + m_passwordButton->setCursor(Qt::PointingHandCursor); + connect(m_passwordButton, &QPushButton::clicked, + this, &AuthDialog::onPasswordButtonClicked); + + m_otherDeviceButton = new QPushButton(m_buttonsWidget); + m_otherDeviceButton->setObjectName(QStringLiteral("otherDeviceButton")); + m_otherDeviceButton->setText(tr("Other Devices")); + m_otherDeviceButton->setSizePolicy(sizePolicy); + m_otherDeviceButton->setMaximumWidth(std::max(width + 20, 110)); + m_otherDeviceButton->setVisible(false); + m_otherDeviceButton->setCursor(Qt::PointingHandCursor); + connect(m_otherDeviceButton, &QPushButton::clicked, + this, &AuthDialog::onOtherDevicesButtonClicked); + + m_retryButton = new QPushButton(m_buttonsWidget); + m_retryButton->setObjectName(QStringLiteral("retryButton")); + m_retryButton->setText(tr("Retry")); + m_retryButton->setSizePolicy(sizePolicy); + m_retryButton->setMaximumWidth(110); + m_retryButton->setVisible(false); + m_retryButton->setCursor(Qt::PointingHandCursor); + connect(m_retryButton, &QPushButton::clicked, + this, &AuthDialog::onRetryButtonClicked); + + QGridLayout *layout = new QGridLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_biometricButton, 0, 0); + layout->addWidget(m_passwordButton, 0, 1); + layout->addWidget(m_otherDeviceButton, 0, 2); + layout->addWidget(m_retryButton, 0, 3); + + m_buttonsWidget->setLayout(layout); + m_buttonsWidget->show(); + + setBiometricButtonWidgetGeometry(); +} + +void AuthDialog::setBiometricWidgetGeometry() +{ + //生物识别 + if(m_biometricAuthWidget) + { + m_biometricAuthWidget->setGeometry(0, m_userWidget->geometry().bottom(), + width(), m_biometricAuthWidget->height()); + } + if(m_biometricDevicesWidget) + { + m_biometricDevicesWidget->setGeometry((width() - m_biometricDevicesWidget->width()) / 2, + (height() - m_biometricDevicesWidget->height()) / 2, + m_biometricDevicesWidget->width(), + m_biometricDevicesWidget->height()); + } +} + +void AuthDialog::setBiometricButtonWidgetGeometry() +{ + if(m_buttonsWidget) + { + m_buttonsWidget->setGeometry(0, height() - m_buttonsWidget->height() - 20, + width(), m_buttonsWidget->height()); + } +} + +void AuthDialog::onDeviceChanged(const DeviceInfoPtr &deviceInfo) +{ + qDebug() << "device changed: " << *deviceInfo; + m_deviceInfo = deviceInfo; + + if(authMode != BIOMETRIC) + { + authMode = BIOMETRIC; + startAuth(); + } + else + { + m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); + } + + m_userWidget->show(); + m_passwdWidget->hide(); + m_biometricAuthWidget->show(); + m_buttonsWidget->show(); + m_biometricDevicesWidget->hide(); + m_biometricButton->hide(); + m_passwordButton->show(); + m_otherDeviceButton->show(); + m_retryButton->hide(); +} + +void AuthDialog::onBiometricAuthComplete(bool result) +{ + if(!result) + { + m_retryButton->setVisible(!m_biometricAuthWidget->isHidden()); + } + else + { + auth->respond(BIOMETRIC_SUCCESS); + } +} + +void AuthDialog::onBiometricButtonClicked() +{ + //当前没有设备,让用户选择设备 + if(!m_deviceInfo) + { + m_otherDeviceButton->click(); + } + else + { + authMode = BIOMETRIC; + startAuth(); + } + +} + +void AuthDialog::onPasswordButtonClicked() +{ + skipBiometricAuth(); +} + +void AuthDialog::onOtherDevicesButtonClicked() +{ + m_biometricAuthWidget->stopAuth(); + + showBiometricDeviceWidget(); +} + +void AuthDialog::onRetryButtonClicked() +{ + m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); + m_retryButton->setVisible(false); +} + +void AuthDialog::showPasswordAuthWidget() +{ + m_userWidget->setVisible(true); + m_passwdWidget->setVisible(true); + + if(m_biometricAuthWidget) + { + m_biometricAuthWidget->setVisible(false); + m_biometricDevicesWidget->setVisible(false); + + m_biometricAuthWidget->stopAuth(); + } + + if(m_buttonsWidget) + { + if(m_deviceCount > 0) + { + m_buttonsWidget->setVisible(true); + m_biometricButton->setVisible(true); + m_passwordButton->setVisible(false); + m_otherDeviceButton->setVisible(false); + m_retryButton->setVisible(false); + } + else + { + qDebug() << "hide buttons widget"; + m_buttonsWidget->setVisible(false); + } + } +} + +void AuthDialog::showBiometricAuthWidget() +{ + m_userWidget->setVisible(true); + m_passwdWidget->setVisible(false); + + if(m_biometricAuthWidget) + { + m_biometricAuthWidget->setVisible(true); + m_biometricDevicesWidget->setVisible(false); + } + + if(m_buttonsWidget && m_deviceCount > 0) + { + m_buttonsWidget->setVisible(true); + m_biometricButton->setVisible(false); + m_passwordButton->setVisible(true); + m_otherDeviceButton->setVisible(m_deviceCount > 1); + m_retryButton->setVisible(!m_biometricAuthWidget->isAuthenticating()); + } + else + { + m_buttonsWidget->setVisible(false); + } +} + +void AuthDialog::showBiometricDeviceWidget() +{ + m_userWidget->setVisible(false); + m_passwdWidget->setVisible(false); + + if(m_biometricAuthWidget) + { + m_biometricAuthWidget->setVisible(false); + m_biometricDevicesWidget->setVisible(true); + } + + if(m_buttonsWidget) + { + m_buttonsWidget->setVisible(false); + m_biometricButton->setVisible(false); + m_passwordButton->setVisible(false); + m_otherDeviceButton->setVisible(false); + m_retryButton->setVisible(false); + } +} diff --git a/src/authdialog.h b/src/authdialog.h new file mode 100644 index 0000000..f38b1e8 --- /dev/null +++ b/src/authdialog.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef AUTHDIALOG_H +#define AUTHDIALOG_H + +#ifndef QT_NO_KEYWORDS +#define QT_NO_KEYWORDS +#endif + +#include +#include "auth-pam.h" +#include "types.h" +#include "users.h" +#include "biometricdeviceinfo.h" + + +namespace Ui { +class AuthDialog; +} + +class QLabel; +class QPushButton; +class IconEdit; +class Auth; +class BiometricProxy; +class BiometricAuthWidget; +class BiometricDevicesWidget; + + +class AuthDialog : public QWidget +{ + Q_OBJECT + +public: + explicit AuthDialog(const UserItem &user, QWidget *parent = 0); + void resizeEvent(QResizeEvent *event); + void closeEvent(QCloseEvent *event); + void setUserOfAuth(); + +private: + void initUI(); + void startWaiting(); + void stopWaiting(); + void clearMessage(); + void performBiometricAuth(); + void skipBiometricAuth(); + void initBiometricWidget(); + void initBiometricButtonWidget(); + void setChildrenGeometry(); + void setBiometricWidgetGeometry(); + void setBiometricButtonWidgetGeometry(); + void showPasswordAuthWidget(); + void showBiometricAuthWidget(); + void showBiometricDeviceWidget(); + +private Q_SLOTS: + void onShowMessage(const QString &message, Auth::MessageType type); + void onShowPrompt(const QString &prompt, Auth::PromptType type); + void onAuthComplete(); + void onRespond(const QString &text); +// void onBioAuthStart(); +// void onBioAuthStop(); +// void setBioMovieImage(); +// void updateIcon(); + void onDeviceChanged(const DeviceInfoPtr &deviceInfo); + void onBiometricAuthComplete(bool result); + void onBiometricButtonClicked(); + void onPasswordButtonClicked(); + void onOtherDevicesButtonClicked(); + void onRetryButtonClicked(); + +public Q_SLOTS: +// void switchToBiometric(); +// void switchToPassword(); +// void switchToDevices(); + void onCapsLockChanged(); + void startAuth(); + void stopAuth(); + +Q_SIGNALS: + void authenticateCompete(bool result); + +private: + UserItem user; + Auth *auth; + + enum AuthMode { PASSWORD, BIOMETRIC, UNKNOWN }; + + AuthMode authMode; + + // biometric auth + int m_deviceCount; + QString m_deviceName; + DeviceInfoPtr m_deviceInfo; + BiometricProxy *m_biometricProxy; + BiometricAuthWidget *m_biometricAuthWidget; + BiometricDevicesWidget *m_biometricDevicesWidget; + QWidget *m_buttonsWidget; + QPushButton *m_biometricButton; + QPushButton *m_passwordButton; + QPushButton *m_otherDeviceButton; + QPushButton *m_retryButton; + + // UI +// QPushButton *m_backButton; //返回用户列表 + QWidget *m_userWidget; //放置用户信息Label + QLabel *m_faceLabel; //头像 + QLabel *m_nameLabel; //用户名 +// QLabel *m_isLoginLabel; //提示是否已登录 + + QWidget *m_passwdWidget; //放置密码输入框和信息列表 + IconEdit *m_passwordEdit; //密码输入框 + QLabel *m_messageLabel; //PAM消息显示 +}; + +#endif // AUTHDIALOG_H diff --git a/src/bioAuthentication/bioAuthentication.pri b/src/bioAuthentication/bioAuthentication.pri deleted file mode 100644 index af8480f..0000000 --- a/src/bioAuthentication/bioAuthentication.pri +++ /dev/null @@ -1,19 +0,0 @@ -QT += core dbus widgets - -greaterThan(QT_MAJOR_VERSION, 4) - -HEADERS += \ - $$PWD/biodeviceview.h \ - $$PWD/biocustomtype.h \ - $$PWD/biodevices.h \ - $$PWD/bioauthentication.h - -SOURCES += \ - $$PWD/biodeviceview.cpp \ - $$PWD/biocustomtype.cpp \ - $$PWD/biodevices.cpp \ - $$PWD/bioauthentication.cpp - -RESOURCES += \ - $$PWD/bioverify.qrc - diff --git a/src/bioAuthentication/bioauthentication.cpp b/src/bioAuthentication/bioauthentication.cpp deleted file mode 100644 index e2ec0f5..0000000 --- a/src/bioAuthentication/bioauthentication.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "bioauthentication.h" -#include - -BioAuthentication::BioAuthentication(qint32 uid, const DeviceInfo &deviceInfo, QObject *parent) - : QObject(parent), - uid(uid), - deviceInfo(deviceInfo) -{ - serviceInterface = new QDBusInterface(DBUS_SERVICE, - DBUS_PATH, - DBUS_INTERFACE, - QDBusConnection::systemBus()); - connect(serviceInterface, SIGNAL(StatusChanged(int, int)), - this, SLOT(onStatusChanged(int,int))); - serviceInterface->setTimeout(2147483647); -} - -void BioAuthentication::startAuthentication() -{ - /* 开始认证识别 */ - LOG() << "start biometric verification"; - QList args; - args << QVariant(deviceInfo.device_id) << QVariant(uid) - << QVariant(0) << QVariant(-1); - QDBusPendingCall call = serviceInterface->asyncCallWithArgumentList("Identify", args); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, &QDBusPendingCallWatcher::finished, this, &BioAuthentication::onSearchResult); -} - - -void BioAuthentication::stopAuthentication() -{ - serviceInterface->asyncCall("StopOps", QVariant(deviceInfo.device_id), QVariant(5)); -} - -void BioAuthentication::onSearchResult(QDBusPendingCallWatcher *watcher) -{ - QDBusPendingReply reply = *watcher; - if(reply.isError()){ - LOG() << reply.error(); - return; - } - qint32 result = reply.argumentAt(0).toInt(); - qint32 retUid = reply.argumentAt(1).toInt(); - LOG() << result << " " << retUid; - - /* 识别生物特征成功,发送认证结果 */ - if(result == DBUS_RESULT_SUCCESS && retUid == uid) - Q_EMIT authenticationComplete(true); - else { - Q_EMIT notify(tr("authentication failed, restart after 2 seconds")); - timer = new QTimer(); - connect(timer, &QTimer::timeout, this, [&]{ - startAuthentication(); - timer->deleteLater(); - }); - timer->setSingleShot(true); - timer->start(2000); - } -} - - -void BioAuthentication::onStatusChanged(int deviceId, int statusType) -{ - if(statusType != STATUS_NOTIFY) - return; - LOG() << "status changed " << deviceId << " " << statusType; - QDBusMessage msg = serviceInterface->call("GetNotifyMesg", QVariant(deviceId)); - if(msg.type() == QDBusMessage::ErrorMessage){ - LOG() << msg.errorMessage(); - return; - } - QString message = msg.arguments().at(0).toString(); - LOG() << message; - Q_EMIT notify(message); -} - diff --git a/src/bioAuthentication/bioauthentication.h b/src/bioAuthentication/bioauthentication.h deleted file mode 100644 index 7e81e60..0000000 --- a/src/bioAuthentication/bioauthentication.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#ifndef BIOAUTHENTICATION_H -#define BIOAUTHENTICATION_H - -#include -#include -#include "biocustomtype.h" - -class QDBusInterface; - -/*! - * \brief The BioAuthentication class - * 负责真正的生物识别操作,通过startAuthentication开始认证, - * 认证完成后会发出携带结果的authenticationComplete信号 - */ -class BioAuthentication : public QObject -{ - Q_OBJECT -public: - explicit BioAuthentication(qint32 uid, const DeviceInfo &deviceInfo, QObject *parent = nullptr); - void startAuthentication(); - void stopAuthentication(); - -signals: - void authenticationComplete(bool result); - void notify(const QString &message); - -private slots: - void onSearchResult(QDBusPendingCallWatcher *watcher); - void onStatusChanged(int deviceId, int statusType); - -private: - QDBusInterface *serviceInterface; - - qint32 uid; - DeviceInfo deviceInfo; - QTimer *timer; -}; - -#endif // BIOAUTHENTICATION_H diff --git a/src/bioAuthentication/biocustomtype.cpp b/src/bioAuthentication/biocustomtype.cpp deleted file mode 100644 index 52eb24e..0000000 --- a/src/bioAuthentication/biocustomtype.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "biocustomtype.h" -#include - -QDBusArgument &operator<<(QDBusArgument &argument, const DeviceInfo &deviceInfo) -{ - argument.beginStructure(); - argument << deviceInfo.device_id << deviceInfo.device_shortname - << deviceInfo.device_fullname << deviceInfo.driver_enable - << deviceInfo.device_available - << deviceInfo.biotype << deviceInfo.stotype - << deviceInfo.eigtype << deviceInfo.vertype - << deviceInfo.idtype << deviceInfo.bustype - << deviceInfo.dev_status << deviceInfo.ops_status; - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, DeviceInfo &deviceInfo) -{ - argument.beginStructure(); - argument >> deviceInfo.device_id >> deviceInfo.device_shortname - >> deviceInfo.device_fullname >> deviceInfo.driver_enable - >> deviceInfo.device_available - >> deviceInfo.biotype >> deviceInfo.stotype - >> deviceInfo.eigtype >> deviceInfo.vertype - >> deviceInfo.idtype >> deviceInfo.bustype - >> deviceInfo.dev_status >> deviceInfo.ops_status; - argument.endStructure(); - return argument; -} - -bool DeviceInfo::operator==(const DeviceInfo& deviceInfo) const -{ - if(this->device_shortname == deviceInfo.device_shortname && - this->device_available == deviceInfo.device_available) - return true; - return false; -} diff --git a/src/bioAuthentication/biocustomtype.h b/src/bioAuthentication/biocustomtype.h deleted file mode 100644 index ff19e9a..0000000 --- a/src/bioAuthentication/biocustomtype.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#ifndef BIOCUSTOMTYPE_H -#define BIOCUSTOMTYPE_H - -#include -#include - -#define BIOMETRIC_PAM "BIOMETRIC_PAM" -#define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" -#define BIOMETRIC_SUCESS "BIOMETRIC_SUCCESS" - -#define DBUS_SERVICE "org.ukui.Biometric" -#define DBUS_PATH "/org/ukui/Biometric" -#define DBUS_INTERFACE "org.ukui.Biometric" - -#ifdef LOG -#undef LOG -#endif -#define LOG() qDebug() << "[BIOMETRIC MODULE]" - -/* the type of device */ -enum BioType { - BIOTYPE_FINGERPRINT, - BIOTYPE_FINGERVEIN, - BIOTYPE_IRIS, - __MAX_NR_BIOTYPES -}; - -/* StatusChanged D-Bus 信号触发时的状态变化类型 */ -enum StatusType { - STATUS_DEVICE, - STATUS_OPERATION, - STATUS_NOTIFY -}; - -/* 录入/删除/搜索等 D-Bus 调用的最终结果,即返回值里的 result */ -enum DBusResult { - DBUS_RESULT_SUCCESS = 0, - DBUS_RESULT_ERROR, - DBUS_RESULT_DEVICEBUSY, - DBUS_RESULT_NOSUCHDEVICE, - DBUS_RESULT_PERMISSIONDENIED -}; - - -/* the info of device */ -struct DeviceInfo { - int device_id; - QString device_shortname; /* aka driverName */ - QString device_fullname; - int driver_enable; /* The corresponding driver is enabled/disabled */ - int device_available; /* The driver is enabled and the device is connected */ - int biotype; - int stotype; - int eigtype; - int vertype; - int idtype; - int bustype; - int dev_status; - int ops_status; - - bool operator==(const DeviceInfo&) const; -}; -Q_DECLARE_METATYPE(DeviceInfo) - -QDBusArgument &operator<<(QDBusArgument &argument, const DeviceInfo &deviceInfo); -const QDBusArgument &operator>>(const QDBusArgument &argument, DeviceInfo &deviceInfo); - - -#endif // BIOCUSTOMTYPE_H diff --git a/src/bioAuthentication/biodevices.cpp b/src/bioAuthentication/biodevices.cpp deleted file mode 100644 index da8f9ac..0000000 --- a/src/bioAuthentication/biodevices.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "biodevices.h" -#include - -bool BioDevices::isFirst = true; -QList BioDevices::deviceInfos; -QMap> BioDevices::savedDeviceInfos; //[uid, featuresNum] - -BioDevices::BioDevices(QObject *parent) - : QObject(parent) -{ - connectToService(); - if(isFirst){ - getDevicesList(); - isFirst = false; - } -} - -void BioDevices::connectToService() -{ - qRegisterMetaType(); - - serviceInterface = new QDBusInterface(DBUS_SERVICE, - DBUS_PATH, - DBUS_INTERFACE, - QDBusConnection::systemBus()); - serviceInterface->setTimeout(2147483647); -} - - -/** - * 获取设备列表 - */ -void BioDevices::getDevicesList() -{ - /* 返回值为 i -- int 和 av -- array of variant */ - QDBusMessage msg = serviceInterface->call("GetDrvList"); - if(msg.type() == QDBusMessage::ErrorMessage){ - LOG() << msg.errorMessage(); - return; - } - /* 设备数量 */ - int deviceNum = msg.arguments().at(0).toInt(); - - /* 读取设备详细信息,并存储到列表中 */ - QDBusArgument argument = msg.arguments().at(1).value(); - QList infos; - argument >> infos; - for(int i = 0; i < deviceNum; i++) { - DeviceInfo *deviceInfo = new DeviceInfo; - infos.at(i).value() >> *deviceInfo; - - if(deviceInfo->device_available > 0) //设备可用 - deviceInfos.push_back(deviceInfo); - } -} - -/** - * 获取设备中的生物特征数量 - */ -void BioDevices::getFeaturesList(qint32 uid) -{ - if(savedDeviceInfos.contains(uid)){ - LOG() << "this uid's deviceInfos saved"; - return; - } - - savedDeviceInfos[uid] = QList(); - - for(int i = 0; i < deviceInfos.size(); i++) { - DeviceInfo *deviceInfo = deviceInfos.at(i); - QDBusMessage msg = serviceInterface->call("GetFeatureList", QVariant(deviceInfo->device_id), - QVariant(uid), QVariant(0), QVariant(-1)); - if(msg.type() == QDBusMessage::ErrorMessage){ - LOG() << msg.errorMessage(); - continue; - } - int featuresNum = msg.arguments().at(0).toInt(); - - if(featuresNum > 0 && !savedDeviceInfos[uid].contains(*deviceInfo)) - savedDeviceInfos[uid].push_back(*deviceInfo); - } - LOG() << "there are" << savedDeviceInfos[uid].size() - << "devices enrolled features"; -} - -int BioDevices::deviceCount() -{ - return deviceInfos.size(); -} - -int BioDevices::featuresNum(qint32 uid) -{ - getFeaturesList(uid); - return savedDeviceInfos[uid].size(); -} - -QList BioDevices::getAvaliableDevices(qint32 uid) -{ - getFeaturesList(uid); - return savedDeviceInfos[uid]; -} - -void BioDevices::clear() -{ - isFirst = true; - for(int i = 0; i < deviceInfos.size(); i++) - delete(deviceInfos.at(i)); - deviceInfos.clear(); - savedDeviceInfos.clear(); -} diff --git a/src/bioAuthentication/biodevices.h b/src/bioAuthentication/biodevices.h deleted file mode 100644 index c131560..0000000 --- a/src/bioAuthentication/biodevices.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#ifndef BIODEVICES_H -#define BIODEVICES_H - -#include -#include -#include -#include "biocustomtype.h" - -class QDBusInterface; - -/*! - * \brief The BioDevices class - * this class saves the list of all device information - * and list of available devices' info list for each uid - */ -class BioDevices : public QObject -{ - Q_OBJECT -public: - explicit BioDevices(QObject *parent = nullptr); - int deviceCount(); - int featuresNum(qint32 uid); - QList getAvaliableDevices(qint32 uid); - void clear(); - -private: - void connectToService(); - void getDevicesList(); - void getFeaturesList(qint32 uid); - -private: - QDBusInterface *serviceInterface; - - static bool isFirst; - static QList deviceInfos; //the list of al device info - static QMap> savedDeviceInfos; //[uid, available DeviceInfos] -}; - - - -#endif // BIODEVICES_H diff --git a/src/bioAuthentication/biodeviceview.cpp b/src/bioAuthentication/biodeviceview.cpp deleted file mode 100644 index 8c4a43c..0000000 --- a/src/bioAuthentication/biodeviceview.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "biodeviceview.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bioauthentication.h" - -BioDeviceView::BioDeviceView(qint32 uid, QWidget *parent) - : QWidget(parent), - devicesList(nullptr), - promptLabel(nullptr), - prevButton(nullptr), - nextButton(nullptr), - uid(uid), - currentIndex(0), - authControl(nullptr) -{ - BioDevices bioDevices; - deviceInfos = bioDevices.getAvaliableDevices(uid); - deviceCount = deviceInfos.size() + 1; - - if(deviceCount > 1){ - deviceTypes << "fingerprint" << "fingervein" << "iris" << "face" << "voiceprint"; - initUI(); - } -} - -void BioDeviceView::initUI() -{ -#ifdef TEST - addTestDevices(); -#endif - /* 只为该用户显示录入了生物特征的设备 */ - - devicesList = new QListWidget(this); - devicesList->setObjectName(QStringLiteral("devicesList")); - devicesList->setFlow(QListWidget::LeftToRight); - devicesList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - devicesList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - devicesList->setFocusPolicy(Qt::NoFocus); - devicesList->setSelectionMode(QListWidget::NoSelection); - devicesList->setEditTriggers(QAbstractItemView::NoEditTriggers); - devicesList->setFixedSize(LISTWIDGET_WIDTH, LISTWIDGET_HEIGHT); - connect(devicesList, &QListWidget::currentItemChanged, this, [&]{ - currentIndex = devicesList->currentRow(); - QListWidgetItem *item = devicesList->currentItem(); - devicesList->itemWidget(item)->setFocus(); - setPromptText(currentIndex); - }); - - - int itemSize; - if(deviceCount <= MAX_NUM) - itemSize = (LISTWIDGET_WIDTH - deviceCount * 10) / deviceCount; - else - itemSize = (LISTWIDGET_WIDTH - MAX_NUM * 10) / MAX_NUM; -#define LABEL_WIDTH itemSize -#define ITEM_WIDTH (LABEL_WIDTH + 10) - - /* 为每一个设备添加一个icon到table中 */ - for(int i = 0; i < deviceCount; i++){ - QString iconName; - if(i == 0) - iconName = QString(":/resource/password-icon.png"); - else{ - DeviceInfo deviceInfo = deviceInfos.at(i - 1); - QString deviceType = deviceTypes.at(deviceInfo.biotype); - iconName = QString(":/resource/%1-icon.png").arg(deviceType); - } - - QListWidgetItem *item = new QListWidgetItem(devicesList); - item->setSizeHint(QSize(ITEM_WIDTH, ITEM_SIZE)); - - QLabel *iconLabel = new QLabel(this); - iconLabel->setObjectName(QString("bioIconLabel")+QString::number(i)); - iconLabel->installEventFilter(this); - iconLabel->setFixedSize(LABEL_WIDTH, ITEM_SIZE); - iconLabel->setStyleSheet("QLabel{border:1px solid #026096;}" - "QLabel::hover{background:rgb(255, 255, 255, 80);}" - "QLabel::focus{background:rgb(255, 255, 255, 120);}"); - QPixmap icon(iconName); - icon = icon.scaled(ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); - iconLabel->setPixmap(icon); - iconLabel->setAlignment(Qt::AlignCenter); - - devicesList->insertItem(i, item); - devicesList->setItemWidget(item, iconLabel); - } - - /* 设备名称提示 */ - promptLabel = new QLabel(this); - QRect promptLbRect(devicesList->geometry().left(), - devicesList->geometry().bottom() + 10, - devicesList->width(), 25); - promptLabel->setGeometry(promptLbRect); - - setCurrentRow(0); - - /* 操作提示 */ - notifyLabel = new QLabel(this); - QRect notifyLbRect(promptLbRect.left(), promptLbRect.bottom() + 10, - promptLbRect.width(), 25); - notifyLabel->setGeometry(notifyLbRect); - notifyLabel->setText("this is a notify label"); - - /* 翻页按键 */ - if(deviceCount > MAX_NUM) { - prevButton = new QPushButton(this); - prevButton->setObjectName(QStringLiteral("bioPrevButton")); - prevButton->setFocusPolicy(Qt::NoFocus); - connect(prevButton, &QPushButton::clicked, this, &BioDeviceView::pageUp); - QRect prevBtnRect(devicesList->geometry().right(), - devicesList->geometry().bottom() - ARROW_SIZE, - ARROW_SIZE, ARROW_SIZE); - prevButton->setGeometry(prevBtnRect); - - nextButton = new QPushButton(this); - nextButton->setObjectName(QStringLiteral("bioNextButton")); - nextButton->setFocusPolicy(Qt::NoFocus); - connect(nextButton, &QPushButton::clicked, this, &BioDeviceView::pageDown); - QRect nextBtnRect(prevBtnRect.right(), prevBtnRect.top(), - ARROW_SIZE, ARROW_SIZE); - nextButton->setGeometry(nextBtnRect); - - prevButton->setStyleSheet("QPushButton{background:url(:/resource/tri-prev.png);border:none}" - "QPushButton::hover{background:url(:/resource/tri-prev_hl.png)}"); - nextButton->setStyleSheet("QPushButton{background:url(:/resource/tri-next.png);border:none}" - "QPushButton::hover{background:url(:/resource/tri-next_hl.png)}"); - } - - devicesList->setStyleSheet("QListWidget{background:transparent;border:none;}"); - promptLabel->setStyleSheet("QLabel{font-family:'droid mono';font-size:12px;color:white;}"); - - resize(BIODEVICEVIEW_WIDTH, BIODEVICEVIEW_HEIGHT); -} - -void BioDeviceView::keyReleaseEvent(QKeyEvent *event) -{ - switch(event->key()){ - case Qt::Key_Up: - setCurrentRow(currentIndex-1); - break; - case Qt::Key_Down: - setCurrentRow(currentIndex+1); - break; - case Qt::Key_PageUp: - pageUp(); - break; - case Qt::Key_PageDown: - pageDown(); - break; - case Qt::Key_Return: - onDeviceIconClicked(currentIndex); - break; - } - return QWidget::keyReleaseEvent(event); -} -void BioDeviceView::focusInEvent(QFocusEvent *event) -{ - QListWidgetItem *item = devicesList->item(currentIndex); - devicesList->itemWidget(item)->setFocus(); - return QWidget::focusInEvent(event); -} -void BioDeviceView::showEvent(QShowEvent *event) -{ - this->setFocus(); - return QWidget::showEvent(event); -} - -bool BioDeviceView::eventFilter(QObject *obj, QEvent *event) -{ - QString objName = obj->objectName(); - if(objName.left(12) == "bioIconLabel"){ - int index = objName.right(objName.size() - 12).toInt(); - if(event->type() == QEvent::MouseButtonRelease) { - QMouseEvent *e = static_cast(event); - if(e->button() == Qt::LeftButton){ - setCurrentRow(index); - onDeviceIconClicked(index); - return true; - } - } else if(event->type() == QEvent::Enter){ - - setPromptText(index); - } else if(event->type() == QEvent::Leave) { - setPromptText(currentIndex); - } - } - return QWidget::eventFilter(obj, event); -} - -void BioDeviceView::setCurrentRow(int row) -{ - if(row >= devicesList->count() || row < 0) - return; - currentIndex = row; - devicesList->setCurrentRow(currentIndex); - setPromptText(currentIndex); -} - -void BioDeviceView::setPromptText(int index) -{ - if(index == 0) - promptLabel->setText(tr("password login")); - else{ - DeviceInfo deviceInfo = deviceInfos.at(index-1); - QString deviceType; - switch(deviceInfo.biotype){ - case BIOTYPE_FINGERPRINT: - deviceType = tr("fingerprint"); - break; - case BIOTYPE_FINGERVEIN: - deviceType = tr("fingerevin"); - break; - case BIOTYPE_IRIS: - deviceType = tr("iris"); - break; - } - promptLabel->setText(deviceType + ": " + deviceInfo.device_fullname); - } -} - -void BioDeviceView::onDeviceIconClicked(int index) -{ - if(index > deviceInfos.size()) - return; - - //每次认证时都会停止之前的认证 - if(authControl){ - authControl->stopAuthentication(); - delete authControl; - authControl = nullptr; - } - - if(index == 0){ - LOG() << "back to unlock using password"; - Q_EMIT backToPasswd(); - return; - } - if(index > deviceCount){ - LOG() << "test device"; - return; - } - - DeviceInfo deviceInfo = deviceInfos.at(index-1); - - authControl = new BioAuthentication(uid, deviceInfo, this); - authControl->startAuthentication(); - connect(authControl, &BioAuthentication::authenticationComplete, - this, &BioDeviceView::authenticationComplete); - connect(authControl, &BioAuthentication::notify, this, &BioDeviceView::notify); -} - -void BioDeviceView::pageUp() -{ - if(devicesList->currentRow() >= MAX_NUM) - setCurrentRow(currentIndex - MAX_NUM); - else - setCurrentRow(0); -} - -void BioDeviceView::pageDown() -{ - if(devicesList->count() - devicesList->currentRow() >= MAX_NUM) - setCurrentRow(currentIndex + MAX_NUM); - else - setCurrentRow(devicesList->count()-1); -} - -#ifdef TEST -void BioDeviceView::addTestDevices() -{ - for(int i = 0; i < 2; i++){ - DeviceInfo info; - info.biotype = BIOTYPE_FINGERPRINT; - info.driver_enable = 1; - info.device_available = 1; - deviceInfos.push_back(info); - } - for(int i = 0; i < 2; i++){ - DeviceInfo info; - info.biotype = BIOTYPE_IRIS; - info.driver_enable = 1; - info.device_available = 1; - deviceInfos.push_back(info); - } - deviceCount += 4; -} - -#endif - diff --git a/src/bioAuthentication/biodeviceview.h b/src/bioAuthentication/biodeviceview.h deleted file mode 100644 index 509cb16..0000000 --- a/src/bioAuthentication/biodeviceview.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#ifndef BIODEVICEVIEW_H -#define BIODEVICEVIEW_H - -#include -#include -#include -#include "biocustomtype.h" -#include "biodevices.h" - -//#define TEST 1 - -#define ICON_SIZE 32 -#define ITEM_SIZE (ICON_SIZE + 4) -#define ARROW_SIZE 24 -#define MAX_NUM 4 -#define LISTWIDGET_WIDTH (ITEM_SIZE * MAX_NUM * 2) -#define LISTWIDGET_HEIGHT ITEM_SIZE -#define BIODEVICEVIEW_WIDTH (LISTWIDGET_WIDTH + ARROW_SIZE * 2) -#define BIODEVICEVIEW_HEIGHT (ITEM_SIZE + 40) - -class QDBusInterface; -class QTableWidget; -class QLabel; -class QListWidget; -class QPushButton; -class BioAuthentication; - -typedef QVector QStringVector; - -class BioDeviceView : public QWidget -{ - Q_OBJECT - -public: - explicit BioDeviceView(qint32 uid=0, QWidget *parent=nullptr); - void initUI(); - void pageUp(); - void pageDown(); -#ifdef TEST - void addTestDevices(); -#endif - -protected: - void keyReleaseEvent(QKeyEvent *event); - bool eventFilter(QObject *obj, QEvent *event); - void showEvent(QShowEvent *event); - void focusInEvent(QFocusEvent *event); - void setCurrentRow(int row); - void setPromptText(int index); - -private Q_SLOTS: - void onDeviceIconClicked(int index); - -Q_SIGNALS: - void backToPasswd(); - void authenticationComplete(bool); - void notify(const QString& message); - -private: - - QListWidget *devicesList; - QLabel *promptLabel; - QLabel *notifyLabel; - QPushButton *prevButton; - QPushButton *nextButton; - - QStringVector deviceTypes; - QList deviceInfos; - qint32 uid; - int deviceCount; - int currentIndex; - BioAuthentication *authControl; -}; - -#endif // BIODEVICEVIEW_H diff --git a/src/bioAuthentication/bioverify.qrc b/src/bioAuthentication/bioverify.qrc deleted file mode 100644 index 589d465..0000000 --- a/src/bioAuthentication/bioverify.qrc +++ /dev/null @@ -1,12 +0,0 @@ - - - resource/iris-icon.png - resource/fingerprint-icon.png - resource/fingervein-icon.png - resource/password-icon.png - resource/tri-next_hl.png - resource/tri-next.png - resource/tri-prev_hl.png - resource/tri-prev.png - - diff --git a/src/bioAuthentication/resource/fingerprint-icon.png b/src/bioAuthentication/resource/fingerprint-icon.png deleted file mode 100644 index c618b52..0000000 Binary files a/src/bioAuthentication/resource/fingerprint-icon.png and /dev/null differ diff --git a/src/bioAuthentication/resource/fingervein-icon.png b/src/bioAuthentication/resource/fingervein-icon.png deleted file mode 100644 index 47e5d52..0000000 Binary files a/src/bioAuthentication/resource/fingervein-icon.png and /dev/null differ diff --git a/src/bioAuthentication/resource/iris-icon.png b/src/bioAuthentication/resource/iris-icon.png deleted file mode 100644 index ebeecaf..0000000 Binary files a/src/bioAuthentication/resource/iris-icon.png and /dev/null differ diff --git a/src/bioAuthentication/resource/password-icon.png b/src/bioAuthentication/resource/password-icon.png deleted file mode 100644 index 31359f5..0000000 Binary files a/src/bioAuthentication/resource/password-icon.png and /dev/null differ diff --git a/src/bioAuthentication/resource/tri-next.png b/src/bioAuthentication/resource/tri-next.png deleted file mode 100644 index d4ca56b..0000000 Binary files a/src/bioAuthentication/resource/tri-next.png and /dev/null differ diff --git a/src/bioAuthentication/resource/tri-next_hl.png b/src/bioAuthentication/resource/tri-next_hl.png deleted file mode 100644 index 62bd3ba..0000000 Binary files a/src/bioAuthentication/resource/tri-next_hl.png and /dev/null differ diff --git a/src/bioAuthentication/resource/tri-prev.png b/src/bioAuthentication/resource/tri-prev.png deleted file mode 100644 index dfde462..0000000 Binary files a/src/bioAuthentication/resource/tri-prev.png and /dev/null differ diff --git a/src/bioAuthentication/resource/tri-prev_hl.png b/src/bioAuthentication/resource/tri-prev_hl.png deleted file mode 100644 index 6d252bf..0000000 Binary files a/src/bioAuthentication/resource/tri-prev_hl.png and /dev/null differ diff --git a/src/configuration.cpp b/src/configuration.cpp index 681df0b..bc380de 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -18,6 +18,7 @@ #include "configuration.h" #include #include +#include #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define KEY_MODE "mode" @@ -29,36 +30,44 @@ #define KEY_BACKGROUND "background" #define XSCREENSAVER_DIRNAME "/usr/lib/xscreensaver" -#define GSETTINGS_SCHEMA_BACKGROUND "org.mate.background" -#define KEY_PICTURE_FILENAME "picture-filename" - Configuration::Configuration(QObject *parent) : QObject(parent) { /* QGSettings for screensaver */ - qgsettingsScreensaver = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER); - connect(qgsettingsScreensaver, &QGSettings::valueChanged, - this, &Configuration::onConfigurationChanged); - - /* QGSettings for background */ - qgsettingsBackground = new QGSettings(GSETTINGS_SCHEMA_BACKGROUND); - connect(qgsettingsBackground, &QGSettings::valueChanged, - this, &Configuration::onConfigurationChanged); + gsettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER, "", this); + connect(gsettings, &QGSettings::changed, + this, &Configuration::onConfigurationChanged); /* Initiailization */ - mode = qgsettingsScreensaver->getEnum(KEY_MODE); - themes = qgsettingsScreensaver->getStringList(KEY_THEMES); - idleActivationEnabled = qgsettingsScreensaver->getBool( - KEY_IDLE_ACTIVATION_ENABLED); - lockEnabled = qgsettingsScreensaver->getBool(KEY_LOCK_ENABLED); - imageSwitchInterval = qgsettingsScreensaver->getInt(KEY_IMAGE_SWITCH_INTERVAL); - imageTSEffect = qgsettingsScreensaver->getEnum(KEY_IMAGE_TRANSITION_EFFECT); - - background = qgsettingsScreensaver->getString(KEY_BACKGROUND); - QFile file(background); - if(!file.exists()) - background = qgsettingsBackground->getString(KEY_PICTURE_FILENAME); - + mode = gsettings->get(KEY_MODE).toString(); + themes = gsettings->get(KEY_THEMES).toStringList(); + idleActivationEnabled = gsettings->get( + KEY_IDLE_ACTIVATION_ENABLED).toBool(); + lockEnabled = gsettings->get(KEY_LOCK_ENABLED).toBool(); + imageSwitchInterval = gsettings->get(KEY_IMAGE_SWITCH_INTERVAL).toInt(); + imageTSEffect = gsettings->get(KEY_IMAGE_TRANSITION_EFFECT).toInt(); + background = gsettings->get(KEY_BACKGROUND).toString(); + + qDebug() << mode << themes; qDebug() << imageSwitchInterval << imageTSEffect; + + //如果org.ukui.screensaver background中的背景图片为空,则设为桌面背景 + if(background.isEmpty()) + { + QString currentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); + if(currentDesktop == "UKUI" || currentDesktop == "MATE") + { + bgGsettings = new QGSettings("org.mate.background"); + background = bgGsettings->get("picture-filename").toString(); + } + else if(currentDesktop == "ubuntu:GNOME") + { + bgGsettings = new QGSettings("org.gnome.desktop.background"); + background = bgGsettings->get("picture-uri").toString(); + //去除前缀:file:///usr/share/background/xxx.png + background.remove(0, 7); + } + } + qDebug() << "background: " << background; } /* Update member value when GSettings changed */ @@ -66,20 +75,17 @@ void Configuration::onConfigurationChanged(QString key) { qDebug() << "GSettings value changed, key = " << key; if (key == KEY_MODE) - mode = qgsettingsScreensaver->getEnum(KEY_MODE); + mode = gsettings->get(KEY_MODE).toString(); else if (key == KEY_THEMES) - themes = qgsettingsScreensaver->getStringList(KEY_THEMES); - else if (key == KEY_PICTURE_FILENAME) - background = qgsettingsBackground->getString(KEY_PICTURE_FILENAME); + themes = gsettings->get(KEY_THEMES).toStringList(); else if (key == KEY_IDLE_ACTIVATION_ENABLED) - idleActivationEnabled = qgsettingsScreensaver->getBool( - KEY_IDLE_ACTIVATION_ENABLED); + idleActivationEnabled = gsettings->get(KEY_IDLE_ACTIVATION_ENABLED).toBool(); else if (key == KEY_LOCK_ENABLED) - lockEnabled = qgsettingsScreensaver->getBool(KEY_LOCK_ENABLED); + lockEnabled = gsettings->get(KEY_LOCK_ENABLED).toBool(); else if(key == KEY_IMAGE_TRANSITION_EFFECT) - imageTSEffect = qgsettingsScreensaver->getEnum(KEY_IMAGE_TRANSITION_EFFECT); + imageTSEffect = gsettings->get(KEY_IMAGE_TRANSITION_EFFECT).toInt(); else if(key == KEY_IMAGE_SWITCH_INTERVAL) - imageSwitchInterval = qgsettingsScreensaver->getInt(KEY_IMAGE_SWITCH_INTERVAL); + imageSwitchInterval = gsettings->get(KEY_IMAGE_SWITCH_INTERVAL).toInt(); } /* @@ -89,27 +95,13 @@ void Configuration::onConfigurationChanged(QString key) /* Get the executable path of xscreensaver */ ScreenSaver *Configuration::getScreensaver() { -// QString selectedTheme; -// if (mode == "single") { -// selectedTheme = themes[0]; -// } else if (mode == "random"){ -// int randomIndex = qrand() % (themes.count()); -// selectedTheme = themes[randomIndex]; -// } else if (mode == "blank-only") { /* Note: blank not black */ -// return QString("blank-only"); -// } else { -// qDebug() << "Fatal error: unrecognized screensaver mode"; -// return QString("blank-only"); -// } -// /* screensavers-ukui-binaryring => binaryring */ -// QStringList strs = selectedTheme.split("-"); -// selectedTheme = strs.at(strs.size() - 1); -// return QString("%1/%2").arg(XSCREENSAVER_DIRNAME, selectedTheme); + QStringList modeStr{"blank-only", "random", "single", "image"}; ScreenSaver *saver = new ScreenSaver; - saver->mode = SaverMode(mode); + int index = modeStr.indexOf(mode); + saver->mode = SaverMode(index); - switch(mode){ + switch(index){ case SAVER_BLANK_ONLY: break; case SAVER_RANDOM: diff --git a/src/configuration.h b/src/configuration.h index eb60093..c9fae51 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -22,11 +22,13 @@ #define QT_NO_KEYWORDS #endif -#include "gsettings.h" +//#include "gsettings.h" #include #include "screensaver.h" +class QGSettings; + class Configuration : public QObject { Q_OBJECT @@ -46,9 +48,9 @@ public Q_SLOTS: QString getXScreensaverPath(const QString &theme); private: - QGSettings *qgsettingsScreensaver; - QGSettings *qgsettingsBackground; - int mode; + QGSettings *gsettings; + QGSettings *bgGsettings; + QString mode; QList themes; QString background; bool idleActivationEnabled; diff --git a/src/displaymanager.cpp b/src/displaymanager.cpp new file mode 100644 index 0000000..436aa5b --- /dev/null +++ b/src/displaymanager.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include "displaymanager.h" +#include +#include +#include +#include +#include "types.h" + +DisplayManager::DisplayManager(QObject *parent) : QObject(parent) +{ + char *seatPath = getenv("XDG_SEAT_PATH"); + qDebug() << seatPath; + dmService = new QDBusInterface(DM_DBUS_SERVICE, + seatPath, + DBUS_PROP_INTERFACE, + QDBusConnection::systemBus()); + dmSeatService = new QDBusInterface(DM_DBUS_SERVICE, + seatPath, + DM_SEAT_INTERFACE, + QDBusConnection::systemBus()); + getProperties(); +} + +bool DisplayManager::canSwitch() +{ + return _canSwitch; +} + +bool DisplayManager::hasGuestAccount() +{ + return _hasGuestAccount; +} + +void DisplayManager::switchToGreeter() +{ + QDBusMessage ret = dmSeatService->call("SwitchToGreeter"); + + handleDBusError(ret); +} + +void DisplayManager::switchToUser(const QString &userName) +{ + QDBusMessage ret = dmSeatService->call("SwitchToUser", userName, ""); + + handleDBusError(ret); +} + +void DisplayManager::switchToGuest() +{ + QDBusMessage ret = dmSeatService->call("SwitchToGuest", ""); + + handleDBusError(ret); +} + +void DisplayManager::getProperties() +{ + QDBusMessage ret = dmService->call("GetAll", DM_SEAT_INTERFACE); + handleDBusError(ret); + const QDBusArgument &arg = ret.arguments().at(0).value(); + qDebug() << arg.currentType(); + + arg.beginMap(); + while(!arg.atEnd()) + { + QString key; + QVariant value; + arg.beginMapEntry(); + arg >> key >> value; + arg.endMapEntry(); + if(key == "CanSwitch") + { + _canSwitch = value.toBool(); + } + else if(key == "HasGuestAccount") + { + _hasGuestAccount = value.toBool(); + } + } + arg.endMap(); +} + +void DisplayManager::handleDBusError(const QDBusMessage &msg) +{ + if(msg.type() == QDBusMessage::ErrorMessage) + { + qWarning() << msg.errorMessage(); + } +} diff --git a/src/displaymanager.h b/src/displaymanager.h new file mode 100644 index 0000000..c0e4897 --- /dev/null +++ b/src/displaymanager.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef DISPLAYMANAGER_H +#define DISPLAYMANAGER_H + +#include + +class QDBusInterface; +class QDBusMessage; + +class DisplayManager : public QObject +{ + Q_OBJECT +public: + explicit DisplayManager(QObject *parent = nullptr); + void switchToGreeter(); + void switchToUser(const QString &userName); + void switchToGuest(); + bool canSwitch(); + bool hasGuestAccount(); + +private: + void getProperties(); + void handleDBusError(const QDBusMessage &msg); + +private: + bool _canSwitch; + bool _hasGuestAccount; + + QDBusInterface *dmService; + QDBusInterface *dmSeatService; +}; + +#endif // DISPLAYMANAGER_H diff --git a/src/event_monitor.cpp b/src/event_monitor.cpp deleted file mode 100644 index 803a681..0000000 --- a/src/event_monitor.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- - * -*- coding: utf-8 -*- - * - * Copyright (C) 2011 ~ 2017 Deepin, Inc. - * 2011 ~ 2017 Wang Yong - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * Author: Wang Yong - * Maintainer: Wang Yong - * - * 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 3 of the License, or - * 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 . - */ - -#include "event_monitor.h" -#include -#include - -EventMonitor::EventMonitor(QObject *parent) - : QThread(parent) -{ -// isPress = false; -} - -EventMonitor::~EventMonitor() -{ - std::cout << "EventMonitor::~EventMonitor()" << std::endl; - requestInterruption(); - quit(); - wait(); -} - -void EventMonitor::run() -{ - if(!isInterruptionRequested()) { - Display* display = XOpenDisplay(0); - if (display == 0) { - fprintf(stderr, "unable to open display\n"); - return; - } - - // Receive from ALL clients, including future clients. - XRecordClientSpec clients = XRecordAllClients; - XRecordRange* range = XRecordAllocRange(); - if (range == 0) { - fprintf(stderr, "unable to allocate XRecordRange\n"); - return; - } - - // Receive KeyPress, KeyRelease, ButtonPress, ButtonRelease and MotionNotify events. - memset(range, 0, sizeof(XRecordRange)); - range->device_events.first = KeyPress; - range->device_events.last = MotionNotify; - - // And create the XRECORD context. - XRecordContext context = XRecordCreateContext(display, 0, &clients, 1, &range, 1); - if (context == 0) { - fprintf(stderr, "XRecordCreateContext failed\n"); - return; - } - XFree(range); - - XSync(display, True); - - Display* display_datalink = XOpenDisplay(0); - if (display_datalink == 0) { - fprintf(stderr, "unable to open second display\n"); - return; - } - if (!XRecordEnableContext(display_datalink, context, callback, (XPointer) this)) { - fprintf(stderr, "XRecordEnableContext() failed\n"); - return; - } - } -} - -void EventMonitor::callback(XPointer ptr, XRecordInterceptData* data) -{ - ((EventMonitor *) ptr)->handleRecordEvent(data); -} - -void EventMonitor::handleRecordEvent(XRecordInterceptData* data) -{ - if (data->category == XRecordFromServer) { - xEvent * event = (xEvent *)data->data; - switch (event->u.u.type) { - - case ButtonPress: - if (filterWheelEvent(event->u.u.detail)) { -// isPress = true; - Q_EMIT buttonPress( - event->u.keyButtonPointer.rootX, - event->u.keyButtonPointer.rootY); - } - - break; - case MotionNotify: - Q_EMIT buttonDrag( - event->u.keyButtonPointer.rootX, - event->u.keyButtonPointer.rootY); - break; - case ButtonRelease: - if (filterWheelEvent(event->u.u.detail)) { -// isPress = false; - Q_EMIT buttonRelease( - event->u.keyButtonPointer.rootX, - event->u.keyButtonPointer.rootY); - } - - break; - case KeyPress: - Q_EMIT keyPress(((unsigned char*) data->data)[1]); - - break; - case KeyRelease: - Q_EMIT keyRelease(((unsigned char*) data->data)[1]); - - break; - default: - break; - } - } - - fflush(stdout); - XRecordFreeData(data); -} - -bool EventMonitor::filterWheelEvent(int detail) -{ - return detail != WheelUp && detail != WheelDown && detail != WheelLeft && detail != WheelRight; -} diff --git a/src/fullbackgroundwidget.cpp b/src/fullbackgroundwidget.cpp new file mode 100644 index 0000000..762b46a --- /dev/null +++ b/src/fullbackgroundwidget.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include "fullbackgroundwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lockwidget.h" +#include "xeventmonitor.h" +#include "monitorwatcher.h" +#include "configuration.h" +#include "screensaver.h" +#include "screensaverwidget.h" +#include "grab-x11.h" + +FullBackgroundWidget::FullBackgroundWidget(QWidget *parent) + : QWidget(parent), + lockWidget(nullptr), + xEventMonitor(new XEventMonitor(this)), + monitorWatcher(new MonitorWatcher(this)), + configuration(new Configuration(this)), + isLocked(false), + screenStatus(UNDEFINED) +{ + qDebug() << "init - screenStatus: " << screenStatus; + + connect(monitorWatcher, &MonitorWatcher::monitorCountChanged, + this, &FullBackgroundWidget::onScreenCountChanged); + QDesktopWidget *desktop = QApplication::desktop(); + connect(desktop, &QDesktopWidget::workAreaResized, + this, &FullBackgroundWidget::onDesktopResized); + connect(desktop, &QDesktopWidget::resized, + this, &FullBackgroundWidget::onDesktopResized); + + init(); +} + +void FullBackgroundWidget::paintEvent(QPaintEvent *event) +{ + for(auto screen : QGuiApplication::screens()) + { + QPainter painter(this); + painter.drawPixmap(screen->geometry(), background); + } + return QWidget::paintEvent(event); +} + +void FullBackgroundWidget::closeEvent(QCloseEvent *event) +{ + qDebug() << "FullBackgroundWidget::closeEvent"; + for(auto obj: children()) + { + QWidget *widget = dynamic_cast(obj); + if(widget) + widget->close(); + } + closeGrab(); + return QWidget::closeEvent(event); +} + +void FullBackgroundWidget::init() +{ + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint + /*| Qt::X11BypassWindowManagerHint*/); +// setAttribute(Qt::WA_DeleteOnClose); + establishGrab(); + + // 监听session信号 + smInterface = new QDBusInterface(SM_DBUS_SERVICE, + SM_DBUS_PATH, + SM_DBUS_INTERFACE, + QDBusConnection::sessionBus()); + connect(smInterface, SIGNAL(StatusChanged(uint)), + this, SLOT(onSessionStatusChanged(uint))); + + connect(xEventMonitor, SIGNAL(keyPress(const QString &)), + this, SLOT(onGlobalKeyPress(const QString &))); + connect(xEventMonitor, SIGNAL(keyRelease(const QString &)), + this, SLOT(onGlobalKeyRelease(const QString &))); + connect(xEventMonitor, SIGNAL(buttonDrag(int, int)), + this, SLOT(onGlobalButtonDrag(int, int))); + + int totalWidth = 0; + int totalHeight = 0; + for(auto screen : QGuiApplication::screens()) + { + totalWidth += screen->geometry().width(); + totalHeight += screen->geometry().height(); + } + setGeometry(0, 0, totalWidth, totalHeight); + + background.load(configuration->getBackground()); + + xEventMonitor->start(); +} + +void FullBackgroundWidget::onCursorMoved(const QPoint &pos) +{ + if(!lockWidget) + { + return; + } + for(auto screen : QGuiApplication::screens()) + { + if(screen->geometry().contains(pos)) + { + lockWidget->setGeometry(screen->geometry()); + break; + } + } +} + +void FullBackgroundWidget::lock() +{ + showLockWidget(); + + lockWidget->startAuth();; +} + + +void FullBackgroundWidget::showLockWidget() +{ + screenStatus = (ScreenStatus)(screenStatus | SCREEN_LOCK); + qDebug() << "showLockWidget - screenStatus: " << screenStatus; + + if(!lockWidget) + { + + lockWidget = new LockWidget(this); + connect(lockWidget, &LockWidget::closed, + this, &FullBackgroundWidget::close); + onCursorMoved(cursor().pos()); + } + lockWidget->setFocus(); +} + +void FullBackgroundWidget::showScreensaver() +{ + screenStatus = (ScreenStatus)(screenStatus | SCREEN_SAVER); + qDebug() << "showScreensaver - screenStatus: " << screenStatus; + + for(auto screen : QGuiApplication::screens()) + { + ScreenSaver *saver = configuration->getScreensaver(); + qDebug() << *saver; + ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this); + widgetXScreensaverList.push_back(saverWidget); + saverWidget->setGeometry(screen->geometry()); + } + setCursor(Qt::BlankCursor); + + //显示屏保时,停止认证(主要针对生物识别) + if(lockWidget) + { + lockWidget->stopAuth(); + } +} + +void FullBackgroundWidget::clearScreensavers() +{ + screenStatus = (ScreenStatus)(screenStatus & ~SCREEN_SAVER); + + for(auto widget : widgetXScreensaverList) + { + widget->close(); + } + widgetXScreensaverList.clear(); + + qDebug() << "clearScreensavers - screenStatus: " << screenStatus; + + + unsetCursor(); + if(screenStatus == UNDEFINED) + { + close(); + } + else + { + lock(); + } +} + +void FullBackgroundWidget::onSessionStatusChanged(uint status) +{ + qDebug() << "session status changed: " << status; + if(status != SESSION_IDLE) + { + //当前session没有处于空闲状态 + return; + } + qDebug() << "onSessionStatusChanged - screenStatus: " << screenStatus; + + if(screenStatus & SCREEN_SAVER) + { + return; + } + else if(screenStatus & SCREEN_LOCK) + { + showScreensaver(); + } + else if(screenStatus == UNDEFINED) + { + if(configuration->xscreensaverActivatedWhenIdle() && + configuration->lockWhenXScreensaverActivated()) + { + //显示锁屏和屏保 + showLockWidget(); + showScreensaver(); + } + else if(configuration->xscreensaverActivatedWhenIdle()) + { + //只显示屏保 + showScreensaver(); + } + } +} + +void FullBackgroundWidget::onGlobalKeyPress(const QString &key) +{ + +} + +void FullBackgroundWidget::onGlobalKeyRelease(const QString &key) +{ + if(key == "Caps_Lock") + { + lockWidget->capsLockChanged(); + } + else if(key == "Escape" && screenStatus == SCREEN_LOCK) + { + showScreensaver(); + } + else if(screenStatus & SCREEN_SAVER) + { + clearScreensavers(); + } +} + +void FullBackgroundWidget::onGlobalButtonDrag(int xPos, int yPos) +{ + if(screenStatus & SCREEN_SAVER) + { + clearScreensavers(); + } +} + + +void FullBackgroundWidget::onScreenCountChanged(int) +{ + QSize newSize = monitorWatcher->getVirtualSize(); + setGeometry(0, 0, newSize.width(), newSize.height()); + repaint(); + clearScreensavers(); +} + +void FullBackgroundWidget::onDesktopResized() +{ + QDesktopWidget *desktop = QApplication::desktop(); + setGeometry(desktop->geometry()); + repaint(); + clearScreensavers(); +} diff --git a/src/fullbackgroundwidget.h b/src/fullbackgroundwidget.h new file mode 100644 index 0000000..8808c8b --- /dev/null +++ b/src/fullbackgroundwidget.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef FULLBACKGROUNDWIDGET_H +#define FULLBACKGROUNDWIDGET_H + +#ifndef QT_NO_KEYWORDS +#define QT_NO_KEYWORDS +#endif + +#include +#include "types.h" + +class LockWidget; +class XEventMonitor; +class MonitorWatcher; +class Configuration; +class QDBusInterface; + +class FullBackgroundWidget : public QWidget +{ + Q_OBJECT +public: + explicit FullBackgroundWidget(QWidget *parent = nullptr); + void paintEvent(QPaintEvent *event); + void closeEvent(QCloseEvent *event); + +public Q_SLOTS: + void onCursorMoved(const QPoint &pos); + void lock(); + void showLockWidget(); + void showScreensaver(); + void onSessionStatusChanged(uint status); + +private: + void init(); + void clearScreensavers(); + +private Q_SLOTS: + void onScreenCountChanged(int); + void onDesktopResized(); + void onGlobalKeyPress(const QString &key); + void onGlobalKeyRelease(const QString &key); + void onGlobalButtonDrag(int xPos, int yPos); + +private: + QDBusInterface *smInterface; + LockWidget *lockWidget; + XEventMonitor *xEventMonitor; + MonitorWatcher *monitorWatcher; + Configuration *configuration; + QList widgetXScreensaverList; + QList xscreensaverPidList; + bool isLocked; + ScreenStatus screenStatus; + QPixmap background; +}; + +#endif // FULLBACKGROUNDWIDGET_H diff --git a/backend/src/types.h b/src/generalauthwidget.cpp similarity index 78% rename from backend/src/types.h rename to src/generalauthwidget.cpp index 577f78b..eaa2efa 100644 --- a/backend/src/types.h +++ b/src/generalauthwidget.cpp @@ -15,18 +15,9 @@ * along with this program; if not, see . * **/ -#ifndef TYPES_H -#define TYPES_H +#include "generalauthwidget.h" -namespace ScreenSaver { - -enum SessionStatus { - SESSION_AVAILABLE = 0, - SESSION_INVISIBLE = 1, - SESSION_BUSY = 2, - SESSION_IDLE = 3 -}; +GeneralAuthWidget::GeneralAuthWidget(QWidget *parent) : QWidget(parent) +{ } - -#endif // TYPES_H diff --git a/src/generalauthwidget.h b/src/generalauthwidget.h new file mode 100644 index 0000000..47f2c57 --- /dev/null +++ b/src/generalauthwidget.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef GENERALAUTHWIDGET_H +#define GENERALAUTHWIDGET_H + +#include + +class GeneralAuthWidget : public QWidget +{ + Q_OBJECT +public: + explicit GeneralAuthWidget(QWidget *parent = nullptr); + +signals: + +public slots: +}; + +#endif // GENERALAUTHWIDGET_H \ No newline at end of file diff --git a/src/auxiliary.cpp b/src/grab-x11.cpp similarity index 81% rename from src/auxiliary.cpp rename to src/grab-x11.cpp index 8af934d..643df80 100644 --- a/src/auxiliary.cpp +++ b/src/grab-x11.cpp @@ -15,21 +15,11 @@ * along with this program; if not, see . * **/ -#include "auxiliary.h" +#include "grab-x11.h" #include #include -#include #include -char *get_char_pointer(QString string) -{ - char *buffer; - buffer = (char *)malloc(string.length() + 1); - strcpy(buffer, string.toLocal8Bit().data()); - return buffer; -} - - class XServerGraber{ public: XServerGraber() { @@ -91,16 +81,3 @@ bool closeGrab() XFlush(QX11Info::display()); return true; } - -bool checkCapsLockState() -{ - //判断大写键状态 - Display *display = XOpenDisplay(NULL); - bool capsState = false; - if(display) { - unsigned int n; - XkbGetIndicatorState(display, XkbUseCoreKbd, &n); - capsState = (n & 0x01) == 1; - } - return capsState; -} diff --git a/src/auxiliary.h b/src/grab-x11.h similarity index 83% rename from src/auxiliary.h rename to src/grab-x11.h index c5a8877..2821f08 100644 --- a/src/auxiliary.h +++ b/src/grab-x11.h @@ -15,14 +15,11 @@ * along with this program; if not, see . * **/ -#ifndef AUXILIARY_H -#define AUXILIARY_H +#ifndef GRABX11_H +#define GRABX11_H -#include -char *get_char_pointer(QString string); bool establishGrab(); bool closeGrab(); -bool checkCapsLockState(); -#endif // AUXILIARY_H +#endif // GRABX11_H diff --git a/src/gsettings.cpp b/src/gsettings.cpp deleted file mode 100644 index 4f2859d..0000000 --- a/src/gsettings.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "gsettings.h" -#include "auxiliary.h" - -QGSettings::QGSettings(QString schema, QObject *parent) : QObject(parent) -{ - gsettings = g_settings_new(schema.toLocal8Bit().data()); - g_signal_connect(gsettings, "changed", - G_CALLBACK(QGSettings::changedCallback), this); -} - -/* value changed callback */ -void QGSettings::changedCallback(GSettings *gsettings, const gchar *key, - gpointer user_data) -{ - (void)gsettings; - QGSettings *qgsettings = (QGSettings *)user_data; - Q_EMIT qgsettings->valueChanged(QString::fromLocal8Bit(key)); -} - -/* - * Getter - */ - -QString QGSettings::getString(QString key) -{ - char *key_str, *value; - key_str = get_char_pointer(key); - value = g_settings_get_string(gsettings, key_str); - free(key_str); - return QString::fromLocal8Bit(value); -} - -int QGSettings::getInt(QString key) -{ - char *key_str; - int value; - key_str = get_char_pointer(key); - value = g_settings_get_int(gsettings, key_str); - free(key_str); - return value; -} - -bool QGSettings::getBool(QString key) -{ - char *key_str; - bool value; - key_str = get_char_pointer(key); - value = g_settings_get_boolean(gsettings, key_str); - free(key_str); - return value; -} - -QList QGSettings::getStringList(QString key) -{ - char *key_str; - char **value; - key_str = get_char_pointer(key); - value = g_settings_get_strv(gsettings, key_str); - free(key_str); - QList list; - for (; *value; value++) - list.append(QString::fromLocal8Bit(*value)); - return list; -} - -int QGSettings::getEnum(QString key) -{ - char *key_str; - int value; - key_str = get_char_pointer(key); - value = g_settings_get_enum(gsettings, key_str); - return value; -} - - -/* - * Setter - */ - -bool QGSettings::setString(QString key, QString value) -{ - char *key_str, *value_str; - bool ret; - key_str = get_char_pointer(key); - value_str = get_char_pointer(value); - ret = g_settings_set_string(gsettings, key_str, value_str); - free(key_str); - free(value_str); - return ret; -} - -bool QGSettings::setInt(QString key, int value) -{ - char *key_str; - bool ret; - key_str = get_char_pointer(key); - ret = g_settings_set_int(gsettings, key_str, value); - free(key_str); - return ret; -} - -bool QGSettings::setBool(QString key, bool value) -{ - char *key_str; - bool ret; - key_str = get_char_pointer(key); - ret = g_settings_set_boolean(gsettings, key_str, value); - free(key_str); - return ret; -} - -bool QGSettings::setStringList(QString key, QList value) -{ - char *key_str; - const char ** string_array; - bool ret; - int i; - key_str = get_char_pointer(key); - string_array = (const char **)malloc(value.count() * sizeof(char *)); - for (i = 0; i < value.count(); i++) { - string_array[i] = value[i].toLocal8Bit().data(); - } - string_array[i] = 0; - ret = g_settings_set_strv(gsettings, key_str, string_array); - free(key_str); - return ret; -} diff --git a/src/iconedit.cpp b/src/iconedit.cpp new file mode 100644 index 0000000..c7e8256 --- /dev/null +++ b/src/iconedit.cpp @@ -0,0 +1,195 @@ +/* iconedit.cpp + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include "iconedit.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + * @brief 判断大写键状态 + * @return true: 大写锁定 + */ +bool checkCapsLockState() +{ + Display *display = XOpenDisplay(NULL); + bool capsState = false; + if(display) { + unsigned int n; + XkbGetIndicatorState(display, XkbUseCoreKbd, &n); + capsState = (n & 0x01) == 1; + } + return capsState; +} + + +IconEdit::IconEdit(QWidget *parent) + : QWidget(parent), + m_timer(nullptr) +{ + m_edit = new QLineEdit(this); + m_edit->setObjectName(QStringLiteral("passwdEdit")); + m_edit->setAttribute(Qt::WA_InputMethodEnabled, false); //禁用输入法 + m_edit->setContextMenuPolicy(Qt::NoContextMenu); //禁用右键菜单 + + m_capsIcon = new QLabel(this); + m_capsIcon->setObjectName(QStringLiteral("capsIconLabel")); + m_capsIcon->setVisible(checkCapsLockState()); + + m_iconButton = new QPushButton(this); + m_iconButton->setObjectName(QStringLiteral("loginButton")); + m_iconButton->setFocusPolicy(Qt::NoFocus); + m_iconButton->setCursor(QCursor(Qt::PointingHandCursor)); + + m_modeButton = new QPushButton(this); + m_modeButton->setObjectName(QStringLiteral("echoModeButton")); + m_modeButton->setCheckable(true); + m_modeButton->setFocusPolicy(Qt::NoFocus); + m_modeButton->setCursor(Qt::PointingHandCursor); + connect(m_modeButton, &QPushButton::clicked, this, [&](bool checked){ + setType(checked ? QLineEdit::Normal : QLineEdit::Password); + }); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(1, 1, 1, 1); + layout->setSpacing(0); + layout->addStretch(); + layout->addWidget(m_capsIcon); + layout->addWidget(m_modeButton); + layout->addWidget(m_iconButton); + + connect(m_edit, &QLineEdit::returnPressed, this, &IconEdit::clicked_cb); + connect(m_iconButton, &QPushButton::clicked, this, &IconEdit::clicked_cb); + + setFocusProxy(m_edit); +} + +void IconEdit::setType(QLineEdit::EchoMode type) +{ + m_edit->setEchoMode(type); +} + + +void IconEdit::resizeEvent(QResizeEvent *) +{ + // 设置输入框中文件输入区,不让输入的文字在被隐藏在按钮下 + m_edit->setTextMargins(1, 1, m_iconButton->width() + m_modeButton->width(), 1); + m_edit->setFixedSize(size()); +} + +void IconEdit::clicked_cb() +{ +// m_iconButton->setFocus(); //按回车后输入框光标会消失或者不再闪烁,先让其他控件获取焦点,就会解决该问题 + startWaiting(); + emit clicked(m_edit->text()); +} + +void IconEdit::onCapsStateChanged() +{ + bool capsState = m_capsIcon->isHidden(); + m_capsIcon->setVisible(capsState); + int w = m_iconButton->width() + m_modeButton->width(); + m_edit->setTextMargins(1, 1, capsState ? w + m_capsIcon->width() : w, 1); +} + +void IconEdit::setIcon(const QString &text) +{ + m_iconButton->setIcon(QIcon()); + m_iconButton->setText(text); + m_iconText = text; + m_icon = QIcon(); +} + +void IconEdit::setIcon(const QIcon &icon) +{ + m_iconButton->setIcon(icon); + m_iconButton->setText(""); + m_icon = icon; + m_iconText = ""; +} + +void IconEdit::clear() +{ + m_edit->setText(""); + setPrompt(""); +} + +void IconEdit::setPrompt(const QString &prompt) +{ + m_edit->setPlaceholderText(prompt); +} + +const QString IconEdit::text() +{ + return m_edit->text(); +} + +void IconEdit::startWaiting() +{ + m_edit->setReadOnly(true); + m_iconButton->setEnabled(false); + + + if(!m_timer) + { + m_timer = new QTimer(this); + m_timer->setInterval(120); + connect(m_timer, &QTimer::timeout, this, &IconEdit::updatePixmap); + } + m_waitingPixmap.load(":/image/assets/waiting.png"); + m_iconButton->setIconSize(m_iconButton->size()); + m_iconButton->setIcon(QIcon(m_waitingPixmap)); + m_timer->start(); +} + + +void IconEdit::stopWaiting() +{ + if(m_timer && m_timer->isActive()) + { + m_timer->stop(); + } + + m_edit->setReadOnly(false); + m_iconButton->setEnabled(true); + if(!m_icon.isNull()) + m_iconButton->setIcon(m_icon); + else + m_iconButton->setText(m_iconText); +} + +void IconEdit::updatePixmap() +{ + QMatrix matrix; + matrix.rotate(90.0); + m_waitingPixmap = m_waitingPixmap.transformed(matrix, Qt::FastTransformation); + m_iconButton->setIcon(QIcon(m_waitingPixmap)); +} + +void IconEdit::setEnabled(bool enabled) +{ + m_edit->setEnabled(enabled); + m_iconButton->setEnabled(enabled); +} diff --git a/src/iconedit.h b/src/iconedit.h new file mode 100644 index 0000000..54baa15 --- /dev/null +++ b/src/iconedit.h @@ -0,0 +1,69 @@ +/* iconedit.h + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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, 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ + +#ifndef ICONEDIT_H +#define ICONEDIT_H + +#include +#include +#include +#include + +class IconEdit : public QWidget +{ + Q_OBJECT +public: + IconEdit(QWidget *parent = 0); + + void setIcon(const QString &text); + void setIcon(const QIcon &icon); + void clear(); + void setPrompt(const QString &); + const QString text(); + void setType(QLineEdit::EchoMode type = QLineEdit::Password); + void startWaiting(); + void stopWaiting(); + void setEnabled(bool enabled); + +protected: + void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; + +private: + void updatePixmap(); + +Q_SIGNALS: + void clicked(const QString &); + void focusOut(); + +public Q_SLOTS: + void clicked_cb(); + void onCapsStateChanged(); + +private: + QLineEdit *m_edit; + QLabel *m_capsIcon; + QPushButton *m_iconButton; + QPushButton *m_modeButton; + QTimer *m_timer; + QPixmap m_waitingPixmap; + QString m_iconText; //文字作为图标 + QIcon m_icon; +}; + +#endif // ICONEDIT_H diff --git a/backend/src/interface.cpp b/src/interface.cpp similarity index 84% rename from backend/src/interface.cpp rename to src/interface.cpp index 26bb5a6..1a0dd4d 100644 --- a/backend/src/interface.cpp +++ b/src/interface.cpp @@ -32,7 +32,12 @@ void Interface::Lock() qDebug() << "Lock requested"; if(!checkExistChild()) - runLocker(false); + { + QString cmd = QString("/usr/bin/ukui-screensaver-dialog --lock"); + qDebug() << cmd; + + process.startDetached(cmd); + } } void Interface::onSessionIdleReceived() @@ -40,15 +45,12 @@ void Interface::onSessionIdleReceived() qDebug() << "emit SessionIdle"; if(!checkExistChild()) - runLocker(true); -} - -void Interface::runLocker(bool sessionIdle) -{ - QString cmd = QString("/usr/bin/ukui-screensaver-dialog --lock %1").arg(sessionIdle ? "--session-idle" : ""); - qDebug() << cmd; + { + QString cmd = QString("/usr/bin/ukui-screensaver-dialog --session-idle"); + qDebug() << cmd; - process.startDetached(cmd); + process.startDetached(cmd); + } } bool Interface::checkExistChild() diff --git a/backend/src/interface.h b/src/interface.h similarity index 92% rename from backend/src/interface.h rename to src/interface.h index ab91738..32e7e7c 100644 --- a/backend/src/interface.h +++ b/src/interface.h @@ -21,13 +21,14 @@ #include #include #include +#include "types.h" class Interface : public QObject, protected QDBusContext { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "cn.kylinos.ScreenSaver") + Q_CLASSINFO("D-Bus Interface", SS_DBUS_SERVICE) public: explicit Interface(QObject *parent = nullptr); @@ -46,7 +47,6 @@ public Q_SLOTS: void onNameLost(const QString&); private: - void runLocker(bool sessionIdle); bool checkExistChild(); private: diff --git a/backend/src/interfaceAdaptor.cpp b/src/interfaceAdaptor.cpp similarity index 84% rename from backend/src/interfaceAdaptor.cpp rename to src/interfaceAdaptor.cpp index 2aa3e97..a1dde90 100644 --- a/backend/src/interfaceAdaptor.cpp +++ b/src/interfaceAdaptor.cpp @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp cn.kylinos.ScreenSaver.xml -i interface.h -a interfaceAdaptor + * Command line was: qdbusxml2cpp org.ukui.ScreenSaver.xml -i interface.h -a interfaceAdaptor * * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * @@ -35,7 +35,7 @@ ScreenSaverAdaptor::~ScreenSaverAdaptor() void ScreenSaverAdaptor::Lock() { - // handle method call cn.kylinos.ScreenSaver.Lock + // handle method call org.ukui.ScreenSaver.Lock QMetaObject::invokeMethod(parent(), "Lock"); } diff --git a/backend/src/interfaceAdaptor.h b/src/interfaceAdaptor.h similarity index 79% rename from backend/src/interfaceAdaptor.h rename to src/interfaceAdaptor.h index 6e12edb..9af51ff 100644 --- a/backend/src/interfaceAdaptor.h +++ b/src/interfaceAdaptor.h @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp cn.kylinos.ScreenSaver.xml -i interface.h -a interfaceAdaptor + * Command line was: qdbusxml2cpp org.ukui.ScreenSaver.xml -i interface.h -a interfaceAdaptor * * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * @@ -25,16 +25,16 @@ class QVariant; QT_END_NAMESPACE /* - * Adaptor class for interface cn.kylinos.ScreenSaver + * Adaptor class for interface org.ukui.ScreenSaver */ class ScreenSaverAdaptor: public QDBusAbstractAdaptor { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "cn.kylinos.ScreenSaver") + Q_CLASSINFO("D-Bus Interface", "org.ukui.ScreenSaver") Q_CLASSINFO("D-Bus Introspection", "" -" \n" -" \n" +" \n" " \n" +" \n" " \n" "") public: diff --git a/src/lockwidget.cpp b/src/lockwidget.cpp new file mode 100644 index 0000000..88b78b7 --- /dev/null +++ b/src/lockwidget.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include "lockwidget.h" +#include "ui_lockwidget.h" + +#include +#include +#include +#include + +#include "authdialog.h" +#include "virtualkeyboard.h" +#include "users.h" +#include "displaymanager.h" + +LockWidget::LockWidget(QWidget *parent) + : QWidget(parent), + ui(new Ui::LockWidget), + usersMenu(nullptr), + users(new Users(this)), + displayManager(new DisplayManager(this)) +{ + ui->setupUi(this); + + UserItem user = users->getUserByName(getenv("USER")); + authDialog = new AuthDialog(user, this); + connect(authDialog, &AuthDialog::authenticateCompete, + this, &LockWidget::closed); + connect(this, &LockWidget::capsLockChanged, + authDialog, &AuthDialog::onCapsLockChanged); + initUI(); +} + +LockWidget::~LockWidget() +{ + delete ui; +} + +void LockWidget::closeEvent(QCloseEvent *event) +{ + qDebug() << "LockWidget::closeEvent"; + authDialog->close(); + return QWidget::closeEvent(event); +} + +void LockWidget::startAuth() +{ + if(authDialog) + { + authDialog->startAuth(); + } +} + +void LockWidget::stopAuth() +{ + if(authDialog) + { + authDialog->stopAuth(); + } +} + +void LockWidget::initUI() +{ + setFocusProxy(authDialog); + + //显示系统时间 + timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, [&]{ + QString time = QDateTime::currentDateTime().toString("hh:mm:ss"); + ui->lblTime->setText(time); + }); + + QString time = QDateTime::currentDateTime().toString("hh:mm:ss"); + ui->lblTime->setText(time); + ui->lblTime->setStyleSheet("QLabel{color:white; font-size: 55px;}"); + ui->lblTime->adjustSize(); + timer->start(1000); + + QString date = QDate::currentDate().toString("yyyy/MM/dd dddd"); + qDebug() << "current date: " << date; + ui->lblDate->setText(date); + ui->lblDate->setStyleSheet("QLabel{color:white; font-size: 20px;}"); + ui->lblDate->adjustSize(); + + //虚拟键盘 + vKeyboard = new VirtualKeyboard(this); + vKeyboard->hide(); + connect(vKeyboard, &VirtualKeyboard::aboutToClose, + vKeyboard, &VirtualKeyboard::hide); + + ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.png")); + ui->btnKeyboard->setFixedSize(39, 39); + ui->btnKeyboard->setIconSize(QSize(39, 39)); + connect(ui->btnKeyboard, &QPushButton::clicked, + this, [&]{ + qDebug() << vKeyboard->isHidden(); + vKeyboard->setVisible(vKeyboard->isHidden()); + }); + + //用户切换 + if(displayManager->canSwitch()) + { + initUserMenu(); + } +} + +void LockWidget::initUserMenu() +{ + ui->btnSwitchUser->setIcon(QIcon(":/image/assets/avatar.png")); + ui->btnSwitchUser->setIconSize(QSize(39, 39)); + ui->btnSwitchUser->setFixedSize(39, 39); + + if(!usersMenu) + { + usersMenu = new QMenu(this); + ui->btnSwitchUser->setMenu(usersMenu); + connect(usersMenu, &QMenu::triggered, + this, &LockWidget::onUserMenuTrigged); + } + + connect(users, &Users::userAdded, this, &LockWidget::onUserAdded); + connect(users, &Users::userDeleted, this, &LockWidget::onUserDeleted); + + for(auto user : users->getUsers()) + { + onUserAdded(user); + } + + if(displayManager->hasGuestAccount()) + { + QAction *action = new QAction(QIcon(users->getDefaultIcon()), + tr("Guest"), this); + action->setData("Guest"); + usersMenu->addAction(action); + } + + { + QAction *action = new QAction(QIcon(users->getDefaultIcon()), + tr("SwitchUser"), this); + action->setData("SwitchUser"); + usersMenu->addAction(action); + } + +} + +/* lockscreen follows cursor */ +void LockWidget::resizeEvent(QResizeEvent */*event*/) +{ + //认证窗口 + authDialog->setGeometry((width()-authDialog->geometry().width())/2, 0, + authDialog->width(), height()); + + //系统时间 + ui->widgetTime->move(0, height() - 150); + + //虚拟键盘按钮 + ui->btnKeyboard->move(width() - 60, 20); + + ui->btnSwitchUser->move(width() - 120, 20); +} + + +void LockWidget::onUserAdded(const UserItem &user) +{ + QAction *action = new QAction(QIcon(user.icon), user.realName, this); + action->setData(user.name); + usersMenu->addAction(action); +} + +void LockWidget::onUserDeleted(const UserItem &user) +{ + for(auto action : usersMenu->actions()) + { + if(action->data() == user.name) + usersMenu->removeAction(action); + } +} + +void LockWidget::onUserMenuTrigged(QAction *action) +{ + qDebug() << action->data().toString() << "selected"; + + QString userName = action->data().toString(); + if(userName == "Guest") + { + displayManager->switchToGuest(); + } + else if(userName == "SwitchUser") + { + displayManager->switchToGreeter(); + } + else + { + displayManager->switchToUser(userName); + } + if(authDialog) + { + authDialog->stopAuth(); + } +} diff --git a/src/lockwidget.h b/src/lockwidget.h new file mode 100644 index 0000000..2ce6ba8 --- /dev/null +++ b/src/lockwidget.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef LOCKWIDGET_H +#define LOCKWIDGET_H + +#ifndef QT_NO_KEYWORDS +#define QT_NO_KEYWORDS +#endif + +#include + +namespace Ui { +class LockWidget; +} + +class VirtualKeyboard; +class AuthDialog; +class Users; +class UserItem; +class DisplayManager; +class QMenu; + +class LockWidget : public QWidget +{ + Q_OBJECT + +public: + explicit LockWidget(QWidget *parent = 0); + ~LockWidget(); + void resizeEvent(QResizeEvent *event); + void closeEvent(QCloseEvent *event); + void startAuth(); + void stopAuth(); + +Q_SIGNALS: + void closed(); + void capsLockChanged(); + +private: + void initUI(); + void initUserMenu(); + +private Q_SLOTS: + void onUserAdded(const UserItem &user); + void onUserDeleted(const UserItem &user); + void onUserMenuTrigged(QAction *action); + +private: + Ui::LockWidget *ui; + AuthDialog *authDialog; + VirtualKeyboard *vKeyboard; + QTimer *timer; + QMenu *usersMenu; + Users *users; + DisplayManager *displayManager; +}; + +#endif // LOCKWIDGET_H diff --git a/src/lockwidget.ui b/src/lockwidget.ui new file mode 100644 index 0000000..900bebf --- /dev/null +++ b/src/lockwidget.ui @@ -0,0 +1,93 @@ + + + LockWidget + + + + 0 + 0 + 748 + 433 + + + + Form + + + + + 660 + 10 + 80 + 26 + + + + PointingHandCursor + + + Qt::NoFocus + + + + + + + + + 10 + 280 + 300 + 150 + + + + + + 13 + 90 + 280 + 20 + + + + Date + + + + + + 10 + 11 + 280 + 60 + + + + Time + + + + + + + 560 + 10 + 80 + 26 + + + + PointingHandCursor + + + Qt::NoFocus + + + + + + + + + diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index e7f13c1..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "mainwindow.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "unixsignallistener.h" -#include "event_monitor.h" -#include - -#define CACHE_DIR "/.cache/ukui-screensaver/" - -static int setup_unix_signal_handlers(); -//static void check_exist(); -//static void redirect(int fd, char *filename); -static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); - -#define WORKING_DIRECTORY "/usr/share/ukui-screensaver" -int main(int argc, char *argv[]) -{ -// qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); - setup_unix_signal_handlers(); - - QApplication a(argc, argv); - QApplication::setSetuidAllowed(true); - - - //命令行参数解析 - QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "Dialog for the ukui ScreenSaver.")); - parser.addHelpOption(); - parser.addVersionOption(); - - QCommandLineOption lockOption(QStringLiteral("lock"), - QCoreApplication::translate("main", "lock the screen immediately")); - QCommandLineOption sessionIdleOption(QStringLiteral("session-idle"), - QCoreApplication::translate("main", "activated by session idle signal")); - parser.addOptions({lockOption, sessionIdleOption}); - parser.process(a); - - - UnixSignalListener unixSignalListener; - - qInstallMessageHandler(messageOutput); - - - //加载翻译文件 - QString locale = QLocale::system().name(); - QTranslator translator; - QString qmFile = QString(WORKING_DIRECTORY"/i18n_qm/%1.qm").arg(locale); - translator.load(qmFile); - a.installTranslator(&translator); - qDebug() << "load translation file " << qmFile; - - MainWindow *window = new MainWindow(); - QObject::connect(&unixSignalListener, &UnixSignalListener::transition, - window, &MainWindow::FSMTransition); - - EventMonitor *monitor = new EventMonitor; - monitor->start(); - - QObject::connect(monitor, &EventMonitor::keyPress, window, &MainWindow::onGlobalKeyPress); - QObject::connect(monitor, &EventMonitor::buttonDrag, window, &MainWindow::onGlobalMouseMove); - - //当主窗口关闭时,退出 - QObject::connect(window, &MainWindow::closed, &a, [&] { - qDebug() << "MainWindow closed, exit " << getpid(); - exit(EXIT_SUCCESS); - }); - - if(parser.isSet(sessionIdleOption)) - window->setShowSaver(true); - - if(parser.isSet(lockOption)) { - window->showDialog(); - return a.exec(); - } -} - -static int setup_unix_signal_handlers() -{ - struct sigaction usr1, chld; - int ret = 0; - - usr1.sa_sigaction = UnixSignalListener::usr1SignalAction; - sigemptyset(&usr1.sa_mask); - usr1.sa_flags = 0; - usr1.sa_flags |= SA_SIGINFO; - - chld.sa_sigaction = UnixSignalListener::chldSignalAction; - sigemptyset(&chld.sa_mask); - chld.sa_flags = 0; - chld.sa_flags |= SA_SIGINFO; - - if (sigaction(SIGUSR1, &usr1, 0)) - ret = 1; - - if (sigaction(SIGCHLD, &chld, 0)) - ret = 2; - - return ret; -} - -///* -// * check whether there is a process running or not -// */ -//static void check_exist() -//{ -// int fd, val; -// char buf[16] = {0}; -// char cache_directory[1024] = {0}; -// char pid_file_path[1024] = {0}; -// char log_file_path[1024] = {0}; -// QDir dir; - -// snprintf(cache_directory, sizeof(cache_directory), "%s" CACHE_DIR, getenv("HOME")); -// if(!dir.exists(cache_directory)){ -// if(!dir.mkdir(cache_directory)){ -// perror("mkdir"); -// exit(EXIT_FAILURE); -// } -// } -// snprintf(pid_file_path, sizeof(pid_file_path), "%spid", cache_directory); -// if( (fd = open(pid_file_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { -// qFatal("open pid file failed: %s", strerror(errno)); -// } - -// /* try and set a write lock on the pid file */ -// struct flock lock; -// lock.l_type = F_WRLCK; -// lock.l_start = 0; -// lock.l_whence = SEEK_SET; -// lock.l_len = 0; -// if(fcntl(fd, F_SETLK, &lock) < 0) { -// qDebug("there is a process running in this session"); -// exit(1); -// } -// /* now, we have the lock */ -// if(ftruncate(fd, 0) < 0) -// qFatal("ftruncate error on the pid file: %s", strerror(errno)); - -// /* write this process ID */ -// sprintf(buf, "%d\n", getpid()); -// if(write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) -// qFatal("write error to the pid file: %s", strerror(errno)); - -// /* set close-on-exec flag for descriptor */ -// if( (val = fcntl(fd, F_GETFD, 0) < 0)) -// qFatal("fcntl F_GETFD error: %s", strerror(errno)); -// val |= FD_CLOEXEC; -// if(fcntl(fd, F_SETFD, val) < 0) -// qFatal("fcntl F_SETFD error: %s", strerror(errno)); - -// snprintf(log_file_path, sizeof(log_file_path), "%slog", cache_directory); -// redirect(STDERR_FILENO, log_file_path); -//} - -//static void redirect(int fd, char *filename) -//{ -// int newfd = open(filename, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); -// if(newfd == -1) -// qFatal("open %s failed: %s", filename, strerror(errno)); -// if( dup2(newfd, fd) == -1) -// qFatal("dup2 failed: %s", strerror(errno)); -//} - -static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) -{ - Q_UNUSED(context) - QDateTime dateTime = QDateTime::currentDateTime(); - QByteArray time = QString("[%1] ").arg(dateTime.toString("MM-dd hh:mm:ss.zzz")).toLocal8Bit(); - QByteArray localMsg = msg.toLocal8Bit(); - switch(type) { - case QtDebugMsg: - fprintf(stderr, "%s Debug: %s:%u: %s\n", time.constData(), context.file, context.line, localMsg.constData()); - break; - case QtInfoMsg: - fprintf(stderr, "%s Info: %s:%u: %s\n", time.constData(), context.file, context.line, localMsg.constData()); - break; - case QtWarningMsg: - fprintf(stderr, "%s Warnning: %s:%u: %s\n", time.constData(), context.file, context.line, localMsg.constData()); - break; - case QtCriticalMsg: - fprintf(stderr, "%s Critical: %s:%u: %s\n", time.constData(), context.file, context.line, localMsg.constData()); - break; - case QtFatalMsg: - fprintf(stderr, "%s Fatal: %s:%u: %s\n", time.constData(), context.file, context.line, localMsg.constData()); - abort(); - } - fflush(stderr); -} diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp deleted file mode 100644 index 38fab1d..0000000 --- a/src/mainwindow.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#include "mainwindow.h" -#include "ui_mainwindow.h" -#include "pam.h" -#include "auxiliary.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "screensaverwidget.h" -#include "monitorwatcher.h" -#include "virtualkeyboard.h" - -extern "C" { - #include -} - -#define DBUS_SESSION_MANAGER_SERVICE "org.gnome.SessionManager" -#define DBUS_SESSION_MANAGER_PATH "/org/gnome/SessionManager/Presence" -#define DBUS_SESSION_MANAGER_INTERFACE "org.gnome.SessionManager.Presence" - -QString screenStates[] = {"UNDEFINED", "LOCKSCREEN", "XSCREENSAVER", "XSCREENSAVER_BY_IDLE"}; - -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), - ui(nullptr), - widgetBioDevices(nullptr), - isActivated(false), - isPasswdFailed(false), - timer(nullptr), - showSaver(false), - vKeyboard(nullptr) -{ - configuration = new Configuration(); - programState = IDLE; - screenState = UNDEFINED; - /* Listen to SessionManager StatusChanged signal for idle activation */ - interface = new QDBusInterface("cn.kylinos.ScreenSaver", - "/", - "cn.kylinos.ScreenSaver", - QDBusConnection::sessionBus()); - connect(interface, SIGNAL(SessionIdle()), this, SLOT(onSessionIdle())); - - monitorWatcher = new MonitorWatcher(); - connect(monitorWatcher, &MonitorWatcher::monitorCountChanged, this, &MainWindow::onScreenCountChanged); - - QDesktopWidget *desktop = QApplication::desktop(); - connect(desktop, &QDesktopWidget::workAreaResized, this, &MainWindow::onScreenResized); - connect(desktop, &QDesktopWidget::resized, this, &MainWindow::onScreenResized); - - monitorWatcher->start(); -} - -MainWindow::~MainWindow() -{ - delete ui; -} - -void MainWindow::setShowSaver(bool showSaver) -{ - this->showSaver = showSaver; -} - -void MainWindow::showDialog() -{ - qDebug() << "MainWindow::show"; - if(showSaver) { - onSessionIdle(); - } else { - FSMTransition(getpid()); - } -} - -void MainWindow::closeEvent(QCloseEvent *event) -{ - hide(); - if(ui) - delete ui; - ui = nullptr; - widgetBioDevices = nullptr; - removeEventFilter(this); - - BioDevices devices; - devices.clear(); - - event->ignore(); /* No further processing */ - - /* ungrab the control of mouse and keyboard events */ - closeGrab(); - - isActivated = false; - - if(timer && timer->isActive()) - timer->stop(); - - Q_EMIT closed(); - return; -} - -void MainWindow::constructUI() -{ - qDebug() << "MainWindow::constructUI"; - ui = new Ui::MainWindow; - ui->setupUi(this); - ui->widgetLockscreen->setFixedSize(750, 200); - /* Put the button in the LineEdit */ - QHBoxLayout *hLayoutPwd = new QHBoxLayout; - hLayoutPwd->setSpacing(0); - hLayoutPwd->setContentsMargins(1, 1, 1, 1); - hLayoutPwd->addStretch(); - hLayoutPwd->addWidget(ui->lblCapsLock); - hLayoutPwd->addWidget(ui->btnHidePwd); - hLayoutPwd->addWidget(ui->btnUnlock); - ui->btnUnlock->setFixedSize(70, 38); - ui->btnUnlock->setFlat(true); - ui->btnUnlock->setCursor(Qt::PointingHandCursor); - ui->lineEditPassword->setLayout(hLayoutPwd); - ui->lineEditPassword->setTextMargins(1, 1, ui->btnUnlock->width() + - ui->btnHidePwd->width(), 1); -// ui->lineEditPassword->setCursor(Qt::IBeamCursor); -// ui->lineEditPassword->setFocusPolicy(Qt::NoFocus); - ui->lineEditPassword->hide(); - ui->lineEditPassword->installEventFilter(this); - ui->btnBiometric->setIcon(QIcon(":/resource/fingerprint-icon.png")); - ui->btnBiometric->setIconSize(QSize(40, 40)); - ui->btnBiometric->hide(); - ui->btnHidePwd->setFocusPolicy(Qt::NoFocus); - ui->btnHidePwd->setCursor(Qt::ArrowCursor); - ui->lblCapsLock->setPixmap(QPixmap(":/image/assets/warn.png")); - connect(ui->btnBiometric, &QPushButton::clicked, this,[&]{ - if(widgetBioDevices && widgetBioDevices->isHidden()) { - widgetBioDevices->show(); - ui->lineEditPassword->hide(); - ui->btnBiometric->hide(); - programState = AUTH_FAILED; - - ::close(toParent[0]); - ::close(toAuthChild[1]); -// ::waitpid(authPID, NULL, 0); - ::raise(SIGUSR1); - } - } ); - - qDebug() << "Background: " << configuration->getBackground(); - pixmap.load(configuration->getBackground()); - /* Set avatar, password entry, button ... */ - QString username = ::getenv("USER"); - QPixmap avatarPixmap; - avatarPixmap.load(getUserAvatarPath(username)); - avatarPixmap = avatarPixmap.scaled(128, 128, Qt::IgnoreAspectRatio); - ui->lblAvatar->setPixmap(avatarPixmap); - ui->lblUsername->setText(username); - ui->lineEditPassword->setFixedSize(350, 40); - ui->btnUnlock->setFixedHeight(40); - - connect(ui->lineEditPassword, &QLineEdit::returnPressed, this, &MainWindow::onPasswordEnter); - connect(ui->btnUnlock, &QPushButton::clicked, this, &MainWindow::onUnlockClicked); - connect(ui->btnHidePwd, &QPushButton::clicked, this, [&]{ - setPasswordVisible(ui->lineEditPassword->echoMode() == QLineEdit::Password); - }); - screenState = LOCKSCREEN; - setRealTimeMouseTracking(); - - // display systime time - timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, [&]{ - QString time = QDateTime::currentDateTime().toString("hh:mm:ss"); - ui->lblTime->setText(time); - }); - - QString time = QDateTime::currentDateTime().toString("hh:mm:ss"); - ui->lblTime->setText(time); - ui->lblTime->setStyleSheet("QLabel{color:white; font-size: 55px;}"); - ui->lblTime->adjustSize(); - timer->start(1000); - - QString date = QDate::currentDate().toString("yyyy/MM/dd dddd"); - qDebug() << "current date: " << date; - ui->lblDate->setText(date); - ui->lblDate->setStyleSheet("QLabel{color:white; font-size: 20px;}"); - ui->lblDate->adjustSize(); - - //虚拟键盘 - vKeyboard = new VirtualKeyboard(this); - vKeyboard->hide(); - connect(vKeyboard, &VirtualKeyboard::aboutToClose, vKeyboard, &VirtualKeyboard::hide); - - ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.png")); - ui->btnKeyboard->setFixedSize(39, 39); - ui->btnKeyboard->setIconSize(QSize(39, 39)); - ui->btnKeyboard->setFocusPolicy(Qt::NoFocus); - connect(ui->btnKeyboard, &QPushButton::clicked, vKeyboard, &VirtualKeyboard::show); - - setWindowStyle(); - - /* grab control of the mouse and keyboard events in lockscreen window */ - if(!establishGrab()) - qWarning("can't grab mouse or keyboard"); - - show(); - /* - * After setting X11BypassWindowManagerHint flag, setFocus can't make - * LineEdit get focus, so we need to activate window manually. - */ - activateWindow(); - - QFile qssFile(":/qss/assets/authdialog.qss"); - if(qssFile.open(QIODevice::ReadOnly)) { - setStyleSheet(qssFile.readAll()); - } - qssFile.close(); - -} - -void MainWindow::setWindowStyle() -{ - /* Calculate the total size of multi-head screen */ - int totalWidth = 0, totalHeight = 0; - Q_FOREACH (QScreen *screen, QGuiApplication::screens()) { - totalWidth += screen->geometry().width(); - totalHeight += screen->geometry().height(); - } - setGeometry(0, 0, totalWidth, totalWidth); /* Full screen */ - - /* Move lockscreen according to cursor position */ - lockscreenFollowCursor(QCursor::pos()); - - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint - | Qt::X11BypassWindowManagerHint); - setAttribute(Qt::WA_DeleteOnClose); -} - -/* Draw background image */ -void MainWindow::paintEvent(QPaintEvent *event) -{ - (void)event; - /* - * MainWindow is stretched to all screens. We can draw background image - * on it based on geometry of each screen. - */ - Q_FOREACH (QScreen *screen, QGuiApplication::screens()) { - QPainter painter(this); - painter.drawPixmap(screen->geometry(), pixmap); - } - return QWidget::paintEvent(event); -} - - -/* Verify if the sender of SIGUSR1 is correct or not */ -bool MainWindow::signalSenderFilter(int senderSenderPid) -{ - if (senderSenderPid == getpid() || senderSenderPid == authPID) - return true; - /* - * If the sender is neither the current process nor the authentication - * child process, then we should check the programState. - * If programState is IDLE and we can read a number from a fifo and the - * data is the pid of the current process, then the signal is sent by - * ukui-screensaver-command. - */ - FILE *fp; - int filedata; - char file[1024]; - snprintf(file, sizeof(file), "%s/.cache/ukui-screensaver/lock", getenv("HOME")); - if (programState == IDLE) { - fp = fopen(file, "r"); - if (!fp) { - qDebug() << "Can't open file"; - perror("Details: "); - return false; - } - int i = fscanf(fp, "%d", &filedata); - (void)i; //eliminate warning - if (filedata == getpid()) { - qDebug() << "ukui-screensaver-command request for locking"; - return true; - } else { - qDebug() << "File data do not match the pid of ukui-screensaver"; - return false; - } - } else { - qDebug() << "Receive a SIGUSR1 but programState is not IDLE." - "Ignore it!"; - return false; - } -} - -void MainWindow::setPasswordVisible(bool visible) -{ - if(visible) { - ui->lineEditPassword->setEchoMode(QLineEdit::Normal); - ui->btnHidePwd->setIcon(QIcon(":/image/assets/show-password.png")); - } else { - ui->lineEditPassword->setEchoMode(QLineEdit::Password); - ui->btnHidePwd->setIcon(QIcon(":/image/assets/hide-password.png")); - } -} - -#define AUTH_STATUS_LENGTH 16 -void MainWindow::FSMTransition(int signalSenderPID) -{ - qDebug() << "FSMTransition"; - struct pam_message_object pam_msg_obj; - char auth_status_buffer[AUTH_STATUS_LENGTH]; - int auth_status; - char *password; - - if(!signalSenderFilter(signalSenderPID)) - return; - - isActivated = true; - - switch (programState) { /* Current program state */ - case IDLE: /* Idle in background */ - case AUTH_FAILED: /* Re-Authenticate */ - if((pipe(toAuthChild) == -1) || (pipe(toParent) == -1)) { - qDebug() << "Can't create pipe for authentication IPC."; - break; - } - authPID = fork(); - if (authPID != 0) { /* Parent process */ - ::close(toAuthChild[0]); /* Close read end */ - ::close(toParent[1]); /* Close write end */ - /* - * During re-authenticating, the GUI has been there, - * we don't need to construct it again. - */ - if (programState == IDLE) - constructUI(); - uiGetReady(true); - programState = SHOW_PAM_MESSAGE; - qDebug() << "UI is ready. Next state: SHOW_PAM_MESSAGE."; - } else { /* Child process */ - qDebug() << "Authentication subprocess detached."; - ::close(toAuthChild[1]); /* Close write end */ - ::close(toParent[0]); /* Close read end */ - /* Child process will invoke pam and will not return */ - authenticate(toParent, toAuthChild); - } - qDebug() << "-----"; - break; - case SHOW_PAM_MESSAGE: /* Triggered by conversation function in pam.c */ - PIPE_OPS_SAFE( - ::read(toParent[0], &pam_msg_obj, sizeof(pam_msg_obj)); - ); - qDebug() << "PAM Message---"<< pam_msg_obj.msg; - - /* Check whether the pam message is from biometric pam module */ - if(strcmp(pam_msg_obj.msg, BIOMETRIC_PAM) == 0) { - BioDevices devices; - if(isPasswdFailed || devices.featuresNum(getuid()) <= 0) { - qDebug() << "no available device, enable password authentication"; - PIPE_OPS_SAFE( - ::write(toAuthChild[1], BIOMETRIC_IGNORE, strlen(BIOMETRIC_IGNORE) + 1); - ); - programState = SHOW_PAM_MESSAGE; - isPasswdFailed = false; - } else { - qDebug() << "enable biometric authentication"; - if(!widgetBioDevices) { - widgetBioDevices = new BioDeviceView(getuid(), ui->widgetLockscreen); - QRect widgetBioDevicesRect(ui->lineEditPassword->geometry().left(), - ui->lineEditPassword->geometry().top() + 2, - BIODEVICEVIEW_WIDTH, BIODEVICEVIEW_HEIGHT); - widgetBioDevices->setGeometry(widgetBioDevicesRect); - connect(widgetBioDevices, &BioDeviceView::backToPasswd, this, [&]{ - widgetBioDevices->hide(); - ui->btnBiometric->show(); - ui->lblPrompt->setText(""); - PIPE_OPS_SAFE( - ::write(toAuthChild[1], BIOMETRIC_IGNORE, strlen(BIOMETRIC_IGNORE) + 1); - ); - programState = SHOW_PAM_MESSAGE; - }); - connect(widgetBioDevices, &BioDeviceView::notify, this, [&](const QString &text){ - ui->lblPrompt->setText(text); - }); - connect(widgetBioDevices, &BioDeviceView::authenticationComplete, this, [&](bool ret){ - if(ret) { - qDebug() << "authentication success"; - PIPE_OPS_SAFE( - ::write(toAuthChild[1], BIOMETRIC_SUCESS, strlen(BIOMETRIC_SUCESS) + 1); - ); - programState = WAIT_AUTH_STATUS; - } - }); - } - widgetBioDevices->show(); - } - break; - } - - ui->lineEditPassword->show(); - ui->lineEditPassword->setFocus(); - - if (pam_msg_obj.msg_style == PAM_PROMPT_ECHO_OFF) { - setPasswordVisible(false); - ui->lineEditPassword->setPlaceholderText( - QString::fromUtf8(pam_msg_obj.msg)); - programState = GET_PASSWORD; - qDebug() << "PAM messages has been shown. Next state: GET_PASSWORD."; - } else if (pam_msg_obj.msg_style == PAM_PROMPT_ECHO_ON){ - setPasswordVisible(true); - ui->lineEditPassword->setPlaceholderText( - QString::fromUtf8(pam_msg_obj.msg)); - programState = GET_PASSWORD; - qDebug() << "PAM messages has been shown. Next state: GET_PASSWORD."; - } else { - ui->lblPrompt->setText(QString::fromUtf8(pam_msg_obj.msg)); - qDebug() << "PAM only want to show message. Next state is still SHOW_PAM_MESSAGE."; - } - break; - case GET_PASSWORD: /* Triggered by ENTER */ - qDebug() << "STATE---GET_PASSWORD"; - password = get_char_pointer(ui->lineEditPassword->text()); - PIPE_OPS_SAFE( - ::write(toAuthChild[1], password, strlen(password) + 1); - ); - free(password); - programState = WAIT_AUTH_STATUS; - qDebug() << "User has input the password. Next state: WAIT_AUTH_STATUS."; - break; - case WAIT_AUTH_STATUS: /* pam_authenticate has returned */ - PIPE_OPS_SAFE( - ::read(toParent[0], auth_status_buffer, AUTH_STATUS_LENGTH); - ); - sscanf(auth_status_buffer, "%d", &auth_status); - qDebug() << "auth_status:" << auth_status; - if (auth_status == PAM_SUCCESS) { - close(); - programState = IDLE; - screenState = UNDEFINED; - qDebug() << "Authenticate successfully. Next state: IDLE"; - } else { - QTimer::singleShot(0, [&]{ - ::raise(SIGUSR1); - }); - ui->lblPrompt->setText(tr("Password Incorrect")); - ui->lineEditPassword->hide(); - isPasswdFailed = true; - programState = AUTH_FAILED; - qDebug() << "Authenticate unsuccessfully. Next state: AUTH_FAILED."; - } - ::close(toParent[0]); - ::close(toAuthChild[1]); - waitpid(authPID, NULL, 0); - qDebug() << "All done."; - break; - default: - break; - } -} - -void MainWindow::onUnlockClicked() -{ - qDebug() << "Click unlock button."; - uiGetReady(false); - ::raise(SIGUSR1); -} - -void MainWindow::onPasswordEnter() -{ - qDebug() << "Press enter key."; - uiGetReady(false); - ::raise(SIGUSR1); -} - -void MainWindow::uiGetReady(bool ready) -{ - ui->lineEditPassword->setEnabled(ready); - ui->btnUnlock->setEnabled(ready); - - - if (ready) { - ui->lineEditPassword->clear(); - ui->lineEditPassword->setFocus(); - } -} - -void MainWindow::setCapsLockWarn() -{ - bool state = checkCapsLockState(); - ui->lblCapsLock->setVisible(state); - int textMargin = ui->btnUnlock->width() + ui->btnHidePwd->width() + - (state ? ui->lblCapsLock->width() : 0); - ui->lineEditPassword->setTextMargins(1, 1, textMargin, 1); -} - -/* - * XScreensaver - */ - - - -void MainWindow::setRealTimeMouseTracking() -{ - /* - * setMouseTracking should be set for all child widgets, otherwise it - * won't work. - * http://www.eastfist.com/qt_tutorials/index.php/2013/08/28/ - * solution-qt-setmousetracking-doesnt-work/ - */ - setMouseTracking(true); - ui->centralWidget->setMouseTracking(true); -} - -/* All events are dispatched in this function */ -bool MainWindow::eventFilter(QObject *watched, QEvent *event) -{ - switch (event->type()) { - case QEvent::KeyRelease: - if(((QKeyEvent*)event)->key() == Qt::Key_CapsLock) - setCapsLockWarn(); - break; - case QEvent::FocusIn: - if(watched == ui->lineEditPassword) - setCapsLockWarn(); - break; - default: - break; - } - return false; -} - -///* Key Press Event */ -//void MainWindow::keyReleaseEvent(QKeyEvent *event) -//{ -// if (screenState == LOCKSCREEN) { -// if (event->key() == Qt::Key_Escape) { -// screenState = XSCREENSAVER; -// switchToXScreensaver(); -// } -// } -// return QMainWindow::keyReleaseEvent(event); -//} - -///* Mouse Move Event */ -//void MainWindow::mouseMoveEvent(QMouseEvent *event) -//{ -// if (screenState == LOCKSCREEN) { -// lockscreenFollowCursor(event->pos()); -// } -// return QMainWindow::mouseMoveEvent(event); -//} - -void MainWindow::onGlobalKeyPress(int keyId) -{ - if(screenState == LOCKSCREEN){ - if(keyId == 9) { // ESC - screenState = XSCREENSAVER; - switchToXScreensaver(); - } - } else if (screenState == XSCREENSAVER) { - switchToLockscreen(); - } else if (screenState == XSCREENSAVER_BY_IDLE) { - clearSavers(); - close(); - screenState = UNDEFINED; - } -} - -void MainWindow::onGlobalMouseMove(int x, int y) -{ - if (screenState == LOCKSCREEN) { - lockscreenFollowCursor(QPoint(x, y)); - } else if (screenState == XSCREENSAVER) { - switchToLockscreen(); - } else if (screenState == XSCREENSAVER_BY_IDLE) { - clearSavers(); - close(); - screenState = UNDEFINED; - } -} - -/* lockscreen follows cursor */ -void MainWindow::lockscreenFollowCursor(QPoint cursorPoint) -{ - QScreen *screen = NULL; - Q_FOREACH (screen, QGuiApplication::screens()) { - if (screen->geometry().contains(cursorPoint)) - break; - } - int x = screen->geometry().x() + (screen->geometry().width() - - ui->widgetLockscreen->geometry().width()) / 2; - int y = 0 + (screen->geometry().height() - - ui->widgetLockscreen->geometry().height()) / 2; - ui->widgetLockscreen->move(x, y); - - x = screen->geometry().x(); - y = screen->geometry().y() + screen->geometry().height() - 150; - ui->widgetTime->move(x, y); - - x = x + screen->geometry().width() - 100; - y = screen->geometry().y() + screen->geometry().height() - 100; - ui->btnKeyboard->move(x, y); -} - - -/* Kill the xscreensaver process and show the lock screen */ -void MainWindow::switchToLockscreen() -{ - qDebug() << "switch to lockscreen"; - - clearSavers(); - - ui->lineEditPassword->setFocus(); - setCursor(Qt::ArrowCursor); - ui->lineEditPassword->grabKeyboard(); - - screenState = LOCKSCREEN; -} - -/* Start a xscreensaver process and embed it onto the widgetXScreensaver widget */ -void MainWindow::switchToXScreensaver() -{ - embedXScreensaver(); - setCursor(Qt::BlankCursor); -} - -/* Embed xscreensavers to each screen */ -void MainWindow::embedXScreensaver() -{ - qDebug() << "embedXScreensaver"; - - for (int i = 0; i < QGuiApplication::screens().count(); i++) { - ScreenSaver *saver = configuration->getScreensaver(); - ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this); - widgetXScreensaverList.push_back(saverWidget); - - qDebug() << QGuiApplication::screens()[i]->geometry(); - saverWidget->setGeometry(QGuiApplication::screens()[i]->geometry()); - } -} - -void MainWindow::clearSavers() -{ - qDebug() << "clear savers"; - - for(auto widget : widgetXScreensaverList) { - widget->close(); - } - widgetXScreensaverList.clear(); -} - -/* Listen to SessionManager StatusChanged D-Bus signal */ -void MainWindow::onSessionIdle() -{ - qDebug() << "session idle"; - /* skip if the lock window is show */ - if(isActivated) { - qDebug() << "Lock Screen is activated"; - if(screenState == LOCKSCREEN) { - switchToXScreensaver(); - screenState = XSCREENSAVER; - } - return; - } - if (configuration->xscreensaverActivatedWhenIdle() && - configuration->lockWhenXScreensaverActivated()) { - qDebug() << "run screensaver and lockscreen"; - /* Start authentication and construct UI */ - FSMTransition(getpid()); - switchToXScreensaver(); - screenState = XSCREENSAVER; - } else if (configuration->xscreensaverActivatedWhenIdle()) { - qDebug() << "only run screensaver"; - /* Only construct UI without start authentication */ - constructUI(); - switchToXScreensaver(); - screenState = XSCREENSAVER_BY_IDLE; - } else { - qDebug() << "Don't run screensaver and lockscreen"; - close(); - } -} - - - -/* - * Others - */ - - - -QString MainWindow::getUserAvatarPath(QString username) -{ - QString iconPath; - QDBusInterface userIface( "org.freedesktop.Accounts", - "/org/freedesktop/Accounts", - "org.freedesktop.Accounts", - QDBusConnection::systemBus()); - if (!userIface.isValid()) - qDebug() << "userIface is invalid"; - QDBusReply userReply = userIface.call("FindUserByName", - username); - if (!userReply.isValid()) { - qDebug() << "userReply is invalid"; - iconPath = "/usr/share/kylin-greeter/default_face.png"; - } - QDBusInterface iconIface( "org.freedesktop.Accounts", - userReply.value().path(), - "org.freedesktop.DBus.Properties", - QDBusConnection::systemBus()); - if (!iconIface.isValid()) - qDebug() << "IconIface is invalid"; - QDBusReply iconReply = iconIface.call("Get", - "org.freedesktop.Accounts.User", "IconFile"); - if (!iconReply.isValid()) { - qDebug() << "iconReply is invalid"; - iconPath = "/usr/share/kylin-greeter/default_face.png"; - } - iconPath = iconReply.value().variant().toString(); - if (access(get_char_pointer(iconPath), R_OK) != 0) /* No Access Permission */ - qDebug() << "Can't access user avatar:" << iconPath - << "No access permission."; - return iconPath; -} - -void MainWindow::on_btnSwitchUser_clicked() -{ - QString seatPath = qgetenv("XDG_SEAT_PATH"); - QDBusInterface interface("org.freedesktop.DisplayManager", - seatPath, - "org.freedesktop.DisplayManager.Seat", - QDBusConnection::systemBus()); - if(!interface.isValid()) { - qWarning() << "XDG_SEAT_PATH is invalid"; - } - - QDBusMessage msg = interface.call("SwitchToGreeter"); - if(msg.type() == QDBusMessage::ErrorMessage) { - qWarning() << "SwitchToGreeter: " << msg.errorMessage(); - } else { -// exit(0); - } -} - -void MainWindow::onScreenResized(int ) -{ - QDesktopWidget *desktop = QApplication::desktop(); - resize(QSize(desktop->geometry().width(), - desktop->geometry().height())); - repaint(); -} - - -void MainWindow::onScreenCountChanged() -{ - QSize newSize = monitorWatcher->getVirtualSize(); - resize(newSize); - repaint(); - clearSavers(); -} diff --git a/src/mainwindow.h b/src/mainwindow.h deleted file mode 100644 index e0d094a..0000000 --- a/src/mainwindow.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. - * - * 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 3, 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 . - * -**/ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#ifndef QT_NO_KEYWORDS -#define QT_NO_KEYWORDS -#endif - -#include -#include -#include "configuration.h" -#include "bioAuthentication/biodeviceview.h" -#include -#include -#include "monitorwatcher.h" - -namespace Ui { -class MainWindow; -} - -enum ScreenState { - UNDEFINED, - LOCKSCREEN, - XSCREENSAVER, - XSCREENSAVER_BY_IDLE /* Xscreensaver is activated by session idle */ -}; - -enum ProgramState { - IDLE, - SHOW_PAM_MESSAGE, - GET_PASSWORD, - WAIT_AUTH_STATUS, - AUTH_FAILED -}; - -/* https://www.narf.ssji.net/~shtrom/wiki/projets/gnomescreensavernosession */ -enum SessionStatus { - SESSION_AVAILABLE = 0, - SESSION_INVISIBLE = 1, - SESSION_BUSY = 2, - SESSION_IDLE = 3 -}; - -class VirtualKeyboard; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); - void setShowSaver(bool showSaver); - void showDialog(); - -private: - void setRealTimeMouseTracking(); - void embedXScreensaver(); - void handleKeyPressEvent(QKeyEvent *event); - void handleMouseMoveEvent(QMouseEvent *event); - void switchToLockscreen(); - void switchToXScreensaver(); - void startXScreensaverWithoutAuth(); - void constructUI(); - void uiGetReady(bool ready); - void setWindowStyle(); - void lockscreenFollowCursor(QPoint cursorPosition); - QString getUserAvatarPath(QString username); - bool signalSenderFilter(int signalSenderPID); - void setPasswordVisible(bool visible); - void setCapsLockWarn(); - void clearSavers(); - -protected: - void paintEvent(QPaintEvent *event); - void closeEvent(QCloseEvent *event); -// void keyReleaseEvent(QKeyEvent *event); -// void mouseMoveEvent(QMouseEvent *event); - bool eventFilter(QObject *watched, QEvent *event); - -Q_SIGNALS: - void closed(); - -public Q_SLOTS: - void FSMTransition(int signalSenderPID); /* Transition FSM states according to signal */ - void onScreenResized(int); - void onScreenCountChanged(); - -private Q_SLOTS: - void onUnlockClicked(); - void onPasswordEnter(); - void onSessionIdle(); - - void on_btnSwitchUser_clicked(); - -public Q_SLOTS: - void onGlobalKeyPress(int keyId); - void onGlobalMouseMove(int x, int y); - -private: - Ui::MainWindow *ui; - unsigned long int winId; - enum ScreenState screenState; - QList xscreensaverPIDList; - QList widgetXScreensaverList; - enum ProgramState programState; - int toAuthChild[2]; - int toParent[2]; - int authPID; - Configuration *configuration; - QPixmap pixmap; - QDBusInterface *interface; - BioDeviceView *widgetBioDevices; - bool isActivated; - bool isPasswdFailed; - QTimer *timer; - bool showSaver; - MonitorWatcher *monitorWatcher; - VirtualKeyboard *vKeyboard; -}; - -#endif // MAINWINDOW_H diff --git a/src/mainwindow.ui b/src/mainwindow.ui deleted file mode 100644 index 85027cc..0000000 --- a/src/mainwindow.ui +++ /dev/null @@ -1,255 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 825 - 430 - - - - MainWindow - - - - - - 0 - 0 - 761 - 200 - - - - - 580 - 200 - - - - - - 535 - 100 - 40 - 40 - - - - border:none; -background-color:transparent; - - - - - - - - - 315 - 100 - 380 - 40 - - - - - - - - - - 315 - 10 - 300 - 25 - - - - Username - - - - - - 315 - 65 - 300 - 30 - - - - - - - - - - 615 - 100 - 80 - 40 - - - - Qt::NoFocus - - - Unlock - - - - - - 315 - 40 - 100 - 25 - - - - Has Logged In - - - - - - 145 - 10 - 130 - 130 - - - - Avatar - - - Qt::AlignCenter - - - - - - 700 - 100 - 40 - 40 - - - - PointingHandCursor - - - Qt::NoFocus - - - - - - - - - - - - 593 - 110 - 22 - 22 - - - - Qt::NoFocus - - - - - - - - - 0 - 0 - 32 - 32 - - - - Qt::NoFocus - - - - - - - - - 38 - 5 - 81 - 25 - - - - Switch User - - - - - - - 0 - 220 - 300 - 150 - - - - - - 13 - 90 - 280 - 20 - - - - TextLabel - - - - - - 10 - 11 - 280 - 60 - - - - TextLabel - - - - - - - 690 - 370 - 80 - 26 - - - - - - - - - - - - diff --git a/backend/src/cn.kylinos.ScreenSaver.xml b/src/org.ukui.ScreenSaver.xml similarity index 85% rename from backend/src/cn.kylinos.ScreenSaver.xml rename to src/org.ukui.ScreenSaver.xml index fe9242a..e0b7065 100644 --- a/backend/src/cn.kylinos.ScreenSaver.xml +++ b/src/org.ukui.ScreenSaver.xml @@ -1,9 +1,9 @@ - - - + + + diff --git a/src/screensaver.cpp b/src/screensaver.cpp index 23bad70..601b325 100644 --- a/src/screensaver.cpp +++ b/src/screensaver.cpp @@ -51,6 +51,20 @@ ScreenSaver::ScreenSaver(ScreenSaver &&screensaver) noexcept { } +bool ScreenSaver::exists() +{ + switch(mode) + { + case SAVER_BLANK_ONLY: + return true; + case SAVER_RANDOM: + case SAVER_SINGLE: + return QFile(path).exists(); + case SAVER_IMAGE: + return QDir(path).exists(); + } +} + void ScreenSaver::startSwitchImages() { qDebug() << "ScreenSaver::startSwitchImages"; diff --git a/src/screensaver.h b/src/screensaver.h index 51d2152..66a4a91 100644 --- a/src/screensaver.h +++ b/src/screensaver.h @@ -58,9 +58,10 @@ class ScreenSaver : public QObject void imagePathChanged(const QString &path); public: - explicit ScreenSaver(QObject *parent=nullptr); + explicit ScreenSaver( QObject *parent=nullptr); explicit ScreenSaver(const ScreenSaver &screensaver); ScreenSaver(ScreenSaver &&screensaver) noexcept; + bool exists(); void startSwitchImages(); void stopSwitchImages(); bool timerStatus(); diff --git a/src/screensaverwidget.cpp b/src/screensaverwidget.cpp index 849183d..8123d62 100644 --- a/src/screensaverwidget.cpp +++ b/src/screensaverwidget.cpp @@ -82,6 +82,11 @@ void ScreenSaverWidget::closeEvent(QCloseEvent *event) void ScreenSaverWidget::paintEvent(QPaintEvent *event) { + if(!screensaver->exists()) + { + QPainter painter(this); + painter.fillRect(geometry(), Qt::black); + } if(screensaver->mode == SAVER_IMAGE) { switch(screensaver->effect) { case TRANSITION_NONE: diff --git a/backend/src/sessionwatcher.cpp b/src/sessionwatcher.cpp similarity index 69% rename from backend/src/sessionwatcher.cpp rename to src/sessionwatcher.cpp index 3364cdf..b482725 100644 --- a/backend/src/sessionwatcher.cpp +++ b/src/sessionwatcher.cpp @@ -20,31 +20,23 @@ #include #include "types.h" -#define DBUS_SESSION_MANAGER_SERVICE "org.gnome.SessionManager" -#define DBUS_SESSION_MANAGER_PATH "/org/gnome/SessionManager/Presence" -#define DBUS_SESSION_MANAGER_INTERFACE "org.gnome.SessionManager.Presence" - -#define DBUS_DISPLAY_MANAGER_SERVICE "org.freedesktop.DisplayManager" -#define DBUS_DISPLAY_MANAGER_PATH "/org/freedesktop/DisplayManager" -#define DBUS_DISPLAY_MANAGER_INTERFACE "org.freedesktop.DisplayManager" - SessionWatcher::SessionWatcher(QObject *parent) : QObject(parent) { sessionPath = qgetenv("XDG_SESSION_PATH"); QDBusInterface *interface = new QDBusInterface( - DBUS_SESSION_MANAGER_SERVICE, - DBUS_SESSION_MANAGER_PATH, - DBUS_SESSION_MANAGER_INTERFACE, + SM_DBUS_SERVICE, + SM_DBUS_PATH, + SM_DBUS_INTERFACE, QDBusConnection::sessionBus()); connect(interface, SIGNAL(StatusChanged(unsigned int)), this, SLOT(onStatusChanged(unsigned int))); QDBusInterface *displayManagerInterface = new QDBusInterface( - DBUS_DISPLAY_MANAGER_SERVICE, - DBUS_DISPLAY_MANAGER_PATH, - DBUS_DISPLAY_MANAGER_INTERFACE, + DM_DBUS_SERVICE, + DM_DBUS_PATH, + DM_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(displayManagerInterface, SIGNAL(SessionRemoved(QDBusObjectPath)), this, SLOT(onSessionRemoved(QDBusObjectPath))); @@ -55,7 +47,7 @@ void SessionWatcher::onStatusChanged(unsigned int status) { qDebug() << "Session Status: " << status; - if(status == ScreenSaver::SESSION_IDLE) { + if(status == SESSION_IDLE) { Q_EMIT sessionIdle(); } } diff --git a/backend/src/sessionwatcher.h b/src/sessionwatcher.h similarity index 100% rename from backend/src/sessionwatcher.h rename to src/sessionwatcher.h diff --git a/src/test-accounts.cpp b/src/test-accounts.cpp new file mode 100644 index 0000000..4da700b --- /dev/null +++ b/src/test-accounts.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include +#include "users.h" +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + Users users; + + qDebug() << users.getUserByName("kylin"); + + return 0; +} diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..87fcc29 --- /dev/null +++ b/src/types.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef TYPES_H +#define TYPES_H + +/* https://www.narf.ssji.net/~shtrom/wiki/projets/gnomescreensavernosession */ +enum SessionStatus +{ + SESSION_AVAILABLE = 0, + SESSION_INVISIBLE = 1, + SESSION_BUSY = 2, + SESSION_IDLE = 3 +}; + +enum ScreenStatus +{ + UNDEFINED = 0x00, + SCREEN_SAVER = 0x01, + SCREEN_LOCK = 0x02 +}; + +#define SM_DBUS_SERVICE "org.gnome.SessionManager" +#define SM_DBUS_PATH "/org/gnome/SessionManager/Presence" +#define SM_DBUS_INTERFACE "org.gnome.SessionManager.Presence" + +#define DM_DBUS_SERVICE "org.freedesktop.DisplayManager" +#define DM_DBUS_PATH "/org/freedesktop/DisplayManager" +#define DM_DBUS_INTERFACE "org.freedesktop.DisplayManager" +#define DM_SEAT_INTERFACE "org.freedesktop.DisplayManager.Seat" + +#define ACT_DBUS_SERVICE "org.freedesktop.Accounts" +#define ACT_DBUS_PATH "/org/freedesktop/Accounts" +#define ACT_DBUS_INTERFACE "org.freedesktop.Accounts" +#define ACT_USER_INTERFACE "org.freedesktop.Accounts.User" + +#define DBUS_PROP_INTERFACE "org.freedesktop.DBus.Properties" + +#define SS_DBUS_SERVICE "org.ukui.ScreenSaver" +#define SS_DBUS_PATH "/" +#define SS_DBUS_INTERFACE "org.ukui.ScreenSaver" + +#define BIO_ERROR -1 +#define BIO_FAILED 0 +#define BIO_SUCCESS 1 +#define BIO_IGNORE 2 + +#define BIOMETRIC_PAM "BIOMETRIC_PAM" +#define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" +#define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS" +#define BIOMETRIC_FAILED "BIOMETRIC_FAILED" + +#endif // TYPES_H diff --git a/backend/src/backend_main.cpp b/src/ukui-screensaver-backend.cpp similarity index 92% rename from backend/src/backend_main.cpp rename to src/ukui-screensaver-backend.cpp index 8ec88a3..b4aea57 100644 --- a/backend/src/backend_main.cpp +++ b/src/ukui-screensaver-backend.cpp @@ -18,14 +18,18 @@ #include #include #include + #include "interface.h" #include "sessionwatcher.h" #include "interfaceAdaptor.h" +#include "types.h" + #include #include #include #include + void sig_chld(int /*signo*/) { pid_t pid; @@ -86,11 +90,11 @@ int main(int argc, char *argv[]) ScreenSaverAdaptor adaptor(interface); QDBusConnection service = QDBusConnection::sessionBus(); - if(!service.registerService("cn.kylinos.ScreenSaver")) { + if(!service.registerService(SS_DBUS_SERVICE)) { qDebug() << service.lastError().message(); exit(EXIT_FAILURE); } - if(!service.registerObject("/", "cn.kylinos.ScreenSaver", &adaptor, + if(!service.registerObject(SS_DBUS_PATH, SS_DBUS_SERVICE, &adaptor, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) { qDebug() << service.lastError().message(); @@ -104,8 +108,8 @@ int main(int argc, char *argv[]) interface, &Interface::onSessionIdleReceived); QObject::connect(watcher, &SessionWatcher::sessionIdle, &a, [&]{ - QDBusMessage message = QDBusMessage::createSignal("/", - "cn.kylinos.ScreenSaver", + QDBusMessage message = QDBusMessage::createSignal(SS_DBUS_PATH, + SS_DBUS_INTERFACE, "SessionIdle"); service.send(message); }); diff --git a/command/command_main.cpp b/src/ukui-screensaver-command.cpp similarity index 87% rename from command/command_main.cpp rename to src/ukui-screensaver-command.cpp index 2ec318d..1f07f39 100644 --- a/command/command_main.cpp +++ b/src/ukui-screensaver-command.cpp @@ -20,7 +20,7 @@ #include #include #include - +#include "types.h" int main(int argc, char **argv) { @@ -39,9 +39,9 @@ int main(int argc, char **argv) if(!parser.isSet(lockOption)) return -1; - QDBusInterface *interface = new QDBusInterface("cn.kylinos.ScreenSaver", - "/", - "cn.kylinos.ScreenSaver"); + QDBusInterface *interface = new QDBusInterface(SS_DBUS_SERVICE, + SS_DBUS_PATH, + SS_DBUS_INTERFACE); QDBusMessage msg = interface->call("Lock"); if(msg.type() == QDBusMessage::ErrorMessage) qDebug() << msg.errorMessage(); diff --git a/src/ukui-screensaver-dialog.cpp b/src/ukui-screensaver-dialog.cpp new file mode 100644 index 0000000..e2a7562 --- /dev/null +++ b/src/ukui-screensaver-dialog.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "fullbackgroundwidget.h" + +#define CACHE_DIR "/.cache/ukui-screensaver/" + +static void +messageOutput(QtMsgType type, const QMessageLogContext &context,const QString &msg); + +#define WORKING_DIRECTORY "/usr/share/ukui-screensaver" +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QApplication::setSetuidAllowed(true); + + + //命令行参数解析 + QCommandLineParser parser; + parser.setApplicationDescription(QCoreApplication::translate("main", "Dialog for the ukui ScreenSaver.")); + parser.addHelpOption(); + parser.addVersionOption(); + + QCommandLineOption lockOption(QStringLiteral("lock"), + QCoreApplication::translate("main", "lock the screen immediately")); + QCommandLineOption sessionIdleOption(QStringLiteral("session-idle"), + QCoreApplication::translate("main", "activated by session idle signal")); + parser.addOptions({lockOption, sessionIdleOption}); + parser.process(a); + + if(!parser.isSet(sessionIdleOption) && !parser.isSet(lockOption)) + { + return 0; + } + + qInstallMessageHandler(messageOutput); + + //加载翻译文件 + QString locale = QLocale::system().name(); + QTranslator translator; + QString qmFile = QString(WORKING_DIRECTORY"/i18n_qm/%1.qm").arg(locale); + translator.load(qmFile); + a.installTranslator(&translator); + qDebug() << "load translation file " << qmFile; + + FullBackgroundWidget *window = new FullBackgroundWidget(); + + QFile qssFile(":/qss/assets/authdialog.qss"); + if(qssFile.open(QIODevice::ReadOnly)) { + a.setStyleSheet(qssFile.readAll()); + } + qssFile.close(); + + if(parser.isSet(lockOption)) + { + window->lock(); + } + + if(parser.isSet(sessionIdleOption)) + { + window->onSessionStatusChanged(SESSION_IDLE); + } + + window->showFullScreen(); + window->activateWindow(); + + return a.exec(); +} + +static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + Q_UNUSED(context) + QDateTime dateTime = QDateTime::currentDateTime(); + QByteArray time = QString("[%1] ").arg(dateTime.toString("MM-dd hh:mm:ss.zzz")).toLocal8Bit(); + QByteArray localMsg = msg.toLocal8Bit(); + + QString filePath(context.file); + int seprator = filePath.lastIndexOf('/'); + QString fileName = filePath.right(filePath.length() - seprator - 1); + const char *file = fileName.toLocal8Bit().data(); + + switch(type) { + case QtDebugMsg: + fprintf(stderr, "%s Debug: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); + break; + case QtInfoMsg: + fprintf(stderr, "%s Info: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); + break; + case QtWarningMsg: + fprintf(stderr, "%s Warnning: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "%s Critical: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); + break; + case QtFatalMsg: + fprintf(stderr, "%s Fatal: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); + abort(); + } + fflush(stderr); +} diff --git a/src/ukui-screensaver.pro b/src/ukui-screensaver.pro index ccf369e..f8b4b43 100644 --- a/src/ukui-screensaver.pro +++ b/src/ukui-screensaver.pro @@ -7,7 +7,7 @@ QT += core gui dbus x11extras greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -include(bioAuthentication/bioAuthentication.pri) +include(BioAuth/bioauth.pri) include(VirtualKeyboard/VirtualKeyboard.pri) TARGET = ukui-screensaver-dialog @@ -32,12 +32,14 @@ PKGCONFIG += gio-2.0 x11 xcb xtst INCLUDEPATH += \ VirtualKeyboard/src/ + BioAuth/include/ SOURCES += \ - main.cpp \ + ukui-screensaver-dialog.cpp \ mainwindow.cpp \ unixsignallistener.cpp \ - pam.cpp \ + auth-pam.cpp \ + authdialog.cpp \ gsettings.cpp \ auxiliary.cpp \ configuration.cpp \ @@ -49,7 +51,9 @@ SOURCES += \ HEADERS += \ mainwindow.h \ unixsignallistener.h \ - pam.h \ + auth-pam.h \ + auth.h \ + authdialog.h \ gsettings.h \ auxiliary.h \ configuration.h \ @@ -59,7 +63,8 @@ HEADERS += \ monitorwatcher.h FORMS += \ - mainwindow.ui + mainwindow.ui \ + authdialog.ui RESOURCES += \ assets.qrc diff --git a/src/users.cpp b/src/users.cpp new file mode 100644 index 0000000..9af8eb2 --- /dev/null +++ b/src/users.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#include "users.h" + +#include +#include +#include +#include +#include + +#include "types.h" + +QDebug operator<<(QDebug stream, const UserItem &user) +{ + stream << user.name << user.realName << user.uid + << user.icon << user.path; + return stream; +} + +Users::Users(QObject *parent) : QObject(parent) +{ + defaultIcon = "/usr/share/pixmaps/faces/stock_person.png"; + loadUsers(); +} + +QList Users::getUsers() +{ + return users; +} + +UserItem Users::getUserByName(const QString &name) +{ + auto iter = std::find_if(users.begin(), users.end(), + [&](const UserItem &user){ + return user.name == name; + }); + return *iter; +} + +QString Users::getDefaultIcon() +{ + return defaultIcon; +} + + +//https://stackoverflow.com/questions/20206376/ +//how-do-i-extract-the-returned-data-from-qdbusmessage-in-a-qt-dbus-call +void Users::loadUsers() +{ + qDebug() << "loadUsers"; + actService = new QDBusInterface(ACT_DBUS_SERVICE, + ACT_DBUS_PATH, + ACT_DBUS_INTERFACE, + QDBusConnection::systemBus()); + + connect(actService, SIGNAL(UserAdded(const QDBusObjectPath&)), + this, SLOT(onUserAdded(const QDBusObjectPath&))); + connect(actService, SIGNAL(UserDeleted(const QDBusObjectPath&)), + this, SLOT(onUserDeleted(const QDBusObjectPath&))); + QDBusMessage ret = actService->call("ListCachedUsers"); + QList outArgs = ret.arguments(); //(QVariant(QDBusArgument,)) + QVariant first = outArgs.at(0); //QVariant(QDBusArgument,) + const QDBusArgument &dbusArgs = first.value(); + QDBusObjectPath path; + dbusArgs.beginArray(); + while (!dbusArgs.atEnd()) + { + dbusArgs >> path; + getUser(path.path()); + } + dbusArgs.endArray(); +} + +UserItem Users::getUser(const QString &path) +{ + QDBusInterface iface(ACT_DBUS_SERVICE, + path, + DBUS_PROP_INTERFACE, + QDBusConnection::systemBus()); + QDBusMessage ret = iface.call("GetAll", ACT_USER_INTERFACE); + QList outArgs = ret.arguments(); + QVariant first = outArgs.at(0); + const QDBusArgument &dbusArgs = first.value(); + UserItem user; + user.path = path; + dbusArgs.beginMap(); + while(!dbusArgs.atEnd()) + { + QString key; + QVariant value; + dbusArgs.beginMapEntry(); + dbusArgs >> key >> value; + if(key == "UserName") + { + user.name = value.toString(); + } + else if(key == "RealName") + { + user.realName = value.toString(); + } + else if(key == "IconFile") + { + user.icon = value.toString(); + if(!QFile(user.icon).exists()) + { + user.icon = defaultIcon; + } + } + else if(key == "Uid") + { + user.uid = value.toUInt(); + } + dbusArgs.endMapEntry(); + } + dbusArgs.endMap(); + if(user.realName.isEmpty()) + { + user.realName = user.name; + } + users.push_back(user); + return user; +} + +void Users::onUserAdded(const QDBusObjectPath& path) +{ + int index = findUserByPath(path.path()); + if(index != -1) + { + UserItem user = getUser(path.path()); + Q_EMIT userAdded(user); + } +} +void Users::onUserDeleted(const QDBusObjectPath& path) +{ + int index = findUserByPath(path.path()); + if(index != -1) + { + UserItem user = users.at(index); + users.removeAt(index); + Q_EMIT userDeleted(user); + } +} + +int Users::findUserByPath(const QString &path) +{ + auto iter = std::find_if(users.begin(), users.end(), + [&](const UserItem &user){ + return user.path == path; + }); + + int index = iter - users.begin(); + + return index; +} + diff --git a/src/users.h b/src/users.h new file mode 100644 index 0000000..d43a01d --- /dev/null +++ b/src/users.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * 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 3, 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 . + * +**/ +#ifndef USERS_H +#define USERS_H + +#include + + +struct UserItem +{ + QString name; + QString realName; + QString icon; + quint64 uid; + QString path; //accounts service path + friend QDebug operator<<(QDebug stream, const UserItem &user); +}; + +class QDBusInterface; +class QDBusObjectPath; +class Users : public QObject +{ + Q_OBJECT +public: + explicit Users(QObject *parent = nullptr); + QList getUsers(); + UserItem getUserByName(const QString &name); + QString getDefaultIcon(); + +private: + void loadUsers(); + UserItem getUser(const QString &path); + int findUserByPath(const QString &path); + +private Q_SLOTS: + void onUserAdded(const QDBusObjectPath& path); + void onUserDeleted(const QDBusObjectPath& path); + +Q_SIGNALS: + void userAdded(const UserItem &user); + void userDeleted(const UserItem &user); + +private: + QDBusInterface *actService; + QList users; + QString defaultIcon; +}; + +#endif // USERS_H diff --git a/src/xeventmonitor.cpp b/src/xeventmonitor.cpp new file mode 100644 index 0000000..b18d658 --- /dev/null +++ b/src/xeventmonitor.cpp @@ -0,0 +1,207 @@ +/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- + * -*- coding: utf-8 -*- + * + * Copyright (C) 2011 ~ 2017 Deepin, Inc. + * 2011 ~ 2017 Wang Yong + * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. + * + * Author: Wang Yong + * Maintainer: Wang Yong + * + * 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 3 of the License, or + * 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 . + */ + +#include "xeventmonitor.h" +#include +#include +#include +#include +#include + +// Virtual button codes that are not defined by X11. +#define Button1 1 +#define Button2 2 +#define Button3 3 +#define WheelUp 4 +#define WheelDown 5 +#define WheelLeft 6 +#define WheelRight 7 +#define XButton1 8 +#define XButton2 9 + +class XEventMonitorPrivate +{ +public: + XEventMonitorPrivate(XEventMonitor *parent); + virtual ~XEventMonitorPrivate(); + void run(); + +protected: + XEventMonitor *q_ptr; + + bool filterWheelEvent(int detail); + static void callback(XPointer trash, XRecordInterceptData* data); + void handleRecordEvent(XRecordInterceptData *); + void emitButtonSignal(const char *member, xEvent *event); + void emitKeySignal(const char *member, xEvent *event); + +private: + Q_DECLARE_PUBLIC(XEventMonitor) +}; + +XEventMonitorPrivate::XEventMonitorPrivate(XEventMonitor *parent) + : q_ptr(parent) +{ + +} + +XEventMonitorPrivate::~XEventMonitorPrivate() +{ + +} + +void XEventMonitorPrivate::emitButtonSignal(const char *member, xEvent *event) +{ + int x = event->u.keyButtonPointer.rootX; + int y = event->u.keyButtonPointer.rootY; + QMetaObject::invokeMethod(q_ptr, member, + Qt::DirectConnection, + Q_ARG(int, x), + Q_ARG(int, y)); +} + +void XEventMonitorPrivate::emitKeySignal(const char *member, xEvent *event) +{ + Display *display = XOpenDisplay(NULL); + int keyCode = event->u.u.detail; + KeySym keySym = XkbKeycodeToKeysym(display, event->u.u.detail, 0, 0); + char *keyStr = XKeysymToString(keySym); + QMetaObject::invokeMethod(q_ptr, member, + Qt::AutoConnection, + Q_ARG(int, keyCode)); + QMetaObject::invokeMethod(q_ptr, member, + Qt::AutoConnection, + Q_ARG(QString, keyStr)); + XCloseDisplay(display); +} + +void XEventMonitorPrivate::run() +{ + Display* display = XOpenDisplay(0); + if (display == 0) { + fprintf(stderr, "unable to open display\n"); + return; + } + + // Receive from ALL clients, including future clients. + XRecordClientSpec clients = XRecordAllClients; + XRecordRange* range = XRecordAllocRange(); + if (range == 0) { + fprintf(stderr, "unable to allocate XRecordRange\n"); + return; + } + + // Receive KeyPress, KeyRelease, ButtonPress, ButtonRelease and MotionNotify events. + memset(range, 0, sizeof(XRecordRange)); + range->device_events.first = KeyPress; + range->device_events.last = MotionNotify; + + // And create the XRECORD context. + XRecordContext context = XRecordCreateContext(display, 0, &clients, 1, &range, 1); + if (context == 0) { + fprintf(stderr, "XRecordCreateContext failed\n"); + return; + } + XFree(range); + + XSync(display, True); + + Display* display_datalink = XOpenDisplay(0); + if (display_datalink == 0) { + fprintf(stderr, "unable to open second display\n"); + return; + } + if (!XRecordEnableContext(display_datalink, context, callback, (XPointer) this)) { + fprintf(stderr, "XRecordEnableContext() failed\n"); + return; + } + +} + +void XEventMonitorPrivate::callback(XPointer ptr, XRecordInterceptData* data) +{ + ((XEventMonitorPrivate *) ptr)->handleRecordEvent(data); +} + +void XEventMonitorPrivate::handleRecordEvent(XRecordInterceptData* data) +{ + + if (data->category == XRecordFromServer) { + xEvent * event = (xEvent *)data->data; + switch (event->u.u.type) + { + case ButtonPress: + if (filterWheelEvent(event->u.u.detail)) { + emitButtonSignal("buttonPress", event); + } + break; + case MotionNotify: + emitButtonSignal("buttonDrag", event); + break; + case ButtonRelease: + if (filterWheelEvent(event->u.u.detail)) { + emitButtonSignal("buttonRelease", event); + } + break; + case KeyPress: + emitKeySignal("keyPress", event); + break; + case KeyRelease: + emitKeySignal("keyRelease", event); + break; + default: + break; + } + } + fflush(stdout); + XRecordFreeData(data); +} + +bool XEventMonitorPrivate::filterWheelEvent(int detail) +{ + return detail != WheelUp && detail != WheelDown && detail != WheelLeft && detail != WheelRight; +} + + +XEventMonitor::XEventMonitor(QObject *parent) + : QThread(parent), + d_ptr(new XEventMonitorPrivate(this)) +{ + Q_D(XEventMonitor); +} + +XEventMonitor::~XEventMonitor() +{ + requestInterruption(); + quit(); + wait(); +} + +void XEventMonitor::run() +{ + if(!isInterruptionRequested()) + { + d_ptr->run(); + } +} diff --git a/src/event_monitor.h b/src/xeventmonitor.h similarity index 61% rename from src/event_monitor.h rename to src/xeventmonitor.h index 63d7853..b30099d 100644 --- a/src/event_monitor.h +++ b/src/xeventmonitor.h @@ -22,48 +22,37 @@ * along with this program. If not, see . */ -#ifndef EVENTMONITOR_H -#define EVENTMONITOR_H +#ifndef XEVENTMONITOR_H +#define XEVENTMONITOR_H #include -#include -#include +#include +#include - -// Virtual button codes that are not defined by X11. -#define Button1 1 -#define Button2 2 -#define Button3 3 -#define WheelUp 4 -#define WheelDown 5 -#define WheelLeft 6 -#define WheelRight 7 -#define XButton1 8 -#define XButton2 9 - -class EventMonitor : public QThread +class XEventMonitorPrivate; +class XEventMonitor : public QThread { Q_OBJECT public: - EventMonitor(QObject *parent = 0); - ~EventMonitor(); + XEventMonitor(QObject *parent = 0); + ~XEventMonitor(); Q_SIGNALS: void buttonPress(int x, int y); void buttonDrag(int x, int y); void buttonRelease(int x, int y); - void keyPress(int code); - void keyRelease(int code); + void keyPress(int keyCode); + void keyRelease(int keyCode); + void keyPress(const QString &key); + void keyRelease(const QString &key); protected: - bool filterWheelEvent(int detail); - static void callback(XPointer trash, XRecordInterceptData* data); - void handleRecordEvent(XRecordInterceptData *); void run(); private: - bool isPress; + XEventMonitorPrivate *d_ptr; + Q_DECLARE_PRIVATE(XEventMonitor) }; #endif