1 //===========================================
2 //  Lumina-DE source code
3 //  Copyright (c) 2015, Ken Moore
4 //  Available under the 3-clause BSD license
5 //  See the LICENSE file for full details
6 //===========================================
7 #include "LScreenSaver.h"
8 #include <QScreen>
9 #include <QApplication>
10 
11 #define DEBUG 0
12 
LScreenSaver()13 LScreenSaver::LScreenSaver() : QWidget(0,Qt::BypassWindowManagerHint | Qt::WindowStaysOnTopHint){
14   starttimer = new QTimer(this);
15     starttimer->setSingleShot(true);
16   locktimer = new QTimer(this);
17     locktimer->setSingleShot(true);
18   hidetimer = new QTimer(this);
19     hidetimer->setSingleShot(true);
20   mouseCheckTimer = new QTimer(this);
21     mouseCheckTimer->setInterval(10000); //10 seconds - fallback timer for mouse movement detection
22 
23   LOCKER = new LLockScreen(this);
24 	LOCKER->hide();
25   SSRunning = SSLocked = updating = false;
26   this->setObjectName("LSCREENSAVERBASE");
27   this->setStyleSheet("LScreenSaver#LSCREENSAVERBASE{ background: grey; }");
28   this->setMouseTracking(true);
29   connect(starttimer, SIGNAL(timeout()), this, SLOT(ShowScreenSaver()) );
30   connect(locktimer, SIGNAL(timeout()), this, SLOT(LockScreen()) );
31   connect(hidetimer, SIGNAL(timeout()), this, SLOT(HideLockScreen()) );
32   connect(mouseCheckTimer, SIGNAL(timeout()), this, SLOT(checkMousePosition()) );
33   connect(LOCKER, SIGNAL(ScreenUnlocked()), this, SLOT(SSFinished()) );
34   connect(LOCKER, SIGNAL(InputDetected()), this, SLOT(newInputEvent()) );
35 }
36 
~LScreenSaver()37 LScreenSaver::~LScreenSaver(){
38 
39 }
40 
isLocked()41 bool LScreenSaver::isLocked(){
42   return SSLocked;
43 }
44 
UpdateTimers()45 void LScreenSaver::UpdateTimers(){
46   //This is generally used for programmatic changes
47   if(starttimer->isActive()){ starttimer->stop();}
48   if(locktimer->isActive()){ locktimer->stop(); }
49   if(hidetimer->isActive()){ hidetimer->stop(); }
50 
51   if(!SSRunning && !SSLocked && (starttimer->interval() > 1000) ){ starttimer->start(); }  //time to SS start
52   else if( SSRunning && !SSLocked && (locktimer->interval() > 1000 ) ){ locktimer->start(); } //time to lock
53   else if( !SSRunning && SSLocked ){ hidetimer->start(); } //time to hide lock screen
54 }
55 
56 // ===========
57 //  PUBLIC SLOTS
58 // ===========
start()59 void LScreenSaver::start(){
60   reloadSettings(); //setup all the initial time frames
61   starttimer->start();
62   mouseCheckTimer->start();
63 }
64 
reloadSettings()65 void LScreenSaver::reloadSettings(){
66   starttimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "timedelaymin",10).toInt() * 60000 );
67   locktimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "lockdelaymin",1).toInt() * 60000 );
68   hidetimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "hidesecs",15).toInt() * 1000 );
69 }
70 
newInputEvent()71 void LScreenSaver::newInputEvent(){
72   if(updating){ return; } //in the middle of making changes which could cause an event
73   if(DEBUG){ qDebug() << "New Input Event"; }
74   if(SSRunning && SSLocked){
75     //Running and locked
76     // Hide the running setting, and display the lock screen
77     HideScreenSaver();
78     ShowLockScreen();
79   }else if(SSRunning){
80     //Only running, not locked
81     HideScreenSaver();
82   }
83   lastMousePos = QCursor::pos(); //update the internal point
84   UpdateTimers();
85 }
86 
LockScreenNow()87 void LScreenSaver::LockScreenNow(){
88   ShowScreenSaver();
89   LockScreen();
90 }
91 
92 // ===========
93 //  PRIVATE SLOTS
94 // ===========
checkMousePosition()95 void LScreenSaver::checkMousePosition(){
96   QPoint pos = QCursor::pos();
97   if(pos != lastMousePos){
98     newInputEvent(); //this will update the internal position automatically
99   }
100 }
101 
ShowScreenSaver()102 void LScreenSaver::ShowScreenSaver(){
103   if(DEBUG){ qDebug() << "Showing Screen Saver:" << QDateTime::currentDateTime().toString(); }
104   //QApplication::setOverrideCursor(QCursor::BlankCursor);
105   SSRunning = true;
106   updating = true;
107   //Now remove any current Base widgets (prevent any lingering painting between sessions)
108   for(int i=0; i<BASES.length(); i++){
109     if(DEBUG){ qDebug() << " - Removing SS Base"; }
110     delete BASES.takeAt(i); i--;
111   }
112   //Now go through and create/show all the various widgets
113   QList<QScreen*> SCREENS = QApplication::screens();
114   QRect bounds;
115   //cBright = LOS::ScreenBrightness();
116   //if(cBright>0){ LOS::setScreenBrightness(cBright/2); } //cut to half while the screensaver is active
117   for(int i=0; i<SCREENS.length(); i++){
118     bounds = bounds.united(SCREENS[i]->geometry());
119     if(DEBUG){ qDebug() << " - New SS Base:" << i; }
120     BASES << new SSBaseWidget(this);
121     connect(BASES[i], SIGNAL(InputDetected()), this, SLOT(newInputEvent()) );
122 
123     //Setup the geometry of the base to match the screen
124     BASES[i]->setGeometry(SCREENS[i]->geometry());  //match this screen geometry
125     QString plug = DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "plugin_"+SCREENS[i]->name(), "").toString();
126     if(plug.isEmpty()){ plug = DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "default_plugin","random").toString();  }
127     BASES[i]->setPlugin(plug);
128   }
129   //Now set the overall parent widget geometry and show everything
130   this->setGeometry(bounds); //overall background widget
131   if(!this->isActiveWindow()){
132     this->raise();
133     this->show();
134     this->activateWindow();
135   }
136   for(int i=0; i<BASES.length(); i++){
137     BASES[i]->show();
138     BASES[i]->startPainting();
139   }
140   updating = false;
141   UpdateTimers();
142 }
143 
ShowLockScreen()144 void LScreenSaver::ShowLockScreen(){
145   if(DEBUG){ qDebug() << "Showing Lock Screen:" << QDateTime::currentDateTime().toString(); }
146   LOCKER->aboutToShow();
147   //Move the screen locker to the appropriate spot
148   QPoint ctr = QApplication::desktop()->screenGeometry(QCursor::pos()).center();
149   LOCKER->resize(LOCKER->sizeHint());
150   LOCKER->move(ctr - QPoint(LOCKER->width()/2, LOCKER->height()/2) );
151   LOCKER->show();
152   //Start the timer for hiding the lock screen due to inactivity
153   UpdateTimers();
154 }
155 
HideScreenSaver()156 void LScreenSaver::HideScreenSaver(){
157   //QApplication::restoreOverrideCursor();
158   if(DEBUG){ qDebug() << "Hiding Screen Saver:" << QDateTime::currentDateTime().toString(); }
159   SSRunning = false;
160   //if(cBright>0){ LOS::setScreenBrightness(cBright); } //return to current brightness
161   if(!SSLocked){
162     this->hide();
163     emit ClosingScreenSaver();
164     emit LockStatusChanged(false);
165   }
166   if(DEBUG){ qDebug() << "Stop ScreenSavers"; }
167   for(int i=0; i<BASES.length(); i++){
168     BASES[i]->stopPainting();
169     BASES[i]->hide();
170 	BASES.takeAt(i)->deleteLater();
171 	i--;
172   }
173   UpdateTimers();
174 }
175 
HideLockScreen()176 void LScreenSaver::HideLockScreen(){
177   if(DEBUG){ qDebug() << "Hiding Lock Screen:" << QDateTime::currentDateTime().toString(); }
178   //Leave the Locked flag set (still locked, just not visible)
179   LOCKER->aboutToHide();
180   LOCKER->hide();
181   this->repaint();
182   if(SSLocked){ ShowScreenSaver(); }
183   UpdateTimers();
184 }
185 
LockScreen()186 void LScreenSaver::LockScreen(){
187   if(SSLocked){ return; }
188   if(DEBUG){ qDebug() << "Locking Screen:" << QDateTime::currentDateTime().toString(); }
189   SSLocked = true;
190   emit LockStatusChanged(true);
191   LOCKER->LoadSystemDetails();
192   UpdateTimers();
193 }
194 
SSFinished()195 void LScreenSaver::SSFinished(){
196   if(DEBUG){ qDebug() << "Screensaver Finished:" << QDateTime::currentDateTime().toString(); }
197   SSLocked = false;
198   emit LockStatusChanged(false);
199   HideLockScreen();
200   HideScreenSaver();
201 }
202