From 35c7c33c23685e00bc981a3809a3f3a3597c2f9a Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 6 Mar 2017 16:01:30 +0100 Subject: [server] Prevent screen standby while clients are connected --- CMakeLists.txt | 11 ++++- src/server/mainwindow/mainwindow.cpp | 35 ++++++++----- src/server/mainwindow/mainwindow.h | 9 ++-- src/server/util/platform/screensaver.h | 26 ++++++++++ src/server/util/platform/screensaver_X11.cpp | 74 ++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 17 deletions(-) create mode 100644 src/server/util/platform/screensaver.h create mode 100644 src/server/util/platform/screensaver_X11.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index af61455..adcaa9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,13 @@ INCLUDE_DIRECTORIES( # ${X11_Xinput_INCLUDE_PATH} ) +IF(X11_Xscreensaver_FOUND) + ADD_DEFINITIONS(-DX11_Xscreensaver_FOUND) +ENDIF() +IF(X11_dpms_FOUND) + ADD_DEFINITIONS(-DX11_dpms_FOUND) +ENDIF() + #IF(NOT X11_XTest_FOUND) # MESSAGE(FATAL_ERROR "Could not find X11 extension XTest or its developer files.") #ENDIF() @@ -48,6 +55,7 @@ SET(SYSDEP_SUFFIX _X11) FILE(GLOB PVSMGR_SRCS src/server/*.cpp src/server/*/*.cpp + src/server/util/platform/*${SYSDEP_SUFFIX}.cpp src/shared/*.cpp ) @@ -163,7 +171,8 @@ ADD_EXECUTABLE(pvsclient TARGET_LINK_LIBRARIES(pvsmgr ${QT_LIBRARIES} # ${VNC_LIBRARIES} -# ${X11_LIBRARIES} + ${X11_LIBRARIES} + ${X11_Xscreensaver_LIB} ) TARGET_LINK_LIBRARIES(pvsclient diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index 0a77240..a984173 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -35,6 +35,7 @@ #include "../net/filedownloader.h" // Others #include "../../shared/settings.h" +#include "../util/platform/screensaver.h" // Auto-generated ui class #include "ui_mainwindow.h" #include "ui_reloadroom.h" @@ -62,7 +63,8 @@ using std::endl; * @param parent */ MainWindow::MainWindow(QWidget* parent) : - QMainWindow(parent), ui(new Ui::MainWindow), _tbIconSize(24), _tbArea(Qt::LeftToolBarArea) + QMainWindow(parent), ui(new Ui::MainWindow), _tbIconSize(24), _tbArea(Qt::LeftToolBarArea), + _lastClientCount(0) { qDebug() << "MainWindow(parent)"; _mode = Mode::Multicast; @@ -108,7 +110,7 @@ MainWindow::MainWindow(QWidget* parent) : ui->toolBar->insertWidget(ui->action_TutorToStudent, _examModeLabel); serverApp->setExam(false); - updateExamMode(); + clientCountChanged(); // Close button in tool bar connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(onButtonExit())); @@ -181,22 +183,22 @@ MainWindow::MainWindow(QWidget* parent) : /** this function determines if the number of clients in exam mode comprise * more than 50%. In that case the whole manager switches to exam mode, * disabling many features in the toolbar **/ -void MainWindow::updateExamMode() +void MainWindow::clientCountChanged() { - int numerator = 0; - int denominator = 0; + int examClientCount = 0; + int clientCount = 0; for (auto it = _clientFrames.begin(); it != _clientFrames.end(); ++it) { Client* c = (*it)->client(); if (c != NULL) { bool b = c->isExamMode(); - numerator += b ? 1 : 0; - denominator++; + examClientCount += b ? 1 : 0; + clientCount++; } } - serverApp->setExam(numerator * 2 >= denominator && denominator > 0); + serverApp->setExam(examClientCount * 2 >= clientCount && clientCount > 0); bool e = serverApp->isExam(); qDebug() << "isExam is " << e; ui->action_TutorToAll->setVisible(!e); @@ -207,8 +209,15 @@ void MainWindow::updateExamMode() _examModeLabel->setVisible(e); _examModeLabel->setFixedHeight(e ? 400 : 0); - - + if (_lastClientCount != clientCount) { + if (clientCount == 0) { + ScreenSaver::allowSaverAndStandby(true); + } else { + ScreenSaver::forceUnlockAndScreenOn(); + ScreenSaver::allowSaverAndStandby(false); + } + _lastClientCount = clientCount; + } } MainWindow::~MainWindow() @@ -1149,7 +1158,7 @@ void MainWindow::onClientAuthenticated(Client* client) // qDebug() << "Should go into this if clause."; existing->assignClient(client); tellClientCurrentSituation(client); - updateExamMode(); + clientCountChanged(); return; } @@ -1160,7 +1169,7 @@ void MainWindow::onClientAuthenticated(Client* client) //resizeEvent(NULL); // This is where all the positioning should be tellClientCurrentSituation(client); - updateExamMode(); + clientCountChanged(); } @@ -1294,7 +1303,7 @@ void MainWindow::onDeleteClient() frame->deleteLater(); _clientFrames.removeOne(frame); lockContextButtons(); - updateExamMode(); + clientCountChanged(); return; } } diff --git a/src/server/mainwindow/mainwindow.h b/src/server/mainwindow/mainwindow.h index 988ac50..27bf264 100644 --- a/src/server/mainwindow/mainwindow.h +++ b/src/server/mainwindow/mainwindow.h @@ -76,6 +76,8 @@ private: ListenServer *_listenServer; DiscoveryListener *_discoveryListener; + int _lastClientCount; + QPoint closestFreeSlot(QPoint preferredPixels, ConnectionFrame* toIgnore); void placeFrameInFreeSlot(ConnectionFrame* frame, QPoint preferred = QPoint(-1, -1)); ConnectionFrame* createFrame(); @@ -101,6 +103,10 @@ private: void reloadCurrentRoom(); + void DisableButtons(); + void EnableButtons(); + void clientCountChanged(); + protected slots: void onSessionNameClick(); void onSessionNameUpdate(); @@ -121,8 +127,6 @@ protected slots: void onButtonExit(); void onButtonHelp(); - void DisableButtons(); - void EnableButtons(); // connection frame void onPlaceFrame(ConnectionFrame* frame); void onFrameClicked(ConnectionFrame* frame); @@ -133,6 +137,5 @@ protected slots: void onVncServerStateChange(Client* client); void onVncClientStateChange(Client* client); - void updateExamMode(); }; #endif diff --git a/src/server/util/platform/screensaver.h b/src/server/util/platform/screensaver.h new file mode 100644 index 0000000..d62f9e1 --- /dev/null +++ b/src/server/util/platform/screensaver.h @@ -0,0 +1,26 @@ +#ifndef SCREENSAVER_H_ +#define SCREENSAVER_H_ + +namespace ScreenSaver { + + /** + * Whether we want to allow the screen saver + * to activate or the screen to enter standby. + * Note: If the screen is already in standby, + * this will not power it on again, or disable + * the screen saver, so to be safe, you might + * want to call forceOn() too. + * @param allow true to allow ss/standby + */ + void allowSaverAndStandby(bool allow); + + /** + * Disable the screen saver (only if password + * locking is disabled!), power screen on if + * it's in standby. + */ + void forceUnlockAndScreenOn(); + +} + +#endif /* SCREENSAVER_H_ */ diff --git a/src/server/util/platform/screensaver_X11.cpp b/src/server/util/platform/screensaver_X11.cpp new file mode 100644 index 0000000..efffba9 --- /dev/null +++ b/src/server/util/platform/screensaver_X11.cpp @@ -0,0 +1,74 @@ +#include "screensaver.h" + +#include +#include +#include +#include + +#ifdef X11_Xscreensaver_FOUND +# include +#endif +#ifdef X11_dpms_FOUND +#include +#endif + +namespace { + + Display *display = NULL; + bool extensionSupported = false; + bool dpmsSupported = false; + + bool init() + { + if (display != NULL) { + return true; + } + display = QX11Info::display(); + if (display == NULL) { + return false; + } +#ifdef X11_Xscreensaver_FOUND + int dummy; + extensionSupported = (XScreenSaverQueryExtension(display, &dummy, &dummy) == True); +#endif +#ifdef X11_dpms_FOUND + dpmsSupported = (DPMSCapable(display) == True); +#endif + return true; + } + +} + +namespace ScreenSaver { + + void allowSaverAndStandby(bool allow) + { + if (!init()) + return; +#ifdef X11_Xscreensaver_FOUND + if (extensionSupported) { + XScreenSaverSuspend(display, allow ? False : True); + return; + } +#endif + // TODO: Maybe try some fallback, call xset, or trigger some event periodically + } + + void forceUnlockAndScreenOn() + { + if (!init()) + return; + QProcess process; + process.start("xscreensaver-command", QStringList() << "-deactivate"); + process.waitForFinished(100); +#ifdef X11_dpms_FOUND + CARD16 power_level; + BOOL state; + if (DPMSInfo(display, &power_level, &state) && state) { + DPMSForceLevel(display, DPMSModeOn); + return; + } +#endif + } + +} -- cgit v1.2.3-55-g7522