diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e63621..e1950f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,12 @@ find_package(Qt5 COMPONENTS Core Widgets DBus X11Extras Xml Network Svg) find_package(PkgConfig REQUIRED) find_package(OpenCV REQUIRED) find_package(PkgConfig) +find_package(KF5Screen REQUIRED) +find_package(KF5Wayland REQUIRED) + pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) +pkg_check_modules(KScreen REQUIRED kscreen2) # 是否是intel项目 option (USE_INTEL "intel项目" OFF) diff --git a/data/screensaver-startup.sh b/data/screensaver-startup.sh index fa8710d..c110d2e 100755 --- a/data/screensaver-startup.sh +++ b/data/screensaver-startup.sh @@ -3,3 +3,5 @@ ukui-screensaver-dialog --lock-startup & >/dev/null 2>&1 /usr/lib/ukui-screensaver/screensaver-focus-helper & >/dev/null 2>&1 +#如果锁屏和桌面进程并行启动,会对锁屏启动时间有较大影响,因此先启动锁屏,1s后再往下执行 +sleep 1 diff --git a/debian/control b/debian/control index d2d85fb..6606284 100644 --- a/debian/control +++ b/debian/control @@ -4,22 +4,24 @@ Priority: optional Maintainer: Kylin Team Uploaders: Aron Xu , handsome_feng -Build-Depends: cmake (>=2.6), - debhelper-compat (= 12), +Build-Depends: debhelper-compat (= 12), + cmake (>=2.6), + qtbase5-dev, + libqt5x11extras5-dev, + libpam0g-dev, + qttools5-dev, + qttools5-dev-tools, libglib2.0-dev, + libopencv-dev, + libx11-dev, + libxtst-dev, + libqt5svg5-dev, + libkf5wayland-dev, + libkf5screen-dev, libgsettings-qt-dev, libkf5windowsystem-dev, libmatemixer-dev, - libopencv-dev, - libpam0g-dev, - libqt5svg5-dev, - libqt5x11extras5-dev, - libukui-log4qt-dev, - libx11-dev, - libxtst-dev, - qtbase5-dev, - qttools5-dev, - qttools5-dev-tools + libukui-log4qt-dev Standards-Version: 4.5.0 Rules-Requires-Root: no Homepage: https://www.github.com/ukui/ukui-screensaver diff --git a/debian/ukui-screensaver.manpages b/debian/ukui-screensaver.manpages index 8f0b2fb..ff36470 100644 --- a/debian/ukui-screensaver.manpages +++ b/debian/ukui-screensaver.manpages @@ -1,3 +1,3 @@ man/ukui-screensaver-backend.1 -man/ukui-screensaver-command.1 man/ukui-screensaver-dialog.1 +man/ukui-screensaver-command.1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c4b7f93..4b841ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,8 @@ include_directories( ${QGS_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${MMIX_INCLUDE_DIRS} + ${MMIX_INCLUDE_DIRS} + ${KF5Wayland_LIBRARIES} ) set(EXTRA_LIBS @@ -36,8 +38,11 @@ set(EXTRA_LIBS ${QGS_LIBRARIES} ${GLIB_LIBRARIES} ${MMIX_LIBRARIES} + ${KF5Wayland_LIBRARIES} -lrt -lpthread + -lKF5WaylandServer + -lKF5WaylandClient ) qt5_wrap_ui(dialog_SRC @@ -86,6 +91,8 @@ qt5_wrap_cpp(dialog_SRC networkwatcher.h digitalkeyboard.h surewindow.h + servicemanager.h + plasma-shell-manager.h PhysicalDeviceSet/brightnessdeviceset.h PhysicalDeviceSet/flightmodeset.h PhysicalDeviceSet/sounddeviceset.h @@ -128,12 +135,15 @@ set(dialog_SRC networkwatcher.cpp digitalkeyboard.cpp surewindow.cpp + servicemanager.cpp + plasma-shell-manager.cpp PhysicalDeviceSet/brightnessdeviceset.cpp PhysicalDeviceSet/flightmodeset.cpp PhysicalDeviceSet/sounddeviceset.cpp PhysicalDeviceSet/touchscreenset.cpp ) add_executable(ukui-screensaver-dialog ${dialog_SRC}) +add_definitions(-DAPP_API_MAJOR=0 -DAPP_API_MINOR=11 -DAPP_API_FUNC=0) target_link_libraries(ukui-screensaver-dialog Qt5::Core @@ -143,7 +153,7 @@ target_link_libraries(ukui-screensaver-dialog Qt5::X11Extras Qt5::Network ${EXTRA_LIBS} - BiometricAuth + BiometricAuth VirtualKeyboard Common Kylin-nm diff --git a/src/authdialog.cpp b/src/authdialog.cpp index 4852dcc..c3f957d 100644 --- a/src/authdialog.cpp +++ b/src/authdialog.cpp @@ -36,6 +36,7 @@ #include "pam-tally.h" #include "commonfunc.h" #include "loginoptionswidget.h" +#include "servicemanager.h" AuthDialog::AuthDialog(const UserItem &user, QWidget *parent) : QWidget(parent), @@ -60,6 +61,9 @@ AuthDialog::AuthDialog(const UserItem &user, QWidget *parent) : connect(auth, &Auth::showMessage, this, &AuthDialog::onShowMessage); connect(auth, &Auth::showPrompt, this, &AuthDialog::onShowPrompt); connect(auth, &Auth::authenticateComplete, this, &AuthDialog::onAuthComplete); + ServiceManager *sm = ServiceManager::instance(); + connect(sm, &ServiceManager::serviceStatusChanged, + this, &AuthDialog::onBiometricDbusChanged); useFirstDevice = getUseFirstDevice(); m_failedTimes.clear(); @@ -88,7 +92,7 @@ void AuthDialog::stopAuth() clearMessage(); // auth->stopAuth(); - m_passwordEdit->readOnly(true); + // m_passwordEdit->readOnly(true); // if(m_passwdWidget) // m_passwdWidget->hide(); } @@ -204,6 +208,8 @@ void AuthDialog::initUI() m_passwordEdit->setFocusPolicy(Qt::StrongFocus); m_passwordEdit->installEventFilter(this); m_passwordEdit->readOnly(true); + /*免密登录时,会出现闪一下密码框的问题,因此初始化时隐藏,收到pam发来的prompt类型的消息后再显示*/ + m_passwordEdit->hide(); m_passwordEdit->setType(QLineEdit::Password); setFocusProxy(m_passwordEdit); connect(m_passwordEdit, SIGNAL(clicked(const QString&)), @@ -1076,3 +1082,84 @@ void AuthDialog::onLoginOptImage(QImage img) setQRCode(img); } } + +void AuthDialog::onBiometricDbusChanged(bool bActive) +{ + qDebug()<<"BiometricDbus:"<isValid()) + { + qWarning() << "An error occurs when connect to the biometric DBus"; + if (m_deviceInfo) { + if (!m_widgetLoginOpts || !m_widgetLoginOpts->findDeviceById(m_deviceInfo->id) + || m_widgetLoginOpts->isDeviceDisable(m_deviceInfo->id)) { + m_deviceInfo = DeviceInfoPtr(); + } + } + return; + } + + //初始化生物识别认证UI + initBiometricWidget(); + + //初始化enableBiometriAuth + if(m_deviceCount <= 0) + { + m_deviceCount = m_widgetLoginOpts->getLoginOptCount(); + } + + //没有可用设备,不启用生物识别认证 + if(m_deviceCount < 1) + { + qWarning() << "No available devices"; + return; + } + + //获取默认设备 + if(m_deviceName.isEmpty()) + { + m_deviceName = GetDefaultDevice(user.name); + } + qDebug() << m_deviceName; + if (m_deviceInfo) { + if (!m_widgetLoginOpts || !m_widgetLoginOpts->findDeviceById(m_deviceInfo->id) + || m_widgetLoginOpts->isDeviceDisable(m_deviceInfo->id)) { + m_deviceInfo = DeviceInfoPtr(); + } + } + + //如果默认设备为空的话,第一次不启动生物识别认证 + if(m_deviceName.isEmpty() && !m_deviceInfo) + { + if(useFirstDevice == true) { + m_deviceInfo = m_widgetLoginOpts->getFirstDevInfo(); + } else { + return; + } + } + + if(!m_deviceInfo) + { + m_deviceInfo = m_widgetLoginOpts->findDeviceByName(m_deviceName); + if (!m_deviceInfo) + m_deviceInfo = m_widgetLoginOpts->getFirstDevInfo(); + } + if(!m_deviceInfo) + { + return; + } + switchLoginOptType(m_widgetLoginOpts->convertDeviceType(m_deviceInfo->deviceType)); + startBioAuth(); + }); + } +} diff --git a/src/authdialog.h b/src/authdialog.h index 73ecd16..aa2d30e 100644 --- a/src/authdialog.h +++ b/src/authdialog.h @@ -96,6 +96,7 @@ private Q_SLOTS: void setFaceImg(QImage& imgFace, int nStatus = 0); void onM_passwordEditClicked(); void setQRCodeMsg(QString strMsg); + void onBiometricDbusChanged(bool bActive); public Q_SLOTS: // void switchToBiometric(); diff --git a/src/configuration.cpp b/src/configuration.cpp index ac964a0..5b88feb 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/src/fullbackgroundwidget.cpp b/src/fullbackgroundwidget.cpp index c199287..847d022 100644 --- a/src/fullbackgroundwidget.cpp +++ b/src/fullbackgroundwidget.cpp @@ -31,6 +31,7 @@ #include #include #include +#include "plasma-shell-manager.h" #include #include #include @@ -198,7 +199,6 @@ QPixmap blurPixmap(QPixmap pixmap) FullBackgroundWidget::FullBackgroundWidget(QWidget *parent) : QWidget(parent), lockWidget(nullptr), - xEventMonitor(new XEventMonitor(this)), //monitorWatcher(new MonitorWatcher(this)), configuration(Configuration::instance()), isLocked(false), @@ -268,6 +268,10 @@ FullBackgroundWidget::FullBackgroundWidget(QWidget *parent) this, SLOT(propertiesChangedSlot(QString, QMap, QStringList))); #endif + if(QX11Info::isPlatformX11()){ + xEventMonitor = new XEventMonitor(this); + } + init(); qApp->installNativeEventFilter(this); installEventFilter(this); @@ -363,6 +367,7 @@ bool FullBackgroundWidget::eventFilter(QObject *obj, QEvent *event) if(event->type() == QEvent::WindowDeactivate){ QTimer::singleShot(50,this,SLOT(laterActivate())); }else if(event->type() == QEvent::WindowActivate){ + PlasmaShellManager::getInstance()->setAppWindowKeepAbove(true); QTimer::singleShot(500,this,SLOT(setLockState())); QTimer::singleShot(200,this,SLOT(killWindow())); } @@ -446,7 +451,10 @@ void FullBackgroundWidget::closeEvent(QCloseEvent *event) if(widget) widget->close(); } - closeGrab(); + + if(QX11Info::isPlatformX11()){ + closeGrab(); + } return QWidget::closeEvent(event); } @@ -523,18 +531,37 @@ void FullBackgroundWidget::mousePressEvent(QMouseEvent *e) void FullBackgroundWidget::init() { /*捕获键盘,如果捕获失败,则可能是由于弹出菜单项已经捕获,那么模拟一次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); + if(QX11Info::isPlatformX11()){ + 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); + } } + + XWindowAttributes rootAttr; + XGetWindowAttributes(QX11Info::display(), QX11Info::appRootWindow(), &rootAttr); + XSelectInput( QX11Info::display(), QX11Info::appRootWindow(), + SubstructureNotifyMask|rootAttr.your_event_mask ); + + 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))); + connect(xEventMonitor, SIGNAL(buttonPress(int, int)), + this, SLOT(onGlobalButtonPressed(int, int))); + + xEventMonitor->start(); + } qDebug()<<"----------------------------------------------------------------开始异步调用"; @@ -548,16 +575,18 @@ void FullBackgroundWidget::init() if(!background.isNull()){ background = blurPixmap(background); } + }); - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint + if(QX11Info::isPlatformX11()){ + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); - setAttribute(Qt::WA_TranslucentBackground); + }else{ + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); + } - XWindowAttributes rootAttr; - XGetWindowAttributes(QX11Info::display(), QX11Info::appRootWindow(), &rootAttr); - XSelectInput( QX11Info::display(), QX11Info::appRootWindow(), - SubstructureNotifyMask|rootAttr.your_event_mask ); + /*x100下会出现黑色小方块问题,设置此属性时正常*/ + setAttribute(Qt::WA_TranslucentBackground); // 监听session信号 // smInterface = new QDBusInterface(SM_DBUS_SERVICE, @@ -567,16 +596,6 @@ void FullBackgroundWidget::init() // 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))); - connect(xEventMonitor, SIGNAL(buttonPress(int, int)), - this, SLOT(onGlobalButtonPressed(int, int))); - - // int totalWidth = 0; // int totalHeight = 0; // for(auto screen : QGuiApplication::screens()) @@ -588,8 +607,6 @@ void FullBackgroundWidget::init() QDesktopWidget *desktop = QApplication::desktop(); setGeometry(desktop->geometry()); - xEventMonitor->start(); - #ifdef USE_INTEL SoundDeviceSet::instance(); #endif @@ -673,7 +690,9 @@ void FullBackgroundWidget::showLockWidget() } onCursorMoved(QCursor::pos()); lockWidget->setFocus(); - XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + if(QX11Info::isPlatformX11() ){ + XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + } activateWindow(); repaint(); } @@ -693,6 +712,13 @@ void FullBackgroundWidget::showScreensaver() for(auto screen : QGuiApplication::screens()) { ScreenSaver *saver = configuration->getScreensaver(); + /*锁屏设置的Qt::WA_TranslucentBackground属性会导致第三方屏保变得透明,因此在使用第三方屏保时 + * 取消该属性,清除屏保时再设置回来*/ + if(saver->path != "/usr/lib/ukui-screensaver/ukui-screensaver-default") + { + setAttribute(Qt::WA_TranslucentBackground,false); + } + ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this); qDebug() << " new ScreenSaverWidget"; widgetXScreensaverList.push_back(saverWidget); @@ -727,7 +753,7 @@ void FullBackgroundWidget::clearScreensavers() widget->close(); } widgetXScreensaverList.clear(); - + setAttribute(Qt::WA_TranslucentBackground,true); qDebug() << "clearScreensavers - screenStatus: " << screenStatus; unsetCursor(); @@ -1038,6 +1064,7 @@ void FullBackgroundWidget::onPrepareForSleep(bool sleep) { ///系统休眠时,会关闭总线,导致设备不可用,发生错误 ///在系统休眠之前停止认证,在系统唤醒后重新开始认证 + qDebug()<<"onPrepareForSleep:"<type() == 23) { - XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + if(QX11Info::isPlatformX11()){ + XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + } update(); }else if(event->type() == QEvent::MouseButtonPress){ - XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + if(QX11Info::isPlatformX11()){ + XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + } update(); } } @@ -174,7 +178,9 @@ void IconEdit::resizeEvent(QResizeEvent *) void IconEdit::setX11Focus() { - XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + if(QX11Info::isPlatformX11()){ + XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + } update(); } diff --git a/src/interface.cpp b/src/interface.cpp index 12d5b60..5daa8fa 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include Interface::Interface(QObject *parent) : QObject(parent), @@ -185,11 +188,48 @@ void Interface::onNameLost(const QString &serviceName) exit(0); } +bool Interface::checkScreenDialogRunning() +{ + int fd = -1; + struct flock lock; + + const QString PID_DIR = QString("/var/run/user/%1").arg(QString::number(getuid())); + QString env = qgetenv("DISPLAY"); + const QString PID_FILE = PID_DIR + QString("/ukui-screensaver%1.pid").arg(env); + + QFileInfo fileInfo(PID_FILE); + if(!fileInfo.exists()) { + return false; + } + if((fd = open(PID_FILE.toLocal8Bit().data(), + O_RDWR, 0666)) == -1){ + return false; + } + + memset(&lock, 0, sizeof(struct flock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + if(fcntl(fd, F_GETLK, &lock) < 0) { + return false; + } else { + if (lock.l_type == F_UNLCK) { + return false; + } else { + return true; + } + } +} + void Interface::onPrepareForSleep(bool sleep) { if(sleep) { - if(!settings->get("sleep-activation-enabled").toBool()){ + if (checkScreenDialogRunning()) { + uninhibit(); + return; + } + if(!settings->get("sleep-activation-enabled").toBool()){ uninhibit(); return; } diff --git a/src/interface.h b/src/interface.h index 411ce5c..e6edaff 100644 --- a/src/interface.h +++ b/src/interface.h @@ -54,6 +54,7 @@ public Q_SLOTS: void onShowBlankScreensaver(); void onNameLost(const QString&); void onPrepareForSleep(bool sleep); + bool checkScreenDialogRunning(); private: bool checkExistChild(); diff --git a/src/lockwidget.cpp b/src/lockwidget.cpp index 19678ae..2186f82 100644 --- a/src/lockwidget.cpp +++ b/src/lockwidget.cpp @@ -79,12 +79,14 @@ LockWidget::LockWidget(QWidget *parent) // updateNetIcon(m_kylinNM->getConnectStatus()); // }); - xEventMonitor = new XEventMonitor(this); - connect(xEventMonitor, SIGNAL(keyPress(const QString &)), this, - SLOT(onGlobalKeyPress(const QString &))); - connect(xEventMonitor, SIGNAL(keyRelease(const QString &)), this, - SLOT(onGlobalkeyRelease(const QString &))); - xEventMonitor->start(); + if(QX11Info::isPlatformX11()){ + xEventMonitor = new XEventMonitor(this); + connect(xEventMonitor, SIGNAL(keyPress(const QString &)), this, + SLOT(onGlobalKeyPress(const QString &))); + connect(xEventMonitor, SIGNAL(keyRelease(const QString &)), this, + SLOT(onGlobalkeyRelease(const QString &))); + xEventMonitor->start(); + } this->installEventFilter(this); initUI(); @@ -336,20 +338,25 @@ void LockWidget::initUI() connect(ui->btnNetworkManager,&QPushButton::clicked ,this,&LockWidget::showNetManager); - //虚拟键盘 - ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.svg")); - ui->btnKeyboard->setFixedSize(48, 48); - ui->btnKeyboard->setIconSize(QSize(24, 24)); - ui->btnKeyboard->setFocusPolicy(Qt::NoFocus); - ui->btnKeyboard->installEventFilter(this); -/* connect(ui->btnKeyboard, &QPushButton::clicked, - this, [&]{ - qDebug() << vKeyboard->isHidden(); - vKeyboard->setVisible(vKeyboard->isHidden()); - }); -*/ - connect(ui->btnKeyboard, &QPushButton::clicked, - this, &LockWidget::showVirtualKeyboard); + if(QX11Info::isPlatformX11()){ + //虚拟键盘 + ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.svg")); + ui->btnKeyboard->setFixedSize(48, 48); + ui->btnKeyboard->setIconSize(QSize(24, 24)); + ui->btnKeyboard->setFocusPolicy(Qt::NoFocus); + ui->btnKeyboard->installEventFilter(this); + ui->btnKeyboard->hide(); + + connect(ui->btnKeyboard, &QPushButton::clicked, + this, [&]{ + qDebug() << vKeyboard->isHidden(); + vKeyboard->setVisible(vKeyboard->isHidden()); + }); + + + connect(ui->btnKeyboard, &QPushButton::clicked, + this, &LockWidget::showVirtualKeyboard); + } //用户切换 if(displayManager->canSwitch()) @@ -746,8 +753,10 @@ void LockWidget::resizeEvent(QResizeEvent *event) x = x + ui->btnPowerManager->width(); ui->btnPowerManager->move(width() - x,height() - y); - x = x+ui->btnKeyboard->width()+16; - ui->btnKeyboard->move(width() - x, height() - y); + if(ui->btnKeyboard->isVisible()){ + x = x+ui->btnKeyboard->width()+16; + ui->btnKeyboard->move(width() - x, height() - y); + } x = x + ui->btnNetworkManager->width()+16; ui->btnNetworkManager->move(width() - x, height() - y); @@ -788,7 +797,9 @@ void LockWidget::resizeEvent(QResizeEvent *event) powermanager->width(),powermanager->height()); } - XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + if(QX11Info::isPlatformX11()){ + XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + } } diff --git a/src/plasma-shell-manager.cpp b/src/plasma-shell-manager.cpp new file mode 100644 index 0000000..73a3c51 --- /dev/null +++ b/src/plasma-shell-manager.cpp @@ -0,0 +1,159 @@ +#include "plasma-shell-manager.h" + +#include + +#include +#include + +#include +#include +#include + +static PlasmaShellManager* global_instance = nullptr; + +PlasmaShellManager *PlasmaShellManager::getInstance() +{ + if (!global_instance) + { + global_instance = new PlasmaShellManager; + qDebug() << "Here create instance..."; + } + qDebug() << "Return instance"; + return global_instance; +} + +bool PlasmaShellManager::setAppWindowActive() +{ + if (!supportPlasmaWindowManagement()) + return false; + + m_appWindow->requestActivate(); + return true; +} + +bool PlasmaShellManager::setAppWindowKeepAbove(bool keep) +{ + if (!supportPlasmaWindowManagement()) + { + qDebug() << "false"; + return false; + } + if(keep != m_appWindow->isKeepAbove()) { + qDebug() << "to keep above"; + m_appWindow->requestToggleKeepAbove(); + } + return true; +} + +bool PlasmaShellManager::setMaximized(QWindow *window) +{ + if (!supportShell()) + return false; + + auto surface = KWayland::Client::Surface::fromWindow(window); + if (!surface) + return false; + + auto shellSurface = m_shell->createSurface(surface, window); + if (!shellSurface) + return false; + + shellSurface->setMaximized(); + return true; +} + +bool PlasmaShellManager::setRole(QWindow *window, KWayland::Client::PlasmaShellSurface::Role role) +{ + if (!supportPlasmaShell()) + return false; + + auto surface = KWayland::Client::Surface::fromWindow(window); + if (!surface) + return false; + + auto plasmaShellSurface = m_plasmaShell->createSurface(surface, window); + if (!plasmaShellSurface) + return false; + + plasmaShellSurface->setRole(role); + return true; +} + +bool PlasmaShellManager::setPos(QWindow *window, const QPoint &pos) +{ + if (!supportPlasmaShell()) + return false; + + auto surface = KWayland::Client::Surface::fromWindow(window); + if (!surface) + return false; + + auto plasmaShellSurface = m_plasmaShell->createSurface(surface, window); + if (!plasmaShellSurface) + return false; + + plasmaShellSurface->setPosition(pos); + return true; +} + +bool PlasmaShellManager::supportPlasmaShell() +{ + return m_plasmaShell; +} + +bool PlasmaShellManager::supportShell() +{ + return m_shell; +} + +bool PlasmaShellManager::supportPlasmaWindowManagement() +{ + return m_windowManager && m_appWindow; +} + +PlasmaShellManager::PlasmaShellManager(QObject *parent) : QObject(parent) +{ + auto connection = KWayland::Client::ConnectionThread::fromApplication(qApp); + auto registry = new KWayland::Client::Registry(this); + registry->create(connection->display()); + + connect(registry, &KWayland::Client::Registry::plasmaShellAnnounced, this, [=](){ + qDebug() << "plasmaShellAnnounced..."; + const auto interface = registry->interface(KWayland::Client::Registry::Interface::PlasmaShell); + if (interface.name != 0) { + qDebug() << "createPlasmaShell..."; + m_plasmaShell = registry->createPlasmaShell(interface.name, interface.version, this); + } + }); + + connect(registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, this, [=](){ + qDebug() << "plasmaWindowManagementAnnounced"; + const auto interface = registry->interface(KWayland::Client::Registry::Interface::PlasmaWindowManagement); + if (interface.name != 0) { + qDebug() << "createPlasmaWindowManagement"; + m_windowManager = registry->createPlasmaWindowManagement(interface.name, interface.version, this); + } + if(m_windowManager) { + connect(m_windowManager, &KWayland::Client::PlasmaWindowManagement::windowCreated, + [this](KWayland::Client::PlasmaWindow *window) { + qDebug()<< "PlasmaWindow..."; + if (window->pid() == getpid()) { + if(isFirstCreate) { + isFirstCreate = false; + m_appWindow = window; + } + } + }); + } + }); + + connect(registry, &KWayland::Client::Registry::shellAnnounced, this, [=](){ + const auto interface = registry->interface(KWayland::Client::Registry::Interface::Shell); + if (interface.name != 0) { + m_shell = registry->createShell(interface.name, interface.version, this); + } + }); + + registry->setup(); + connection->roundtrip(); +} diff --git a/src/plasma-shell-manager.h b/src/plasma-shell-manager.h new file mode 100644 index 0000000..1437a88 --- /dev/null +++ b/src/plasma-shell-manager.h @@ -0,0 +1,37 @@ +#ifndef PLASMASHELLMANAGER_H +#define PLASMASHELLMANAGER_H + +#include +#include +#include +#include +#include + +class PlasmaShellManager : public QObject +{ + Q_OBJECT +public: + static PlasmaShellManager *getInstance(); + + bool setAppWindowActive(); + bool setAppWindowKeepAbove(bool keep); + bool setMaximized(QWindow *window); + bool setRole(QWindow *window, KWayland::Client::PlasmaShellSurface::Role role); + bool setPos(QWindow *window, const QPoint &pos); + bool supportPlasmaShell(); + bool supportShell(); + bool supportPlasmaWindowManagement(); + +private: + explicit PlasmaShellManager(QObject *parent = nullptr); + + KWayland::Client::PlasmaShell *m_plasmaShell = nullptr; + KWayland::Client::Shell *m_shell = nullptr; + KWayland::Client::PlasmaWindowManagement *m_windowManager = nullptr; + KWayland::Client::PlasmaWindow *m_appWindow = nullptr; + + bool isFirstCreate = true; +}; + + +#endif // PLASMASHELLMANAGER_H diff --git a/src/screensaver.h b/src/screensaver.h index d3f2ad3..2476042 100644 --- a/src/screensaver.h +++ b/src/screensaver.h @@ -44,7 +44,7 @@ class ScreenSaver : public QObject public: SaverMode mode; //path is a directory or a file path if mode is SAVER_IMAGE - QString path; + QString path = ""; QString lastPath; //for images saver diff --git a/src/screensaverwidget.cpp b/src/screensaverwidget.cpp index e194c54..c232201 100644 --- a/src/screensaverwidget.cpp +++ b/src/screensaverwidget.cpp @@ -139,7 +139,9 @@ bool ScreenSaverWidget::eventFilter(QObject *obj, QEvent *event) { if(event->type() == 23) { - XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + if(QX11Info::isPlatformX11()){ + XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); + } } return false; } diff --git a/src/servicemanager.cpp b/src/servicemanager.cpp new file mode 100644 index 0000000..427678e --- /dev/null +++ b/src/servicemanager.cpp @@ -0,0 +1,122 @@ +/* + * 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 "servicemanager.h" +#include +#include + +#define SERVICE "biometric-authentication.service" +#define DBUS_SERVICE "org.ukui.Biometric" +#define DBUS_PATH "/org/ukui/Biometric" +#define DBUS_INTERFACE "org.ukui.Biometric" + +#define FD_DBUS_SERVICE "org.freedesktop.DBus" +#define FD_DBUS_PATH "/org/freedesktop/DBus" +#define FD_DBUS_INTERFACE "org.freedesktop.DBus" + +ServiceManager *ServiceManager::instance_ = nullptr; + +ServiceManager::ServiceManager(QObject *parent) + : QObject(parent), + dbusService(nullptr), + bioService(nullptr) +{ + init(); +} + +void ServiceManager::init() +{ + if(!dbusService) + { + dbusService = new QDBusInterface(FD_DBUS_SERVICE, + FD_DBUS_PATH, + FD_DBUS_INTERFACE, + QDBusConnection::systemBus()); + connect(dbusService, SIGNAL(NameOwnerChanged(QString, QString, QString)), + this, SLOT(onDBusNameOwnerChanged(QString,QString,QString))); + } +} + +ServiceManager *ServiceManager::instance() +{ + if(!instance_) + { + instance_ = new ServiceManager; + } + return instance_; +} + +bool ServiceManager::connectToService() +{ + if(!bioService) + { + bioService = new QDBusInterface(DBUS_SERVICE, + DBUS_PATH, + DBUS_INTERFACE, + QDBusConnection::systemBus()); + } + return bioService->isValid(); +} + +void ServiceManager::onDBusNameOwnerChanged(const QString &name, + const QString &oldOwner, + const QString &newOwner) +{ + if(name == DBUS_SERVICE) + { + qDebug() << "service status changed:" + << (newOwner.isEmpty() ? "inactivate" : "activate"); + Q_EMIT serviceStatusChanged(!newOwner.isEmpty()); + } +} + +/*! + * \brief checkServiceExist + * 检查生物识别后台服务是否已启动 + */ +bool ServiceManager::serviceExists() +{ + QDBusReply reply = dbusService->call("NameHasOwner", DBUS_SERVICE); + if(!reply.isValid()) + { + qDebug() << "check service exists error:" << reply.error(); + return false; + } + return reply.value(); +} + +/*! + * \brief ServiceManager::apiCompatible + * 检查API版本和服务的版本是否兼容 + */ +bool ServiceManager::apiCompatible() +{ + if(!connectToService()) + return false; + + QDBusReply reply = bioService->call("CheckAppApiVersion", + APP_API_MAJOR, + APP_API_MINOR, + APP_API_FUNC); + if(!reply.isValid()) + { + qDebug() << "check api compatibility error: " << reply.error(); + return false; + } + return (reply.value() == 0); +} diff --git a/src/servicemanager.h b/src/servicemanager.h new file mode 100644 index 0000000..548cf1d --- /dev/null +++ b/src/servicemanager.h @@ -0,0 +1,53 @@ +/* + * 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 SERVICEMANAGER_H +#define SERVICEMANAGER_H + +#include +#include + +class ServiceManager : public QObject +{ + Q_OBJECT +public: + static ServiceManager *instance(); + bool serviceExists(); + bool apiCompatible(); + +private: + explicit ServiceManager(QObject *parent = nullptr); + void init(); + bool connectToService(); + +Q_SIGNALS: + void serviceStatusChanged(bool activate); + +public Q_SLOTS: + void onDBusNameOwnerChanged(const QString &name, + const QString &oldOwner, + const QString &newOwner); + +private: + static ServiceManager *instance_; + QDBusInterface *dbusService; + QDBusInterface *bioService; + bool serviceStatus; +}; + +#endif // SERVICEMANAGER_H diff --git a/src/ukui-screensaver-dialog.cpp b/src/ukui-screensaver-dialog.cpp index bd7bb1e..5bdace1 100644 --- a/src/ukui-screensaver-dialog.cpp +++ b/src/ukui-screensaver-dialog.cpp @@ -28,6 +28,7 @@ #include #include #include +#include "plasma-shell-manager.h" #include #include #include @@ -247,6 +248,16 @@ int main(int argc, char *argv[]) window->show(); window->activateWindow(); #endif + + + bool isWayland = false; + if(QString(qgetenv("XDG_SESSION_TYPE")) == "wayland") { + isWayland = true; + } + if (isWayland){ + PlasmaShellManager::getInstance(); + PlasmaShellManager::getInstance()->setAppWindowKeepAbove(true); + } QString username = getenv("USER"); int uid = getuid();