ukui-screensaver/0000755000175000017500000000000013637125674013007 5ustar fengfengukui-screensaver/man/0000755000175000017500000000000013517013306013543 5ustar fengfengukui-screensaver/man/ukui-screensaver-dialog.10000644000175000017500000000423513517013306020361 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB\-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), .BR ukui-screensaver-preferences (1), .BR gtk-options (7) ukui-screensaver/man/ukui-screensaver-command.10000644000175000017500000000415713517013306020543 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB \-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated/re-written for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), ukui-screensaver/man/ukui-screensaver-backend.10000644000175000017500000000423513517013306020511 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB\-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), .BR ukui-screensaver-preferences (1), .BR gtk-options (7) ukui-screensaver/i18n_ts/0000755000175000017500000000000013637125674014274 5ustar fengfengukui-screensaver/i18n_ts/pt.ts0000644000175000017500000001547013637125674015276 0ustar fengfeng AuthDialog 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 Password: Account locked %1 minutes due to %2 fail attempts Authentication failure,there are still %1 remaining opportunities Biometric Authentication Password Authentication Other Devices BioAuthWidget Form Formato TextLabel TextLabel More Mais Retry Tente novamente Password Senha BioDevices FingerPrint Impressão digital FingerVein FingerVein Iris Íris Face Face VoicePrint VoicePrint BioDevicesWidget Form Formato Please select other biometric devices Por favor, selecione outros dispositivos biométricos Device Type: Tipo de dispositivo: Device Name: Nome do dispositivo: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK DeviceType FingerPrint Impressão digital FingerVein FingerVein Iris Íris Face Face VoicePrint VoicePrint KeyboardWidget KeyboardWidget KeyboardWidget LockWidget Form Formato Date Encontro Time Tempo Guest Convidado SwitchUser Mudar de utilizador main 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 ukui-screensaver/i18n_ts/es.ts0000644000175000017500000001557613637125674015271 0ustar fengfeng 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 Password: Account locked %1 minutes due to %2 fail attempts Authentication failure,there are still %1 remaining opportunities Biometric Authentication Password Authentication Other Devices 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: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK DeviceType FingerPrint Huella dactilar FingerVein FingerVein Iris Iris Face Cara VoicePrint Impresión de voz 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 ukui-screensaver/i18n_ts/zh_CN.ts0000644000175000017500000001764013637125674015655 0ustar fengfeng AuthDialog More Devices 选择其他设备 Biometric 使用生物识别认证 Password 使用密码认证 Retry 重试 UnLock 解锁 LoggedIn 已登录 Password: 密码: Account locked %1 minutes due to %2 fail attempts 账户锁定%1分钟由于%2次错误尝试 Password Incorrect, Please try again 密码错误,请重试 Authentication failure,there are still %1 remaining opportunities 认证失败,还剩%1次尝试机会 Biometric Authentication 生物识别认证 Password Authentication 密码认证 Other Devices 其他设备 BioDevices FingerPrint 指纹 FingerVein 指静脉 Iris 虹膜 Face 人脸 VoicePrint 声纹 BioDevicesWidget Please select other biometric devices 请选择其他生物识别设备 Device Type: 设备类型: Device Name: 设备名称: BiometricAuthWidget Current device: 当前设备: Identify failed, Please retry. 识别失败,请重试 BiometricDevicesWidget Please select the biometric device 请选择生物设备 Device type: 设备类型: Device name: 设备型号: OK 确定 DeviceType FingerPrint 指纹 FingerVein 指静脉 Iris 虹膜 Face 人脸 VoicePrint 声纹 KeyboardWidget KeyboardWidget LockWidget Form Date Time Guest 游客 SwitchUser 切换用户 main Start command for the ukui ScreenSaver. lock the screen immediately Dialog for the ukui ScreenSaver. activated by session idle signal ukui-screensaver/i18n_ts/ru.ts0000644000175000017500000001606513637125674015302 0ustar fengfeng AuthDialog Form форма More Devices Дополнительные устройства Biometric Биометрические Password пароль Retry Retry UnLock отпереть LoggedIn LoggedIn Password Incorrect, Please try again Пароль неверен, повторите попытку Password: Account locked %1 minutes due to %2 fail attempts Authentication failure,there are still %1 remaining opportunities Biometric Authentication Password Authentication Other Devices BioAuthWidget Form форма TextLabel TextLabel More Больше Retry Retry Password пароль BioDevices FingerPrint FingerPrint FingerVein FingerVein Iris Ирис Face Лицо VoicePrint Voiceprint BioDevicesWidget Form форма Please select other biometric devices Выберите другие биометрические устройства Device Type: Тип устройства: Device Name: Имя устройства: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK DeviceType FingerPrint FingerPrint FingerVein FingerVein Iris Ирис Face Лицо VoicePrint Voiceprint KeyboardWidget KeyboardWidget KeyboardWidget LockWidget Form форма Date Дата Time Время Guest гость SwitchUser Сменить пользователя main Start command for the ukui ScreenSaver. Начните команду для ukui ScreenSaver. lock the screen immediately немедленно заблокируйте экран Dialog for the ukui ScreenSaver. Диалог для экранного экрана ukui. activated by session idle signal активируется сигналом холостого хода ukui-screensaver/i18n_ts/CMakeLists.txt0000644000175000017500000000054013517013306017014 0ustar fengfengfind_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/) ukui-screensaver/i18n_ts/fr.ts0000644000175000017500000001561713637125674015265 0ustar fengfeng AuthDialog 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 Password: Account locked %1 minutes due to %2 fail attempts Authentication failure,there are still %1 remaining opportunities Biometric Authentication Password Authentication Other Devices BioAuthWidget Form Forme TextLabel TextLabel More Plus Retry Réessayez Password Mot de passe BioDevices FingerPrint Empreinte digitale FingerVein FingerVein Iris Iris Face Visage VoicePrint VoicePrint BioDevicesWidget Form Forme Please select other biometric devices Veuillez sélectionner d'autres appareils biométriques Device Type: Type d'appareil: Device Name: Nom de l'appareil: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK DeviceType FingerPrint Empreinte digitale FingerVein FingerVein Iris Iris Face Visage VoicePrint VoicePrint KeyboardWidget KeyboardWidget KeyboardWidget LockWidget Form Forme Date Rendez-vous amoureux Time Temps Guest Client SwitchUser Changer d'utilisateur main 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 ukui-screensaver/VirtualKeyboard/0000755000175000017500000000000013630646305016106 5ustar fengfengukui-screensaver/VirtualKeyboard/VirtualKeyboard.pro0000644000175000017500000000200313630646305021732 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-10-12T16:43:42 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = VirtualKeyboard TEMPLATE = app # The following define makes your compiler emit warnings if you use # 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 # 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 CONFIG += link_pkgconfig debug PKGCONFIG += xtst x11 include(VirtualKeyboard.pri) SOURCES += \ $$PWD/src/main.cpp ukui-screensaver/VirtualKeyboard/CMakeLists.txt0000644000175000017500000000103313630646305020643 0ustar fengfengfind_package(Qt5 COMPONENTS Core Widgets REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) qt5_add_resources(VirtualKeyboard_SRC src/keyboard.qrc) set(VirtualKeyboard_SRC ${VirtualKeyboard_SRC} src/cursormonitor.cpp src/keyboardwidget.cpp src/virtualkeyboard.cpp src/x11keyboard.cpp src/keyboard.qrc) include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ) add_library(VirtualKeyboard STATIC ${VirtualKeyboard_SRC}) target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets) ukui-screensaver/VirtualKeyboard/src/0000755000175000017500000000000013630646305016675 5ustar fengfengukui-screensaver/VirtualKeyboard/src/cursormonitor.cpp0000644000175000017500000000400013630646305022320 0ustar fengfeng/** * 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 "cursormonitor.h" #include #include CursorMonitor::CursorMonitor(QObject *parent) : QThread(parent) { } void CursorMonitor::run() { Display *display; XEvent xevent; Window window; display = XOpenDisplay(NULL); window = DefaultRootWindow(display); XAllowEvents(display, AsyncBoth, CurrentTime); XGrabPointer(display, window, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask , GrabModeAsync, GrabModeAsync, None, None, CurrentTime); while(1) { XNextEvent(display, &xevent); switch (xevent.type) { case MotionNotify: //printf("Mouse move : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root); Q_EMIT cursorPosChanged(QPoint(xevent.xmotion.x_root, xevent.xmotion.y_root)); break; case ButtonPress: // printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]); break; case ButtonRelease: // printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]); break; } } } ukui-screensaver/VirtualKeyboard/src/cursormonitor.h0000644000175000017500000000210113630646305021765 0ustar fengfeng/** * 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 CURSORMONITOR_H #define CURSORMONITOR_H #include #include class CursorMonitor : public QThread { Q_OBJECT public: explicit CursorMonitor(QObject *parent = nullptr); void run(); Q_SIGNALS: void cursorPosChanged(const QPoint& pos); }; #endif // CURSORMONITOR_H ukui-screensaver/VirtualKeyboard/src/keyboardwidget.cpp0000644000175000017500000003740513630646305022416 0ustar fengfeng/** * 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 "keyboardwidget.h" #include "ui_keyboardwidget.h" #include #include #include #define SYMBOL_KEY_COUNT 29 #define SYMBOL_PAGE_COUNT 2 #define BUTTON_BG "QPushButton{background:#1E1B18}" #define BUTTON_BG_PRESSED "QPushButton{background: #181613;}" #define BUTTON_BG_HL "QPushButton{background:#80c342}" #define BUTTON_BG_HL_PRESSED "QPushButton{background:#486E25}" QChar symbols[SYMBOL_PAGE_COUNT][SYMBOL_KEY_COUNT] = { {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'}, {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '`', '-', '=', '[', ']', '\\', '|', '{', '}', '~','<', '>', ':', ';', '\'', '"', '-', '+', '?'}}; KeyboardWidget::KeyboardWidget(QWidget *parent) : QWidget(parent), ui(new Ui::KeyboardWidget), capsLock(false), isShift(false), page(0) { vKeyboard = new X11Keyboard(this); connect(this, SIGNAL(keyPressed(QChar)), vKeyboard, SLOT(onKeyPressed(QChar))); connect(this, SIGNAL(keyPressed(FuncKey::FUNCKEY)), vKeyboard, SLOT(onKeyPressed(FuncKey::FUNCKEY))); ui->setupUi(this); bindSingal(); setDefaultIcon(); } KeyboardWidget::~KeyboardWidget() { delete ui; } void KeyboardWidget::resizeEvent(QResizeEvent */*event*/) { int w = width(); int h = height(); int mainLeftMargin = ui->hl_main->contentsMargins().left(); int mainRightMargin = ui->hl_main->contentsMargins().right(); int mainTopMargin = ui->hl_main->contentsMargins().left(); int mainBottomMargin = ui->hl_main->contentsMargins().right(); int mainSpacing = ui->hl_main->spacing(); int itemSpacing = ui->hl_1->spacing(); int btnWidthCount = w - 11 * itemSpacing - mainSpacing- mainLeftMargin - mainRightMargin; int btnHeightCount = h - 3 * itemSpacing - mainTopMargin - mainBottomMargin; double btnWidth = btnWidthCount / 12; double btnHeight = btnHeightCount / 4; for(int i = 0; i <= 28; i++) { QString btnObjName = "btn_" + QString::number(i); QPushButton *btn = ui->page_letter->findChild(btnObjName); btn->setFixedSize(btnWidth, btnHeight); } ui->btn_ctrl_l->setFixedSize(btnWidth * 1.3, btnHeight); ui->btn_ctrl_r->setFixedSize(btnWidth * 1.3, btnHeight); ui->btn_alt_l->setFixedSize(btnWidth, btnHeight); ui->btn_alt_r->setFixedSize(btnWidth, btnHeight); ui->btn_super->setFixedSize(btnWidth, btnHeight); ui->btn_shift_l->setFixedSize(btnWidth, btnHeight); ui->spacer_2->changeSize(btnWidth / 2, 20); for(int i = 1; i <= 9; i++) { QString btnObjName = "btn_num_" + QString::number(i); QPushButton *btn = ui->page_number->findChild(btnObjName); btn->setFixedWidth(btnWidth); } ui->btn_backspace_num->setFixedSize(btnWidth,btnHeight); ui->btn_insert->setFixedWidth(btnWidth); ui->btn_delete->setFixedWidth(btnWidth); ui->btn_home->setFixedWidth(btnWidth); ui->btn_end->setFixedWidth(btnWidth); ui->btn_pgup->setFixedWidth(btnWidth); ui->btn_pgdn->setFixedWidth(btnWidth); ui->btn_up->setFixedSize(btnWidth,btnHeight); ui->btn_down->setFixedSize(btnWidth,btnHeight); ui->btn_left->setFixedSize(btnWidth,btnHeight); ui->btn_right->setFixedSize(btnWidth,btnHeight); ui->btn_close->setFixedHeight(btnHeight); ui->btn_letter->setFixedHeight(btnHeight); ui->btn_symbol->setFixedHeight(btnHeight); ui->btn_number->setFixedHeight(btnHeight); setIconSize(); } float hScale = 0.6; float wScale = hScale; #define SET_ICON_SIZE_SCALE(btn) \ ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width() * hScale, ui->btn_##btn->height() * wScale)); #define SET_ICON_SIZE(btn) \ ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width(), ui->btn_##btn->height())); void KeyboardWidget::setIconSize() { SET_ICON_SIZE_SCALE(backspace); SET_ICON_SIZE_SCALE(enter); SET_ICON_SIZE_SCALE(close); SET_ICON_SIZE_SCALE(super); SET_ICON_SIZE_SCALE(shift_l); SET_ICON_SIZE_SCALE(shift_r); SET_ICON_SIZE(up); SET_ICON_SIZE(down); SET_ICON_SIZE(left); SET_ICON_SIZE(right); } void KeyboardWidget::bindSingal() { for(auto obj : ui->page_letter->children()) { if(obj->metaObject()->className() == QString("QPushButton")) { QPushButton *btn = static_cast(obj); btn->setFocusPolicy(Qt::NoFocus); connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onButtonClicked); connect(btn, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed); connect(btn, &QPushButton::released, this, &KeyboardWidget::onButtonReleased); } } for(auto obj : ui->page_number->children()) { if(obj->metaObject()->className() == QString("QPushButton")) { QPushButton *btn = static_cast(obj); btn->setFocusPolicy(Qt::NoFocus); connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onButtonClicked); connect(btn, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed); connect(btn, &QPushButton::released, this, &KeyboardWidget::onButtonReleased); } } ui->btn_close->setFocusPolicy(Qt::NoFocus); ui->btn_letter->setFocusPolicy(Qt::NoFocus); ui->btn_symbol->setFocusPolicy(Qt::NoFocus); ui->btn_number->setFocusPolicy(Qt::NoFocus); connect(ui->btn_letter, &QPushButton::clicked, this, [&] { ui->stackedWidget->setCurrentWidget(ui->page_letter); page = 0; switchPage(); }); connect(ui->btn_symbol, &QPushButton::clicked, this, [&] { ui->stackedWidget->setCurrentWidget(ui->page_letter); page = 1; switchPage(); }); connect(ui->btn_number, &QPushButton::clicked, this, [&] { ui->stackedWidget->setCurrentWidget(ui->page_number); }); connect(ui->btn_close, &QPushButton::clicked, this, &KeyboardWidget::aboutToClose); connect(ui->btn_close, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed); connect(ui->btn_close, &QPushButton::released, this, &KeyboardWidget::onButtonReleased); } void KeyboardWidget::setDefaultIcon() { ui->btn_backspace->setIcon(QIcon(":/images/images/backspace.svg")); ui->btn_backspace_num->setIcon(QIcon(":/images/images/backspace.svg")); ui->btn_enter->setIcon(QIcon(":/images/images/enter.svg")); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_close->setIcon(QIcon(":/images/images/close.svg")); ui->btn_super->setIcon(QIcon(":/images/images/super.svg")); ui->btn_up->setIcon(QIcon(":/images/images/up.svg")); ui->btn_down->setIcon(QIcon(":/images/images/down.svg")); ui->btn_left->setIcon(QIcon(":/images/images/left.svg")); ui->btn_right->setIcon(QIcon(":/images/images/right.svg")); } QString KeyboardWidget::getKeyName(QPushButton *btn) { QString objName = btn->objectName(); int lastUnderline = objName.lastIndexOf('_'); int start = strlen("btn_"); int keyLength = lastUnderline - start; QString keyName = objName.mid(start, keyLength); return keyName; } void KeyboardWidget::changeFuncKeyStyle(QPushButton *btn, bool isPressed) { QString modName = getKeyName(btn); Modifier::MOD mod = Modifier::getModifier(modName); if(vKeyboard->hasModifier(mod)) { if(isPressed) btn->setStyleSheet(BUTTON_BG_HL_PRESSED); else btn->setStyleSheet(BUTTON_BG_HL); } else { if(isPressed) btn->setStyleSheet(BUTTON_BG_PRESSED); else btn->setStyleSheet(BUTTON_BG); } } void KeyboardWidget::changeShitKeyStyle(QPushButton *btn, bool isPressed) { if(page == 0){ if(isShift) { if(capsLock){ if(isPressed) { btn->setStyleSheet(BUTTON_BG_HL_PRESSED); btn->setIcon(QIcon(":/images/images/capslock_click.svg")); } else { btn->setStyleSheet(BUTTON_BG_HL); btn->setIcon(QIcon(":/images/images/capslock.svg")); } } else { if(isPressed) btn->setIcon(QIcon(":/images/images/capslock_hl_click.svg")); else btn->setIcon(QIcon(":/images/images/capslock_hl.svg")); } } else { if(isPressed) btn->setIcon(QIcon(":/images/images/capslock_click.svg")); else btn->setIcon(QIcon(":/images/images/capslock.svg")); } } } void KeyboardWidget::changeDirectKeyStyle(QPushButton *btn, bool isPressed) { QString keyName = getKeyName(btn); FuncKey::FUNCKEY key = FuncKey::getKey(keyName); if(key == FuncKey::UNKNOWN) return; QString iconName = QString(":/images/images/%1.svg").arg(keyName); QString iconNamePressed = QString(":/images/images/%1_click.svg").arg(keyName); if(isPressed) btn->setIcon(QIcon(iconNamePressed)); else btn->setIcon(QIcon(iconName)); } /** * @brief 修改按键样式 * @param obj 按键 * @param isPressed 按下或者松开 */ void KeyboardWidget::changeKeyStyle(QPushButton *btn, bool isPressed) { if(btn == ui->btn_ctrl_l || btn == ui->btn_ctrl_r || btn == ui->btn_alt_l || btn == ui->btn_alt_r || btn == ui->btn_super) { changeFuncKeyStyle(btn, isPressed); } if(btn == ui->btn_shift_l) changeShitKeyStyle(ui->btn_shift_l, isPressed); if(btn == ui->btn_shift_r) changeShitKeyStyle(ui->btn_shift_r, isPressed); changeDirectKeyStyle(btn, isPressed); } void KeyboardWidget::onButtonPressed() { QPushButton *btn = static_cast(sender()); changeKeyStyle(btn, true); } void KeyboardWidget::onButtonReleased() { QPushButton *btn = static_cast(sender()); changeKeyStyle(btn, false); } void KeyboardWidget::onButtonClicked() { QObject *obj = sender(); if(obj->metaObject()->className() != QString("QPushButton")) return; QPushButton *btn = static_cast(obj); QString keyName = getKeyName(btn); qDebug() << "keyName: " << keyName; Modifier::MOD mod = Modifier::getModifier(keyName); FuncKey::FUNCKEY funcKey = FuncKey::getKey(keyName); if(keyName == "shift") { if(page == 0) { isShift = !isShift; if(isShift) { //第一次被按下 capsLock = false; shiftLastClicked = QTime::currentTime(); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock_hl.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock_hl.svg")); } else { int doubleClickInterval = QApplication::doubleClickInterval(); if(shiftLastClicked.msecsTo(QTime::currentTime()) <= doubleClickInterval) { //shift键双击,锁定大写 capsLock = true; isShift = true; ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_l->setStyleSheet("QPushButton{background:#80c342}"); ui->btn_shift_r->setStyleSheet("QPushButton{background:#80c342}"); } else { ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_l->setStyleSheet("QPushButton{background:#1e1b18}"); ui->btn_shift_r->setStyleSheet("QPushButton{background:#1e1b18}"); } } toggleCase(); } else { page = page % (SYMBOL_PAGE_COUNT - 1) + 1; switchPage(); } } else if(mod != Modifier::UNKNOWN) { if(vKeyboard->hasModifier(mod)) { vKeyboard->removeModifier(mod); btn->setStyleSheet(BUTTON_BG); btn->setStyleSheet(BUTTON_BG); } else { vKeyboard->addModifier(mod); btn->setStyleSheet(BUTTON_BG_HL); btn->setStyleSheet(BUTTON_BG_HL); } } else if(funcKey != FuncKey::UNKNOWN) { Q_EMIT keyPressed(funcKey); } else { //字符键 QChar c; QString text = btn->text(); qDebug() << "clicked button text: " << text; if(text == "&&") c = '&'; else if(text.length() == 1) c = text.at(0); Q_EMIT keyPressed(c); //如果shift键被单击,按一个键后就恢复为小写 if(isShift && !capsLock) { isShift = false; toggleCase(); changeShitKeyStyle(ui->btn_shift_l, false); changeShitKeyStyle(ui->btn_shift_r, false); } clearModifier(); } } void KeyboardWidget::clearModifier() { for(auto mod : vKeyboard->getAllModifier()) { QString modName = Modifier::getModifierName(mod); if(mod == Modifier::SUPER) { QString objName = QString("btn_%1").arg(modName); QPushButton *btn = ui->page_letter->findChild(objName); btn->setStyleSheet(BUTTON_BG); } else { QString objName = QString("btn_%1_l").arg(modName); QPushButton *btn = ui->page_letter->findChild(objName); btn->setStyleSheet(BUTTON_BG); objName = QString("btn_%1_r").arg(modName); btn = ui->page_letter->findChild(objName); btn->setStyleSheet(BUTTON_BG); } } vKeyboard->clearModifier(); } void KeyboardWidget::toggleCase() { for(int i = 0; i < 26; i++) { QString objName = "btn_" + QString::number(i); QPushButton *btn = findChild(objName); QChar ch; if(isShift) { //切换到大写 ch = symbols[0][i].toUpper(); } else { ch = symbols[0][i]; } btn->setText(ch); } } void KeyboardWidget::switchPage() { if(page == 0) { ui->btn_shift_l->setText(""); ui->btn_shift_r->setText(""); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); } else { QString text = QString("%1/%2").arg(page).arg(SYMBOL_PAGE_COUNT - 1); ui->btn_shift_l->setText(text); ui->btn_shift_r->setText(text); ui->btn_shift_l->setIcon(QIcon()); ui->btn_shift_r->setIcon(QIcon()); } for(int i = 0; i < SYMBOL_KEY_COUNT; i++) { QString btnObjName = "btn_" + QString::number(i); QPushButton *btn = ui->page_letter->findChild(btnObjName); QChar c = symbols[page][i]; if(c == '&') btn->setText("&&"); else btn->setText(c); } } ukui-screensaver/VirtualKeyboard/src/keyboardwidget.ui0000644000175000017500000012247613630646305022254 0ustar fengfeng KeyboardWidget Qt::NonModal 0 0 1106 293 0 0 0 0 KeyboardWidget 0 QLayout::SetMinAndMaxSize 0 0 0 0 20 QLayout::SetNoConstraint 10 10 10 10 0 0 QLayout::SetNoConstraint 0 0 0 0 5 QLayout::SetNoConstraint Qt::Vertical 20 40 10 QLayout::SetNoConstraint 0 0 q 0 0 w 0 0 e 0 0 r 0 0 t 0 0 y 0 0 u 0 0 i 0 0 o 0 0 p 0 0 10 QLayout::SetNoConstraint Qt::Horizontal QSizePolicy::Maximum 40 20 0 0 a 0 0 s 0 0 d 0 0 f 0 0 g 0 0 h 0 0 j 0 0 k 0 0 l 0 0 10 QLayout::SetNoConstraint 0 0 0 0 z 0 0 x 0 0 c 0 0 v 0 0 b 0 0 n 0 0 m 0 0 , 0 0 . 0 0 10 QLayout::SetNoConstraint 0 0 Ctrl 0 0 0 0 Alt 0 0 0 0 Alt 0 0 / 0 0 Ctrl Qt::Vertical 20 40 QLayout::SetNoConstraint Qt::Horizontal 40 20 10 QLayout::SetNoConstraint QLayout::SetNoConstraint 10 0 0 9 0 0 5 0 0 8 0 0 4 0 0 2 0 0 7 0 0 1 0 0 6 0 0 3 0 0 0 0 0 Qt::Horizontal 40 20 QLayout::SetNoConstraint 10 0 0 Delete 0 0 End 0 0 Insert 0 0 PgUp 0 0 0 0 0 0 Home 0 0 0 0 0 0 PgDn Qt::Horizontal 40 20 5 QLayout::SetNoConstraint 0 0 0 0 Qt::Vertical 20 40 0 0 100 16777215 0 0 100 16777215 Abc 0 0 100 16777215 @ 0 0 100 16777215 123 Qt::Vertical 20 40 ukui-screensaver/VirtualKeyboard/src/virtualkeyboard.h0000644000175000017500000000241613630646305022260 0ustar fengfeng/** * 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 VIRTUALKEYBOARD_H #define VIRTUALKEYBOARD_H #include #include #include "keyboardwidget.h" #include "cursormonitor.h" class VirtualKeyboard : public QWidget { Q_OBJECT public: explicit VirtualKeyboard(QWidget *parent = 0); private: void adjustGeometry(int screen); Q_SIGNALS: void aboutToClose(); private: KeyboardWidget *keyboardWidget; CursorMonitor *cursorMonitor; bool isApplication; }; #endif // VIRTUALKEYBOARD_H ukui-screensaver/VirtualKeyboard/src/x11keyboard.h0000644000175000017500000000555613630646305021213 0ustar fengfeng/** * 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 X11KEYBOARD_H #define X11KEYBOARD_H #include #include class Modifier : public QObject { Q_OBJECT public: Modifier(){} enum MOD{ UNKNOWN = -1, CTRL, SHIFT, ALT, SUPER }; Q_ENUM(MOD) static QString getModifierName(int mod) { QMetaEnum metaEnum = QMetaEnum::fromType(); const char* modName = metaEnum.valueToKey(mod); QString result = QString(modName).toLower(); return result; } static MOD getModifier(const QString &modName) { QMetaEnum metaEnum = QMetaEnum::fromType(); MOD mod = (MOD)metaEnum.keyToValue(modName.toUpper().toLocal8Bit().data()); return mod; } }; class FuncKey : public QObject { Q_OBJECT public: FuncKey(){} enum FUNCKEY { UNKNOWN = -1, SPACE = 0, BACKSPACE, ENTER, HOME, END, PGUP, PGDN, INSERT, DELETE, UP, DOWN, LEFT, RIGHT }; Q_ENUM(FUNCKEY) static QString getKeyName(int key) { QMetaEnum metaEnum = QMetaEnum::fromType(); const char* keyName = metaEnum.valueToKey(key); QString result = QString(keyName).toLower(); return result; } static FUNCKEY getKey(const QString &keyName) { QMetaEnum metaEnum = QMetaEnum::fromType(); FUNCKEY key = (FUNCKEY)metaEnum.keyToValue(keyName.toUpper().toLocal8Bit().data()); return key; } }; class X11Keyboard : public QObject { Q_OBJECT public: explicit X11Keyboard(QObject *parent = nullptr); ~X11Keyboard(); void addModifier(Modifier::MOD mod); void removeModifier(Modifier::MOD mod); bool hasModifier(Modifier::MOD mod); QList getAllModifier(); void clearModifier(); public Q_SLOTS: void onKeyPressed(QChar c); void onKeyPressed(FuncKey::FUNCKEY key); private: void sendKey(unsigned int keyCode); private: QList modList; }; #endif // X11KEYBOARD_H ukui-screensaver/VirtualKeyboard/src/keyboard.qrc0000644000175000017500000000172413630646305021210 0ustar fengfeng keyboard.qss images/backspace_click.svg images/backspace.svg images/capslock_click.svg images/capslock_hl.svg images/capslock.svg images/down_click.svg images/down.svg images/enter_click.svg images/enter.svg images/left_click.svg images/left.svg images/right_click.svg images/right.svg images/super_click.svg images/super.svg images/up.svg images/close_click.svg images/close.svg images/capslock_hl_click.svg images/up_click.svg ukui-screensaver/VirtualKeyboard/src/main.cpp0000644000175000017500000000220313630646305020322 0ustar fengfeng/** * 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 "virtualkeyboard.h" #include int main(int argc, char *argv[]) { // qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); QApplication a(argc, argv); VirtualKeyboard *keyboard = new VirtualKeyboard; QObject::connect(keyboard, &VirtualKeyboard::aboutToClose, &a, &QApplication::quit); keyboard->show(); return a.exec(); } ukui-screensaver/VirtualKeyboard/src/keyboardwidget.h0000644000175000017500000000423413630646305022055 0ustar fengfeng/** * 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 KEYBOARDWIDGET_H #define KEYBOARDWIDGET_H #include #include #include #include "x11keyboard.h" namespace Ui { class KeyboardWidget; } class QPushButton; class KeyboardWidget : public QWidget { Q_OBJECT public: explicit KeyboardWidget(QWidget *parent = 0); ~KeyboardWidget(); protected: void resizeEvent(QResizeEvent *event); private: void bindSingal(); void toggleCase(); void switchPage(); void setDefaultIcon(); void setIconSize(); void changeKeyStyle(QPushButton *btn, bool isPressed); void changeFuncKeyStyle(QPushButton *btn, bool isPressed); void changeShitKeyStyle(QPushButton *btn, bool isPressed); void changeDirectKeyStyle(QPushButton *btn, bool isPressed); void clearModifier(); QString getKeyName(QPushButton *btn); private Q_SLOTS: void onButtonClicked(); void onButtonPressed(); void onButtonReleased(); Q_SIGNALS: void aboutToClose(); void keyPressed(QChar c); void keyPressed(FuncKey::FUNCKEY key); private: Ui::KeyboardWidget *ui; bool capsLock; //是否大写锁定 bool isShift; QTime shiftLastClicked; //shift键上次被点击的时间 int page; //当前是第几页的键盘 X11Keyboard *vKeyboard; }; #endif // KEYBOARDWIDGET_H ukui-screensaver/VirtualKeyboard/src/images/0000755000175000017500000000000013630646305020142 5ustar fengfengukui-screensaver/VirtualKeyboard/src/images/up_click.svg0000644000175000017500000000106013630646305022451 0ustar fengfeng 画板 13 ukui-screensaver/VirtualKeyboard/src/images/capslock.svg0000644000175000017500000000041413630646305022461 0ustar fengfeng画板 1ukui-screensaver/VirtualKeyboard/src/images/right.svg0000644000175000017500000000033513630646305022001 0ustar fengfeng画板 17ukui-screensaver/VirtualKeyboard/src/images/capslock_hl.svg0000644000175000017500000000106013630646305023142 0ustar fengfengukui-screensaver/VirtualKeyboard/src/images/capslock_hl_click.svg0000644000175000017500000000106013630646305024307 0ustar fengfengukui-screensaver/VirtualKeyboard/src/images/super_click.svg0000644000175000017500000000222713630646305023171 0ustar fengfeng画板 12ukui-screensaver/VirtualKeyboard/src/images/backspace_click.svg0000644000175000017500000000110613630646305023742 0ustar fengfeng画板 6ukui-screensaver/VirtualKeyboard/src/images/capslock_click.svg0000644000175000017500000000045613630646305023634 0ustar fengfeng画板 2ukui-screensaver/VirtualKeyboard/src/images/enter.svg0000644000175000017500000000136613630646305022006 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/enter_click.svg0000644000175000017500000000140213630646305023142 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/close.svg0000644000175000017500000000231613630646305021772 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/close_click.svg0000644000175000017500000000242113630646305023134 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/down.svg0000644000175000017500000000033513630646305021633 0ustar fengfeng画板 15ukui-screensaver/VirtualKeyboard/src/images/left.svg0000644000175000017500000000032613630646305021616 0ustar fengfeng画板 19ukui-screensaver/VirtualKeyboard/src/images/super.svg0000644000175000017500000000221313630646305022017 0ustar fengfeng画板 11ukui-screensaver/VirtualKeyboard/src/images/left_click.svg0000644000175000017500000000034213630646305022761 0ustar fengfeng画板 20ukui-screensaver/VirtualKeyboard/src/images/backspace.svg0000644000175000017500000000104413630646305022576 0ustar fengfeng画板 5ukui-screensaver/VirtualKeyboard/src/images/right_click.svg0000644000175000017500000000035113630646305023144 0ustar fengfeng画板 18ukui-screensaver/VirtualKeyboard/src/images/down_click.svg0000644000175000017500000000035113630646305022776 0ustar fengfeng画板 16ukui-screensaver/VirtualKeyboard/src/images/up.svg0000644000175000017500000000033513630646305021310 0ustar fengfeng画板 13ukui-screensaver/VirtualKeyboard/src/x11keyboard.cpp0000644000175000017500000001237413630646305021542 0ustar fengfeng/** * 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 "x11keyboard.h" #include #include #include #include struct CharMap { QChar name; KeySym code; }; struct CharMap XSpecialSymbolMap[] { {' ', XK_space}, {',', XK_comma}, {'.', XK_period}, {'\'', XK_quoteright}, {'@', XK_at}, {'#', XK_numbersign}, {'$', XK_dollar}, {'%', XK_percent}, {'&', XK_ampersand}, {'*', XK_asterisk}, {'(', XK_parenleft}, {')', XK_parenright}, {'-', XK_minus}, {'+', XK_plus}, {'!', XK_exclam}, {'"', XK_quotedbl}, {'<', XK_less}, {'>', XK_greater}, {':', XK_colon}, {';', XK_semicolon}, {'/', XK_slash}, {'?', XK_question}, {'=', XK_equal}, {'.', XK_kana_middledot}, {'~', XK_asciitilde}, {'`', XK_grave}, {'|', XK_bar}, {'^', XK_asciicircum}, {'{', XK_braceleft}, {'}', XK_braceright}, {'[', XK_bracketleft}, {']', XK_bracketright}, {'_', XK_underscore}, {'\\', XK_backslash}, }; QMap funckeyMap = { {FuncKey::SPACE, XK_space}, {FuncKey::BACKSPACE, XK_BackSpace}, {FuncKey::ENTER, XK_Return}, {FuncKey::HOME, XK_Home}, {FuncKey::END, XK_End}, {FuncKey::PGUP, XK_Page_Up}, {FuncKey::PGDN, XK_Page_Down}, {FuncKey::INSERT, XK_Insert}, {FuncKey::DELETE, XK_Delete}, {FuncKey::UP, XK_Up}, {FuncKey::DOWN, XK_Down}, {FuncKey::LEFT, XK_Left}, {FuncKey::RIGHT, XK_Right} }; QMap modifierMap = { {Modifier::CTRL, XK_Control_L}, {Modifier::ALT, XK_Alt_L}, {Modifier::SUPER, XK_Super_L}, {Modifier::SHIFT, XK_Shift_L} }; QVector shiftKeyVec = {'~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '{', '}', '|', ':', '"', '>', '?'}; static Display *display = XOpenDisplay(0); bool isShift = false; bool isLetter = false; unsigned int keyCodeOfChar(QChar c) { QString text(c); KeySym keysym = XStringToKeysym(text.toLocal8Bit().data()); if(keysym == NoSymbol) { int symbolCount = sizeof(XSpecialSymbolMap) / sizeof(struct CharMap); for(int i = 0; i < symbolCount; i++) { if(XSpecialSymbolMap[i].name == c) { keysym = XSpecialSymbolMap[i].code; break; } } } qDebug() << "keysym: " << keysym; isShift = shiftKeyVec.contains(c) || (c >= 'A' && c <= 'Z'); isLetter = c.isLetter(); KeyCode code = XKeysymToKeycode(display, keysym); return code; } X11Keyboard::X11Keyboard(QObject *parent) : QObject(parent) { } X11Keyboard::~X11Keyboard() { XCloseDisplay(display); } void X11Keyboard::addModifier(Modifier::MOD mod) { modList.push_back(mod); } void X11Keyboard::removeModifier(Modifier::MOD mod) { modList.removeOne(mod); } bool X11Keyboard::hasModifier(Modifier::MOD mod) { return modList.contains(mod); } QList X11Keyboard::getAllModifier() { return modList; } void X11Keyboard::clearModifier() { modList.clear(); } void X11Keyboard::onKeyPressed(QChar c) { unsigned int keyCode = keyCodeOfChar(c); sendKey(keyCode); } void X11Keyboard::onKeyPressed(FuncKey::FUNCKEY key) { KeyCode keyCode; KeySym keysym = funckeyMap[key]; if(keysym != NoSymbol) keyCode = XKeysymToKeycode(display, keysym); sendKey(keyCode); } void X11Keyboard::sendKey(unsigned int keyCode) { Window focusWindow; int revert; XGetInputFocus(display, &focusWindow, &revert); for(auto mod : modList){ KeyCode keyCode = XKeysymToKeycode(display, modifierMap[mod]); XTestFakeKeyEvent(display, keyCode, True, 2); } //如果使用了修饰键(如ctrl、alt)且字符键是字母,则不起用shift键,否则快捷键不起作用 if(!modList.isEmpty() && isLetter) isShift = false; if(isShift) XTestFakeKeyEvent(display, XKeysymToKeycode(display, XK_Shift_L), True, 2); XTestFakeKeyEvent(display, keyCode, True, CurrentTime); XTestFakeKeyEvent(display, keyCode, False, CurrentTime); if(isShift) XTestFakeKeyEvent(display, XKeysymToKeycode(display, XK_Shift_L), False, 2); for(auto mod : modList){ KeyCode keyCode = XKeysymToKeycode(display, modifierMap[mod]); XTestFakeKeyEvent(display, keyCode, False, 2); } XFlush(display); } ukui-screensaver/VirtualKeyboard/src/virtualkeyboard.cpp0000644000175000017500000000522713630646305022616 0ustar fengfeng/** * 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 "virtualkeyboard.h" #include #include #include #include VirtualKeyboard::VirtualKeyboard(QWidget *parent) : QWidget(parent) { Q_INIT_RESOURCE(keyboard); setAutoFillBackground(true); QPalette plt; plt.setBrush(QPalette::Background, Qt::black); setPalette(plt); setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus); keyboardWidget = new KeyboardWidget(this); QHBoxLayout *hl_keyboard = new QHBoxLayout(this); QSpacerItem *spacer = new QSpacerItem(40, 20); hl_keyboard->addSpacerItem(spacer); hl_keyboard->addWidget(keyboardWidget); QSpacerItem *spacer2 = new QSpacerItem(40, 20); hl_keyboard->addSpacerItem(spacer2); QFile qssFile(":/qss/keyboard.qss"); qssFile.open(QIODevice::ReadOnly); setStyleSheet(qssFile.readAll()); qssFile.close(); QDesktopWidget *desktop = QApplication::desktop(); cursorMonitor = new CursorMonitor(this); //在多显示器情况下,监视鼠标指针的位置和主显示器变化信号 connect(cursorMonitor, &CursorMonitor::cursorPosChanged, this, [&](const QPoint &pos){ adjustGeometry(desktop->screenNumber(pos)); }); connect(desktop, &QDesktopWidget::primaryScreenChanged, this, [&]{ adjustGeometry(desktop->primaryScreen()); }); connect(keyboardWidget, &KeyboardWidget::aboutToClose, this, &VirtualKeyboard::aboutToClose); adjustGeometry(desktop->primaryScreen()); } void VirtualKeyboard::adjustGeometry(int screen) { QDesktopWidget *desktop = QApplication::desktop(); QWidget *activateScreen = desktop->screen(screen); setGeometry(0, activateScreen->height() - activateScreen->height() / 3, activateScreen->width(), activateScreen->height() / 3); } ukui-screensaver/VirtualKeyboard/src/keyboard.qss0000644000175000017500000000133413630646305021226 0ustar fengfengQPushButton { border: none; font: 24px; color: white; background: #35322f; border-radius: 5px; } QPushButton::pressed { color: gray; background: #2a2826; } #btn_backspace, #btn_enter, #btn_shift_l, #btn_shift_r, #btn_ctrl_l, #btn_ctrl_r, #btn_alt_l, #btn_alt_r, #btn_super { font: 16px; background: #1e1b18 } #btn_backspace::pressed, #btn_enter::pressed, #btn_shift_l::pressed, #btn_shift_r::pressed, #btn_ctrl_l::pressed, #btn_ctrl_r::pressed, #btn_alt_l::pressed, #btn_alt_r::pressed, #btn_super::pressed { background: #181613; color: gray; } #btn_letter, #btn_symbol, #btn_number, #btn_insert, #btn_delete, #btn_home, #btn_end, #btn_pgup, #btn_pgdn, #btn_close { font: 16px; } ukui-screensaver/VirtualKeyboard/README.md0000644000175000017500000000004113630646305017360 0ustar fengfengA simple virtual keyboard in X11 ukui-screensaver/VirtualKeyboard/VirtualKeyboard.pri0000644000175000017500000000064213630646305021733 0ustar fengfengSOURCES += \ $$PWD/src/keyboardwidget.cpp \ $$PWD/src/x11keyboard.cpp \ $$PWD/src/cursormonitor.cpp \ $$PWD/src/virtualkeyboard.cpp HEADERS += \ $$PWD/src/keyboardwidget.h \ $$PWD/src/x11keyboard.h \ $$PWD/src/cursormonitor.h \ $$PWD/src/virtualkeyboard.h FORMS += \ $$PWD/src/keyboardwidget.ui RESOURCES += \ $$PWD/src/keyboard.qrc ukui-screensaver/CMakeLists.txt0000644000175000017500000000210613637125674015546 0ustar fengfengcmake_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) ukui-screensaver/src/0000755000175000017500000000000013645021611013557 5ustar fengfengukui-screensaver/src/interface.cpp0000644000175000017500000000524613637125674016251 0ustar fengfeng/* * 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 "interface.h" #include #include #include #include #include Interface::Interface(QObject *parent) : QObject(parent) { m_logind = new LogindIntegration(this); connect(m_logind, &LogindIntegration::requestLock, this, [this]() { this->onSessionIdleReceived(); } ); connect(m_logind, &LogindIntegration::requestUnlock, this, [this]() { char cmd[228] = {0}; char str[16]; FILE *fp; int pid; int n = sprintf(cmd, "ps -o ruser=abcdefghijklmnopqrstuvwxyz1234567890 -e -o pid,stime,cmd| grep ukui-screensaver-dialog | grep %s | grep -v grep | awk '{print $2}'", getenv("USER")); Q_UNUSED(n) fp = popen(cmd, "r"); while(fgets(str, sizeof(str)-1, fp)) { pid = atoi(str); if(pid > 0 && pid != getpid()) { kill(pid, SIGKILL); } } pclose(fp); } ); } void Interface::Lock() { qDebug() << "Lock requested"; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --lock"); qDebug() << cmd; process.startDetached(cmd); } void Interface::onSessionIdleReceived() { qDebug() << "emit SessionIdle"; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --session-idle"); qDebug() << cmd; process.startDetached(cmd); } bool Interface::checkExistChild() { char cmd[128] = {0}; char str[4]; FILE *fp; int num; sprintf(cmd, "ps -aux | grep ukui-screensaver-dialog | grep %s | grep -v grep | wc -l", getenv("USER")); fp = popen(cmd, "r"); if(fgets(str, sizeof(str)-1, fp) == NULL) qDebug() << "fgets: " << strerror(errno); pclose(fp); num = atoi(str); qDebug() << (num > 0 ? "exist dialog running" : ""); return num > 0; } void Interface::onNameLost(const QString &serviceName) { if(serviceName == "cn.kylinos.ScreenSaver") exit(0); } ukui-screensaver/src/ukui-screensaver-command.cpp0000644000175000017500000000336113517013306021175 0ustar fengfeng/* * 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 "types.h" int main(int argc, char **argv) { QCoreApplication a(argc, argv); QCommandLineParser parser; parser.setApplicationDescription(QCoreApplication::translate("main", "Start command for the ukui ScreenSaver.")); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption lockOption({"l", QStringLiteral("lock")}, QCoreApplication::translate("main", "lock the screen immediately")); parser.addOption(lockOption); parser.process(a); if(!parser.isSet(lockOption)) return -1; 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(); return 0; } ukui-screensaver/src/displaymanager.cpp0000644000175000017500000000545413517013306017273 0ustar fengfeng/* * 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(); } } ukui-screensaver/src/monitorwatcher.h0000644000175000017500000000302213517013306016772 0ustar fengfeng/* monitorwatcher.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 MONITORWATCHER_H #define MONITORWATCHER_H #include #include #include /*! * \brief The MonitorWatcher class * 监控显示器的插拔 */ class MonitorWatcher : public QThread { Q_OBJECT public: MonitorWatcher(QObject *parent=nullptr); ~MonitorWatcher(); QSize getVirtualSize(); int getMonitorCount(); Q_SIGNALS: void monitorCountChanged(int newCount); void virtualSizeChanged(const QSize &newVirtualSize); protected: void run(); private: QSize getMonitorMaxSize(const QString &drm); QMap drmStatus; QSize virtualSize; int monitorCount; bool firstDetect; }; #endif // MONITORWATCHER_H ukui-screensaver/src/iconedit.h0000644000175000017500000000360213524655606015544 0ustar fengfeng/* 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; bool eventFilter(QObject *obj, QEvent *event); 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 ukui-screensaver/src/logind.cpp0000644000175000017500000000452513630646305015554 0ustar fengfeng/* * Copyright (C) 2020 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 "logind.h" #include #include #include #include #include const static QString login1Service = QStringLiteral("org.freedesktop.login1"); const static QString login1Path = QStringLiteral("/org/freedesktop/login1"); const static QString login1ManagerInterface = QStringLiteral("org.freedesktop.login1.Manager"); const static QString login1SessionInterface = QStringLiteral("org.freedesktop.login1.Session"); LogindIntegration::LogindIntegration(QObject *parent) : QObject(parent) { QDBusInterface loginInterface(login1Service, login1Path, login1ManagerInterface, QDBusConnection::systemBus()); QDBusReply sessionPath = loginInterface.call("GetSessionByPID",(quint32) QCoreApplication::applicationPid()); if(!sessionPath.isValid()){ qWarning()<< "Get session error:" << sessionPath.error(); } else{ QString session = sessionPath.value().path(); QDBusConnection::systemBus().connect(login1Service, session, login1SessionInterface, QStringLiteral("Lock"), this, SIGNAL(requestLock())); QDBusConnection::systemBus().connect(login1Service, session, login1SessionInterface, QStringLiteral("Unlock"), this, SIGNAL(requestUnlock())); } return; } LogindIntegration::~LogindIntegration() = default; ukui-screensaver/src/xeventmonitor.cpp0000644000175000017500000001345013645021611017207 0ustar fengfeng/* -*- 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 #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) { if(QX11Info::display()){ int keyCode = event->u.u.detail; KeySym keySym = XkbKeycodeToKeysym(QX11Info::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)); } } 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(); } } ukui-screensaver/src/pam-tally.c0000644000175000017500000001636213645021611015633 0ustar fengfeng/* * 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 "pam-tally.h" #include #include #include #include #include #include #include #include //#include "gs-debug.h" char shm_tally_real[128]; #define FILE_MODE (S_IRUSR | S_IWUSR) #define CONFIG_FILE "/usr/share/lightdm/lightdm.conf.d/96-kylin-setting.conf" static int get_is_open_other_authentication() { char buf[128]; FILE *config_file; if( (config_file = fopen(CONFIG_FILE, "r")) == NULL) { //gs_debug("open %s failed", CONFIG_FILE); return 0; } int open_other_authentication = 0; while(fgets(buf, sizeof(buf), config_file)) { if(strlen(buf) == 0 || buf[0] == '#') { memset(buf, sizeof(buf), 0); continue; } if(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; char *p = strchr(buf, '='); if(!p) continue; *p = '\0'; size_t len = strlen(buf); if(len == 0) continue; //去掉=之前的空格 while(len--) if(buf[len] == ' ' || buf[len] == '\t') buf[len] = '\0'; if(strcmp(buf, "open-other-authentication") != 0) continue; p++; len = strlen(p); if(len == 0) break; //去掉等号之后的空格 while(*p == ' ' || *p == '\t') { p++; len--; } //去掉尾部空格 while(len--) if(*(p+len) == ' ' || *(p+len) == '\t') *(p+len) = '\0'; if(*p == '0') break; if(*p == '1') { open_other_authentication = 1; break; } } fclose(config_file); //gs_debug("--------------------------%d", open_other_authentication); return open_other_authentication; } static int get_pam_tally(int *deny, int *unlock_time) { char buf[128]; FILE *auth_file; if( (auth_file = fopen("/etc/pam.d/common-auth", "r")) == NULL) return -1; while(fgets(buf, sizeof(buf), auth_file)) { if(strlen(buf) == 0 || buf[0] == '#') continue; if(!strstr(buf, "deny")) continue; char *ptr = strtok(buf, " \t"); while(ptr) { if(strncmp(ptr, "deny=", 5)==0){ sscanf(ptr, "deny=%d", deny); //gs_debug("-------------------- deny=%d", *deny); } if(strncmp(ptr, "unlock_time=", 12)==0){ sscanf(ptr, "unlock_time=%d", unlock_time); //gs_debug("-------------------- unlock_time=%d", *unlock_time); } ptr = strtok(NULL, " \t"); } return 1; } return 0; } static void set_shm_tally_real() { sprintf(shm_tally_real, "%s_%d", SHM_TALLY, getuid()); } int pam_tally_init() { int fd; int deny = 0, unlock_time = 0; pam_tally *tally_ptr; set_shm_tally_real(); printf("shm path =========== : %s\n", shm_tally_real); shm_unlink(shm_tally_real); if(get_is_open_other_authentication()) { //gs_debug("open other authentication, disable pam_tally."); return 0; } if(!get_pam_tally(&deny, &unlock_time)) { //gs_debug("get pam_tally configuration failed, disable pam_tally."); return 0; } /* if(deny <= 0) deny = 3; if(unlock_time <= 0) unlock_time = 1800; */ if( (fd = shm_open(shm_tally_real, O_RDWR | O_CREAT, FILE_MODE)) == -1) { printf("shm_open error: %s\n", strerror(errno)); return -1; } ftruncate(fd, sizeof(pam_tally)); if( (tally_ptr = mmap(NULL, sizeof(pam_tally), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { //gs_debug("mmap error: %s", strerror(errno)); close(fd); return -1; } close(fd); tally_ptr->deny = deny; tally_ptr->unlock_time = unlock_time; tally_ptr->failed = 0; tally_ptr->lock_start_time = 0; return 1; } static pam_tally* pam_tally_memory() { int fd; pam_tally *tally_ptr; set_shm_tally_real(); if( (fd = shm_open(shm_tally_real, O_RDWR, FILE_MODE)) == -1) { //gs_debug("shm_open error: %s", strerror(errno)); return NULL; } if( (tally_ptr = mmap(NULL, sizeof(pam_tally), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { //gs_debug("mmap error: %s", strerror(errno)); close(fd); return NULL; } close(fd); return tally_ptr; } int pam_tally_is_enbled() { int fd; set_shm_tally_real(); if( (fd = shm_open(shm_tally_real, O_RDONLY, FILE_MODE)) == -1) { printf("shm_open error: %s\n", strerror(errno)); return 0; } pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL){ close(fd); return -1; } if(tally_ptr->deny == 0 || tally_ptr->unlock_time == 0){ close(fd); return 0; } close(fd); return 1; } int pam_tally_add_failed() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; tally_ptr->failed++; //如果失败次数达到上限,开始计时 if(tally_ptr->failed >= tally_ptr->deny) tally_ptr->lock_start_time = time(NULL); return 0; } int pam_tally_clear_failed() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; tally_ptr->failed = 0; tally_ptr->lock_start_time = 0; return 0; } int pam_tally_failure_is_out() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return (tally_ptr->failed >= tally_ptr->deny ? 1 : 0); } int pam_tally_deny() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return tally_ptr->deny; } int pam_tally_failed_count() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return tally_ptr->failed; } int pam_tally_unlock_time() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; printf("########################### unlock time = %d\n", tally_ptr->unlock_time); return tally_ptr->unlock_time; } int pam_tally_is_canUnlock() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; if(tally_ptr->failed >= tally_ptr->deny && time(NULL) - tally_ptr->lock_start_time < tally_ptr->unlock_time) return 0; return 1; } ukui-screensaver/src/screensaverwidget.h0000644000175000017500000000270113630646305017463 0ustar fengfeng/* * 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 SCREENSAVERWIDGET_H #define SCREENSAVERWIDGET_H #include #include "screensaver.h" class ScreenSaverWidget : public QWidget { Q_OBJECT public: ScreenSaverWidget(ScreenSaver *screensaver, QWidget *parent = nullptr); ~ScreenSaverWidget() ; protected: void closeEvent(QCloseEvent *); void paintEvent(QPaintEvent *event); bool eventFilter(QObject *obj, QEvent *event); private: void embedXScreensaver(const QString &path); private Q_SLOTS: void onBackgroundChanged(const QString &path); private: QTimer *timer; int xscreensaverPid; ScreenSaver *screensaver; bool closing; float opacity; }; #endif // SCREENSAVERWIDGET_H ukui-screensaver/src/authdialog.h0000644000175000017500000000755613637125674016105 0ustar fengfeng/* * 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" #include "pam-tally.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; int m_featureCount; 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 ukui-screensaver/src/users.h0000644000175000017500000000325213517013306015073 0ustar fengfeng/* * 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 ukui-screensaver/src/unixsignallistener.cpp0000644000175000017500000000355613517013306020223 0ustar fengfeng/* * 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 "unixsignallistener.h" #include #include #include #include #include int UnixSignalListener::sigusr1Fd[2]; UnixSignalListener::UnixSignalListener(QObject *parent) : QObject(parent) { if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigusr1Fd)) qFatal("Couldn't create SIGUSR1 socketpair"); snUsr1 = new QSocketNotifier(sigusr1Fd[1], QSocketNotifier::Read, this); connect(snUsr1, &QSocketNotifier::activated, this, &UnixSignalListener::handleSigUsr1); } void UnixSignalListener::usr1SignalAction(int sig, siginfo_t *siginfo, void *ucontext) { (void)sig; (void)ucontext; char buffer[16]; sprintf(buffer, "%d", siginfo->si_pid); int ignore = ::write(sigusr1Fd[0], buffer, strlen(buffer) + 1); (void)ignore; } void UnixSignalListener::chldSignalAction(int /*sig*/, siginfo_t */*siginfo*/, void */*ucontext*/) { ::waitpid(-1, NULL, 0); } void UnixSignalListener::handleSigUsr1() { snUsr1->setEnabled(false); char buffer[16]; int pid; int ignore = ::read(sigusr1Fd[1], buffer, sizeof(buffer)); sscanf(buffer, "%d", &pid); (void)ignore; /* Do Qt stuff */ Q_EMIT transition(pid); snUsr1->setEnabled(true); } ukui-screensaver/src/generalauthwidget.h0000644000175000017500000000171213517013306017434 0ustar fengfeng/* * 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_Hukui-screensaver/src/screensaver.cpp0000644000175000017500000000721413630646305016616 0ustar fengfeng/* * 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 "screensaver.h" #include #include #include ScreenSaver::ScreenSaver(QObject *parent) : QObject(parent), imageIndex(0), timer(nullptr) { } ScreenSaver::ScreenSaver(const ScreenSaver &screensaver) : mode(screensaver.mode), path(screensaver.path), effect(screensaver.effect), interval(screensaver.interval), imageIndex(screensaver.imageIndex), timer(screensaver.timer), imagePaths(screensaver.imagePaths) { } ScreenSaver::ScreenSaver(ScreenSaver &&screensaver) noexcept : mode(screensaver.mode), path(screensaver.path), effect(screensaver.effect), interval(screensaver.interval), imageIndex(screensaver.imageIndex), timer(screensaver.timer), imagePaths(screensaver.imagePaths) { } 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"; if(mode != SAVER_IMAGE) return; QFileInfo fileInfo(path); if(fileInfo.isFile()) return; QList formats = QImageReader::supportedImageFormats(); if(fileInfo.isDir()) { QDir dir(path); QStringList files = dir.entryList(QDir::Files | QDir::Readable); for(QString file : files) { fileInfo.setFile(file); QString suffix = fileInfo.suffix(); if(formats.contains(suffix.toUtf8())) imagePaths.push_back(path + "/" + file); } if(!imagePaths.empty()) { path = imagePaths[0]; timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [&]{ imageIndex = (imageIndex + 1) % imagePaths.size(); path = imagePaths[imageIndex]; lastPath = imagePaths[imageIndex - 1 < 0 ? imagePaths.size() - 1 : imageIndex - 1]; Q_EMIT imagePathChanged(path); }); timer->start(interval * 1000); Q_EMIT imagePathChanged(path); } } } void ScreenSaver::stopSwitchImages() { if(timer && timer->isActive()) timer->stop(); } bool ScreenSaver::timerStatus() { return timer->isActive(); } QDebug &operator<<(QDebug debug, const ScreenSaver &screensaver) { QString modes[] = {"blank-only", "random", "single", "image"}; QString effects[] = {"none", "fade-in-out"}; debug.nospace()<< "screensaver: "<< modes[screensaver.mode]; switch(screensaver.mode) { case SAVER_BLANK_ONLY: break; case SAVER_RANDOM: case SAVER_SINGLE: debug.nospace() << screensaver.path; break; case SAVER_IMAGE: debug.nospace() << screensaver.path << effects[screensaver.effect] << screensaver.interval; } return debug.maybeSpace(); } ukui-screensaver/src/ukui-screensaver.pro0000644000175000017500000000377313517013306017606 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-04-09T11:40:40 # #------------------------------------------------- QT += core gui dbus x11extras greaterThan(QT_MAJOR_VERSION, 4): QT += widgets include(BioAuth/bioauth.pri) include(VirtualKeyboard/VirtualKeyboard.pri) TARGET = ukui-screensaver-dialog TEMPLATE = app # The following define makes your compiler emit warnings if you use # 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 \ QT_MESSAGELOGCONTEXT LIBS += -lpam -lpam_misc -lX11 -lXext -lXtst CONFIG += link_pkgconfig PKGCONFIG += gio-2.0 x11 xcb xtst # 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 INCLUDEPATH += \ VirtualKeyboard/src/ BioAuth/include/ SOURCES += \ ukui-screensaver-dialog.cpp \ mainwindow.cpp \ unixsignallistener.cpp \ auth-pam.cpp \ authdialog.cpp \ gsettings.cpp \ auxiliary.cpp \ configuration.cpp \ screensaverwidget.cpp \ screensaver.cpp \ event_monitor.cpp \ monitorwatcher.cpp HEADERS += \ mainwindow.h \ unixsignallistener.h \ auth-pam.h \ auth.h \ authdialog.h \ gsettings.h \ auxiliary.h \ configuration.h \ screensaverwidget.h \ screensaver.h \ event_monitor.h \ monitorwatcher.h FORMS += \ mainwindow.ui \ authdialog.ui RESOURCES += \ assets.qrc TRANSLATIONS = ../i18n_ts/zh_CN.ts \ ../i18n_ts/ru.ts \ ../i18n_ts/fr.ts \ ../i18n_ts/pt.ts \ ../i18n_ts/es.ts target.path = /usr/bin/ INSTALLS += target ukui-screensaver/src/generalauthwidget.cpp0000644000175000017500000000146513517013306017774 0ustar fengfeng/* * 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 "generalauthwidget.h" GeneralAuthWidget::GeneralAuthWidget(QWidget *parent) : QWidget(parent) { } ukui-screensaver/src/org.ukui.ScreenSaver.xml0000644000175000017500000000045413517013306020266 0ustar fengfeng ukui-screensaver/src/types.h0000644000175000017500000000422013517013306015072 0ustar fengfeng/* * 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 ukui-screensaver/src/pam-tally.h0000644000175000017500000000267213630646305015646 0ustar fengfeng/* * 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 PAM_TALLY_H #define PAM_TALLY_H #include #ifdef __cplusplus extern "C" { #endif #define SHM_TALLY "/shm_tally" struct _pam_tally { int deny; //失败次数上限 int unlock_time; //失败次数达到上限后,多少秒之后才能解锁 int failed; //当前失败的次数 time_t lock_start_time; //失败次数达到上限后,开始计时 }; typedef struct _pam_tally pam_tally; int pam_tally_init(); int pam_tally_add_failed(); int pam_tally_clear_failed(); int pam_tally_falure_is_out(); int pam_tally_deny(); int pam_tally_failed_count(); int pam_tally_unlock_time(); int pam_tally_is_enbled(); int pam_tally_is_canUnlock(); #ifdef __cplusplus } #endif #endif // PAM_TALLY_H ukui-screensaver/src/xeventmonitor.h0000644000175000017500000000313213517013306016650 0ustar fengfeng/* -*- 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 . */ #ifndef XEVENTMONITOR_H #define XEVENTMONITOR_H #include #include #include class XEventMonitorPrivate; class XEventMonitor : public QThread { Q_OBJECT public: 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 keyCode); void keyRelease(int keyCode); void keyPress(const QString &key); void keyRelease(const QString &key); protected: void run(); private: XEventMonitorPrivate *d_ptr; Q_DECLARE_PRIVATE(XEventMonitor) }; #endif ukui-screensaver/src/image.qrc0000644000175000017500000000026713517013306015355 0ustar fengfeng image/hide-password.png image/show-password.png image/warn.png ukui-screensaver/src/grab-x11.cpp0000644000175000017500000000441313524655606015624 0ustar fengfeng/* * 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 "grab-x11.h" #include #include #include class XServerGraber{ public: XServerGraber() { xcb_grab_server(QX11Info::connection()); } ~XServerGraber() { xcb_ungrab_server(QX11Info::connection()); xcb_flush(QX11Info::connection()); } }; static bool grabKeyboard() { int rv = XGrabKeyboard(QX11Info::display(), QX11Info::appRootWindow(), True, GrabModeAsync, GrabModeAsync, CurrentTime); return (rv == GrabSuccess); } static bool grabMouse() { #define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask int rv = XGrabPointer(QX11Info::display(), QX11Info::appRootWindow(), True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); #undef GRABEVENTS return (rv == GrabSuccess); } bool establishGrab() { XSync(QX11Info::display(), False); XServerGraber xserverGraber; Q_UNUSED(xserverGraber); if(!grabKeyboard()) return false; if(!grabMouse()) { XUngrabKeyboard(QX11Info::display(), CurrentTime); XFlush(QX11Info::display()); return false; } return true; } bool closeGrab() { XSync(QX11Info::display(), False); XServerGraber xserverGraber; Q_UNUSED(xserverGraber); XUngrabKeyboard(QX11Info::display(), CurrentTime); XUngrabPointer(QX11Info::display(), CurrentTime); XFlush(QX11Info::display()); return true; } ukui-screensaver/src/pam.cpp0000644000175000017500000000721313517013306015043 0ustar fengfeng/* * 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 "pam.h" extern "C" { #include #include #include } #define TO_AUTHCHILD_RD_SHIFT 16 #define TO_PARENT_WR_SHIFT 0 #define PIPE_FD_MASK ((1 << TO_AUTHCHILD_RD_SHIFT) - 1) void authenticate(int toParent[2], int toAuthChild[2]) { pam_handle_t *pamh = NULL; char *username; int retval; int auth_status; struct pam_conv conv; unsigned long fd = 0; fd = fd | toAuthChild[0] << TO_AUTHCHILD_RD_SHIFT | toParent[1] << TO_PARENT_WR_SHIFT; /* authentication child process */ username=getenv("USER"); conv.conv = pam_conversation; conv.appdata_ptr = (void *)fd; retval = pam_start("ukui-screensaver-qt", username, &conv, &pamh); if(retval == PAM_SUCCESS) qDebug("PAM started successfully."); else qDebug("PAM started unsuccessfully."); qDebug("Invoke pam authentication."); auth_status = pam_authenticate(pamh, 0); qDebug("Complete pam authentication."); if(pam_end(pamh, retval) != PAM_SUCCESS){ qDebug("Failed to terminate PAM."); _exit(1); } qDebug("PAM ended successfully."); kill(getppid(), SIGUSR1); char buffer[16]; sprintf(buffer, "%d", auth_status); PIPE_OPS_SAFE( write(toParent[1], buffer, strlen(buffer) + 1) ); qDebug("Auth status has been written to pipe."); ::close(toParent[1]); ::close(toAuthChild[0]); qDebug("Authenticate child process now exits."); _exit(0); } #define MAX_PASSWORD_LENGTH 1024 int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { unsigned long fd; int read_from_parent; int write_to_parent; int count; char *password; struct pam_response *tmp_save; qDebug("Into pam_conversation"); fd = (unsigned long)appdata_ptr; read_from_parent = (fd >> TO_AUTHCHILD_RD_SHIFT) & PIPE_FD_MASK; write_to_parent = (fd >> TO_PARENT_WR_SHIFT) & PIPE_FD_MASK; count = num_msg; password = (char *)malloc(MAX_PASSWORD_LENGTH); *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response)); tmp_save = (struct pam_response *)(*resp); memset(*resp, 0, num_msg * sizeof(struct pam_response)); qDebug("Resolve PAM messages."); while(count-- >= 1){ struct pam_message_object pam_msg_obj; pam_msg_obj.msg_style = (*msg)->msg_style; strncpy(pam_msg_obj.msg, (*msg)->msg, MAX_MSG_LENGTH); PIPE_OPS_SAFE( write(write_to_parent, &pam_msg_obj, sizeof(pam_msg_obj)); ); qDebug("PAM message has been written to pipe."); kill(getppid(), SIGUSR1); if ((*msg)->msg_style == PAM_PROMPT_ECHO_OFF || (*msg)->msg_style == PAM_PROMPT_ECHO_ON){ int n; PIPE_OPS_SAFE( n = read(read_from_parent, password, MAX_PASSWORD_LENGTH); ); qDebug("%d bytes response received from pipe.", n); (*resp)->resp = password; (*resp)->resp_retcode = 0; } else { ; } if(count != 0){ msg++; (*resp)++; } } (*resp) = tmp_save; qDebug("Out pam_conversation."); return PAM_SUCCESS; } ukui-screensaver/src/authdialog.cpp0000644000175000017500000004413113645021611016407 0ustar fengfeng/* * 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 #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(); pam_tally_init(); connect(auth, &Auth::showMessage, this, &AuthDialog::onShowMessage); connect(auth, &Auth::showPrompt, this, &AuthDialog::onShowPrompt); connect(auth, &Auth::authenticateComplete, this, &AuthDialog::onAuthComplete); } bool biometricIsStopped = false; void AuthDialog::startAuth() { if(biometricIsStopped) { biometricIsStopped = false; m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); return; } auth->authenticate(user.name); showPasswordAuthWidget(); m_passwordEdit->clear(); m_passwordEdit->setEnabled(false); } void AuthDialog::stopAuth() { //这里只是为了在显示屏幕保护程序时停止生物识别认证 if(m_biometricAuthWidget && m_biometricAuthWidget->isVisible()) { biometricIsStopped = true; 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); QPixmap pixMap= facePixmap.scaled(128,128, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); m_faceLabel->setAlignment(Qt::AlignCenter); m_faceLabel->setPixmap(pixMap); /* 用户名 */ 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_passwdWidget->setInputMethodHints(Qt::ImhNone); 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); m_passwordEdit->setType(QLineEdit::Password); 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() - 600)/2, m_passwordEdit->geometry().bottom() + 25, 600, 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(text == "Password: ") text = tr("Password: "); m_passwordEdit->clear(); m_passwordEdit->setPrompt(text); } } void AuthDialog::onAuthComplete() { if(auth->isAuthenticated()) { if(pam_tally_is_enbled() && !pam_tally_is_canUnlock()) { pam_tally_add_failed(); int unlock_time = pam_tally_unlock_time(); int failed_count = pam_tally_failed_count(); int unlock_time_min = unlock_time /60; // sprintf(msg, "您已经输错%d次,将锁定账户%d分钟", failed_count, unlock_time_min); // onShowMessage(tr(msg), Auth::MessageTypeError); int deny = pam_tally_deny(); onShowMessage(tr("Account locked %1 minutes due to %2 fail attempts").arg(unlock_time_min).arg(deny), Auth::MessageTypeError); authMode = PASSWORD; startAuth(); } else { pam_tally_clear_failed(); Q_EMIT authenticateCompete(true); } } else { onShowMessage(tr("Password Incorrect, Please try again"), Auth::MessageTypeError); //认证失败,重新认证 if(pam_tally_is_enbled()) { pam_tally_add_failed(); int deny = pam_tally_deny(); int failed_count = pam_tally_failed_count(); int unlock_time = pam_tally_unlock_time(); int unlock_time_min = unlock_time / 60; if (failed_count >= 0 && failed_count < deny) { onShowMessage(tr("Authentication failure,there are still %1 remaining opportunities").arg(deny-failed_count), Auth::MessageTypeError); } else if (failed_count >= deny) { onShowMessage(tr("Account locked %1 minutes due to %2 fail attempts").arg(unlock_time_min).arg(deny), 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; } //初始化用户对应特征数量 m_featureCount = m_biometricProxy->GetFeatureCount(user.uid); qDebug()<<"m_featureCount = "<shortName : ""); //如果默认设备为空的话,第一次不启动生物识别认证 if(m_deviceName.isEmpty() && !m_deviceInfo) { qDebug() << "No default device"; skipBiometricAuth(); return; } 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(38); 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(std::max(width + 20, 190)); 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, 140)); 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, 140)); 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() - 100, 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) { qDebug() << "hasn't device, to choice device."; m_otherDeviceButton->click(); } else { qDebug() << "restart the PAM process"; 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() { qDebug() << "show password authentication widget"; 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() { qDebug() << "show biometric authentication widget"; 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() { qDebug() << "show biometric devices widget"; 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); } } ukui-screensaver/src/monitorwatcher.cpp0000644000175000017500000000715313517013306017336 0ustar fengfeng/* * 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 "monitorwatcher.h" #include #include #include #include #define DRM_DIR "/sys/class/drm/" MonitorWatcher::MonitorWatcher(QObject *parent) : QThread(parent), virtualSize(0, 0), monitorCount(0), firstDetect(true) { } MonitorWatcher::~MonitorWatcher() { requestInterruption(); terminate(); wait(); } void MonitorWatcher::run() { QDir drmDir(DRM_DIR); QStringList drms = drmDir.entryList(QDir::Dirs); for(auto iter = drms.begin(); iter != drms.end(); ) { if((*iter).indexOf("card") == 0 || iter->length() > 5) iter++; else iter = drms.erase(iter); } FILE * fp = popen("xrandr", "r"); Q_UNUSED(fp) /* 每隔3秒遍历一次显卡接口的连接状态 */ while(!isInterruptionRequested()) { int width = 0; int height = 0; QMap tmpStatus; for(const QString & drm : drms) { QFile drmStatusFile(DRM_DIR + drm + "/status"); if(drmStatusFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream in(&drmStatusFile); QString status = in.readLine(); tmpStatus[drm] = status; if(status == "connected") { QSize maxMode = getMonitorMaxSize(drm); width += maxMode.width(); height = height > maxMode.height() ? height : maxMode.height(); } } } if(drmStatus != tmpStatus) { drmStatus = tmpStatus; int count = 0; for(auto &pair : tmpStatus) if(pair == "connected") count++; qDebug() << "monitor count changed ---" << count; if(monitorCount != count) { monitorCount = count; if(!firstDetect) { firstDetect = false; Q_EMIT monitorCountChanged(count); } } FILE *fp = popen("xrandr", "r"); Q_UNUSED(fp) } virtualSize = QSize(width, height); sleep(3); } } /** * 获取显示器的最大分辨率 */ QSize MonitorWatcher::getMonitorMaxSize(const QString &drm) { int width = 0, height = 0; QFile drmModeFile(DRM_DIR + drm + "/modes"); if(drmModeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream in2(&drmModeFile); QString maxMode = in2.readLine(); int xpos = maxMode.indexOf('x', 0); width = maxMode.left(xpos).toInt(); int ipos = maxMode.indexOf('i', 0); if(ipos != -1) height = maxMode.mid(xpos+1, ipos-xpos-1).toInt(); else height = maxMode.mid(xpos+1).toInt(); } return QSize(width, height); } QSize MonitorWatcher::getVirtualSize() { return virtualSize; } int MonitorWatcher::getMonitorCount() { return monitorCount; } ukui-screensaver/src/interface.h0000644000175000017500000000250513524655606015707 0ustar fengfeng/* * 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 INTERFACE_H #define INTERFACE_H #include #include #include #include "types.h" #include "logind.h" class Interface : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", SS_DBUS_SERVICE) public: explicit Interface(QObject *parent = nullptr); LogindIntegration *m_logind; Q_SIGNALS: void SessionIdle(); public Q_SLOTS: /** * Lock the screen */ void Lock(); void onSessionIdleReceived(); void onNameLost(const QString&); private: bool checkExistChild(); private: QProcess process; }; #endif // INTERFACE_H ukui-screensaver/src/assets.qrc0000644000175000017500000000151213645021611015567 0ustar fengfeng assets/authdialog.qss assets/show-password.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 assets/default_face.png ukui-screensaver/src/grab-x11.h0000644000175000017500000000145313517013306015255 0ustar fengfeng/* * 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 GRABX11_H #define GRABX11_H bool establishGrab(); bool closeGrab(); #endif // GRABX11_H ukui-screensaver/src/assets/0000755000175000017500000000000013645021611015061 5ustar fengfengukui-screensaver/src/assets/waiting.png0000644000175000017500000000064113517013306017232 0ustar fengfengPNG  IHDR((mhIDATXѕ E)(,b v`t~H`P xwN~+B$H@d9rgcs !&8C =6X{)pdhJύ盀07_|1-s5.?598N{bq XV@`21J/@ Hjx~kBId͘mKsɻ3a*fi{|m}.M{{&8R3!)Un. 5-CmƎ(||zyu~]%xܘs9e]35x cͳOPVHn]IENDB`ukui-screensaver/src/assets/scrollbar_up_hover.png0000644000175000017500000000016313517013306021461 0ustar fengfengPNG  IHDR;֕J:IDAT(c-\Xsh543ft8 @׌bh # OW$WIENDB`ukui-screensaver/src/assets/keyboard.png0000644000175000017500000000213713637125674017411 0ustar fengfengPNG  IHDR''Q5tEXtSoftwareAdobe ImageReadyqe<qiTXtXML:com.adobe.xmp IDATx @m{}^c s P1TC pp݋:gn[EN<ݹ>l\s6a>VBZW5ۭѩ`t=NMCh֘O6a8)%t;9IENDB`ukui-screensaver/src/assets/authdialog.qss0000644000175000017500000000764713637125674017767 0ustar fengfengQPushButton { 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; } #userWidget{ /* background: rgba(255, 0, 255, 30%);*/ } /* 头像 */ #faceLabel { border:2px solid white; } /* 用户名 */ #login_nameLabel{ font-size: 28px; } /* 密码输入框 */ 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; } /* 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; } /* 切换用户 */ 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); } /* 虚拟键盘开启按钮、用户切换按钮 */ #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%); } /********************** 下拉选项 *************************/ QComboBox{ background: rgba(255, 255, 255, 20); border: 1px solid rgb(255, 255, 255, 30); font-size:18px; color: white; combobox-popup: 0; /* 配合setMaxVisibleItems设置下拉框显示的条数,超过的滚动显示 */ } QComboBox::down-arrow{ image:url(:/image/assets/combobox_down.png); } QComboBox::drop-down{ width: 30px; border: none; } QComboBox QListView{ border: 1px solid #5187bd; background: #4682B4; background: rgba(255, 255, 255, 30%); font-size: 18px; color: white; } QComboBox QListView::item:hover{ background: rgba(255, 255, 255, 20%); } QComboBox QListView::item:selected{ background-color: rgba(255, 255, 255, 30%); } /********************** 生物识别切换按钮 **************************/ #biometricButton, #passwordButton, #otherDeviceButton, #retryButton, #OKButton { background: rgba(255, 255, 255, 20%); font-size: 18px; border: 1px solid rgba(255, 255, 255, 30%); color: white; } #biometricButton::hover, #passwordButton::hover, #otherDeviceButton::hover, #retryButton::hover, #OKButton::hover { background: rgba(255, 255, 255, 35%); border: 1px solid rgba(255, 255, 255, 50%); } #biometricButton::pressed, #passwordButton::pressed, #otherDeviceButton::pressed, #retryButton::pressed, #OKButton::pressed { background: rgba(0, 0, 0, 15%); border: 1px solid rgba(255, 255, 255, 20%); } /********************** 生物识别设备选择界面 ************************/ #lblBioetricDevicesPrompt { font-size: 30px; } #lblDeviceType, #lblDeviceName, #cmbDeviceType, #cmbDeviceName{ font-size: 18px; } ukui-screensaver/src/assets/hide-password.png0000644000175000017500000000051713517013306020343 0ustar fengfengPNG  IHDRĴl;IDAT8ұJQ߷X|@|-TLl%4V2[[JHa'hHk%#R.; cƌMDD\۶^{"b>" 3kf ؃m[9|FUݼpKUi{NmAU=c{|Uqf.V 1ՎqQU3s 3X:.[U=XjU R|yf'`xUkQ݌G{+"6~+bϏ>G`GՎ?(-IENDB`ukui-screensaver/src/assets/scrollbar_down_clicked.png0000644000175000017500000000017713517013306022264 0ustar fengfengPNG  IHDR;֕JFIDAT(c 2p(05DRYfl`ՈK3604ӌFBj$F3^0D5 NIENDB`ukui-screensaver/src/assets/scrollbar_up_clicked.png0000644000175000017500000000016313517013306021734 0ustar fengfengPNG  IHDR;֕J:IDAT(c 2pr5DkiXl54]3F4>)4 ý΄IENDB`ukui-screensaver/src/assets/combobox_down.png0000644000175000017500000000026513517013306020431 0ustar fengfengPNG  IHDR |IDATuα AwۂbVdX-rl &# 7ǟr_0H `VbRCr#yIENDB`ukui-screensaver/src/assets/scrollbar_up.png0000644000175000017500000000016313517013306020256 0ustar fengfengPNG  IHDR;֕J:IDAT(c\XMr5D Ӡl54]3F4>)4rNGIENDB`ukui-screensaver/src/assets/scrollbar_down.png0000644000175000017500000000017613517013306020605 0ustar fengfengPNG  IHDR;֕JEIDAT(c\HM(05#)D׈,U36jĥiFրU#!x5/ AK.IENDB`ukui-screensaver/src/assets/unlock-button.png0000644000175000017500000000031713637125674020413 0ustar fengfengPNG  IHDRJLIDATH |$KN,,֏CAĄM YZXl&m.40IHr#iܻAAX +`%AgXjռ"b%Zdtx ?[}T۠ D,@ j\k:Et"IENDB`ukui-screensaver/src/assets/capslock.png0000644000175000017500000000044413517013306017370 0ustar fengfengPNG  IHDRĴl;IDAT8q@ D_%@ na[0-mB q a!|1_d|j%G%I ׼V  pyYdvAl(i qlkW#hKcl T^RTg%]Yh:%:$,6 q䂄[!ql_SbCUcUIPZ e>),LjxVт~ڮBI9`ouE'ݕ2IENDB`ukui-screensaver/src/assets/scrollbar_down_hover.png0000644000175000017500000000017613517013306022010 0ustar fengfengPNG  IHDR;֕JEIDAT(c-\HscrkDǪX5Ҍ 4#kfь Q ٪IENDB`ukui-screensaver/src/assets/show-password.png0000644000175000017500000000110613517013306020405 0ustar fengfengPNG  IHDRĴl; IDAT8ˋq#a( Q.)?@԰U{\"epye1&e!. Pr f=Nӹ|y~K]Zֈh4Zj Ef"bBD\?z]l~l׸V;xTIhF<Wф \F<8TG1X4h6Eb̓0'U?3_nC\́~ޣRx ډYE~38x<]q3Vefoŷ#b"F|O2/GمKW籪X?-⫑* "b/7Ef.̥ލ؇򽃲3QHJX/J.X.sqg3TujjeDOf +2 .a&VgAߐ4=؁~ ba8_Âk}#+Pf满j/ gIENDB`ukui-screensaver/src/assets/default_face.png0000644000175000017500000000205413645021611020172 0ustar fengfengPNG  IHDR>a pHYs  ~IDATxQAE\E#@ G`9!(Xd@H|Pbg* =`lr*|c9|5ZJr қA}*i"ixgLs 0#aäK)WG d'[mo\L4MJz4 XR0D+aK@5})"*irn{|El%n)=iqYQ~ץG8Wnz?SnTYZ}cdqRų@}D)z/QGP=zuPl3IӜe%J?n)(RfR0sCpg3ŞÜY ksS)q?Jߣ d+c1/9E8Gf!^yv}0*$U>^rU_*$U*nyIENDB`ukui-screensaver/src/assets/avatar.png0000644000175000017500000014030413637125674017066 0ustar fengfengPNG  IHDRw= pHYs  iTXtXML:com.adobe.xmp Adobe Photoshop CC 2017 (Windows) 2018-05-28T17:19:26+08:00 2018-06-27T14:24:54+08:00 2018-06-27T14:24:54+08:00 image/png 3 食指 大拇指 食指 中指 小指 食指 大拇指 食指 大拇指 食指 中指 小指 食指 大拇指 kylin123123 ubuntukylin guo1234 米小粒666 kylin123123 ubuntukylin guo1234 米小粒666 1 2 3 4 1 2 3 4 序列号 用户名 序列号 用户名 指纹名称 指纹列表 指纹列表 食指 大拇指 食指 中指 中指 小指 大拇指 食指 大拇指 食指 中指 中指 小指 大拇指 kylin123123 ubuntukylin guo1234 米小粒666 终端产品中心 UIKylin666 131*** kylin123123 ubuntukylin guo1234 米小粒666 终端产品中心 UIKylin666 131******59 1 2 3 4 5 6 7 1 2 3 4 5 6 7 序列号 用户名 序列号 用户名 指纹名称 指纹列表 指纹列表 左-食指 左-大拇指 左-中指 左-小指 左-无名指 右-食指 右-大拇指 左-食指 左-大拇指 左-中指 左-小指 左-无名指 右-食指 右-大拇指 1 2 3 4 5 6 7 1 2 3 4 5 6 7 序列号 指纹名称 序列号 指纹名称 指纹列表 指纹列表 设备简称:uru4000 设备全称:Digital Persona U.are.U 4000 设备简称:uru4000 设备全称:Digital Persona U.are.U 4000/4000B/4500 验证类型:软件验证 存储类型:系统存储 总线类型:USB 识别类型:软件识别 设备开启: 开 设为默认设备: 搜索 搜索 删除所有 删除所有 删除 删除 验证 验证 录入 录入 录入 录入 aes4000 elan etes603 uru4000 upeke2 upeksonly upektc_img upekts aes4000 elan etes603 uru4000 upeke2 upeksonly upektc_img upekts vcom5s vfs0050 vfs101 设备名称 状态 设备名称 状态 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 up 拷贝 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 upektc_img 设备名称 状态 设备名称 状态 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 up aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 upektc_img 设备名称 状态 设备名称 状态 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 up 拷贝 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 upektc_img 设备名称 状态 设备名称 状态 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 up aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 upektc_img 设备名称 状态 设备名称 状态 默认设备 默认设备 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 up 拷贝 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 upektc_img 设备名称 状态 设备名称 状态 aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 up aes4000 elan etes603 fdu2000 upeke2 upeksonly vfs101 uru4000 upektc_img 全部设备 指纹 指静脉 虹膜 人脸 脸静脉 声纹 全部设备 指纹 指静脉 虹膜 人脸 脸静脉 声纹 全部设备 指纹 指静脉 虹膜 人脸 脸静脉 声纹 全部设备 指纹 指静脉 虹膜 人脸 脸静脉 声纹 生物识别可进行系统认证,包括登录、锁屏、sudo/su授权和 Polkit 授权。 生物识别可进行系统认证,包括登录、锁屏、sudo/su授权和 Polkit 授权。 生物识别状态: 开 生物识别状态: 开 当前没有可用生物识别设备,或者该用户没有录入任何特征。 当前没有可用生物识别设备,或者该用户没有录入任何特征。 生物识别状态: 关 生物识别状态: 关 人脸管理 人脸管理 虹膜管理 虹膜管理 指静脉管理 指静脉管理 指纹管理 指纹管理 主界面 主界面 取消 取消 请按下手指,验证指纹信息...... 请按下手指,验证指纹信息...... 验证指纹 验证指纹 取消 取消 请按下手指,录入指纹信息...... 请按下手指,录入指纹信息...... 录入指纹 录入指纹 左-食指1 左-食指2 左-食指3 左-食指4 左-食指5 左-食指6 左-食指7 左-食指1 左-食指2 左-食指3 左-食指4 左-食指5 左-食指6 左-食指7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 序列号 指纹名称 序列号 指纹名称 kylin123123 ubuntukylin guo1234 米小粒666 终端产品中心 UIKylin666 131*** kylin123123 ubuntukylin guo1234 米小粒666 终端产品中心 UIKylin666 131******59 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 左-食指 1 2 3 4 5 6 7 1 2 3 4 5 6 7 序列号 用户名 指纹名称 序列号 用户名 指纹名称 搜索结果 搜索结果 搜索指纹 搜索指纹 取消 取消 请按下手指,搜索指纹信息...... 请按下手指,搜索指纹信息...... 指纹搜索 指纹搜索 授权 授权 详情 详情 polikit subject-pid: polkit caller-pid: 动作: 厂商: polikit subject-pid: polkit caller-pid: 动作: 厂商: 9454 9455 com.ubuntu.pkexec.gparted 9454 9455 com.ubuntu.pkexec.gparted 使用密码授权 使用密码授权 请按下手指,进行授权..... 请按下手指,进行授权..... 一个程序正试图执行一个需要授权的动作, 要求授权以执行该动作。 一个程序正试图执行一个需要授权的动作, 要求授权以执行该动作。 运行GParted 分区编辑器需要授权。 运行GParted 分区编辑器需要授权。 授权 授权 授权 授权 详情 详情 使用密码授权 使用密码授权 请按下手指,进行授权..... 请按下手指,进行授权..... 一个程序正试图执行一个需要授权的动作, 要求授权以执行该动作。 一个程序正试图执行一个需要授权的动作, 要求授权以执行该动作。 运行GParted 分区编辑器需要授权。 运行GParted 分区编辑器需要授权。 授权 授权 管理员 管理员 kylin123123 kylin123123 生物特征管理 生物特征管理 2B419E7FD5D6B35BEB7E011A30AFAA6E 4B171412BBA33EC084505A85E9A558CD 4D5D3D5DFA69F1EB977AE0D3360AB7F3 5BB0B97B1D9547A4F72875AF61B6E223 63BEB43AE5B35A4FE12AE361969B3558 807B0024A9C116E5938D55EB45B69F4B 8F8A20612E10AA1310410BDCB3C3F1CD 96BFE49D256286CA67242602B276D6FF 9702EF5D951C33BE76B26F3CCDC6BEE4 A20E395EF191F6DC5B95AC02E80C9DF6 B09AB0E06009DBED6650A5626F7B257D D04B055410DFA6624BCDFC2A93EF1997 D7E1CD25D0FC046474AB008AEF35D0C7 D9EBD6D1C46ED6598682EAE833BCCF48 DA942C05F3DF035C9FB2F0B9631481BB F964BB0667A87E61E3B8651E2ABE81CB adobe:docid:photoshop:0f640d1c-feb9-11e2-b7b7-d221b7d949f3 adobe:docid:photoshop:2605cbbd-55ad-11e7-a1f8-f7b49b79dbe6 adobe:docid:photoshop:3ebba7a5-1de9-11e8-b017-e03dd2e431da adobe:docid:photoshop:441a4ea5-5167-11e7-87e1-94ede75d9a45 adobe:docid:photoshop:5cdff2ef-5ae3-11e7-b1cf-d6f1f8f4ceb3 adobe:docid:photoshop:66714eeb-c8a5-11dd-8f66-c83426845e8a adobe:docid:photoshop:736ca551-5aec-11e7-b1cf-d6f1f8f4ceb3 adobe:docid:photoshop:772c815a-4f1d-11e7-a29c-ee28c792f004 adobe:docid:photoshop:846d4175-5167-11e7-87e1-94ede75d9a45 adobe:docid:photoshop:93143041-5ade-11e7-b1cf-d6f1f8f4ceb3 adobe:docid:photoshop:947b4a64-5ae3-11e7-b1cf-d6f1f8f4ceb3 adobe:docid:photoshop:ac36efe8-2699-11e8-b8de-bbfa7e130112 adobe:docid:photoshop:b5724603-6956-11e8-b779-936e4966a2be adobe:docid:photoshop:f9834ab5-219e-11e8-a1f6-f3d8ec6703e5 adobe:docid:photoshop:ff8b6d6f-517e-11e7-87e1-94ede75d9a45 uuid:0E01E77E6B9CDF11AB9CBA34577D0F4A uuid:147B99929250DC11A396C8F5A189D4EF uuid:232F7EE5FB51E111A96F9CABB5125E84 uuid:2509A5BA95F2E311BF87EE4E01F5F502 uuid:52EFCD134194DD11A771EFA2A3BF877C uuid:5C38636EF751E111A96F9CABB5125E84 uuid:77AF53C62E44E2118D079A0E2E2B6900 uuid:7E9650911912DD118087EC141FF20056 uuid:A91EF0BB646EDD11860499D57E378043 uuid:FCE867DF3272E211A33A8755952F88B0 xmp.did:00510f87-6516-394e-bc8d-139224b085f9 xmp.did:022CD70176C711E4B70BC77971DC391F xmp.did:0ab84a72-dc60-bd49-bc27-dba47e158e9a xmp.did:14018063-7600-e044-9d00-2ef52490f5c2 xmp.did:1802f50c-111d-5149-bf6a-aed7435a8dab xmp.did:196575bb-9e8f-ac46-a320-6e0e284dd93e xmp.did:2036247A5E5711E8B8AF9B3785EA8D10 xmp.did:23ebe318-d3bf-d548-ad87-da423b50f04f xmp.did:28353ed1-53c0-4748-a533-d24cdd89de49 xmp.did:28419DD1540811E491839F74ABC931DB xmp.did:2eb6f697-ce34-674b-99a6-da8e9c6d5cc1 xmp.did:31B8A8EAABDD11E2BB579B541E6151AC xmp.did:32b8cc4d-b12b-d745-9d46-d68fd2dd106b xmp.did:33eaa353-cf74-6f45-9cc4-eeac871f3c63 xmp.did:37a2bcf6-f410-b142-8d18-172520d745d8 xmp.did:3A7285004AC4E111A211DE80EFF84864 xmp.did:3D309369DBE011E78BC8BED2996E6A41 xmp.did:42CE125ACC21E4118163B9B34D573CFE xmp.did:45128139-f57f-c24c-b707-789187cc3b7d xmp.did:4EF2BE1AF25E11E5802D974948D7D415 xmp.did:4cead092-d3f7-7b41-aa39-18ab8628cf29 xmp.did:507b73ba-4727-1240-8c2d-64add0b70420 xmp.did:551a33d5-db18-6845-a472-9ed0ff4bc53d xmp.did:5824750BA13911DF8D3A987F4C75D795 xmp.did:592056d9-8675-0942-a1ba-5b0818775d17 xmp.did:5d7139e8-13a5-ff41-a601-4f0fd4398bd5 xmp.did:6170861c-bacc-ad47-8ddd-c6ad7cf65c56 xmp.did:647C4C531C7411E4B172B49588B90DEC xmp.did:6603c538-c0c0-bf4e-9df7-4b8d60a43c1f xmp.did:6E7DC14CC3E311E18B83ED8C3DD11555 xmp.did:73C644426EC111E4A607BDFE98441376 xmp.did:793C84FA7D90DF11BB44E7D84CC8D86E xmp.did:79aeda5f-bf0f-44dd-8935-d5e3555ce49c xmp.did:7b6f3510-5473-b34f-ad64-ea33965a8c54 xmp.did:923862F94F80DF11ACFABA5FFC257096 xmp.did:96e1c83d-0c23-6848-8c0e-aee0a79ceb8a xmp.did:974FA0314BECDE11A8C8B6F4E6013B0B xmp.did:9C7F9CAB1B6411E792A0C63D7D80D255 xmp.did:9b12360a-e24d-fc4e-ada3-d3d74481729b xmp.did:9d762551-cecd-6f4f-9851-e2f14c178a6d xmp.did:A3A5157983E0DE11BEFAD89BC807DCEA xmp.did:B241FDB99A2011E497BD939F1CDDCD4D xmp.did:D027A0A9358ADF11B6B4DDCF3B1E6118 xmp.did:E17E8C8EEB0ADF11977BC713C73EE05B xmp.did:E3ECF986B80111DF8F96A1EF39E2E0BF xmp.did:ECC883491DD811E49D20C134A1A5771B xmp.did:F36B06E81C4D11E488C5BA56A693B514 xmp.did:F3AB9B686ECF11E48759D02C6767DE9F xmp.did:F49259B87E7811E3A04C8D5211748078 xmp.did:F6782DAF2C12E011BCFE9F0666BC6A9E xmp.did:FAC8674AABF411E284C691E3D9B8F21F xmp.did:FE9A27789A1F11E48AE5DADCCC86B35E xmp.did:a197722e-9c11-2345-b198-75ab4459928b xmp.did:a4afbed9-175e-ab41-83d5-f7770112dd44 xmp.did:aa5de98f-81aa-1249-a2b4-19b4e8095725 xmp.did:ab27d981-9bee-9e40-9f31-359b018214da xmp.did:ab5cbc38-aaea-ec49-9298-3b7fc52d4432 xmp.did:b072d007-708f-384b-b900-a449469ff4aa xmp.did:b09960b0-1dd5-534d-86a0-4bfd8b293eb9 xmp.did:b4ab0c11-cf8e-434a-a5e0-f23e6562ba09 xmp.did:b82b042f-712d-574d-b317-44e3bde6a21c xmp.did:bb791d93-505a-5643-afd3-b72613cf525c xmp.did:c36ec2d2-2523-6a45-882c-74f4f84a9d42 xmp.did:de987db1-85aa-7444-ac11-f92a14112225 xmp.did:ea611bb8-3a04-424f-b2fd-5ded41a8f638 xmp.did:eda16775-a861-3b41-9382-4601fbd33f4d xmp.did:efd76445-a176-9048-854b-ca73fc06519f xmp.did:efe3257b-13db-1f48-a7b6-8d341bf39697 xmp.did:f66e690c-e66e-1544-a714-3ecbac309c5a xmp.did:fe827bdd-3389-8e4b-b05c-177801cf39d8 xmp.id:af87b9bc-f28b-7944-b538-18da6b4211ea xmp.iid:94330442-dc33-004e-9893-0173ed0c56a2 adobe:docid:photoshop:c779d353-79d2-11e8-b2bc-f4ac6e3038cc xmp.did:4090daef-cef2-1a42-a98c-f6749e7b4646 created xmp.iid:4090daef-cef2-1a42-a98c-f6749e7b4646 2018-05-28T17:19:26+08:00 Adobe Photoshop CC 2017 (Windows) converted from image/png to application/vnd.adobe.photoshop saved xmp.iid:e996088c-e3cb-7e41-b6f8-2a7b81632f0a 2018-06-06T14:56:16+08:00 Adobe Photoshop CC 2017 (Windows) / saved xmp.iid:c6c4f86a-9fbf-0741-a39d-4f111b4f33ba 2018-06-27T14:24:54+08:00 Adobe Photoshop CC 2017 (Windows) / converted from application/vnd.adobe.photoshop to image/png derived converted from application/vnd.adobe.photoshop to image/png saved xmp.iid:94330442-dc33-004e-9893-0173ed0c56a2 2018-06-27T14:24:54+08:00 Adobe Photoshop CC 2017 (Windows) / xmp.iid:c6c4f86a-9fbf-0741-a39d-4f111b4f33ba adobe:docid:photoshop:b5724603-6956-11e8-b779-936e4966a2be xmp.did:4090daef-cef2-1a42-a98c-f6749e7b4646 1 720000/10000 720000/10000 2 65535 24 24 a^ cHRMz%u0`:o_FuIDATxڤMOQ;mZjm!P!`Ycƥֵqa b{=22X (-e\i̴9{>AT0B@ l_@@+`p,W*U` pcXOG ϚM78o/[:7cx DY2Dy64! [@[p MG+إYA``Kx&AEuqA#Aqͮ9DmRֺnJjP1+ۥtMvَ˘ܰɰSlB0 v$P#AckF<x4ğSaW~"Cj>OOu=|!aQO_~ 5ْX\Ā9 .?4zB7@V4`+iR Q͈d&Wl $320ӼM=0KkY8ڼ\WX7x <J^} VX?Jc"?ihN "~뿊"~jNV- <#tIv/+nwGTgDȶqCIENDB`ukui-screensaver/src/sessionwatcher.h0000644000175000017500000000220413517013306016767 0ustar fengfeng/* * 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 SESSIONWATCHER_H #define SESSIONWATCHER_H #include #include class SessionWatcher : public QObject { Q_OBJECT public: explicit SessionWatcher(QObject *parent = nullptr); Q_SIGNALS: void sessionIdle(); private Q_SLOTS: void onStatusChanged(unsigned int status); void onSessionRemoved(const QDBusObjectPath &objectPath); private: QString sessionPath; }; #endif // SESSIONWATCHER_H ukui-screensaver/src/sessionwatcher.cpp0000644000175000017500000000363613517013306017334 0ustar fengfeng/* * 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 "sessionwatcher.h" #include #include #include "types.h" SessionWatcher::SessionWatcher(QObject *parent) : QObject(parent) { sessionPath = qgetenv("XDG_SESSION_PATH"); QDBusInterface *interface = new QDBusInterface( 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( DM_DBUS_SERVICE, DM_DBUS_PATH, DM_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(displayManagerInterface, SIGNAL(SessionRemoved(QDBusObjectPath)), this, SLOT(onSessionRemoved(QDBusObjectPath))); } void SessionWatcher::onStatusChanged(unsigned int status) { qDebug() << "Session Status: " << status; if(status == SESSION_IDLE) { Q_EMIT sessionIdle(); } } void SessionWatcher::onSessionRemoved(const QDBusObjectPath &objectPath) { //如果session注销了,则结束进程 if(objectPath.path() == sessionPath) exit(0); } ukui-screensaver/src/configuration.cpp0000644000175000017500000001551613637125674017161 0ustar fengfeng/* * 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 "configuration.h" #include #include #include #include #include #include #include #include #include #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define KEY_MODE "mode" #define KEY_THEMES "themes" #define KEY_IDLE_ACTIVATION_ENABLED "idle-activation-enabled" #define KEY_LOCK_ENABLED "lock-enabled" #define KEY_IMAGE_TRANSITION_EFFECT "image-transition-effect" #define KEY_IMAGE_SWITCH_INTERVAL "image-switch-interval" #define KEY_BACKGROUND "background" #define XSCREENSAVER_DIRNAME "/usr/lib/xscreensaver" Configuration::Configuration(QObject *parent) : QObject(parent) { /* QGSettings for screensaver */ gsettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER, "", this); connect(gsettings, &QGSettings::changed, this, &Configuration::onConfigurationChanged); /* Initiailization */ 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; int FileisExist = 0; if(!background.isEmpty()) { QFileInfo file(background); if(file.exists()==false) FileisExist = 0; else FileisExist = 1; } //如果org.ukui.screensaver background中的背景图片为空,则设为桌面背景 if(background.isEmpty()||0==FileisExist) { 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; if(themes.count() == 1 && themes[0] == "kyccss-personal-slideshow") mode ="image"; } /* Update member value when GSettings changed */ void Configuration::onConfigurationChanged(QString key) { qDebug() << "GSettings value changed, key = " << key; if (key == KEY_MODE) mode = gsettings->get(KEY_MODE).toString(); else if (key == KEY_THEMES) themes = gsettings->get(KEY_THEMES).toStringList(); else if (key == KEY_IDLE_ACTIVATION_ENABLED) idleActivationEnabled = gsettings->get(KEY_IDLE_ACTIVATION_ENABLED).toBool(); else if (key == KEY_LOCK_ENABLED) lockEnabled = gsettings->get(KEY_LOCK_ENABLED).toBool(); else if(key == KEY_IMAGE_TRANSITION_EFFECT) imageTSEffect = gsettings->get(KEY_IMAGE_TRANSITION_EFFECT).toInt(); else if(key == KEY_IMAGE_SWITCH_INTERVAL) imageSwitchInterval = gsettings->get(KEY_IMAGE_SWITCH_INTERVAL).toInt(); } /* * Getter */ /* Get the executable path of xscreensaver */ ScreenSaver *Configuration::getScreensaver() { QStringList modeStr{"blank-only", "random", "single", "image"}; ScreenSaver *saver = new ScreenSaver; int index = modeStr.indexOf(mode); saver->mode = SaverMode(index); saver->interval = imageSwitchInterval; saver->effect = TransitionEffect(imageTSEffect); switch(index){ case SAVER_BLANK_ONLY: break; case SAVER_RANDOM: { qsrand((unsigned)time(0)); int index = qrand() % themes.count(); while(QString::compare(themes[index], "kyccss-personal-slideshow")==0) { index = qrand() % themes.count(); } saver->path = getXScreensaverPath(themes[index]); break; } case SAVER_SINGLE: saver->path = getXScreensaverPath(themes[0]); break; case SAVER_IMAGE: QString lang = qgetenv("LANG"); if (!lang.isEmpty()){ qDebug()<<"lang = "<path = QDir::homePath() + "/图片"; break; } } saver->path = QDir::homePath() + "/" + QStandardPaths::displayName(QStandardPaths::PicturesLocation); break; } return saver; } QString Configuration::getXScreensaverPath(const QString &theme) { /* screensavers-ukui-binaryring => binaryring */ QStringList strs = theme.split("-"); QString str = strs.at(strs.size() - 1); return QString("%1/%2").arg(XSCREENSAVER_DIRNAME, str); } bool Configuration::ispicture(QString filepath) { QMimeDatabase db; QMimeType mime = db.mimeTypeForFile(filepath); qDebug() << "mime: " << filepath << mime.name(); return mime.name().startsWith("image/"); } QString getSystemVersion() { QSettings settings("/etc/lsb-release", QSettings::IniFormat); QString release = settings.value("DISTRIB_RELEASE").toString(); QString description = settings.value("DISTRIB_DESCRIPTION").toString(); if(description.right(3) == "LTS") release = release + " LTS"; return release; } QString Configuration::getSystemDistrib() { QSettings settings("/etc/lsb-release", QSettings::IniFormat); QString distribId = settings.value("DISTRIB_ID").toString(); return distribId; } QString Configuration::getBackground() { if(ispicture(background)) return background; else if(getSystemDistrib().contains("Ubuntu",Qt::CaseInsensitive)) return "/usr/share/backgrounds/warty-final-ubuntukylin.jpg"; else return "/usr/share/backgrounds/kylin/kylin-background.png"; } bool Configuration::xscreensaverActivatedWhenIdle() { return idleActivationEnabled; } bool Configuration::lockWhenXScreensaverActivated() { return lockEnabled; } ukui-screensaver/src/ukui-screensaver-dialog.cpp0000644000175000017500000001635713637125674021046 0ustar fengfeng/* * 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 #include #include "fullbackgroundwidget.h" #define CACHE_DIR "/.cache/ukui-screensaver/" static void messageOutput(QtMsgType type, const QMessageLogContext &context,const QString &msg); void checkIslivecd() { char cmd[128] = {0}; char str[1024]; FILE *fp; int pid; int n = sprintf(cmd, "cat /proc/cmdline"); Q_UNUSED(n) fp = popen(cmd, "r"); while(fgets(str, sizeof(str)-1, fp)) { if(strstr(str,"boot=casper")) { printf("is livecd\n"); exit(0); } } pclose(fp); QString filepath = QDir::homePath() + "/Desktop" + "/ubiquity.desktop"; QString folderpath = "/cdrom"; QFileInfo file(filepath); QFileInfo folder(folderpath); if(!file.exists()) return; if(!folder.exists()) return; if(getuid() != 999) return; exit(0); } void checkIsRunning() { int fd, len; char buf[32]; struct flock lock; const QString PID_DIR = QString("/var/run/user/%1").arg(QString::number(getuid())); const QString PID_FILE = PID_DIR + "/ukui-screensaver.pid"; qDebug() << PID_DIR; QDir dir(PID_DIR); if(!dir.exists()) { if(!dir.mkdir(PID_DIR.toLocal8Bit().data())) { perror("create pid directory failed"); exit(1); } } if( (fd = open(PID_FILE.toLocal8Bit().data(), O_RDWR | O_CREAT, 0666)) == -1){ perror("open pid file failed"); exit(1); } memset(&lock, 0, sizeof(struct flock)); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; if(fcntl(fd, F_SETLK, &lock) < 0) { // perror("fcntl F_SETLK failed"); printf("There is already an instance running\n"); exit(1); } len = snprintf(buf, sizeof(buf), "%d", getpid()); ftruncate(fd, 0); if(write(fd, buf, len) != len) { perror("write pid to lock file failed"); exit(1); } } #define WORKING_DIRECTORY "/usr/share/ukui-screensaver" int main(int argc, char *argv[]) { checkIsRunning(); checkIslivecd(); 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; } else { if(parser.isSet(lockOption)) { if("fcitx" == qgetenv("QT_IM_MODULE")) { qunsetenv("QT_IM_MODULE"); // QProcess * process = new QProcess;//不阻塞 // process->start("/usr/bin/ukui-screensaver-dialog --lock"); // exit(EXIT_SUCCESS); } } if(parser.isSet(sessionIdleOption)) { if("fcitx" == qgetenv("QT_IM_MODULE")) { qunsetenv("QT_IM_MODULE"); // QProcess * process = new QProcess;//不阻塞 // process->start("/usr/bin/ukui-screensaver-dialog --session-idle"); // exit(EXIT_SUCCESS); } } } 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)) { if(window->onSessionStatusChanged(SESSION_IDLE) == -1) return 0; } QString username = getenv("USER"); int uid = getuid(); QDBusInterface *interface = new QDBusInterface("cn.kylinos.Kydroid2", "/cn/kylinos/Kydroid2", "cn.kylinos.Kydroid2", QDBusConnection::systemBus(), window); QDBusMessage msg = interface->call(QStringLiteral("SetPropOfContainer"),username, uid, "is_kydroid_on_focus", "0"); window->show(); 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); } ukui-screensaver/src/unixsignallistener.h0000644000175000017500000000271513517013306017664 0ustar fengfeng/* * 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 UNIXSIGNALLISTENER_H #define UNIXSIGNALLISTENER_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include #include class UnixSignalListener : public QObject { Q_OBJECT public: explicit UnixSignalListener(QObject *parent = nullptr); public: /* Unix signal handlers. */ static void usr1SignalAction(int sig, siginfo_t *siginfo, void *ucontext); static void chldSignalAction(int sig, siginfo_t *siginfo, void *ucontext); Q_SIGNALS: /* pid is the sending process id */ void transition(int pid); /* Finite State Machine Driven Signal */ public Q_SLOTS: /* Qt signal handlers. */ void handleSigUsr1(); private: static int sigusr1Fd[2]; QSocketNotifier *snUsr1; }; #endif // UNIXSIGNALLISTENER_H ukui-screensaver/src/logind.h0000644000175000017500000000210513630646305015211 0ustar fengfeng/* * Copyright (C) 2020 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 LOGIND_H #define LOGIND_H #include #include class QDBusServiceWatcher; class LogindIntegration : public QObject { Q_OBJECT public: explicit LogindIntegration(QObject *parent = nullptr); ~LogindIntegration() override; Q_SIGNALS: void requestLock(); void requestUnlock(); void connectedChanged(); private: }; #endif ukui-screensaver/src/configuration.h0000644000175000017500000000312413630646305016606 0ustar fengfeng/* * 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 CONFIGURATION_H #define CONFIGURATION_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif //#include "gsettings.h" #include #include "screensaver.h" class QGSettings; class Configuration : public QObject { Q_OBJECT public: explicit Configuration(QObject *parent = nullptr); public: ScreenSaver *getScreensaver(); QString getBackground(); bool xscreensaverActivatedWhenIdle(); bool lockWhenXScreensaverActivated(); public Q_SLOTS: void onConfigurationChanged(QString key); private: QString getXScreensaverPath(const QString &theme); private: QGSettings *gsettings; QGSettings *bgGsettings; QString mode; QList themes; QString background; bool idleActivationEnabled; bool lockEnabled; int imageTSEffect; int imageSwitchInterval; QString getSystemDistrib(); bool ispicture(QString filepath); }; #endif // CONFIGURATION_H ukui-screensaver/src/lockwidget.cpp0000644000175000017500000001617613637125674016451 0ustar fengfeng/* * 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 #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); this->installEventFilter(this); initUI(); } LockWidget::~LockWidget() { delete ui; } void LockWidget::closeEvent(QCloseEvent *event) { qDebug() << "LockWidget::closeEvent"; authDialog->close(); return QWidget::closeEvent(event); } bool LockWidget::eventFilter(QObject *obj, QEvent *event) { if(obj == this){ if(event->type() == 2){ if(usersMenu->isVisible()) usersMenu->hide(); return false; } } return false; } 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 date = QDate::currentDate().toString("yyyy/MM/dd dddd"); ui->lblDate->setText(date); }); 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()); }); */ connect(ui->btnKeyboard, &QPushButton::clicked, this, &LockWidget::showVirtualKeyboard); //用户切换 if(displayManager->canSwitch()) { initUserMenu(); } } void LockWidget::showVirtualKeyboard() { vKeyboard->setVisible(vKeyboard->isHidden()); setVirkeyboardPos(); } void LockWidget::setVirkeyboardPos() { if(vKeyboard) { vKeyboard->setGeometry(0, height() - height()/3, width(), height()/3); } } 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); //如果没有设置x11属性,则由于弹出菜单受窗口管理器管理,而主窗口不受,在点击菜单又点回主窗口会闪屏。 usersMenu->setWindowFlags(Qt::X11BypassWindowManagerHint); usersMenu->hide(); usersMenu->move(width() - 150, 60); // ui->btnSwitchUser->setMenu(usersMenu); connect(usersMenu, &QMenu::triggered, this, &LockWidget::onUserMenuTrigged); connect(ui->btnSwitchUser, &QPushButton::clicked, this, [&]{ if(usersMenu->isVisible()) usersMenu->hide(); else usersMenu->show(); }); } 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); setVirkeyboardPos(); usersMenu->move(width() - 150, 60); XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); } 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(); } } ukui-screensaver/src/iconedit.cpp0000644000175000017500000001347513637125674016112 0ustar fengfeng/* 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 #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_edit->installEventFilter(this); 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); if(type == 0) m_modeButton->setChecked(true); else m_modeButton->setChecked(false); } void IconEdit::resizeEvent(QResizeEvent *) { // 设置输入框中文件输入区,不让输入的文字在被隐藏在按钮下 m_edit->setTextMargins(1, 1, m_iconButton->width() + m_modeButton->width(), 1); m_edit->setFixedSize(size()); } bool IconEdit::eventFilter(QObject *obj, QEvent *event) { if(obj == m_edit){ if(event->type() == 6){ QKeyEvent *keyEvent = static_cast(event); if(keyEvent->key()==80 &&keyEvent->modifiers() ==(Qt::MetaModifier)){ event->ignore(); return true; } } if(event->type() == 23) { XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); } } return false; } void IconEdit::clicked_cb() { 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->setAttribute(Qt::WA_InputMethodEnabled, false); m_edit->setEnabled(enabled); m_iconButton->setEnabled(enabled); } ukui-screensaver/src/auth.h0000644000175000017500000000307213517013306014673 0ustar fengfeng/* * 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 AUTH_H #define AUTH_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include class Auth : public QObject { Q_OBJECT Q_ENUMS(PromptType MessageType) public: explicit Auth(QObject *parent = nullptr) : QObject(parent) { } enum PromptType { PromptTypeQuestion, PromptTypeSecret }; enum MessageType { MessageTypeInfo, MessageTypeError }; Q_SIGNALS: void showPrompt(const QString &prompt, Auth::PromptType type); void showMessage(const QString &message, Auth::MessageType type); void authenticateComplete(); 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 // AUTH_H ukui-screensaver/src/users.cpp0000644000175000017500000001156513645021611015434 0ustar fengfeng/* * 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" #include #include 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 = ":/image/assets/default_face.png"; loadUsers(); } QList Users::getUsers() { return users; } UserItem Users::getUserByName(const QString &name) { for(int i = 0 ; i < users.size() ; i++) { if(users.at(i).name == name) { return users.at(i); } } UserItem user; if(name == "root") { user.icon = "/root/.face"; } else { user.icon = qgetenv("HOME")+"/.face"; } user.name = name; user.path = ""; user.realName = name; user.uid = getuid(); return user; } 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 >=0 &&index= 0 && index 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 ukui-screensaver/src/screensaver.h0000644000175000017500000000363513637125674016276 0ustar fengfeng/* * 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 SCREENSAVER_H #define SCREENSAVER_H #include #include #include enum SaverMode { SAVER_BLANK_ONLY = 0, SAVER_RANDOM, SAVER_SINGLE, SAVER_IMAGE }; enum TransitionEffect { TRANSITION_NONE, TRANSITION_FADE_IN_OUT }; class ScreenSaver : public QObject { Q_OBJECT public: SaverMode mode; //path is a directory or a file path if mode is SAVER_IMAGE QString path; QString lastPath; //for images saver TransitionEffect effect; int interval; private: int imageIndex; QTimer *timer; QStringList imagePaths; Q_SIGNALS: void imagePathChanged(const QString &path); public: explicit ScreenSaver( QObject *parent=nullptr); explicit ScreenSaver(const ScreenSaver &screensaver); ScreenSaver(ScreenSaver &&screensaver) noexcept; bool exists(); void startSwitchImages(); void stopSwitchImages(); bool timerStatus(); friend QDebug &operator<<(QDebug stream, const ScreenSaver &screensaver); }; Q_DECLARE_METATYPE(ScreenSaver) QDebug &operator<<(QDebug stream, const ScreenSaver &screensaver); #endif // SCREENSAVER_H ukui-screensaver/src/pam.h0000644000175000017500000000242713517013306014512 0ustar fengfeng/* * 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 PAM_H #define PAM_H #include #include #include void authenticate(int toParent[2], int toAuthChild[2]); int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); #define MAX_MSG_LENGTH 1024 struct pam_message_object { int msg_style; char msg[MAX_MSG_LENGTH + 1]; } __attribute__((packed)); #define PIPE_OPS_SAFE(statement) do { \ int return_value = statement; \ if (return_value == -1)\ qWarning("PIPE write/read error: %s", strerror(errno)); \ } while (0) #endif // PAM_H ukui-screensaver/src/auth-pam.cpp0000644000175000017500000002175213645021611016006 0ustar fengfeng/* * 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) { close(toParent[0]); close(toChild[1]); _authenticate(userName.toLocal8Bit().data()); } else { close(toParent[1]); close(toChild[0]); _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); close(toParent[0]); close(toChild[1]); if(notifier){ notifier->deleteLater(); notifier = nullptr; } 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; if(notifier){ notifier->deleteLater(); notifier = nullptr; } 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); } } ukui-screensaver/src/displaymanager.h0000644000175000017500000000247213517013306016735 0ustar fengfeng/* * 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 ukui-screensaver/src/fullbackgroundwidget.h0000644000175000017500000000455413637125674020165 0ustar fengfeng/* * 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" #include class LockWidget; class XEventMonitor; class MonitorWatcher; class Configuration; class QDBusInterface; class FullBackgroundWidget : public QWidget , public QAbstractNativeEventFilter { Q_OBJECT public: explicit FullBackgroundWidget(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event); void closeEvent(QCloseEvent *event); void showEvent(QShowEvent *event); virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; void mouseMoveEvent(QMouseEvent *e); public Q_SLOTS: void onCursorMoved(const QPoint &pos); void lock(); void showLockWidget(); void showScreensaver(); int 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); void onPrepareForSleep(bool sleep); void switchToLinux(); private: QDBusInterface *smInterface; LockWidget *lockWidget; XEventMonitor *xEventMonitor; MonitorWatcher *monitorWatcher; Configuration *configuration; QList widgetXScreensaverList; QList xscreensaverPidList; bool isLocked; ScreenStatus screenStatus; QPixmap background; }; #endif // FULLBACKGROUNDWIDGET_H ukui-screensaver/src/ukui-screensaver-backend.cpp0000644000175000017500000000747413517013306021157 0ustar fengfeng/* * 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 "interface.h" #include "sessionwatcher.h" #include "screensaveradaptor.h" #include "types.h" #include #include #include #include void sig_chld(int /*signo*/) { pid_t pid; while( (pid = waitpid(-1, NULL, WNOHANG)) > 0) qDebug() << "child" << pid << "terminated"; return; } int main(int argc, char *argv[]) { if(signal(SIGCHLD, sig_chld) == SIG_ERR) { perror("signal error"); exit(EXIT_FAILURE); } QCoreApplication a(argc, argv); // 检查该程序是否已经有实例在运行 QDBusInterface *checkInterface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus()); QDBusReply ret = checkInterface->call("NameHasOwner", "cn.kylinos.ScreenSaver"); if(ret.value()) { qDebug() << "There is an instance running"; exit(EXIT_FAILURE); } // 如果已经有实例在运行则kill, 主要是针对注销后重新登录时之前的实例没有被kill掉 char cmd[128] = {0}; char str[16]; FILE *fp; int pid; int n = sprintf(cmd, "ps aux | grep ukui-screensaver-backend | grep %s | grep -v grep | awk '{print $2}'", getenv("USER")); Q_UNUSED(n) fp = popen(cmd, "r"); while(fgets(str, sizeof(str)-1, fp)) { pid = atoi(str); if(pid > 0 && pid != getpid()) { qDebug() << "existing instance pid: " << pid; kill(pid, SIGKILL); } } pclose(fp); // for PowerManager fp = popen("xset s 0 0", "r"); // Q_UNUSED(fp) // 注册DBus Interface *interface = new Interface(); ScreenSaverAdaptor adaptor(interface); QDBusConnection service = QDBusConnection::sessionBus(); if(!service.registerService(SS_DBUS_SERVICE)) { qDebug() << service.lastError().message(); exit(EXIT_FAILURE); } if(!service.registerObject(SS_DBUS_PATH, SS_DBUS_SERVICE, &adaptor, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) { qDebug() << service.lastError().message(); exit(EXIT_FAILURE); } qDebug() << service.baseService(); // 发送DBus信号 SessionWatcher *watcher = new SessionWatcher; QObject::connect(watcher, &SessionWatcher::sessionIdle, interface, &Interface::onSessionIdleReceived); QObject::connect(watcher, &SessionWatcher::sessionIdle, &a, [&]{ QDBusMessage message = QDBusMessage::createSignal(SS_DBUS_PATH, SS_DBUS_INTERFACE, "SessionIdle"); service.send(message); }); QObject::connect(checkInterface, SIGNAL(NameLost(QString)), interface, SLOT(onNameLost(QString))); return a.exec(); } ukui-screensaver/src/test-accounts.cpp0000644000175000017500000000164513517013306017065 0ustar fengfeng/* * 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; } ukui-screensaver/src/lockwidget.h0000644000175000017500000000354513637125674016112 0ustar fengfeng/* * 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(); void setVirkeyboardPos(); private Q_SLOTS: void onUserAdded(const UserItem &user); void onUserDeleted(const UserItem &user); void onUserMenuTrigged(QAction *action); void showVirtualKeyboard(); protected: bool eventFilter(QObject *obj, QEvent *event); private: Ui::LockWidget *ui; AuthDialog *authDialog; VirtualKeyboard *vKeyboard; QTimer *timer; QMenu *usersMenu; Users *users; DisplayManager *displayManager; }; #endif // LOCKWIDGET_H ukui-screensaver/src/fullbackgroundwidget.cpp0000644000175000017500000003441113637125674020513 0ustar fengfeng/* * 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 #include #include #include #include #include #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" enum { SWITCH_TO_LINUX = 0, SWITCH_TO_ANDROID = 1, BACK_TO_DESKTOP = 2, TEST_CONNECTION = 3, }; int connect_to_switch(const char* path) { int ret; int connect_fd; struct sockaddr_un srv_addr; connect_fd = socket(PF_UNIX,SOCK_STREAM,0); if(connect_fd < 0) { return -1; } srv_addr.sun_family=AF_UNIX; strcpy(srv_addr.sun_path, path); ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); if(ret < 0) { perror("cannot connect to the server"); close(connect_fd); return -1; } return connect_fd; } int switch_to_linux(const char* container) { int connect_fd; int32_t switch_to = BACK_TO_DESKTOP; char path[1024] = {0}; sprintf(path, "/var/lib/kydroid/%s/sockets/%s", container, "desktop-switch"); printf("path = %s\n",path); connect_fd = connect_to_switch(path); if(connect < 0) return -1; write(connect_fd, &switch_to, sizeof(switch_to)); close(connect_fd); return 0; } void x11_get_screen_size(int *width,int *height) { Display* display; display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Cannot connect to X server %s/n", "simey:0"); exit (-1); } int screen_num; screen_num = DefaultScreen(display); *width = DisplayWidth(display, screen_num); *height = DisplayHeight(display, screen_num); XCloseDisplay(display); } 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; setMouseTracking(true); connect(monitorWatcher, &MonitorWatcher::monitorCountChanged, this, &FullBackgroundWidget::onScreenCountChanged); QDesktopWidget *desktop = QApplication::desktop(); connect(desktop, &QDesktopWidget::resized, this, &FullBackgroundWidget::onDesktopResized); connect(desktop, &QDesktopWidget::workAreaResized, this, &FullBackgroundWidget::onDesktopResized); QDBusInterface *iface = new QDBusInterface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus(), this); connect(iface, SIGNAL(PrepareForSleep(bool)), this, SLOT(onPrepareForSleep(bool))); init(); qApp->installNativeEventFilter(this); /* QString username = getenv("USER"); int uid = getuid(); QDBusInterface *interface = new QDBusInterface("cn.kylinos.Kydroid2", "/cn/kylinos/Kydroid2", "cn.kylinos.Kydroid2", QDBusConnection::systemBus(), this); QDBusMessage msg = interface->call(QStringLiteral("SetPropOfContainer"),username, uid, "is_kydroid_on_focus", "0"); */ QTimer::singleShot(500,this,SLOT(switchToLinux())); } void FullBackgroundWidget::switchToLinux() { struct passwd *pwd; pwd = getpwuid(getuid()); char *username = pwd->pw_name; int uid = pwd->pw_uid; char container[100]= {0}; sprintf(container,"kydroid2-%d-%s",uid,username); switch_to_linux(container); } void FullBackgroundWidget::paintEvent(QPaintEvent *event) { QDesktopWidget *desktop = QApplication::desktop(); if(!desktop->isVirtualDesktop()) { int width=0,height = 0; x11_get_screen_size(&width,&height); QPainter painter(this); QRect rec(0,0,width,height); painter.drawPixmap(rec, background); } else { 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::showEvent(QShowEvent *event) { // XSetWindowAttributes top_attrs; // top_attrs.override_redirect = False; // XChangeWindowAttributes(QX11Info::display(), this->winId(), CWOverrideRedirect, &top_attrs); // XRaiseWindow(QX11Info::display(), this->winId()); // raise(); return QWidget::showEvent(event); } bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { if (qstrcmp(eventType, "xcb_generic_event_t") != 0) { return false; } xcb_generic_event_t *event = reinterpret_cast(message); const uint8_t responseType = event->response_type & ~0x80; if (responseType == XCB_CONFIGURE_NOTIFY) { xcb_configure_notify_event_t *xc = reinterpret_cast(event); if (xc->event == QX11Info::appRootWindow()) { this->onDesktopResized(); XRaiseWindow(QX11Info::display(), this->winId()); XFlush(QX11Info::display()); } return false; } else if(responseType == XCB_PROPERTY_NOTIFY) { XRaiseWindow(QX11Info::display(), this->winId()); XFlush(QX11Info::display()); } return false; } void FullBackgroundWidget::mouseMoveEvent(QMouseEvent *e) { onCursorMoved(cursor().pos()); return QWidget::mouseMoveEvent(e); } void FullBackgroundWidget::init() { setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); // setAttribute(Qt::WA_DeleteOnClose); /*捕获键盘,如果捕获失败,则可能是由于弹出菜单项已经捕获,那么模拟一次esc按键来退出菜单,如果仍捕获失败,则放弃锁屏,避免密码无法输入*/ if(establishGrab()) qDebug()<<"establishGrab : true"; else { qDebug()<<"establishGrab : false"; XTestFakeKeyEvent(QX11Info::display(), XKeysymToKeycode(QX11Info::display(),XK_Escape), True, 1); XTestFakeKeyEvent(QX11Info::display(), XKeysymToKeycode(QX11Info::display(),XK_Escape), False, 1); XFlush(QX11Info::display()); sleep(1); if(!establishGrab()) { exit(1); } } // 监听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->hide(); //避免闪屏,所以先隐藏,设置大小后再显示 lockWidget->setGeometry(screen->geometry()); // lockWidget->show(); 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(); XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); } 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(); } // XSetInputFocus(QX11Info::display(),this->winId(),RevertToNone,CurrentTime); } 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(); } } int FullBackgroundWidget::onSessionStatusChanged(uint status) { qDebug() << "session status changed: " << status; if(status != SESSION_IDLE) { //当前session没有处于空闲状态 return -1; } qDebug() << "onSessionStatusChanged - screenStatus: " << screenStatus; if(!configuration->xscreensaverActivatedWhenIdle()) { return -1; } if(screenStatus & SCREEN_SAVER) { return -1; } else if(screenStatus & SCREEN_LOCK) { showScreensaver(); } else if(screenStatus == UNDEFINED) { if(configuration->xscreensaverActivatedWhenIdle() && configuration->lockWhenXScreensaverActivated()) { //显示锁屏和屏保 showLockWidget(); showScreensaver(); } else if(configuration->xscreensaverActivatedWhenIdle()) { //只显示屏保 showScreensaver(); } } return 0; } 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(); update(); clearScreensavers(); } void FullBackgroundWidget::onDesktopResized() { QDesktopWidget *desktop = QApplication::desktop(); if(!desktop->isVirtualDesktop()) { int width=0,height = 0; x11_get_screen_size(&width,&height); if(width==0||height==0) { setGeometry(desktop->geometry()); if(lockWidget) lockWidget->setGeometry(QApplication::primaryScreen()->geometry()); } else { qDebug()<<"width = "<setGeometry(0,0,width,height); } } else{ qDebug()<<"desktop"<geometry(); setGeometry(desktop->geometry()); if(lockWidget) onCursorMoved(cursor().pos()); } // clearScreensavers(); //repaint(); update(); } void FullBackgroundWidget::onPrepareForSleep(bool sleep) { ///系统休眠时,会关闭总线,导致设备不可用,发生错误 ///在系统休眠之前停止认证,在系统唤醒后重新开始认证 if(sleep) { lockWidget->stopAuth(); } else { if(screenStatus & SCREEN_SAVER) { lockWidget->startAuth(); } } } ukui-screensaver/src/screensaverwidget.cpp0000644000175000017500000001134513637125674020032 0ustar fengfeng/* * 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 "screensaverwidget.h" #include #include #include #include #include #include #include #include ScreenSaverWidget::ScreenSaverWidget(ScreenSaver *screensaver, QWidget *parent) : QWidget(parent), timer(nullptr), xscreensaverPid(-1), screensaver(screensaver), closing(false) { qDebug() << "ScreenSaverWidget::ScreenSaverWidget"; qDebug() << *screensaver; setMouseTracking(true); setFocus(); this->installEventFilter(this); QPalette plt; plt.setBrush(QPalette::Window, Qt::black); setPalette(plt); setAutoFillBackground(true); switch(screensaver->mode) { case SAVER_RANDOM: case SAVER_SINGLE: embedXScreensaver(screensaver->path); break; case SAVER_BLANK_ONLY: break; case SAVER_IMAGE: { setAutoFillBackground(true); screensaver->startSwitchImages(); QPalette plt; plt.setBrush(QPalette::Background, Qt::black); setPalette(plt); connect(screensaver, &ScreenSaver::imagePathChanged, this, &ScreenSaverWidget::onBackgroundChanged); break; } } show(); } ScreenSaverWidget::~ScreenSaverWidget() { } void ScreenSaverWidget::closeEvent(QCloseEvent *event) { qDebug() << "ScreenSaverWidget::closeEvent---beginStop"; if(xscreensaverPid > 0) kill(xscreensaverPid, SIGKILL); if(!closing){ closing = true; screensaver->stopSwitchImages(); delete screensaver; if(timer && timer->isActive()) timer->stop(); } qDebug() << "ScreenSaverWidget::closeEvent---endStop"; return QWidget::closeEvent(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: { QPixmap pixmap(screensaver->path); pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QPainter painter(this); painter.drawPixmap(geometry(), pixmap); break; } case TRANSITION_FADE_IN_OUT: { QPainter painter(this); QPixmap pixmap1(screensaver->lastPath); pixmap1.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); painter.setOpacity(opacity); painter.drawPixmap(geometry(), pixmap1); QPixmap pixmap(screensaver->path); pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); painter.setOpacity(1 - opacity); painter.drawPixmap(geometry(), pixmap); break; } } } return QWidget::paintEvent(event); } bool ScreenSaverWidget::eventFilter(QObject *obj, QEvent *event) { if(event->type() == 23) { XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); } return false; } /* Embed xscreensavers */ void ScreenSaverWidget::embedXScreensaver(const QString &path) { unsigned long wid = winId(); char widStr[20] = {0}; snprintf(widStr, sizeof(widStr), "%lu", wid); if((xscreensaverPid = fork()) == 0) { execl(path.toStdString().c_str(), "xscreensaver", "-window-id", widStr, (char*)0); qWarning() << "exec " << path << "failed"; } qDebug() << "xscreensaver pid: " << xscreensaverPid; } void ScreenSaverWidget::onBackgroundChanged(const QString &/*path*/) { switch(screensaver->effect) { case TRANSITION_NONE: repaint(); break; case TRANSITION_FADE_IN_OUT: opacity = 1.0; timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [&]{ opacity -= 0.1; if(opacity <= 0) timer->stop(); else repaint(); }); timer->start(50); break; } } ukui-screensaver/src/auth-pam.h0000644000175000017500000000307513517013306015451 0ustar fengfeng/* * 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 ukui-screensaver/BiometricAuth/0000755000175000017500000000000013637125674015546 5ustar fengfengukui-screensaver/BiometricAuth/biometricdeviceswidget.cpp0000644000175000017500000002011013637125674022770 0ustar fengfeng/** * 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); } } ukui-screensaver/BiometricAuth/biometricproxy.h0000644000175000017500000000722313630646305020772 0ustar fengfeng/** * 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 获取当前用户已连接设备对应特征数目 * @param uid 用户id * @param indexStart 用于认证的特征索引范围 * @param indexEnd * @return */ int GetFeatureCount(int uid, int indexStart = 0, int indexEnd = -1); /** * @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 ukui-screensaver/BiometricAuth/biometricauthwidget.cpp0000644000175000017500000001606613630646305022316 0ustar fengfeng/** * 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), retrytimer(nullptr), failedCount(0), timeoutCount(0), beStopped(false) { initUI(); resize(400, 200); 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; proxy->StopOps(device->id); 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); if(retrytimer&&retrytimer->isActive()){ retrytimer->stop(); delete retrytimer; retrytimer = nullptr; } 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.")); if(!beStopped){ // QTimer::singleShot(1000, this, &BiometricAuthWidget::startAuth_); if(!retrytimer){ retrytimer = new QTimer(this); retrytimer->setSingleShot(true); connect(retrytimer, &QTimer::timeout, this, &BiometricAuthWidget::startAuth_); } retrytimer->start(1000); } } } //识别发生错误 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); } ukui-screensaver/BiometricAuth/BiometricAuth.pri0000644000175000017500000000037513517013306021007 0ustar fengfengSOURCES += \ $$PWD/biometricproxy.cpp \ $$PWD/biometricauthwidget.cpp \ $$PWD/biometricdeviceswidget.cpp HEADERS += \ $$PWD/biometricproxy.h \ $$PWD/biometricauthwidget.h \ $$PWD/biometricdeviceswidget.h ukui-screensaver/BiometricAuth/biometricdeviceswidget.h0000644000175000017500000000437713517013306022437 0ustar fengfeng/** * 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 ukui-screensaver/BiometricAuth/BiometricAuth.pro0000644000175000017500000000216013517013306021007 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-12-06T09:17:41 # #------------------------------------------------- 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 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 # 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 += \ main.cpp \ biometricauthwidget.cpp \ biometricproxy.cpp \ biometricdeviceswidget.cpp HEADERS += \ biometricauthwidget.h \ biometricproxy.h \ biometricdeviceswidget.h FORMS += ukui-screensaver/BiometricAuth/biometricproxy.cpp0000644000175000017500000001260713637125674021337 0ustar fengfeng/** * 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" #include 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::GetFeatureCount(int uid, int indexStart, int indexEnd) { QDBusMessage result = call(QStringLiteral("GetDevList")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return 0; } auto dbusArg = result.arguments().at(1).value(); QList variantList; dbusArg >> variantList; int res = 0; for(int i = 0; i < variantList.size(); i++) { DeviceInfoPtr pDeviceInfo = std::make_shared(); auto arg = variantList.at(i).value(); arg >> *pDeviceInfo; StopOps(pDeviceInfo->id); QDBusMessage FeatureResult = call(QStringLiteral("GetFeatureList"),pDeviceInfo->id,uid,indexStart,indexEnd); if(FeatureResult.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetFeatureList error:" << FeatureResult.errorMessage(); return 0; } res += FeatureResult.arguments().takeFirst().toInt(); } return res; } 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; } ukui-screensaver/BiometricAuth/CMakeLists.txt0000644000175000017500000000076413517013306020276 0ustar fengfengqt5_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) ukui-screensaver/BiometricAuth/biometricauthwidget.h0000644000175000017500000000456413630646305021763 0ustar fengfeng/** * 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; QTimer *retrytimer; }; #endif // BIOMETRICAUTHWIDGET_H ukui-screensaver/BiometricAuth/main.cpp0000644000175000017500000000317613517013306017166 0ustar fengfeng/** * 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(); } ukui-screensaver/BiometricAuth/biometricdeviceinfo.h0000644000175000017500000000764513517013306021725 0ustar fengfeng/** * 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 ukui-screensaver/BiometricAuth/biometricdeviceinfo.cpp0000644000175000017500000001110113517013306022236 0ustar fengfeng/** * 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"); } ukui-screensaver/data/0000755000175000017500000000000013637125674013720 5ustar fengfengukui-screensaver/data/ukui-screensaver.desktop0000644000175000017500000000075613637125674020616 0ustar fengfeng[Desktop Entry] Type=Application Name=Screensaver Name[zh_CN]=屏幕保护程序 Name[zh_HK]=螢幕保護程式 Name[zh_TW]=螢幕保護程式 Comment[zh_CN]=运行屏幕保护及锁定程序 Comment[zh_TW]=啟動螢幕保護程式以及鎖定程式 Exec=ukui-screensaver-backend NoDisplay=true X-UKUI-Autostart-Phase=Application X-UKUI-Autostart-Notify=true X-UKUI-Bugzilla-Bugzilla=UKUI X-UKUI-Bugzilla-Product=ukui-screensaver X-UKUI-Bugzilla-Component=general X-UKUI-Bugzilla-Version=1.0.0 ukui-screensaver/data/org.ukui.screensaver.gschema.xml0000644000175000017500000001314613637125674022137 0ustar fengfeng true Activate when idle Set this to TRUE to activate the screensaver when the session is idle. true Lock on activation Set this to TRUE to lock the screen when the screensaver goes active. 'blank-only' Screensaver theme selection mode The selection mode used by screensaver. May be "blank-only" to enable the screensaver without using any theme on activation, "single" to enable screensaver using only one theme on activation (specified in "themes" key), and "random" to enable the screensaver using a random theme on activation. 'fade-in-out' Effect for images transition The selection effect used by screensaer which play images. May be "none" to play images without any transition effect. It's ignored when "mode" is not "image". 60 Time interval of switching images The number of seconds of time interval of switching images [] Screensaver themes This key specifies the list of themes to be used by the screensaver. It's ignored when "mode" key is "blank-only", should provide the theme name when "mode" is "single", and should provide a list of themes when "mode" is "random". 30 Time before power management baseline The number of seconds of inactivity before signalling to power management. This key is set and maintained by the session power management agent. 10 Time before theme change The number of minutes to run before changing the screensaver theme. 0 Time before locking The number of minutes after screensaver activation before locking the screen. false Allow embedding a keyboard into the window Set this to TRUE to allow embedding a keyboard into the window when trying to unlock. The "keyboard_command" key must be set with the appropriate command. '' Embedded keyboard command The command that will be run, if the "embedded_keyboard_enabled" key is set to TRUE, to embed a keyboard widget into the window. This command should implement an XEMBED plug interface and output a window XID on the standard output. false Allow logout Set this to TRUE to offer an option in the unlock dialog to allow logging out after a delay. The delay is specified in the "logout_delay" key. 120 Time before logout option The number of minutes after the screensaver activation before a logout option will appear in the unlock dialog. This key has effect only if the "logout_enable" key is set to TRUE. '' Logout command The command to invoke when the logout button is clicked. This command should simply log the user out without any interaction. This key has effect only if the "logout_enable" key is set to TRUE. true Allow user switching Set this to TRUE to offer an option in the unlock dialog to switch to a different user account. true Allow the session status message to be displayed Allow the session status message to be displayed when the screen is locked. '' the background iamge of lockscreen Allow the user to set the background iamge of lockscreen. ukui-screensaver/data/ukui-screensaver-qt0000644000175000017500000000007013517013306017536 0ustar fengfeng@include common-auth auth optional pam_gnome_keyring.so ukui-screensaver/data/ukui-screensaver.directory0000644000175000017500000001630113517013306021123 0ustar fengfeng[Desktop Entry] Encoding=UTF-8 Name=Screensavers Name[am]=የመመልከቻው ማዳኛዎች Name[ar]=حافظات الشاشة Name[as]=স্ক্ৰীনছেভাৰ Name[ast]=Curiapantalles Name[be]=Ахоўнікі экрану Name[be@latin]=Źbierahalniki ekranu Name[bg]=Предпазители на екрана Name[bn]=স্ক্রীন সেভার Name[bn_IN]=স্ক্রীনসেভার Name[br]=Damanterioù skramm Name[ca]=Estalvis de pantalla Name[ca@valencia]=Estalvis de pantalla Name[cmn]=螢幕保護程式 Name[crh]=Ekran qoruyıcıları Name[cs]=Šetřiče obrazovky Name[cy]=Arbedwyr Sgrin Name[da]=Pauseskærme Name[de]=Bildschirmschoner Name[dz]=གསལ་གཞི་ཉེན་སྲུང་ཚུ། Name[el]=Θέματα Name[en_AU]=Screensavers Name[en_CA]=Screensavers Name[en_GB]=Screensavers Name[es]=Salvapantallas Name[es_AR]=Protectores de pantalla Name[et]=Ekraanisäästjad Name[eu]=Pantaila-babeslea Name[fa]=محافظ‌های صفحهٔ نمایش Name[fi]=Näytönsäästäjät Name[fr]=Économiseurs d'écran Name[ga]=Spárálaithe Scáileáin Name[gl]=Protectores de pantalla Name[gu]=સ્ક્રીનસેવરો Name[he]=שומרי מסך Name[hi]=स्क्रीनसेवरs Name[hr]=Zaslonski čuvari Name[hu]=Képernyővédők Name[id]=Screensaver Name[is]=Skjáhvílur Name[it]=Salvaschermo Name[ja]=いろいろなスクリーンセーバーを格納するフォルダ Name[ka]=ეკრანმზოგები Name[kn]=ಸ್ಕ್ರೀನ್‌ಸೇವರುಗಳು Name[ko]=화면 보호기 Name[ku]=Parêzvanên ekranê Name[ky]=Экран сактагычтар Name[lt]=Ekrano užsklandos Name[lv]=Ekrānsaudzētāji Name[mai]=स्क्रीनसेवर Name[mg]=Sary mitsitsy Name[mk]=Чувари на екранот Name[ml]=സ്ക്രീന്‍സേവറുകള്‍ Name[mn]=_Дэлгэц гамнагчүүд Name[mr]=स्क्रीनसेवर Name[ms]=Penyelamat skrin Name[nb]=Skjermsparere Name[nds]=Billschirmschoners Name[ne]=स्क्रिनसेभर Name[nl]=Screensavers Name[nn]=Skjermsparare Name[oc]=Estalviaires d'ecran Name[or]=ପରଦା ସଂରକ୍ଷକ Name[pa]=ਸਕਰੀਨ-ਸੇਵਰ Name[pl]=Wygaszacze ekranu Name[ps]=پرده ساتونکي Name[pt]=Protetores de Ecrã Name[pt_BR]=Proteções de tela Name[ro]=Economizoare de ecran Name[ru]=Хранители экрана Name[si]=තිරආවරක Name[sk]=Šetriče obrazovky Name[sl]=Ohranjevalniki zaslona Name[sq]=Ruajtës ekrani Name[sr]=Чувари екрана Name[sr@latin]=Čuvari ekrana Name[sv]=Skärmsläckare Name[ta]=திரைசேமிப்பிகள் Name[te]=తెరకాపరులు Name[th]=โปรแกรมรักษาหน้าจอ Name[tr]=Ekran koruyucular Name[uk]=Заставки екрану Name[ur]=سکرین سیور Name[vi]=Ảnh bảo vệ màn hình Name[zh_CN]=屏幕保护程序 Name[zh_HK]=螢幕保護程式 Name[zh_TW]=螢幕保護程式 Comment=Screensaver themes Comment[am]=የመመልከቻው ማዳኛ ገጽታዎች Comment[ar]=سِمات حافظة الشاشة Comment[as]=স্ক্ৰীনছেভাৰ থিম Comment[ast]=Temes del Curiapantalles Comment[be]=Тэмы ахоўніка экрану Comment[be@latin]=Matyvy źbierahalnika ekranu Comment[bg]=Теми за предпазителя Comment[bn]=স্ক্রীনসেভার থীম Comment[bn_IN]=স্ক্রীনসেভার থিম Comment[br]=Neuzioù an damanter skramm Comment[ca]=Temes de l'estalvi de pantalla Comment[ca@valencia]=Temes de l'estalvi de pantalla Comment[cmn]=螢幕保護程式布景主題 Comment[crh]=Ekran qoruyıcısı temaları Comment[cs]=Motivy šetřiče obrazovky Comment[cy]=Themâu arbedwr sgrin Comment[da]=Pauseskærm temaer Comment[de]=Bildschirmschonerthemen Comment[dz]=གསལ་གཞི་ཉེན་སྲུང་བརྗོད་དོན་ཚུ། Comment[el]=Θέματα προστασίας οθόνης Comment[en@shaw]=𐑕𐑒𐑮𐑰𐑯𐑕𐑱𐑝𐑼 𐑔𐑰𐑥𐑟 Comment[en_AU]=Screensaver themes Comment[en_CA]=Screensaver themes Comment[en_GB]=Screensaver themes Comment[es]=Temas del salvapantallas Comment[es_AR]=Temas de protector de pantalla Comment[et]=Ekraanisäästja teemad Comment[eu]=Pantaila-babeslearen gaiak Comment[fa]=تم‌های محافظ صفحهٔ نمایش Comment[fi]=Näytönsäästäjän teemat Comment[fr]=Thèmes de l'économiseur d'écran Comment[ga]=Téamaí spárálaí scáileáin Comment[gl]=Temas do protector de pantalla Comment[gu]=સ્ક્રીનસેવર થીમો Comment[he]=ערכות נושא לשומר המסך Comment[hi]=स्क्रीनसेवर थीम Comment[hr]=Teme zaslonskog čuvara Comment[hu]=Képernyővédő-témák Comment[id]=Tema screensaver Comment[is]=Ásýnd skjáhvílu Comment[it]=Temi del salvaschermo Comment[ja]=スクリーンセーバーのテーマ Comment[ka]=ეკრანმზოგის გაფორმების თემები Comment[kn]=ಸ್ಕ್ರೀನ್‌ಸೇವರ್ ಥೀಮ್‌ಗಳು Comment[ko]=화면 보호기 테마 Comment[ku]=Dirbên dîmenderparêzê Comment[ky]=Экран сактагыч темалары Comment[lt]=Ekrano užsklandos temos Comment[lv]=Ekrānsaudzētāja tēmas Comment[mai]=स्क्रीनसेवर थीम Comment[mg]=Endri-tsary mitsitsy Comment[mk]=Теми за чуварот на екранот Comment[ml]=സ്ക്രീന്‍സേവറിന്റെ പ്രമേയങ്ങള്‍ Comment[mn]=_Дэлгэц гамнагчийн загварууд Comment[mr]=स्क्रीनसेवर सुत्रयोजना Comment[ms]=Tema penyelamat skrin Comment[nb]=Tema for skjermsparer Comment[nds]=Billschirmschonerthemen Comment[ne]=स्क्रिनसेभर विषयवस्तु Comment[nl]=Screensavers Comment[nn]=Tema for skjermsparar Comment[oc]=Tèmas d'estalviaire d'ecran Comment[or]=ପରଦା ସଂରକ୍ଷକ ପ୍ରସଙ୍ଗ Comment[pa]=ਸਕਰੀਨ-ਸੇਵਰ ਥੀਮ Comment[pl]=Motywy wygaszacza ekranu Comment[ps]=د پرده ساتونکي کوندې Comment[pt]=Temas do Protetor de Ecrã Comment[pt_BR]=Temas de proteção de tela Comment[ro]=Teme pentru economizor Comment[ru]=Темы хранителя экрана Comment[si]=තිරආවරකයේ තේමා Comment[sk]=Témy šetriča obrazovky Comment[sl]=Teme ohranjevalnika zaslona Comment[sq]=Temat e ruajtësit të ekranit Comment[sr]=Теме чувара екрана Comment[sr@latin]=Teme čuvara ekrana Comment[sv]=Skärmsläckarteman Comment[ta]=திரைசேமிப்பி சூழல்கள் Comment[te]=తెరకాపరి వైవిద్యాంశాలు Comment[th]=ชุดโปรแกรมรักษาหน้าจอ Comment[tr]=Ekran koruyucu temaları Comment[uk]=Теми збереження екрану Comment[ur]=سکرین سیور کی تھیم Comment[vi]=Sắc thái của ảnh bảo vệ màn hình Comment[zh_CN]=屏幕保护程序主题 Comment[zh_HK]=螢幕保護程式佈景主題 Comment[zh_TW]=螢幕保護程式布景主題 Icon=screensaver Type=Directory NoDisplay=false ukui-screensaver/data/CMakeLists.txt0000644000175000017500000000055713543101534016450 0ustar fengfenginstall(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/menus) install(FILES ukui-screensaver-qt DESTINATION /etc/pam.d) ukui-screensaver/data/ukui-screensavers.menu0000644000175000017500000000074713517013306020255 0ustar fengfeng Screensavers ukui-screensaver.directory Screensaver