aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md19
-rw-r--r--src-qt5/OS-detect.pri9
-rw-r--r--src-qt5/core-utils/lumina-xconfig/MainUI.cpp2
-rw-r--r--src-qt5/core/core.pro5
-rw-r--r--src-qt5/core/libLumina/LuminaX11.cpp18
-rw-r--r--src-qt5/core/libLumina/LuminaX11.h5
-rw-r--r--src-qt5/core/libLumina/LuminaX11.pri2
-rw-r--r--src-qt5/core/lumina-checkpass/main.c22
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.h2
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.cpp27
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.h5
-rw-r--r--src-qt5/core/lumina-desktop/Globals.h30
-rw-r--r--src-qt5/core/lumina-desktop/LDesktop.cpp3
-rw-r--r--src-qt5/core/lumina-desktop/LSession.cpp24
-rw-r--r--src-qt5/core/lumina-desktop/LSession.h4
-rw-r--r--src-qt5/core/lumina-desktop/LWinInfo.cpp11
-rw-r--r--src-qt5/core/lumina-desktop/SystemWindow.cpp6
-rw-r--r--src-qt5/core/lumina-desktop/defaults/compton.conf3
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/Lumina-DE.pngbin0 -> 2847 bytes
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/Fireflies.json26
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/Grav.json26
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/Matrix.json26
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/README.md79
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/Video.json26
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/Warp.json25
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Fireflies.qml19
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Firefly.qml63
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Grav.qml132
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Matrix.qml71
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Video.qml48
-rw-r--r--src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Warp.qml64
-rw-r--r--src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys1
-rw-r--r--src-qt5/core/lumina-desktop/global-includes.h85
-rw-r--r--src-qt5/core/lumina-desktop/lumina-desktop.pro23
-rw-r--r--src-qt5/core/lumina-desktop/main.cpp4
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/systemdashboard/SysMenuQuick.cpp17
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp3
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp15
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h2
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/userbutton/LUserButton.cpp2
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp32
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp16
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h7
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.cpp112
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.h42
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.ui144
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.cpp231
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.h63
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.cpp64
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.h50
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.cpp51
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.h40
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/Fireflies.h122
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/Grav.h195
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/ImageSlideshow.h165
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/SampleAnimation.h45
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/Text.h100
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/VideoSlideshow.h85
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/animations/animations.pri10
-rw-r--r--src-qt5/core/lumina-desktop/src-screensaver/screensaver.pri15
-rw-r--r--src-qt5/core/lumina-pingcursor/lumina-pingcursor.pro14
-rw-r--r--src-qt5/core/lumina-pingcursor/main.cpp44
-rw-r--r--src-qt5/core/lumina-session/session.cpp14
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp4
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp6
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h1
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h107
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax2
-rw-r--r--src-qt5/src-cpp/plugins-screensaver.cpp1
69 files changed, 2554 insertions, 182 deletions
diff --git a/README.md b/README.md
index 638664ca..0e01c62c 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ https://lumina-desktop.org/
**Lumina Project Info: Table of Contents**
- [Description](#description)
+- [Operating Systems and Distributions](#osdistros)
- [Latest Versions](#latestversions)
- [Translations](#translations)
- [How to file bug reports or feature requests](#filebugs)
@@ -23,10 +24,26 @@ Description <a name="description"></a>
The Lumina Desktop Environment is a lightweight system interface that is designed for use on any Unix-like operating system. It takes a plugin-based approach, allowing the entire interface to be assembled/arranged by each individual user as desired, with a system-wide default layout which can be setup by the system administrator. This allows every system (or user session) to be designed to maximize the individual user's productivity.
+
+Operating Systems and Distributions <a name="osdistros"></a>
+----
Supported operating systems include (but are not limited to):
* BSD: TrueOS, FreeBSD, OpenBSD, NetBSD, DragonflyBSD, GNU/kFreeBSD
- * Linux: Gentoo, Debian, "Generic" Linux (including Arch, Ubuntu, and more)
+ * Linux: Void, Gentoo, Debian, "Generic" Linux (including Arch, Ubuntu, and more)
+
+Known OS distributions that provide the Lumina desktop out-of-box:
+
+ * [Project Trident (Void Linux)](https://project-trident.org)
+
+Some operating systems package the Lumina desktop under the name `lumina` and some use `lumina-desktop`.
+
+Operating system repos with a `lumina` package
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/lumina.svg)](https://repology.org/project/lumina/versions)
+
+Operating system repos with a `lumina-desktop` package
+[![Packaging status](https://repology.org/badge/vertical-allrepos/lumina-desktop.svg)](https://repology.org/project/lumina-desktop/versions)
Latest Versions <a name="latestversions"></a>
----
diff --git a/src-qt5/OS-detect.pri b/src-qt5/OS-detect.pri
index 2214016d..b61a137e 100644
--- a/src-qt5/OS-detect.pri
+++ b/src-qt5/OS-detect.pri
@@ -30,8 +30,7 @@ isEmpty(OS){
QMAKE_LIBDIR = $${PWD}/core/libLumina $$[QT_INSTALL_LIBS] $$LIBPREFIX/qt5 $$LIBPREFIX
#Setup the default values for build settings (if not explicitly set previously)
- isEmpty(PREFIX){ PREFIX=/usr/local }
- isEmpty(LIBPREFIX){ LIBPREFIX=$${PREFIX}/lib }
+
#message("General Settings: PREFIX=$${PREFIX}, LIBPREFIX=$${LIBPREFIX}")
#Now go through and setup any known OS build settings
# which are different from the defaults
@@ -41,21 +40,25 @@ isEmpty(OS){
LIBS += -L/usr/local/lib -L/usr/lib
}else : freebsd-*{
+ isEmpty(PREFIX){ PREFIX=/usr/local }
OS = FreeBSD
LIBS += -L/usr/local/lib -L/usr/lib
#Use the defaults for everything else
}else : openbsd-*{
+ isEmpty(PREFIX){ PREFIX=/usr/local }
OS = OpenBSD
LIBS += -L/usr/local/lib -L/usr/lib
#Use the defaults for everything else
}else : netbsd-*{
+ isEmpty(PREFIX){ PREFIX=/usr/local }
OS = NetBSD
LIBS += -L/usr/local/lib -L/usr/lib
#Use the defaults for everything else
}else : linux-*{
+ isEmpty(PREFIX){ PREFIX=/usr }
L_SESSDIR=/usr/share/xsessions
OS=Linux
LIBS += -L/usr/local/lib -L/usr/lib -L/lib
@@ -87,6 +90,7 @@ isEmpty(OS){
isEmpty(L_MANDIR){ L_MANDIR = $${PREFIX}/share/man }
}
}else{
+ isEmpty(PREFIX){ PREFIX=/usr/local }
OS="Unknown";
}
@@ -96,6 +100,7 @@ isEmpty(OS){
# Setup the dirs needed to find/load libraries
INCLUDEPATH +=$${PREFIX}/include
+ isEmpty(LIBPREFIX){ LIBPREFIX=$${PREFIX}/lib }
# If the detailed install variables are not set - create them from the general vars
isEmpty(L_BINDIR){ L_BINDIR = $${PREFIX}/bin }
diff --git a/src-qt5/core-utils/lumina-xconfig/MainUI.cpp b/src-qt5/core-utils/lumina-xconfig/MainUI.cpp
index 9abc30b2..98a8be0a 100644
--- a/src-qt5/core-utils/lumina-xconfig/MainUI.cpp
+++ b/src-qt5/core-utils/lumina-xconfig/MainUI.cpp
@@ -414,7 +414,7 @@ void MainUI::SaveSettings(bool quiet){
}
void MainUI::RestartFluxbox(){
- QProcess::startDetached("killall fluxbox");
+ QProcess::startDetached("pkill fluxbox");
}
void MainUI::removeProfile(){
diff --git a/src-qt5/core/core.pro b/src-qt5/core/core.pro
index 1ae58167..452d2fb7 100644
--- a/src-qt5/core/core.pro
+++ b/src-qt5/core/core.pro
@@ -8,9 +8,10 @@ SUBDIRS+= lumina-desktop \
lumina-session \
lumina-open \
lumina-info \
+ lumina-pingcursor \
$${PWD}/../../icon-theme \
- lumina-theme-engine
-# lumina-checkpass
+ lumina-theme-engine \
+ lumina-checkpass
# lumina-desktop-unified
#Also install any special menu scripts
diff --git a/src-qt5/core/libLumina/LuminaX11.cpp b/src-qt5/core/libLumina/LuminaX11.cpp
index 1df5a9f0..6a71f629 100644
--- a/src-qt5/core/libLumina/LuminaX11.cpp
+++ b/src-qt5/core/libLumina/LuminaX11.cpp
@@ -27,6 +27,7 @@
#include <xcb/xcb_aux.h>
#include <xcb/composite.h>
#include <xcb/damage.h>
+#include <xcb/dpms.h>
//XLib includes
#include <X11/extensions/Xdamage.h>
@@ -184,6 +185,17 @@ void LXCB::SetCurrentWorkspace(int number){
xcb_ewmh_request_change_showing_desktop(&EWMH, QX11Info::appScreen(), number);
}
+//Display Power Management System (DPMS)
+// ===== enableDPMS() =====
+void LXCB::enableDPMS(){
+ xcb_dpms_enable(QX11Info::connection());
+}
+
+// ===== disableDPMS() =====
+void LXCB::disableDPMS(){
+ xcb_dpms_disable(QX11Info::connection());
+}
+
// === WindowClass() ===
QString LXCB::WindowClass(WId win){
if(DEBUG){ qDebug() << "XCB: WindowClass()" << win; }
@@ -462,12 +474,12 @@ int LXCB::WindowIsFullscreen(WId win){
int i = 0;
for(it = screens.constBegin(); it != screens.constEnd(); ++it, ++i) {
QRect sgeom = (*it)->availableGeometry();
- qDebug() << " -- Check Window Geom:" << sgeom << geom << this->WindowClass(win);
+ //qDebug() << " -- Check Window Geom:" << sgeom << geom << this->WindowClass(win);
if( sgeom.contains(geom.center()) ){
//Allow a 1 pixel variation in "full-screen" detection
- qDebug() << " -- Found Screen:" << i;
+ //qDebug() << " -- Found Screen:" << i;
if( geom.width() >= (sgeom.width()-1) && geom.height()>=(sgeom.height()-1) ){
- qDebug() << " -- Is Fullscreen!";
+ //qDebug() << " -- Is Fullscreen!";
//fullS = true;
fscreen = i;
}
diff --git a/src-qt5/core/libLumina/LuminaX11.h b/src-qt5/core/libLumina/LuminaX11.h
index 453d3443..a2c0c58a 100644
--- a/src-qt5/core/libLumina/LuminaX11.h
+++ b/src-qt5/core/libLumina/LuminaX11.h
@@ -90,7 +90,7 @@ public:
//XCB Library replacement for LX11 (Qt5 uses XCB instead of XLib)
class LXCB{
-
+
public:
enum WINDOWVISIBILITY {IGNORE, INVISIBLE, VISIBLE, ACTIVE, ATTENTION}; //note that this in order of priority
enum ICCCM_STATE {WITHDRAWN, NORMAL, ICONIC};
@@ -123,6 +123,9 @@ public:
bool CheckDisableXinerama(); //returns true if Xinerama was initially set but now disabled
void RegisterVirtualRoots(QList<WId> roots);
void SetCurrentWorkspace(int);
+ //Display Power Management System (DPMS)
+ void enableDPMS();
+ void disableDPMS();
//Window Information
QString WindowClass(WId);
diff --git a/src-qt5/core/libLumina/LuminaX11.pri b/src-qt5/core/libLumina/LuminaX11.pri
index 0e472dd4..e22b83ad 100644
--- a/src-qt5/core/libLumina/LuminaX11.pri
+++ b/src-qt5/core/libLumina/LuminaX11.pri
@@ -1,7 +1,7 @@
QT *= x11extras
-LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lXdamage
+LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lxcb-dpms -lXdamage
#LUtils Files
SOURCES *= $${PWD}/LuminaX11.cpp
diff --git a/src-qt5/core/lumina-checkpass/main.c b/src-qt5/core/lumina-checkpass/main.c
index 70caf396..f7d55c7d 100644
--- a/src-qt5/core/lumina-checkpass/main.c
+++ b/src-qt5/core/lumina-checkpass/main.c
@@ -22,7 +22,18 @@
//PAM/security libraries
#include <sys/types.h>
#include <security/pam_appl.h>
-#include <security/openpam.h>
+
+//Found this little snippet from SDDM - nice alternative to using the entire openpam library from FreeBSD
+static int PAM_conv(
+ int num_msg,
+ const struct pam_message **msg,
+ struct pam_response **resp,
+ void *ctx)
+{
+ return 0;
+}
+//-----
+
void showUsage(){
puts("lumina-checkpass: Simple user-level check for password validity (for screen unlockers and such).");
@@ -74,12 +85,17 @@ int main(int argc, char** argv){
if( getuid() != pwd->pw_uid ){ return 1; } //Current UID does not match currently logged-in user UID
//Create the non-interactive PAM structures
pam_handle_t *pamh;
- struct pam_conv pamc = { openpam_nullconv, NULL };
+ struct pam_conv pamc = { &PAM_conv, 0 };
//Place the user-supplied password into the structure
+#ifdef __linux__
int ret = pam_start( "system", cUser, &pamc, &pamh);
- if(ret != PAM_SUCCESS){ return 1; } //could not init PAM
+#else
+ int ret = pam_start( "system-auth", cUser, &pamc, &pamh);
+#endif
+ if(ret != PAM_SUCCESS){ puts("Could not initialize PAM"); return 1; } //could not init PAM
//char* cPassword = argv[1];
ret = pam_set_item(pamh, PAM_AUTHTOK, pass);
+ if(ret != PAM_SUCCESS){ puts("Could not set conversation structure"); }
//Authenticate with PAM
ret = pam_authenticate(pamh,0); //this can be true without verifying password if pam_self.so is used in the auth procedures (common)
if( ret == PAM_SUCCESS ){ ret = pam_acct_mgmt(pamh,0); } //Check for valid, unexpired account and verify access restrictions
diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.h b/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.h
index 5470128a..147b0db8 100644
--- a/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.h
+++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.h
@@ -7,7 +7,7 @@
#ifndef _LUMINA_DESKTOP_LOCK_SCREEN_WIDGET_H
#define _LUMINA_DESKTOP_LOCK_SCREEN_WIDGET_H
-#include "global-includes.h"
+#include "globals.h"
namespace Ui{
class LLockScreen;
diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.cpp b/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.cpp
index bd812744..cffde639 100644
--- a/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.cpp
@@ -17,8 +17,10 @@ LScreenSaver::LScreenSaver() : QWidget(0,Qt::BypassWindowManagerHint | Qt::Windo
locktimer->setSingleShot(true);
hidetimer = new QTimer(this);
hidetimer->setSingleShot(true);
- mouseCheckTimer = new QTimer(this);
- mouseCheckTimer->setInterval(10000); //10 seconds - fallback timer for mouse movement detection
+ checkTimer = new QTimer(this);
+ checkTimer->setInterval(1500); //1.5 seconds
+
+ lastTimeCode = 0;
LOCKER = new LLockScreen(this);
LOCKER->hide();
@@ -29,7 +31,7 @@ LScreenSaver::LScreenSaver() : QWidget(0,Qt::BypassWindowManagerHint | Qt::Windo
connect(starttimer, SIGNAL(timeout()), this, SLOT(ShowScreenSaver()) );
connect(locktimer, SIGNAL(timeout()), this, SLOT(LockScreen()) );
connect(hidetimer, SIGNAL(timeout()), this, SLOT(HideLockScreen()) );
- connect(mouseCheckTimer, SIGNAL(timeout()), this, SLOT(checkMousePosition()) );
+ connect(checkTimer, SIGNAL(timeout()), this, SLOT(checkInputEvents()) );
connect(LOCKER, SIGNAL(ScreenUnlocked()), this, SLOT(SSFinished()) );
connect(LOCKER, SIGNAL(InputDetected()), this, SLOT(newInputEvent()) );
}
@@ -59,7 +61,7 @@ void LScreenSaver::UpdateTimers(){
void LScreenSaver::start(){
reloadSettings(); //setup all the initial time frames
starttimer->start();
- mouseCheckTimer->start();
+ checkTimer->start();
}
void LScreenSaver::reloadSettings(){
@@ -80,7 +82,6 @@ void LScreenSaver::newInputEvent(){
//Only running, not locked
HideScreenSaver();
}
- lastMousePos = QCursor::pos(); //update the internal point
UpdateTimers();
}
@@ -92,11 +93,23 @@ void LScreenSaver::LockScreenNow(){
// ===========
// PRIVATE SLOTS
// ===========
-void LScreenSaver::checkMousePosition(){
+void LScreenSaver::checkInputEvents(){
+ //Check mouse position first
QPoint pos = QCursor::pos();
+ bool change = false;
if(pos != lastMousePos){
- newInputEvent(); //this will update the internal position automatically
+ lastMousePos = QCursor::pos(); //update the internal point
+ change = true;
+ }
+ //Check the last keyboard input timestamp
+ unsigned int timecode = LSession::instance()->XCB->WM_Get_User_Time( LSession::instance()->XCB->WM_Get_Active_Window() );
+ //unsigned int timecode = 0; //Not done yet - read the _NET_WM_USER_TIME number on the active window
+ if(timecode > lastTimeCode){
+ lastTimeCode = timecode;
+ change = true;
}
+ //If there was an input event detected, update timers and such
+ if(change){ newInputEvent(); }
}
void LScreenSaver::ShowScreenSaver(){
diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.h b/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.h
index eec42481..71121e4e 100644
--- a/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.h
+++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/LScreenSaver.h
@@ -21,10 +21,11 @@ public:
bool isLocked();
private:
- QTimer *starttimer, *locktimer, *hidetimer, *mouseCheckTimer;
+ QTimer *starttimer, *locktimer, *hidetimer, *CheckTimer;
QList<SSBaseWidget*> BASES;
LLockScreen *LOCKER;
QPoint lastMousePos;
+ unsigned int lastTimeCode;
int cBright;
bool SSRunning, SSLocked, updating;
@@ -37,7 +38,7 @@ public slots:
void LockScreenNow();
private slots:
- void checkMousePosition();
+ void checkInputEvents();
void ShowScreenSaver();
void ShowLockScreen();
void HideScreenSaver();
diff --git a/src-qt5/core/lumina-desktop/Globals.h b/src-qt5/core/lumina-desktop/Globals.h
index f7821466..3da9b3ae 100644
--- a/src-qt5/core/lumina-desktop/Globals.h
+++ b/src-qt5/core/lumina-desktop/Globals.h
@@ -45,37 +45,7 @@ public:
}
return QString::fromLocal8Bit(name,count);
}
- /*//Shutdown the system
-#ifdef __linux
- static void shutdown(){ system("(shutdown -h now) &"); }
-#else // #ifdef __linux
- static void shutdown(){ system("(shutdown -p now) &"); }
-#endif // #ifdef __linux
- //Restart the system
- static void restart(){ system("(shutdown -r now) &"); }
- //Determine if there is battery support
- static bool hasBattery(){
- int val = LUtils::getCmdOutput("apm -l").join("").toInt();
- return (val >= 0 && val <= 100);
- }
-
- //Get the current battery charge percentage
- static int batteryCharge(){
- int charge = LUtils::getCmdOutput("apm -l").join("").toInt();
- if(charge > 100){ charge = -1; } //invalid charge
- return charge;
- }
-
- //Get the current battery charge percentage
- static bool batteryIsCharging(){
- return (LUtils::getCmdOutput("apm -a").join("").simplified() == "1");
- }
-
- //Get the amount of time remaining for the battery
- static int batterySecondsLeft(){
- return LUtils::getCmdOutput("apm -t").join("").toInt();
- }*/
};
#endif
diff --git a/src-qt5/core/lumina-desktop/LDesktop.cpp b/src-qt5/core/lumina-desktop/LDesktop.cpp
index 6ca48a28..9d77af61 100644
--- a/src-qt5/core/lumina-desktop/LDesktop.cpp
+++ b/src-qt5/core/lumina-desktop/LDesktop.cpp
@@ -109,7 +109,8 @@ void LDesktop::UpdateGeometry(){
}
void LDesktop::SystemLock(){
- QProcess::startDetached("xscreensaver-command -lock");
+ QTimer::singleShot(30,LSession::handle(), SLOT(LockScreen()) );
+ //QProcess::startDetached("xscreensaver-command -lock");
}
void LDesktop::SystemLogout(){
diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp
index a49bbc96..996b3acf 100644
--- a/src-qt5/core/lumina-desktop/LSession.cpp
+++ b/src-qt5/core/lumina-desktop/LSession.cpp
@@ -21,10 +21,7 @@
#include <LIconCache.h>
#include <unistd.h> //for usleep() usage
-
-#ifndef DEBUG
#define DEBUG 0
-#endif
XCBEventFilter *evFilter = 0;
LIconCache *ICONS = 0;
@@ -67,6 +64,7 @@ LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lu
currTranslator=0;
mediaObj=0;
sessionsettings=0;
+ ScreenSaver=0;
//Setup the event filter for Qt5
evFilter = new XCBEventFilter(this);
this->installNativeEventFilter( evFilter );
@@ -90,6 +88,7 @@ LSession::~LSession(){
//delete WM;
settingsmenu->deleteLater();
appmenu->deleteLater();
+ if(ScreenSaver!=0){ ScreenSaver->deleteLater(); }
delete currTranslator;
if(mediaObj!=0){delete mediaObj;}
}
@@ -162,8 +161,8 @@ void LSession::setupSession(){
splash.showScreen("init");
qDebug() << "Initializing Session";
if(QFile::exists("/tmp/.luminastopping")){ QFile::remove("/tmp/.luminastopping"); }
- QTime* timer = 0;
- if(DEBUG){ timer = new QTime(); timer->start(); qDebug() << " - Init srand:" << timer->elapsed();}
+ QElapsedTimer* timer = 0;
+ if(DEBUG){ timer = new QElapsedTimer(); timer->start(); qDebug() << " - Init srand:" << timer->elapsed();}
//Setup the QSettings default paths
splash.showScreen("settings");
@@ -238,6 +237,9 @@ void LSession::setupSession(){
connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(watcherChange(QString)) );
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherChange(QString)) );
connect(this, SIGNAL(aboutToQuit()), this, SLOT(SessionEnding()) );
+ if(DEBUG){ qDebug() << " - Start screensaver:" << timer->elapsed(); }
+ ScreenSaver = new LScreenSaver();
+ ScreenSaver->start();
//if(DEBUG){ qDebug() << " - Process Events (4x):" << timer->elapsed();}
//for(int i=0; i<4; i++){ LSession::processEvents(); } //Again, just a few event loops here so thing can settle before we close the splash screen
if(DEBUG){ qDebug() << " - Launch Startup Apps:" << timer->elapsed();}
@@ -339,6 +341,8 @@ void LSession::NewCommunication(QStringList list){
screensChanged();
}else if(list[i]=="--show-start"){
emit StartButtonActivated();
+ }else if(list[i]=="--lock"){
+ QTimer::singleShot(10, ScreenSaver, SLOT(LockScreenNow()) );
}else if(list[i]=="--logout"){ QTimer::singleShot(1000, this, SLOT(StartLogout()));}
}
}
@@ -395,6 +399,10 @@ void LSession::StartReboot(bool skipupdates){
QCoreApplication::exit(0);
}
+void LSession::LockScreen(){
+ QTimer::singleShot(10, ScreenSaver, SLOT(LockScreenNow()) );
+}
+
void LSession::reloadIconTheme(){
//Wait a moment for things to settle before sending out the signal to the interfaces
QApplication::processEvents();
@@ -561,7 +569,7 @@ void LSession::updateDesktops(){
//Make sure fluxbox also gets prompted to re-load screen config if the number of screens changes in the middle of a session
if(!firstrun && xchange){
qDebug() << "Update WM";
- //QProcess::startDetached("killall fluxbox");
+ //QProcess::startDetached("pkill fluxbox");
xchange = false;
}
@@ -719,6 +727,10 @@ QSettings* LSession::DesktopPluginSettings(){
return DPlugSettings;
}
+LScreenSaver* LSession::screenSaver(){
+ return ScreenSaver;
+}
+
WId LSession::activeWindow(){
//Check the last active window pointer first
WId active = XCB->ActiveWindow();
diff --git a/src-qt5/core/lumina-desktop/LSession.h b/src-qt5/core/lumina-desktop/LSession.h
index ee17660d..0cd9f1d2 100644
--- a/src-qt5/core/lumina-desktop/LSession.h
+++ b/src-qt5/core/lumina-desktop/LSession.h
@@ -30,6 +30,7 @@
#include "LDesktop.h"
//#include "WMProcess.h"
//#include "BootSplash.h"
+#include <LScreenSaver.h>
#include <LuminaX11.h>
#include <LuminaSingleApplication.h>
@@ -97,6 +98,7 @@ public:
QSettings* sessionSettings();
QSettings* DesktopPluginSettings();
+ LScreenSaver* screenSaver();
//Keep track of which non-desktop window should be treated as active
WId activeWindow(); //This will return the last active window if a desktop element is currently active
@@ -125,6 +127,7 @@ private:
QMediaPlayer *mediaObj;
QSettings *sessionsettings, *DPlugSettings;
bool cleansession;
+ LScreenSaver *ScreenSaver;
//QList<QRect> savedScreens;
//System Tray Variables
@@ -151,6 +154,7 @@ public slots:
void StartLogout();
void StartShutdown(bool skipupdates = false);
void StartReboot(bool skipupdates = false);
+ void LockScreen();
void reloadIconTheme();
diff --git a/src-qt5/core/lumina-desktop/LWinInfo.cpp b/src-qt5/core/lumina-desktop/LWinInfo.cpp
index 6a6cea0b..6adde234 100644
--- a/src-qt5/core/lumina-desktop/LWinInfo.cpp
+++ b/src-qt5/core/lumina-desktop/LWinInfo.cpp
@@ -30,15 +30,18 @@ QIcon LWinInfo::icon(bool &noicon){
noicon = false;
QIcon ico = LSession::handle()->XCB->WindowIcon(window);
//Check for a null icon, and supply one if necessary
- if(ico.isNull()){ ico = LXDG::findIcon( this->Class().toLower(),""); }
- if(ico.isNull()){ico = LXDG::findIcon("preferences-system-windows",""); noicon=true;}
+ if(ico.isNull()){
+ QString cls = this->Class();
+ ico = LXDG::findIcon( cls, cls.toLower());
+ }
+ if(ico.isNull()){ico = LXDG::findIcon("window","preferences-system-windows"); noicon=true;}
return ico;
}
-
+
QString LWinInfo::Class(){
return LSession::handle()->XCB->WindowClass(window);
}
-
+
LXCB::WINDOWVISIBILITY LWinInfo::status(bool update){
if(window==0){ return LXCB::IGNORE; }
if(update || cstate == LXCB::IGNORE){
diff --git a/src-qt5/core/lumina-desktop/SystemWindow.cpp b/src-qt5/core/lumina-desktop/SystemWindow.cpp
index bfad961d..6a4172d3 100644
--- a/src-qt5/core/lumina-desktop/SystemWindow.cpp
+++ b/src-qt5/core/lumina-desktop/SystemWindow.cpp
@@ -105,7 +105,8 @@ void SystemWindow::sysSuspend(){
this->hide();
LSession::processEvents();
//Make sure to lock the system first (otherwise anybody can access it again)
- LUtils::runCmd("xscreensaver-command -lock");
+ LSession::handle()->LockScreen();
+ //LUtils::runCmd("xscreensaver-command -lock");
//Now suspend the system
LOS::systemSuspend();
}
@@ -114,5 +115,6 @@ void SystemWindow::sysLock(){
this->hide();
LSession::processEvents();
qDebug() << "Locking the desktop...";
- QProcess::startDetached("xscreensaver-command -lock");
+ QTimer::singleShot(30,LSession::handle(), SLOT(LockScreen()) );
+ //QProcess::startDetached("xscreensaver-command -lock");
}
diff --git a/src-qt5/core/lumina-desktop/defaults/compton.conf b/src-qt5/core/lumina-desktop/defaults/compton.conf
index a14fee29..b5561e51 100644
--- a/src-qt5/core/lumina-desktop/defaults/compton.conf
+++ b/src-qt5/core/lumina-desktop/defaults/compton.conf
@@ -15,7 +15,8 @@ shadow-exclude = [
"class_g = 'Conky'",
"class_g ?= 'Notify-osd'",
"class_g = 'Cairo-clock'",
- "_GTK_FRAME_EXTENTS@:c"
+ "_GTK_FRAME_EXTENTS@:c",
+ "name = 'lumina-pingcursor'"
];
# shadow-exclude = "n:e:Notification";
# shadow-exclude-reg = "x10+0+0";
diff --git a/src-qt5/core/lumina-desktop/extrafiles/Lumina-DE.png b/src-qt5/core/lumina-desktop/extrafiles/Lumina-DE.png
new file mode 100644
index 00000000..ce88a252
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/Lumina-DE.png
Binary files differ
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/Fireflies.json b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Fireflies.json
new file mode 100644
index 00000000..c09de308
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Fireflies.json
@@ -0,0 +1,26 @@
+{
+ "name" : {
+ "default" : "Fireflies"
+ },
+ "description" : {
+ "default" : "Dancing balls of light on the screen"
+ },
+ "author" : {
+ "name" : "Ken Moore",
+ "email" : "ken@ixsystems.com",
+ "website" : "https://github.com/beanpole135",
+ "company" : "iXsystems",
+ "company_website" : "http://ixsystems.com"
+ },
+ "meta" : {
+ "license" : "3-clause BSD",
+ "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE",
+ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)",
+ "date_created" : "20171010",
+ "version" : "1.0"
+ },
+ "qml" : {
+ "exec" : "qml_scripts/Fireflies.qml",
+ "additional_files" : ["qml_scripts/Firefly.qml"]
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/Grav.json b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Grav.json
new file mode 100644
index 00000000..c75ae170
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Grav.json
@@ -0,0 +1,26 @@
+{
+ "disabled" : true,
+ "name" : {
+ "default" : "Grav"
+ },
+ "description" : {
+ "default" : "Simulates a solar system, with a single star and planets erratically orbiting that star"
+ },
+ "author" : {
+ "name" : "Zackary Welch",
+ "email" : "zwelch@ixsystems.com",
+ "website" : "https://github.com/ZackaryWelch",
+ "company" : "iXsystems",
+ "company_website" : "http://ixsystems.com"
+ },
+ "meta" : {
+ "license" : "3-clause BSD",
+ "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE",
+ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)",
+ "date_created" : "20171101",
+ "version" : "1.0"
+ },
+ "qml" : {
+ "exec" : "qml_scripts/Grav.qml"
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/Matrix.json b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Matrix.json
new file mode 100644
index 00000000..8c9a351f
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Matrix.json
@@ -0,0 +1,26 @@
+{
+ "disabled" : true,
+ "name" : {
+ "default" : "Matrix"
+ },
+ "description" : {
+ "default" : "Erratic falling columns of various characters with a set color"
+ },
+ "author" : {
+ "name" : "Zackary Welch",
+ "email" : "zwelch@ixsystems.com",
+ "website" : "https://github.com/ZackaryWelch",
+ "company" : "iXsystems",
+ "company_website" : "http://ixsystems.com"
+ },
+ "meta" : {
+ "license" : "3-clause BSD",
+ "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE",
+ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)",
+ "date_created" : "20180103",
+ "version" : "1.0"
+ },
+ "qml" : {
+ "exec" : "qml_scripts/Matrix.qml"
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/README.md b/src-qt5/core/lumina-desktop/extrafiles/screensavers/README.md
new file mode 100644
index 00000000..d9093b44
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/README.md
@@ -0,0 +1,79 @@
+## Screensaver Format
+The screensaver system for the Lumina desktop allows for the creation and use of scripts written in the QML language, with a number of screensavers and other examples installed out-of-box. There are only a couple warnings/caveats to consider when developing a new screensaver:
+
+1. The root object in your QML script will be automatically sized to fit the screen as needed. Avoid trying to hard-code specific screen dimensions within your script as it will not work properly.
+2. A JSON manifest file must be created (format listed below) and placed into one of the screensaver plugin directories for it to be recognized as a valid screensaver by the desktop.
+
+
+### JSON Manifest
+The manifest file contains all the information needed to actually validate/launch the screensaver, as well as additional information about the author and/or the screensaver itself.
+
+Example JSON manifest file (sample.json):
+```
+{
+ "name" : {
+ "default" : "sample",
+ "en_US" : "US English localization of the name",
+ "en" : "Generic english localization of the name"
+ },
+
+ "description" : {
+ "default" : "sample screensaver",
+ "en_US" : "US English Localization of the description"
+ },
+
+ "author" : {
+ "name" : "Me",
+ "email" : "Me@myself.net",
+ "website" : "http://mywebsite.net",
+ "company" : "iXsystems",
+ "company_website" : "http://ixsystems.com"
+ },
+
+ "meta" : {
+ "license" : "3-clause BSD",
+ "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE",
+ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)",
+ "date_created" : "20171010",
+ "date_updated" : "20171011",
+ "version" : "1.0"
+ },
+
+ "qml" : {
+ "exec" : "absolute/or/relative/path/to/script.qml",
+ "additional_files" : ["file/which/must/exist.png"],
+ "qt_min_version" : "5.0",
+ "qt_max_version" : "6.0"
+ }
+}
+```
+
+Details of the individual items in the manifest:
+* NOTE: for locale codes, both long and short version are acceptable:
+ Example 1: If the current locale is "en_GB", but the JSON manifest lists translations for "en_US" and "en", then the "en" translation will be used.
+ Example 2: If the current locale is "en_GB", but neither "en_GB" nor "en" translations exist, then the "default" version will be used.
+
+* **name** : (required) This is the official name of the screensaver to show to users
+ * *default* : (required) Non-translated name of the screensaver
+ * *[locale]* : (optional) Translated name for specific [locale]
+* **description** : (required) This is a short description of the screensaver to show to users
+ * *default* : (required) Non-translated description of the screensaver
+ * *[locale]* : (optional) Translated description for specific [locale]
+* **author** : (all optional) Additional information about the author(s) of the screensaver
+ * *name* : Name of the author
+ * *email* : Email to contact the author (useful for licensing questions and such)
+ * *website* : Personal website for the author (github/facebook/twitter profile, etc)
+ * *company* : Company for which the author is creating this screensaver
+ * *company_website* : Website for the company
+* **meta** : (all optional) Additional information about the screensaver itself
+ * *license* : License the screensaver is released under
+ * *license_url* : Website which contains the full text of the license
+ * *copyright* : Copyright notice for this screensaver
+ * *date_created* : (yyyyMMdd) Date the screensaver was initially created
+ * *date_updated* : (yyyyMMdd) Date the screensaver was last updated
+ * *version* : Current version of the screensaver (typically updated every time "date_updated" is changed)
+* **qml** : (required) Information about launching the screensaver and checking validity
+ * *exec* : (required) Absolute or relative path to the QML script (relative to the directory which contains the JSON manifest)
+ * *additional_files* : (optional) Array of paths for other files/scripts which must exist for the screensaver to work properly.
+ * *qt_min_version* : (optional) Minimum version of the Qt libraries that this screensaver supports
+ * *qt_max_version* : (optional) Maximum version of the Qt libraries that this screensaver supports
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/Video.json b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Video.json
new file mode 100644
index 00000000..8bd86157
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Video.json
@@ -0,0 +1,26 @@
+{
+ "disabled" : true,
+ "name" : {
+ "default" : "Video"
+ },
+ "description" : {
+ "default" : "Play a single video or a list of videos in a loop"
+ },
+ "author" : {
+ "name" : "Zackary Welch",
+ "email" : "zwelch@ixsystems.com",
+ "website" : "https://github.com/ZackaryWelch",
+ "company" : "iXsystems",
+ "company_website" : "http://ixsystems.com"
+ },
+ "meta" : {
+ "license" : "3-clause BSD",
+ "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE",
+ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)",
+ "date_created" : "20171025",
+ "version" : "1.0"
+ },
+ "qml" : {
+ "exec" : "qml_scripts/Video.qml"
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/Warp.json b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Warp.json
new file mode 100644
index 00000000..888df01f
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/Warp.json
@@ -0,0 +1,25 @@
+{
+ "name" : {
+ "default" : "Warp"
+ },
+ "description" : {
+ "default" : "Warp trail through the stars"
+ },
+ "author" : {
+ "name" : "Ken Moore",
+ "email" : "ken@ixsystems.com",
+ "website" : "https://github.com/beanpole135",
+ "company" : "iXsystems",
+ "company_website" : "http://ixsystems.com"
+ },
+ "meta" : {
+ "license" : "3-clause BSD",
+ "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE",
+ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)",
+ "date_created" : "20171012",
+ "version" : "1.0"
+ },
+ "qml" : {
+ "exec" : "qml_scripts/Warp.qml"
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Fireflies.qml b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Fireflies.qml
new file mode 100644
index 00000000..d8dcc1ed
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Fireflies.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.0
+import QtGraphicalEffects 1.0
+import "." as QML
+
+Rectangle {
+ id : canvas
+ anchors.fill: parent
+ color: "black"
+
+ Repeater {
+ model: Math.round(Math.random()*canvas.width/10)+100
+ QML.Firefly {
+ parent: canvas
+ x: Math.round(Math.random()*canvas.width)
+ y: Math.round(Math.random()*canvas.height)
+ }
+ } //end of Repeater
+
+} //end of canvas rectangle
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Firefly.qml b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Firefly.qml
new file mode 100644
index 00000000..7b65d8ec
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Firefly.qml
@@ -0,0 +1,63 @@
+import QtQuick 2.0
+import QtQuick.Window 2.2
+import QtGraphicalEffects 1.0
+
+Item {
+
+ RectangularGlow {
+ anchors.fill: fly
+ glowRadius: Math.round(fly.radius /2)
+ spread: 0.5
+ color: Qt.rgba(1,1,1,0.3)
+ cornerRadius: fly.radius + glowRadius
+ }
+
+ Rectangle {
+ id: fly
+ width: Math.round(Math.random()*canvas.width/200)+2
+ height: width
+ x: parent.x
+ y: parent.y
+ color: Qt.rgba(Math.random(),Math.random(),0,0.5)
+ radius: Math.floor(width/2)
+ property int jitterX: Math.round(Math.random()*100)+10
+ property int jitterY: Math.round(Math.random()*100)+10
+
+ Behavior on color {
+ ColorAnimation {
+ duration: 500
+ }
+ }
+ Behavior on x {
+ SmoothedAnimation {
+ velocity: 10+Math.random()*canvas.width/100
+ }
+ }
+ Behavior on y {
+ SmoothedAnimation {
+ velocity: 10+Math.random()*canvas.height/100
+ }
+ }
+
+ }
+
+
+
+ Timer {
+ interval: 5
+ repeat: true
+ running: true
+ property bool starting: true
+ onTriggered: {
+ if(starting){ interval = Math.round(Math.random()*1000)+500; starting = false; }
+ if ( (fly.x+fly.jitterX)>parent.width || (fly.x+fly.jitterX)<0 ){ fly.jitterX = 0-fly.jitterX }
+ fly.x = fly.x+fly.jitterX
+ if( (fly.y+fly.jitterY)>parent.height || (fly.y+fly.jitterY)<0 ){ fly.jitterY = 0-fly.jitterY }
+ fly.y = fly.y+fly.jitterY
+ fly.jitterX = (Math.round(Math.random())*2 - 1) *fly.jitterX
+ fly.jitterY = (Math.round(Math.random())*2 - 1) *fly.jitterY
+ fly.color = Qt.rgba(Math.random(),Math.random(),Math.random(),0.5)
+
+ }
+ } //end of timer
+} //end of item
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Grav.qml b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Grav.qml
new file mode 100644
index 00000000..d1e5d3c9
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Grav.qml
@@ -0,0 +1,132 @@
+import QtQuick 2.7
+import QtGraphicalEffects 1.0
+
+Rectangle {
+ id : canvas
+ anchors.fill: parent
+ width: Screen.width
+ height: Screen.height
+ color: "black"
+
+ //TODO Add orbital trails option
+ //TODO Fix jitteryness and start position
+ //TODO Make orbits more extreme
+
+ //Between 5 and 15 planets, read from settings
+ property int planets: Math.round(( Math.random() * 10 ) + 5 )
+ property int cx: Math.round(width/2)
+ property int cy: Math.round(height/2)
+
+ //Create planets
+ Repeater {
+ id: planetRepeater
+ model: planets
+
+ Rectangle {
+ id : index
+ parent: canvas
+
+ //Creates random distance for elipse
+ property double c: Math.random() * 250
+ property double b: Math.random() * 150 + c
+ property double a: Math.sqrt(b*b+c*c)
+ //Random angle of rotation
+ property double th: Math.random() * Math.PI
+ property var path: []
+
+ //Calculates starting position
+ x: Math.round(cx + a * Math.cos(th))
+ y: Math.round(cy + b * Math.sin(th))
+
+ //Planet size between 14 and 32 pixels
+ width: Math.round(1.75 * (((Math.random() * 10) + 8 )))
+ height: width
+
+ //Make each rectangle look circular
+ radius: width / 2
+
+ //Give each planet a random color, semi-transparent
+ color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5)
+
+ /*Timer {
+ //Each planet updates between 1ms and 51ms (smaller times=faster)
+ interval: Math.round(Math.random() * 50 ) + 1
+ repeat: true
+ running: true
+ property int time: 0
+
+ onTriggered: {
+ //Parametric equation that calculates the position of the general ellipse. Completes a loop ever 314 cycles. Credit to
+ x = cx+a*Math.cos(2*Math.PI*(time/314.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(time/314.0))*Math.sin(th)
+ y = cy+a*Math.cos(2*Math.PI*(time/314.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(time/314.0))*Math.cos(th)
+ time++;
+
+ //Move a planet 80 pixels away from the sun if the planet is too close
+ if(x > cx && Math.abs(cx-x) < 80) {
+ x+=80
+ }else if(x < cx && Math.abs(cx-x) < 80) {
+ x-=80
+ }
+
+ if(y > cy && Math.abs(cy-y) < 80) {
+ y+=80
+ }else if(y < cy && Math.abs(cy-y) < 80) {
+ y-=80
+ }
+ }
+ }*/
+
+ Component.onCompleted: {
+ pahtX[0] = x
+ pahtY[0] = y
+ for(int i = 1; i <= 200; i++) {
+ pathX[i] = cx+a*Math.cos(2*Math.PI*(i/200.0)*Math.cos(th) - b*Math.sin(2*Math.PI*(i/200.0)*Math.sin(th)
+ pathY[i] = cy+a*Math.cos(2*Math.PI*(i/200.0)*Math.sin(th) + b*Math.sin(2*Math.PI*(i/200.0)*Math.cos(th)
+ }
+ }
+ }
+ }
+
+ //Create the star
+ Rectangle{
+ id: star
+ parent: canvas
+
+ //Centers in star in the center of the canvas, with an offset to center the animation
+ x: cx - 30
+ y: cy - 30
+
+ width: 60
+ height: width
+
+ //Create the wobble animation
+ SequentialAnimation on height {
+ loops: Animation.Infinite
+ PropertyAnimation { duration: 2000; to: 90 }
+ PropertyAnimation { duration: 2000; to: 60 }
+ }
+
+ SequentialAnimation on width {
+ loops: Animation.Infinite
+ PropertyAnimation { duration: 2000; to: 90 }
+ PropertyAnimation { duration: 2000; to: 60 }
+ }
+
+ color: "black"
+ radius: width / 2
+
+ //Creates a radial gradient to make the star look cool
+ RadialGradient {
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { position:0 ;color: Qt.rgba(0,0,0,0)}
+ GradientStop { position:0.18 ;color: Qt.rgba(0,0,0,0)}
+ GradientStop { position:0.2 ;color: Qt.rgba(0.32,0.47,0.30,0.13)}
+ GradientStop { position:0.3 ;color: Qt.rgba(0.62,0.92,0.58,0.25)}
+ GradientStop { position:0.4 ;color: Qt.rgba(1.00,0.93,0.59,0.51)}
+ GradientStop { position:0.5 ;color: Qt.rgba(0,0,0,0)}
+ }
+ }
+
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Matrix.qml b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Matrix.qml
new file mode 100644
index 00000000..d4031201
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Matrix.qml
@@ -0,0 +1,71 @@
+import QtQuick 2.0
+import QtMultimedia 5.7
+import QtQuick.Window 2.2
+
+Rectangle {
+ width: Window.width
+ height: Window.height
+ color: "black"
+
+ Row{
+ id: masterRow
+ anchors.left: parent.left
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width
+ spacing: 5
+ Repeater {
+ id: cR
+ model: Window.width / 15 + 1
+ Column {
+ id: masterColumn
+ width: 10
+ Text {
+ id: column
+ color: "#ff4d4d"
+ font.pixelSize: 10
+ transform: Rotation { origin.x: 0; origin.y: 0; angle: 90 }
+ Timer {
+ interval: 50
+ repeat: true
+ running: true
+ onTriggered: {
+ if(Math.random() < 0.95) {
+ var bottom = column.text.charAt(column.text.length-1)
+ var newString = bottom+column.text.substring(0, column.text.length-1)
+ column.text = newString
+ interval = 50
+ }else{
+ interval = 1000
+ }
+ }
+ }
+ Component.onCompleted: {
+ var str = " "
+ var numberChar = Math.random() * 100 + (Window.height * 0.1);
+ if(Math.random() < 0.80) {
+ while(str.length < numberChar) {
+ if(Math.random() < 0.5) {
+ var charCount = Math.random() * 8 + 10
+ var segStr = ""
+ while(segStr.length < charCount) {
+ var randChar = String.fromCharCode(0x30A0 + Math.random() * (0x30FF-0x30A0+1));
+ segStr += randChar
+ }
+ str += segStr
+ }else{
+ var charCount = Math.random() * 6 + 14
+ var segStr = ""
+ while(segStr.length < charCount) {
+ segStr += " "
+ }
+ str += segStr
+ }
+ }
+ }
+ column.text = str
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Video.qml b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Video.qml
new file mode 100644
index 00000000..9948537b
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Video.qml
@@ -0,0 +1,48 @@
+import QtQuick 2.0
+import QtMultimedia 5.7
+import QtQuick.Window 2.2
+import Qt.labs.folderlistmodel 2.1
+
+Rectangle {
+ width: Screen.width
+ height: Screen.height
+ color: "black"
+
+ FolderListModel {
+ id: folderModel
+ folder: "/usr/local/videos"
+ }
+
+ Repeater {
+ model: folderModel
+ Component {
+ Item {
+ Component.onCompleted: { playlist.addItem(fileURL) }
+ }
+ }
+ }
+
+ Playlist {
+ id: playlist
+ playbackMode: Playlist.Random
+ PlaylistItem { source: "/" }
+ onError: { console.log("ERROR") }
+ }
+
+ MediaPlayer {
+ id: player
+ autoPlay: true
+ playlist: playlist
+ }
+
+ VideoOutput {
+ id: videoOutput
+ source: player
+ anchors.fill: parent
+ }
+
+ Component.onCompleted: {
+ playlist.shuffle()
+ console.log(playlist.itemCount)
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Warp.qml b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Warp.qml
new file mode 100644
index 00000000..1cf9bc37
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/extrafiles/screensavers/qml_scripts/Warp.qml
@@ -0,0 +1,64 @@
+import QtQuick 2.0
+import QtGraphicalEffects 1.0
+
+Rectangle {
+ id : canvas
+ anchors.fill: parent
+ color: "black"
+
+ function getStarColor(num){
+ if(num < 1) { return "white" }
+ if(num < 2) { return "mistyrose" }
+ return "lightblue"
+ }
+
+ // CREATE STARFIELD
+ Repeater {
+ model: Math.round(Math.random()*canvas.width/10)+500
+ Rectangle {
+ parent: canvas
+ x: Math.round(Math.random()*canvas.width)
+ y: Math.round(Math.random()*canvas.height)
+ width: Math.round(Math.random()*3)+3
+ height: width
+ radius: width/2
+ color: getStarColor( (index%3) )
+
+ }
+ } //end of Repeater
+
+ // NOW CREATE THE WARP EFFECT
+ ZoomBlur {
+ id: blur
+ anchors.fill: canvas
+ source: canvas
+ samples: 24
+ length: canvas.width / 20
+ horizontalOffset: 0
+ verticalOffset: 0
+
+ Behavior on horizontalOffset{
+ NumberAnimation{
+ duration: 3000
+ }
+ }
+ Behavior on verticalOffset{
+ NumberAnimation{
+ duration: 3000
+ }
+ }
+ } //end of zoom blur
+
+ Timer {
+ interval: 5
+ repeat: true
+ running: true
+ property bool starting: true
+ onTriggered: {
+ if(starting){ interval = 3010; starting = false; }
+ blur.horizontalOffset = (Math.random()*canvas.width/4) - (canvas.width/8)
+ blur.verticalOffset = (Math.random()*canvas.height/4) - (canvas.height/8)
+ }
+ } //end of timer
+
+} //end of canvas rectangle
diff --git a/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys b/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys
index 9726d5a4..92f58e71 100644
--- a/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys
+++ b/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys
@@ -144,3 +144,4 @@ Print :Exec lumina-screenshot
Mod1 Home :Exec lumina-open -brightnessup
Mod1 End :Exec lumina-open -brightnessdown
Pause :Exec xscreensaver-command -lock
+Control Mod1 space :Exec lumina-pingcursor
diff --git a/src-qt5/core/lumina-desktop/global-includes.h b/src-qt5/core/lumina-desktop/global-includes.h
new file mode 100644
index 00000000..be33a45b
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/global-includes.h
@@ -0,0 +1,85 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2015-2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// Global defines and enumerations for external includes
+//===========================================
+#ifndef _LUMINA_EXTERNAL_GLOBAL_DEFINES_H
+#define _LUMINA_EXTERNAL_GLOBAL_DEFINES_H
+
+//Qt includes
+#include <QObject>
+#include <QFrame>
+#include <QLabel>
+#include <QToolButton>
+#include <QMenu>
+#include <QHBoxLayout>
+#include <QMouseEvent>
+#include <QAction>
+#include <QPoint>
+#include <QTemporaryFile>
+#include <QFile>
+#include <QDir>
+#include <QString>
+#include <QTextStream>
+#include <QUrl>
+#include <QDebug>
+#include <QStringList>
+#include <QAbstractNativeEventFilter>
+#include <QList>
+#include <QX11Info>
+#include <QCoreApplication>
+#include <QPropertyAnimation>
+#include <QAnimationGroup>
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
+#include <QGraphicsOpacityEffect>
+#include <QWindow>
+#include <QWidget>
+#include <QWidgetAction>
+#include <QBackingStore>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QSettings>
+#include <QHostInfo>
+#include <QDesktopWidget>
+#include <QStyleOption>
+#include <QThread>
+#include <QMediaObject>
+#include <QMediaPlayer>
+#include <QVideoWidget>
+#include <QMediaPlaylist>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QQuickView>
+#include <QQmlContext>
+#include <QQmlEngine>
+#include <QQuickImageProvider>
+#include <QtConcurrent>
+
+// libLumina includes
+#include <LuminaX11.h>
+#include <LuminaXDG.h>
+#include <LuminaOS.h>
+#include <LuminaThemes.h>
+#include <LUtils.h>
+#include <LDesktopUtils.h>
+#include <LuminaSingleApplication.h>
+#include <DesktopSettings.h>
+#include <ExternalProcess.h>
+#include <XDGMime.h>
+#include <LIconCache.h>
+#include <LFileInfo.h>
+#include <framework-OSInterface.h>
+
+// C++ Backend classes for QML interface
+//#include <NativeWindowObject.h>
+//#include <ScreenObject.h>
+
+//Setup any global defines (no classes or global objects: use "global-objects.h" for that)
+
+
+#endif
diff --git a/src-qt5/core/lumina-desktop/lumina-desktop.pro b/src-qt5/core/lumina-desktop/lumina-desktop.pro
index cc4b63ae..678a8526 100644
--- a/src-qt5/core/lumina-desktop/lumina-desktop.pro
+++ b/src-qt5/core/lumina-desktop/lumina-desktop.pro
@@ -1,8 +1,14 @@
include($${PWD}/../../OS-detect.pri)
-QT += core gui network
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras multimedia concurrent svg
-
+lessThan(QT_MAJOR_VERSION, 5) {
+ message("[ERROR] Qt 5.11+ is required to use the Lumina Desktop!")
+ exit
+}
+lessThan(QT_MINOR_VERSION, 11){
+ message("[ERROR] Qt 5.11+ is required to use the Lumina Desktop!")
+ exit
+}
+QT += core gui network widgets x11extras multimedia multimediawidgets concurrent svg quick qml
TARGET = lumina-desktop
@@ -17,6 +23,7 @@ include(../libLumina/LuminaSingleApplication.pri)
include(../libLumina/LuminaThemes.pri)
include(../libLumina/ExternalProcess.pri)
include(../libLumina/LIconCache.pri)
+include(../libLumina/DesktopSettings.pri)
TEMPLATE = app
@@ -37,6 +44,7 @@ SOURCES += main.cpp \
HEADERS += Globals.h \
+ global-includes.h \
WMProcess.h \
LXcbEventFilter.h \
LSession.h \
@@ -60,6 +68,10 @@ FORMS += SystemWindow.ui \
BootSplash.ui
+#include the individual desktop components
+include(../../src-cpp/plugins-base.pri)
+include(src-screensaver/screensaver.pri)
+
#Now include all the files for the various plugins
include(panel-plugins/panel-plugins.pri)
include(desktop-plugins/desktop-plugins.pri)
@@ -84,6 +96,9 @@ defaults.path = $${L_SHAREDIR}/lumina-desktop/
conf.path = $${L_ETCDIR}
+extrafiles.path = $${L_SHAREDIR}/lumina-desktop
+extrafiles.files = extrafiles/*
+
#Now do any OS-specific defaults (if available)
#First see if there is a known OS override first
!isEmpty(DEFAULT_SETTINGS){
@@ -173,7 +188,7 @@ dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INST
manpage.path=$${L_MANDIR}/man1/
manpage.extra="$${MAN_ZIP} $$PWD/lumina-desktop.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-desktop.1.gz"
-INSTALLS += target desktop icons defaults conf fluxconf manpage
+INSTALLS += target desktop icons defaults conf fluxconf manpage extrafiles
WITH_I18N{
INSTALLS += dotrans
diff --git a/src-qt5/core/lumina-desktop/main.cpp b/src-qt5/core/lumina-desktop/main.cpp
index 826d697c..c8a51462 100644
--- a/src-qt5/core/lumina-desktop/main.cpp
+++ b/src-qt5/core/lumina-desktop/main.cpp
@@ -84,8 +84,8 @@ int main(int argc, char ** argv)
return 787; //return special restart code
}*/
//Setup the log file
- QTime *timer=0;
- if(DEBUG){ timer = new QTime(); timer->start(); }
+ QElapsedTimer *timer=0;
+ if(DEBUG){ timer = new QElapsedTimer(); timer->start(); }
if(DEBUG){ qDebug() << "Session Setup:" << timer->elapsed(); }
a.setupSession();
if(DEBUG){ qDebug() << "Exec Time:" << timer->elapsed(); delete timer;}
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemdashboard/SysMenuQuick.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemdashboard/SysMenuQuick.cpp
index 56ad0788..83aaceea 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/systemdashboard/SysMenuQuick.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/systemdashboard/SysMenuQuick.cpp
@@ -92,22 +92,11 @@ void LSysMenuQuick::UpdateMenu(){
if(hasBat){
ui->group_battery->setVisible(true);
val = LOS::batteryCharge();
- if(LOS::batteryIsCharging()){
- if(val < 15){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-charging-low","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 30){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-charging-caution","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 50){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-charging-040","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 70){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-charging-060","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 90){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-charging-080","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else{ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-charging","").pixmap(ui->label_bat_icon->maximumSize()) ); }
+ bool charging = LOS::batteryIsCharging();
+ ui->label_bat_icon->setPixmap( LXDG::findIcon(LSession::batteryIconName(val,charging), "").pixmap(ui->label_bat_icon->maximumSize()) );
+ if(charging){
ui->label_bat_text->setText( QString("%1%\n(%2)").arg(QString::number(val), tr("connected")) );
}else{
- if(val < 1){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-missing","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 15){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-low","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 30){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-caution","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 50){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-040","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 70){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-060","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else if(val < 90){ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-080","").pixmap(ui->label_bat_icon->maximumSize()) ); }
- else{ ui->label_bat_icon->setPixmap( LXDG::findIcon("battery-100","").pixmap(ui->label_bat_icon->maximumSize()) ); }
ui->label_bat_text->setText( QString("%1%\n(%2)").arg(QString::number(val), getRemainingTime()) );
}
}else{
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp
index 57c17d47..38f5246f 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp
@@ -578,7 +578,8 @@ void StartMenu::on_tool_launch_deskinfo_clicked(){
//Logout Buttons
void StartMenu::on_tool_lock_clicked(){
//QProcess::startDetached("xscreensaver-command -lock");
- LaunchItem("xscreensaver-command -lock",false);
+ QTimer::singleShot(30,LSession::handle(), SLOT(LockScreen()) );
+ //LaunchItem("xscreensaver-command -lock",false);
}
void StartMenu::on_tool_logout_clicked(){
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
index 8f867261..67964c3f 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
@@ -21,6 +21,7 @@ LTaskButton::LTaskButton(QWidget *parent, bool smallDisplay) : LTBWidget(parent)
this->setFocusPolicy(Qt::NoFocus);
this->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
winMenu->setContextMenuPolicy(Qt::CustomContextMenu);
+ LWINLIST = 0;
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(openActionMenu()) );
connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked()) );
connect(winMenu, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(openActionMenu()) );
@@ -84,8 +85,8 @@ LWinInfo LTaskButton::currentWindow(){
void LTaskButton::UpdateButton(){
if(winMenu->isVisible()){ return; } //skip this if the window menu is currently visible for now
- bool statusOnly = (WINLIST.length() == LWINLIST.length());
- LWINLIST = WINLIST;
+ bool statusOnly = (WINLIST.length() == LWINLIST);
+ LWINLIST = WINLIST.length();
winMenu->clear();
LXCB::WINDOWVISIBILITY showstate = LXCB::IGNORE;
@@ -95,7 +96,7 @@ void LTaskButton::UpdateButton(){
i--;
continue;
}
- if(i==0 && !statusOnly){
+ if(i==0 && (!statusOnly || noicon) ){
//Update the button visuals from the first window
this->setIcon(WINLIST[i].icon(noicon));
cname = WINLIST[i].Class();
@@ -171,7 +172,7 @@ void LTaskButton::buttonClicked(){
if(WINLIST.length() > 1){
winMenu->popup(QCursor::pos());
}else{
- triggerWindow();
+ triggerWindow();
}
}
@@ -189,7 +190,7 @@ void LTaskButton::maximizeWindow(){
LWinInfo win = currentWindow();
LSession::handle()->XCB->MaximizeWindow(win.windowID());
//LSession::handle()->adjustWindowGeom(win.windowID(), true); //run this for now until the WM works properly
- cWin = LWinInfo(); //clear the current
+ cWin = LWinInfo(); //clear the current
}
void LTaskButton::minimizeWindow(){
@@ -197,7 +198,7 @@ void LTaskButton::minimizeWindow(){
if(winMenu->isVisible()){ winMenu->hide(); }
LWinInfo win = currentWindow();
LSession::handle()->XCB->MinimizeWindow(win.windowID());
- cWin = LWinInfo(); //clear the current
+ cWin = LWinInfo(); //clear the current
QTimer::singleShot(100, this, SLOT(UpdateButton()) ); //make sure to update this button if losing active status
}
@@ -244,7 +245,7 @@ void LTaskButton::winClicked(QAction* act){
//Get the window from the action
if(act->data().toInt() < WINLIST.length()){
cWin = WINLIST[act->data().toInt()];
- cstate = cWin.status();
+ cstate = cWin.status();
}else{ cWin = LWinInfo(); } //clear it
//Now trigger the window
triggerWindow();
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h
index ff551998..3062bb74 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h
+++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h
@@ -42,7 +42,7 @@ public:
private:
QList<LWinInfo> WINLIST;
- QList<LWinInfo> LWINLIST;
+ int LWINLIST;
QMenu *actMenu; // action menu (custom context menu)
QMenu *winMenu; // window menu (if more than 1)
LWinInfo cWin;
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/LUserButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/LUserButton.cpp
index acb27135..c1cf2907 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/LUserButton.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/LUserButton.cpp
@@ -23,7 +23,7 @@ LUserButtonPlugin::LUserButtonPlugin(QWidget *parent, QString id, bool horizonta
mact = new QWidgetAction(this);
mact->setDefaultWidget(usermenu);
menu->addAction(mact);
-
+
button->setMenu(menu);
connect(menu, SIGNAL(aboutToHide()), this, SLOT(updateButtonVisuals()) );
//Setup the global shortcut handling for opening the start menu
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp
index 8d7dab7a..dc89525c 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp
@@ -33,7 +33,7 @@ UserItemWidget::UserItemWidget(QWidget *parent, QString itemPath, QString type,
name->setText( tr("Go Back") );
}else{
icon->setPixmap( LXDG::findIcon("folder","").pixmap(32,32) );
- name->setText( this->fontMetrics().elidedText(itemPath.section("/",-1), Qt::ElideRight, TEXTCUTOFF) );
+ name->setText( this->fontMetrics().elidedText(itemPath.section("/",-1), Qt::ElideRight, TEXTCUTOFF) );
}
}else{
actButton->setVisible(false);
@@ -46,7 +46,7 @@ UserItemWidget::UserItemWidget(QWidget *parent, QString itemPath, QString type,
}else{
icon->setPixmap( LXDG::findMimeIcon(itemPath.section("/",-1)).pixmap(32,32) );
}
- name->setText( this->fontMetrics().elidedText(itemPath.section("/",-1), Qt::ElideRight, TEXTCUTOFF) );
+ name->setText( this->fontMetrics().elidedText(itemPath.section("/",-1), Qt::ElideRight, TEXTCUTOFF) );
}
icon->setWhatsThis(itemPath);
if(!goback){ this->setWhatsThis(name->text()); }
@@ -77,7 +77,7 @@ UserItemWidget::UserItemWidget(QWidget *parent, XDGDesktop *item) : QFrame(paren
}
//Now fill it appropriately
icon->setPixmap( LXDG::findIcon(item->icon,"preferences-system-windows-actions").pixmap(32,32) );
- name->setText( this->fontMetrics().elidedText(item->name, Qt::ElideRight, TEXTCUTOFF) );
+ name->setText( this->fontMetrics().elidedText(item->name, Qt::ElideRight, TEXTCUTOFF) );
this->setWhatsThis(name->text());
icon->setWhatsThis(item->filePath);
//Now setup the buttons appropriately
@@ -85,7 +85,7 @@ UserItemWidget::UserItemWidget(QWidget *parent, XDGDesktop *item) : QFrame(paren
setupActions(item);
}
-UserItemWidget::~UserItemWidget(){
+UserItemWidget::~UserItemWidget(){
delete button;
delete icon;
delete name;
@@ -98,7 +98,7 @@ void UserItemWidget::createWidget(){
menuopen = false;
menureset = new QTimer(this);
menureset->setSingleShot(true);
- menureset->setInterval(1000); //1 second
+ menureset->setInterval(1000); //1 second
this->setContentsMargins(0,0,0,0);
button = new QToolButton(this);
button->setIconSize( QSize(14,14) );
@@ -125,7 +125,7 @@ void UserItemWidget::createWidget(){
void UserItemWidget::setupButton(bool disable){
//if(isDirectory){ qDebug() << "Directory Entry:" << isShortcut << linkPath << icon->whatsThis(); }
-
+
if(disable){
button->setVisible(false);
}else if(isShortcut && !linkPath.isEmpty()){ //Favorite Item - can always remove this
@@ -141,7 +141,7 @@ void UserItemWidget::setupButton(bool disable){
}else if(!isShortcut){// if( !QFile::exists( QDir::homePath()+"/Desktop/"+icon->whatsThis().section("/",-1) ) && !LUtils::isFavorite(icon->whatsThis() ) ){
//This file does not have a shortcut yet -- allow the user to add it
button->setWhatsThis("add");
- button->setIcon( LXDG::findIcon("bookmark-toolbar","") );
+ button->setIcon( LXDG::findIcon("bookmark-toolbar","") );
button->setToolTip(tr("Create Shortcut"));
connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked()) );
}else{
@@ -161,7 +161,7 @@ void UserItemWidget::setupActions(XDGDesktop *app){
QAction *act = new QAction(LXDG::findIcon(app->actions[i].icon, app->icon), app->actions[i].name, this);
act->setToolTip(app->actions[i].ID);
act->setWhatsThis(app->actions[i].ID);
- actButton->menu()->addAction(act);
+ actButton->menu()->addAction(act);
}
connect(actButton->menu(), SIGNAL(triggered(QAction*)), this, SLOT(actionClicked(QAction*)) );
connect(actButton->menu(), SIGNAL(aboutToShow()), this, SLOT(actionMenuOpen()) );
@@ -171,22 +171,22 @@ void UserItemWidget::setupActions(XDGDesktop *app){
void UserItemWidget::buttonClicked(){
button->setVisible(false);
- if(button->whatsThis()=="add"){
+ if(button->whatsThis()=="add"){
LDesktopUtils::addFavorite(icon->whatsThis());
//QFile::link(icon->whatsThis(), QDir::homePath()+"/.lumina/favorites/"+icon->whatsThis().section("/",-1) );
- emit NewShortcut();
- }else if(button->whatsThis()=="remove"){
- if(linkPath.isEmpty()){
+ emit NewShortcut();
+ }else if(button->whatsThis()=="remove"){
+ if(linkPath.isEmpty()){
//This is a desktop file
if(isDirectory){
QProcess::startDetached("rm -r \""+icon->whatsThis()+"\"");
}else{
- QFile::remove(icon->whatsThis());
- }
+ QFile::remove(icon->whatsThis());
+ }
//Don't emit the RemovedShortcut signal here - the automatic ~/Desktop watcher will see the change when finished
- }else{
+ }else{
LDesktopUtils::removeFavorite(icon->whatsThis()); //This is a favorite
- emit RemovedShortcut();
+ emit RemovedShortcut();
}
}
}
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp
index a0ba8996..9fdc7169 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp
@@ -15,7 +15,7 @@ UserWidget::UserWidget(QWidget* parent) : QTabWidget(parent), ui(new Ui::UserWid
if(parent!=0){ parent->setMouseTracking(true); }
this->setMouseTracking(true);
sysapps = LSession::handle()->applicationMenu()->currentAppHash(); //get the raw info
-
+
//Connect the signals/slots
connect(ui->tool_desktopsettings, SIGNAL(clicked()), this, SLOT(openDeskSettings()) );
connect(ui->tool_config_screensaver, SIGNAL(clicked()), this, SLOT(openScreenSaverConfig()) );
@@ -28,13 +28,13 @@ UserWidget::UserWidget(QWidget* parent) : QTabWidget(parent), ui(new Ui::UserWid
connect(ui->tool_home_browse, SIGNAL(clicked()), this, SLOT(slotOpenDir()) );
connect(ui->tool_home_search, SIGNAL(clicked()), this, SLOT(slotOpenSearch()) );
connect(ui->tool_config_about, SIGNAL(clicked()), this, SLOT(openLuminaInfo()) );
-
+
//Setup the special buttons
connect(ui->tool_app_store, SIGNAL(clicked()), this, SLOT(openStore()) );
connect(ui->tool_controlpanel, SIGNAL(clicked()), this, SLOT(openControlPanel()) );
//connect(ui->tool_qtconfig, SIGNAL(clicked()), this, SLOT(openQtConfig()) );
-
- lastUpdate = QDateTime(); //make sure it refreshes
+
+ lastUpdate = QDateTime(); //make sure it refreshes
connect(LSession::handle()->applicationMenu(), SIGNAL(AppMenuUpdated()), this, SLOT(UpdateMenu()) );
connect(QApplication::instance(), SIGNAL(DesktopFilesChanged()), this, SLOT(updateFavItems()) );
@@ -68,7 +68,7 @@ void UserWidget::SortScrollArea(QScrollArea *area){
for(int i=0; i<lay->count(); i++){
items << lay->itemAt(i)->widget()->whatsThis().toLower();
}
-
+
items.sort();
//qDebug() << " - Sorted Items:" << items;
for(int i=0; i<items.length(); i++){
@@ -84,7 +84,7 @@ void UserWidget::SortScrollArea(QScrollArea *area){
}
}
}
-
+
}
QIcon UserWidget::rotateIcon(QIcon ico){
@@ -119,13 +119,13 @@ void UserWidget::UpdateAll(){
ui->tool_fav_dirs->setIcon( LXDG::findIcon("folder","") );
ui->tool_fav_files->setIcon( LXDG::findIcon("document-multiple","") );
ui->tool_desktopsettings->setIcon( LXDG::findIcon("preferences-desktop","") );
- ui->tool_config_screensaver->setIcon( LXDG::findIcon("preferences-desktop-screensaver","") );
+ ui->tool_config_screensaver->setIcon( LXDG::findIcon("preferences-desktop-screensaver","") );
ui->tool_config_screensettings->setIcon( LXDG::findIcon("preferences-other","") );
ui->tool_home_gohome->setIcon( LXDG::findIcon("go-home","") );
ui->tool_home_browse->setIcon( LXDG::findIcon("document-open","") );
ui->tool_home_search->setIcon( LXDG::findIcon("system-search","") );
ui->tool_config_about->setIcon( LXDG::findIcon("lumina","") );
-
+
//Setup the special buttons
QString APPSTORE = LOS::AppStoreShortcut();
if(QFile::exists(APPSTORE) && !APPSTORE.isEmpty()){
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h
index 8b03c489..c112ac0f 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h
+++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h
@@ -24,8 +24,6 @@
#include <LuminaOS.h>
#include "UserItemWidget.h"
-#define SSAVER QString("xscreensaver-demo")
-
namespace Ui{
class UserWidget;
};
@@ -81,7 +79,8 @@ private slots:
LaunchItem("lumina-config", false);
}
void openScreenSaverConfig(){
- LaunchItem(SSAVER, false);
+ LaunchItem("lumina-config",false);
+ //LaunchItem(SSAVER, false);
}
void openScreenConfig(){
LaunchItem("lumina-xconfig",false);
@@ -89,7 +88,7 @@ private slots:
void openLuminaInfo(){
LaunchItem("lumina-info",false);
}
-
+
protected:
void mouseMoveEvent( QMouseEvent *event);
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.cpp b/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.cpp
new file mode 100644
index 00000000..4253a115
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.cpp
@@ -0,0 +1,112 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LLockScreen.h"
+#include "ui_LLockScreen.h"
+
+#include <unistd.h>
+
+#define NUMTRIES 3
+#define DEBUG 1
+
+LLockScreen::LLockScreen(QWidget *parent) : QWidget(parent), ui(new Ui::LLockScreen()){
+ ui->setupUi(this);
+ waittime = new QTimer(this);
+ waittime->setSingleShot(true);
+ refreshtime = new QTimer(this); //timer to update the wait time display
+ refreshtime->setInterval(6000); //6 seconds (1/10 second)
+
+ connect(ui->tool_unlock, SIGNAL(clicked()), this, SLOT(TryUnlock()) );
+ connect(ui->line_password, SIGNAL(returnPressed()), this, SLOT(TryUnlock()) );
+ connect(ui->line_password, SIGNAL(textEdited(QString)), this, SIGNAL(InputDetected()) );
+ connect(ui->line_password, SIGNAL(cursorPositionChanged(int,int)), this, SIGNAL(InputDetected()) );
+ connect(waittime, SIGNAL(timeout()), this, SLOT(aboutToShow()) );
+ connect(refreshtime, SIGNAL(timeout()), this, SLOT(UpdateLockInfo()) );
+}
+
+LLockScreen::~LLockScreen(){
+
+}
+
+void LLockScreen::LoadSystemDetails(){
+ //Run every time the screen is initially locked
+ QString user = QString(getlogin());
+ ui->label_username->setText( QString(tr("Locked by: %1")).arg(user) );
+ ui->label_hostname->setText( QHostInfo::localHostName() );
+ ui->tool_unlock->setIcon( LXDG::findIcon("document-decrypt","") );
+ attempts = 0;
+}
+
+void LLockScreen::aboutToHide(){
+ //auto-hide timeout - clear display
+ ui->line_password->clear();
+ ui->line_password->clearFocus();
+ if(refreshtime->isActive()){ refreshtime->stop(); }
+ ui->line_password->releaseKeyboard();
+}
+
+void LLockScreen::aboutToShow(){
+ if(!waittime->isActive()){
+ ui->label_info->clear();
+ this->setEnabled(true);
+ triesleft = NUMTRIES; //back to initial number of tries
+ if(refreshtime->isActive()){ refreshtime->stop(); }
+ }else{
+ if(!refreshtime->isActive()){ refreshtime->start(); }
+ }
+ UpdateLockInfo();
+ ui->line_password->clear();
+ ui->line_password->setFocus();
+ ui->line_password->grabKeyboard();
+}
+
+// =================
+// PRIVATE SLOTS
+// =================
+void LLockScreen::UpdateLockInfo(){
+ QString info;
+ if(waittime->isActive()){
+ info = tr("Too Many Failures")+"\n"+ QString(tr("Wait %1 Minutes")).arg( QString::number(qRound(waittime->remainingTime()/6000.0)/10.0) );
+ }else if(attempts>0){ info.append("\n"+QString(tr("Failed Attempts: %1")).arg(QString::number(attempts)) ); }
+ ui->label_info->setText(info);
+}
+
+void LLockScreen::TryUnlock(){
+ attempts++;
+ this->setEnabled(false);
+ QString pass = ui->line_password->text();
+ ui->line_password->clear();
+ //Create a temporary file for the password, then pass that file descriptor to lumina-checkpass
+ QTemporaryFile *TF = new QTemporaryFile(".XXXXXXXXXX");
+ TF->setAutoRemove(true);
+ bool ok = false;
+ if( TF->open() ){
+ QTextStream in(TF);
+ in << pass.toUtf8()+"\0"; //make sure it is null-terminated
+ TF->close();
+ if(DEBUG){ qDebug() << "Trying to unlock session:" << getlogin(); }
+ LUtils::runCommand(ok, "lumina-checkpass",QStringList() << "-f" << TF->fileName() );
+ if(DEBUG){ qDebug() << " - Success:" << ok; }
+ ok = true; //bypass for the moment
+ }
+ delete TF; //ensure the temporary file is removed **right now** for security purposes
+ if(ok){
+ emit ScreenUnlocked();
+ this->setEnabled(true);
+ }else{
+ triesleft--;
+ if(triesleft>0){
+ this->setEnabled(true);
+ }else{
+ waittime->setInterval( (attempts/NUMTRIES)*60000);
+ waittime->start();
+ refreshtime->start();
+ }
+ ui->line_password->setFocus();
+ }
+ UpdateLockInfo();
+
+}
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.h b/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.h
new file mode 100644
index 00000000..79892714
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.h
@@ -0,0 +1,42 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_LOCK_SCREEN_WIDGET_H
+#define _LUMINA_DESKTOP_LOCK_SCREEN_WIDGET_H
+
+#include "global-includes.h"
+
+namespace Ui{
+ class LLockScreen;
+};
+
+class LLockScreen : public QWidget{
+ Q_OBJECT
+public:
+ LLockScreen(QWidget *parent = 0);
+ ~LLockScreen();
+
+ void LoadSystemDetails(); //Run right after the screen is initially locked
+
+public slots:
+ void aboutToHide(); //auto-hide timeout (can happen multiple times per lock)
+ void aboutToShow(); //about to be re-shown (can happen multiple times per lock)
+
+private:
+ Ui::LLockScreen *ui;
+ int triesleft, attempts;
+ QTimer *waittime;
+ QTimer *refreshtime;
+
+private slots:
+ void UpdateLockInfo();
+ void TryUnlock();
+
+signals:
+ void ScreenUnlocked();
+ void InputDetected();
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.ui b/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.ui
new file mode 100644
index 00000000..7f0b45b8
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/LLockScreen.ui
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LLockScreen</class>
+ <widget class="QWidget" name="LLockScreen">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>289</width>
+ <height>188</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="frame_unlock">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_hostname">
+ <property name="font">
+ <font>
+ <weight>50</weight>
+ <italic>true</italic>
+ <bold>false</bold>
+ <underline>true</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">hostname</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_username">
+ <property name="text">
+ <string notr="true">Locked by username</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_info">
+ <property name="font">
+ <font>
+ <italic>true</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="line_password">
+ <property name="inputMask">
+ <string notr="true"/>
+ </property>
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="placeholderText">
+ <string>Password</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QToolButton" name="tool_unlock">
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="text">
+ <string>Unlock Session</string>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.cpp b/src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.cpp
new file mode 100644
index 00000000..6ccd8420
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.cpp
@@ -0,0 +1,231 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LScreenSaver.h"
+#include <QScreen>
+#include <QApplication>
+
+#include <LSession.h>
+#define DEBUG 0
+
+LScreenSaver::LScreenSaver() : QWidget(0,Qt::BypassWindowManagerHint | Qt::WindowStaysOnTopHint){
+ starttimer = new QTimer(this);
+ starttimer->setSingleShot(true);
+ locktimer = new QTimer(this);
+ locktimer->setSingleShot(true);
+ hidetimer = new QTimer(this);
+ hidetimer->setSingleShot(true);
+ checkTimer = new QTimer(this);
+ checkTimer->setInterval(1500); //1.5 seconds
+
+ lastTimeCode = 0;
+
+ LOCKER = new LLockScreen(this);
+ LOCKER->hide();
+ SSRunning = SSLocked = updating = false;
+ this->setObjectName("LSCREENSAVERBASE");
+ this->setStyleSheet("LScreenSaver#LSCREENSAVERBASE{ background: darkgrey; }");
+ this->setMouseTracking(true);
+ connect(starttimer, SIGNAL(timeout()), this, SLOT(ShowScreenSaver()) );
+ connect(locktimer, SIGNAL(timeout()), this, SLOT(LockScreen()) );
+ connect(hidetimer, SIGNAL(timeout()), this, SLOT(HideLockScreen()) );
+ connect(checkTimer, SIGNAL(timeout()), this, SLOT(checkInputEvents()) );
+ connect(LOCKER, SIGNAL(ScreenUnlocked()), this, SLOT(SSFinished()) );
+ connect(LOCKER, SIGNAL(InputDetected()), this, SLOT(newInputEvent()) );
+}
+
+LScreenSaver::~LScreenSaver(){
+
+}
+
+bool LScreenSaver::isLocked(){
+ return SSLocked;
+}
+
+void LScreenSaver::UpdateTimers(){
+ //This is generally used for programmatic changes
+ if(starttimer->isActive()){ starttimer->stop();}
+ if(locktimer->isActive()){ locktimer->stop(); }
+ if(hidetimer->isActive()){ hidetimer->stop(); }
+
+ if(!SSRunning && !SSLocked && (starttimer->interval() > 1000) ){
+ //time to SS start
+ WId active = LSession::handle()->XCB->WM_Get_Active_Window();
+ bool skip = (LSession::handle()->XCB->WindowName(active) != "Lumina Desktop Environment") && LSession::handle()->XCB->WindowIsFullscreen(active);
+ if(!skip){ starttimer->start(); } //do not start if current window is fullscreen (videos, movies, etc)
+ }
+ else if( SSRunning && !SSLocked && (locktimer->interval() > 1000 ) ){ locktimer->start(); } //time to lock
+ else if( !SSRunning && SSLocked ){ hidetimer->start(); } //time to hide lock screen
+}
+
+// ===========
+// PUBLIC SLOTS
+// ===========
+void LScreenSaver::start(){
+ reloadSettings(); //setup all the initial time frames
+ LSession::handle()->XCB->disableDPMS(); //disable this initially - this only gets turned on when the screensaver activates
+ starttimer->start();
+ checkTimer->start();
+}
+
+void LScreenSaver::reloadSettings(){
+ starttimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "timedelaymin",10).toInt() * 60000 );
+ locktimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "lockdelaymin",1).toInt() * 60000 );
+ hidetimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "hidesecs",15).toInt() * 1000 );
+}
+
+void LScreenSaver::newInputEvent(){
+ if(updating){ return; } //in the middle of making changes which could cause an event
+ if(DEBUG){ qDebug() << "New Input Event"; }
+ if(SSRunning && SSLocked){
+ //Running and locked
+ // Hide the running setting, and display the lock screen
+ HideScreenSaver();
+ ShowLockScreen();
+ }else if(SSRunning){
+ //Only running, not locked
+ HideScreenSaver();
+ }
+ UpdateTimers();
+}
+
+void LScreenSaver::LockScreenNow(){
+ ShowScreenSaver();
+ LockScreen();
+}
+
+// ===========
+// PRIVATE SLOTS
+// ===========
+void LScreenSaver::checkInputEvents(){
+ //Check mouse position first
+ QPoint pos = QCursor::pos();
+ bool change = false;
+ if(pos != lastMousePos){
+ lastMousePos = QCursor::pos(); //update the internal point
+ change = true;
+ }
+ //Check the last keyboard input timestamp
+ WId active = LSession::handle()->XCB->WM_Get_Active_Window();
+ if(active != lastActiveWindow){
+ lastActiveWindow = active;
+ change = true;
+ }
+ unsigned int timecode = LSession::handle()->XCB->WM_Get_User_Time(active);
+ if(timecode > lastTimeCode){
+ lastTimeCode = timecode;
+ change = true;
+ }
+ //If there was an input event detected (or a window is currently full-screen), update timers and such
+ if(change){ newInputEvent(); }
+}
+
+void LScreenSaver::ShowScreenSaver(){
+ if(DEBUG){ qDebug() << "Showing Screen Saver:" << QDateTime::currentDateTime().toString(); }
+ checkInputEvents(); //update all the internal times to now
+ //QApplication::setOverrideCursor(QCursor::BlankCursor);
+ SSRunning = true;
+ updating = true;
+ LSession::handle()->XCB->enableDPMS();
+ //Now remove any current Base widgets (prevent any lingering painting between sessions)
+ for(int i=0; i<BASES.length(); i++){
+ if(DEBUG){ qDebug() << " - Removing SS Base"; }
+ delete BASES.takeAt(i); i--;
+ }
+ //Now go through and create/show all the various widgets
+ QList<QScreen*> SCREENS = QApplication::screens();
+ QRect bounds;
+ //cBright = LOS::ScreenBrightness();
+ //if(cBright>0){ LOS::setScreenBrightness(cBright/2); } //cut to half while the screensaver is active
+ for(int i=0; i<SCREENS.length(); i++){
+ bounds = bounds.united(SCREENS[i]->geometry());
+ if(DEBUG){ qDebug() << " - New SS Base:" << i; }
+ BASES << new SSBaseWidget(this);
+ connect(BASES[i], SIGNAL(InputDetected()), this, SLOT(newInputEvent()) );
+
+ //Setup the geometry of the base to match the screen
+ BASES[i]->setGeometry(SCREENS[i]->geometry()); //match this screen geometry
+ QString plug = DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "plugin_"+SCREENS[i]->name(), "").toString();
+ if(plug.isEmpty()){ plug = DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "default_plugin","random").toString(); }
+ BASES[i]->setPlugin(plug);
+ }
+ //Now set the overall parent widget geometry and show everything
+ this->setGeometry(bounds); //overall background widget
+ if(!this->isActiveWindow()){
+ this->raise();
+ this->show();
+ this->activateWindow();
+ }
+ for(int i=0; i<BASES.length(); i++){
+ BASES[i]->show();
+ BASES[i]->startPainting();
+ }
+ this->grabKeyboard();
+ updating = false;
+ UpdateTimers();
+}
+
+void LScreenSaver::ShowLockScreen(){
+ if(DEBUG){ qDebug() << "Showing Lock Screen:" << QDateTime::currentDateTime().toString(); }
+ LOCKER->aboutToShow();
+ //Move the screen locker to the appropriate spot
+ QPoint ctr = QApplication::screenAt(QCursor::pos())->geometry().center();
+ LOCKER->resize(LOCKER->sizeHint());
+ LOCKER->move(ctr - QPoint(LOCKER->width()/2, LOCKER->height()/2) );
+ LOCKER->show();
+ LOCKER->activateWindow();
+ //Start the timer for hiding the lock screen due to inactivity
+ UpdateTimers();
+}
+
+void LScreenSaver::HideScreenSaver(){
+ //QApplication::restoreOverrideCursor();
+ if(DEBUG){ qDebug() << "Hiding Screen Saver:" << QDateTime::currentDateTime().toString(); }
+ SSRunning = false;
+ LSession::handle()->XCB->disableDPMS();
+ //if(cBright>0){ LOS::setScreenBrightness(cBright); } //return to current brightness
+ this->releaseKeyboard();
+ if(!SSLocked){
+ this->hide();
+ emit ClosingScreenSaver();
+ emit LockStatusChanged(false);
+ }
+ if(DEBUG){ qDebug() << "Stop ScreenSavers"; }
+ for(int i=0; i<BASES.length(); i++){
+ BASES[i]->stopPainting();
+ BASES[i]->hide();
+ BASES.takeAt(i)->deleteLater();
+ i--;
+ }
+ UpdateTimers();
+}
+
+void LScreenSaver::HideLockScreen(){
+ if(DEBUG){ qDebug() << "Hiding Lock Screen:" << QDateTime::currentDateTime().toString(); }
+ //Leave the Locked flag set (still locked, just not visible)
+ LOCKER->aboutToHide();
+ LOCKER->hide();
+ this->repaint();
+ if(SSLocked){ ShowScreenSaver(); }
+ UpdateTimers();
+}
+
+void LScreenSaver::LockScreen(){
+ if(SSLocked){ return; }
+ if(DEBUG){ qDebug() << "Locking Screen:" << QDateTime::currentDateTime().toString(); }
+ SSLocked = true;
+ emit LockStatusChanged(true);
+ LOCKER->LoadSystemDetails();
+ UpdateTimers();
+}
+
+void LScreenSaver::SSFinished(){
+ if(DEBUG){ qDebug() << "Screensaver Finished:" << QDateTime::currentDateTime().toString(); }
+ SSLocked = false;
+ emit LockStatusChanged(false);
+ HideLockScreen();
+ HideScreenSaver();
+}
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.h b/src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.h
new file mode 100644
index 00000000..5d154e64
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/LScreenSaver.h
@@ -0,0 +1,63 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_H
+
+#include "global-includes.h"
+
+#include "SSBaseWidget.h"
+#include "LLockScreen.h"
+
+class LScreenSaver : public QWidget{
+ Q_OBJECT
+public:
+ LScreenSaver();
+ ~LScreenSaver();
+
+ bool isLocked();
+
+private:
+ QTimer *starttimer, *locktimer, *hidetimer, *checkTimer;
+ QList<SSBaseWidget*> BASES;
+ LLockScreen *LOCKER;
+ QPoint lastMousePos;
+ unsigned int lastTimeCode;
+ WId lastActiveWindow;
+ int cBright;
+ bool SSRunning, SSLocked, updating;
+
+ void UpdateTimers();
+
+public slots:
+ void start();
+ void reloadSettings();
+ void newInputEvent();
+ void LockScreenNow();
+
+private slots:
+ void checkInputEvents();
+ void ShowScreenSaver();
+ void ShowLockScreen();
+ void HideScreenSaver();
+ void HideLockScreen();
+
+ void LockScreen();
+ void SSFinished();
+
+signals:
+ void StartingScreenSaver();
+ void ClosingScreenSaver();
+ void LockStatusChanged(bool locked);
+
+protected:
+ void mouseMoveEvent(QMouseEvent*){
+ QTimer::singleShot(0,this, SLOT(newInputEvent()));
+ }
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.cpp b/src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.cpp
new file mode 100644
index 00000000..840eb12a
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.cpp
@@ -0,0 +1,64 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+
+#include "SSBaseWidget.h"
+
+//Relative directory to search along the XDG paths for screensavers
+#define REL_DIR QString("/lumina-desktop/screensavers")
+
+#define DEBUG 1
+
+// ========
+// PUBLIC
+// ========
+SSBaseWidget::SSBaseWidget(QWidget *parent) : QQuickView(parent->windowHandle()){
+ this->setObjectName("LuminaBaseSSWidget");
+ this->setResizeMode(QQuickView::SizeRootObjectToView);
+ this->setColor(QColor("black")); //default color for the view
+ this->setCursor(Qt::BlankCursor);
+ plugType="none";
+ restartTimer = new QTimer(this);
+ restartTimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "globals/plugin_time_seconds", 120).toInt() * 1000);
+ restartTimer->setSingleShot(true);
+ connect(restartTimer, SIGNAL(timeout()), this, SLOT(startPainting()) );
+}
+
+SSBaseWidget::~SSBaseWidget(){
+}
+
+void SSBaseWidget::setPlugin(QString plug){
+ plugType = plug.toLower();
+}
+
+// =============
+// PUBLIC SLOTS
+// =============
+void SSBaseWidget::startPainting(){
+ //free up any old animation instance
+ stopPainting();
+ //If a random plugin - grab one of the known plugins
+ if(plugType=="random"){
+ QList<SSPlugin> valid = PluginSystem::findAllPlugins<SSPlugin>(REL_DIR);
+ if(!valid.isEmpty()){ cplug = valid[ qrand()%valid.length() ]; } //grab a random plugin
+ }else if(plugType!="none"){
+ cplug = PluginSystem::findPlugin<SSPlugin>(plugType, REL_DIR);
+ }
+ if(DEBUG){ qDebug() << " - Screen Saver:" << plugType << cplug.scriptURL() << cplug.isValid(); }
+ if(cplug.isValid()){
+ this->setSource( cplug.scriptURL() );
+ if(plugType=="random"){ restartTimer->start(); }
+ }
+
+}
+
+void SSBaseWidget::stopPainting(){
+ if(!this->source().isEmpty()){
+ this->setSource(QUrl());
+ cplug = SSPlugin(); //empty structure
+ }
+ if(restartTimer->isActive()){ restartTimer->stop(); }
+}
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.h b/src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.h
new file mode 100644
index 00000000..e0a03d17
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/SSBaseWidget.h
@@ -0,0 +1,50 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class is the widget which provides the screensaver painting/plugin functionality
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_BASE_WIDGET_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_BASE_WIDGET_H
+
+#include "global-includes.h"
+#include <plugins-base.h>
+#include <plugins-screensaver.h>
+
+class SSBaseWidget : public QQuickView{
+ Q_OBJECT
+public:
+ SSBaseWidget(QWidget *parent);
+ ~SSBaseWidget();
+
+ void setPlugin(QString);
+
+public slots:
+ void startPainting();
+ void stopPainting();
+
+private:
+ QString plugType;
+ SSPlugin cplug;
+ QTimer *restartTimer;
+
+private slots:
+
+signals:
+ void InputDetected(); //just in case no event handling setup at the WM level
+
+protected:
+ void mouseMoveEvent(QMouseEvent *ev){
+ ev->accept();
+ emit InputDetected();
+ }
+ void keyPressEvent(QKeyEvent *ev){
+ ev->accept();
+ emit InputDetected();
+ }
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.cpp b/src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.cpp
new file mode 100644
index 00000000..9b095fe4
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.cpp
@@ -0,0 +1,51 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015-2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "BaseAnimGroup.h"
+
+//Include all the known subclasses here, then add a unique ID for it to the functions at the bottom
+//#include "SampleAnimation.h"
+#include "Fireflies.h"
+#include "Grav.h"
+#include "SampleAnimation.h"
+#include "Text.h"
+#include "ImageSlideshow.h"
+#include "VideoSlideshow.h"
+
+
+QVariant BaseAnimGroup::readSetting(QString variable, QVariant defaultvalue){
+ return DesktopSettings::instance()->value(DesktopSettings::ScreenSaver,
+ "Animations/"+animPlugin+"/"+variable, defaultvalue);
+}
+
+//==============================
+// PLUGIN LOADING/LISTING
+//==============================
+BaseAnimGroup* BaseAnimGroup::NewAnimation(QString type, QWidget *parent){
+ //This is where we place all the known plugin ID's, and load the associated subclass
+ BaseAnimGroup *anim = 0;
+ if(type=="fireflies"){
+ anim = new FirefliesAnimation(parent);
+ }else if(type == "grav") {
+ anim = new GravAnimation(parent);
+ }else if(type == "text") {
+ anim = new TextAnimation(parent);
+ }else if(type == "imageSlideshow") {
+ anim = new ImageAnimation(parent);
+ }else if(type == "videoSlideshow") {
+ anim = new VideoAnimation(parent);
+ }else {
+ //Unknown screensaver, return a blank animation group
+ anim = new BaseAnimGroup(parent);
+ }
+ //tag the animation with the type it is and return it
+ if(anim!=0){ anim->animPlugin = type; }
+ return anim;
+}
+
+QStringList BaseAnimGroup::KnownAnimations(){
+ return (QStringList() << "none" << "grav" << "text" << "imageSlideshow" << "videoSlideshow" << "fireflies");
+}
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.h
new file mode 100644
index 00000000..92e038ed
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/BaseAnimGroup.h
@@ -0,0 +1,40 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015-2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class is the container which provides the screensaver animations
+// and should be subclassed for each of the various animation types
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_BASE_ANIMATION_GROUP_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_BASE_ANIMATION_GROUP_H
+
+#include "global-includes.h"
+
+class BaseAnimGroup : public QParallelAnimationGroup{
+ Q_OBJECT
+public:
+ QWidget *canvas;
+ QString animPlugin;
+
+ virtual void LoadAnimations(){} //This is the main function which needs to be subclassed
+
+ BaseAnimGroup(QWidget *parent){
+ canvas = parent;
+ canvas->setCursor( QCursor(Qt::BlankCursor) );
+ }
+ ~BaseAnimGroup(){}
+
+ QVariant readSetting(QString variable, QVariant defaultvalue = QVariant());
+
+
+ //==============================
+ // PLUGIN LOADING/LISTING (Change in the .cpp file)
+ //==============================
+ static BaseAnimGroup* NewAnimation(QString type, QWidget *parent);
+ static QStringList KnownAnimations();
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/Fireflies.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/Fireflies.h
new file mode 100644
index 00000000..dfc12e79
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/Fireflies.h
@@ -0,0 +1,122 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class is the sample plugin for a ScreenSaver animation
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_FIREFLIES_ANIMATION_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_FIREFLIES_ANIMATION_H
+
+#include "global-includes.h"
+#include "BaseAnimGroup.h"
+#include <QSequentialAnimationGroup>
+#include <QGraphicsOpacityEffect>
+
+class Firefly : public QSequentialAnimationGroup{
+ Q_OBJECT
+private:
+ QWidget *fly;
+ QPropertyAnimation *movement, *flash;
+ int maxX, maxY; //maximum jitter in X/Y directions
+ QSize range;
+private slots:
+ void LoopChanged(){
+ //Adjust the movement animation a bit
+ movement->setStartValue(movement->endValue()); //start at the previous end point
+ QPoint pt = movement->startValue().toPoint();
+ QPoint diff( (qrand()% maxX) - (maxX/2), (qrand()% maxY) - (maxY/2) );
+ //Need to ensure it stays in the current box
+ if( (pt.x()+diff.x()) < 0 || (pt.x()+diff.x())>range.width()){ pt.setX(pt.x() - diff.x()); } //reverse the direction - otherwise will go out of bounds
+ else{ pt.setX( pt.x() + diff.x() ); }
+ if( (pt.y()+diff.y()) < 0 || (pt.y()+diff.y())>range.height()){ pt.setY(pt.y() - diff.y()); } //reverse the direction - otherwise will go out of bounds
+ else{ pt.setY( pt.y() + diff.y() ); }
+ movement->setEndValue(pt);
+ movement->setDuration( qrand() %500 + 1000); //between 1000->1500 ms animations for movements
+ //Adjust the flash duration/size a bit
+ flash->setDuration(qrand() %200 + 500); //500-700 ms
+ int sz = qrand()%4 + 4; //6-10 pixel square
+ //flash->setKeyValueAt(0.5, (qrand()%50) /100.0);
+ //fly->resize(sz,sz);
+ flash->setKeyValueAt(0.5, QSize(sz,sz)); //half-way point for the flash
+
+ fly->show();
+ }
+ void stopped(){ fly->hide(); }
+
+public:
+ Firefly(QWidget *parent) : QSequentialAnimationGroup(parent){
+ fly = new QWidget(parent);
+ range = parent->size();
+ maxX = range.width()/4; maxY = range.height()/4;
+ QString B = QString::number(qrand()%70);
+ QString RY = QString::number(qrand()%200+50);
+ QString style = "background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(245, 245, 143, 200), stop:0.83871 rgba(%1, %1, %2, 140), stop:0.99 rgba(0, 0, 0, 255), stop:1 transparent);";
+ fly->setStyleSheet(style.arg(RY, B) );
+ //setup the movement animation
+ movement = new QPropertyAnimation(fly);
+ movement->setTargetObject(fly);
+ movement->setPropertyName("pos");
+ movement->setEndValue( QPoint( qrand() % range.width(), qrand()%range.height()) ); //on anim start, this will become the starting point
+ //setup the flashing animation
+ /*QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(parent);
+ fly->setGraphicsEffect(eff);
+ flash = new QPropertyAnimation(eff, "opacity");*/
+ flash = new QPropertyAnimation(this);
+ flash->setTargetObject(fly);
+ flash->setPropertyName("size");
+ flash->setStartValue(QSize(0,0));
+ flash->setEndValue(flash->startValue());
+ //fly->setProperty("opacity",0);
+ //flash->setPropertyName("opacity");
+ //flash->setStartValue(0);
+ //flash->setEndValue(0);
+ //now setup the order of the animations
+ this->setLoopCount(100); //do this 100 times
+ //Roughly half the number of fireflies with start with movement/flash
+ if(qrand()%2 == 1){
+ this->addAnimation(movement);
+ this->addAnimation(flash);
+ }else{
+ this->addAnimation(flash);
+ this->addAnimation(movement);
+ }
+ //Start up this firefly
+ LoopChanged(); //load initial values
+
+ fly->setGeometry( QRect(movement->startValue().toPoint(), flash->startValue().toSize()) );
+ connect(this, SIGNAL(currentLoopChanged(int)), this, SLOT(LoopChanged()) );
+ connect(this, SIGNAL(finished()), this, SLOT(stopped()) );
+ }
+ ~Firefly(){}
+
+};
+
+class FirefliesAnimation : public BaseAnimGroup{
+ Q_OBJECT
+private:
+ QList<Firefly*> fireflies;
+
+public:
+ FirefliesAnimation(QWidget *parent) : BaseAnimGroup(parent){}
+ ~FirefliesAnimation(){
+ this->stop();
+ //while(fireflies.length()>0){ fireflies.takeAt(0)->deleteLater(); }
+ }
+
+ void LoadAnimations(){
+ while(fireflies.length()>0){ fireflies.takeAt(0)->deleteLater(); }
+ canvas->setStyleSheet("background: black;");
+ int number = readSetting("number",qrand()%30 + 50).toInt();
+ for(int i=0; i<number; i++){
+ if(fireflies.length()>number){ continue; }
+ Firefly *tmp = new Firefly(canvas);
+ this->addAnimation(tmp);
+ fireflies << tmp;
+ }
+
+ }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/Grav.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/Grav.h
new file mode 100644
index 00000000..df75ad67
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/Grav.h
@@ -0,0 +1,195 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_GRAV_ANIMATION_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_GRAV_ANIMATION_H
+
+//PI is equal to 2*pi
+#define PI 6.2832
+#include "global-includes.h"
+#include "BaseAnimGroup.h"
+#include <QtMath>
+#include <QMatrix>
+
+class Grav: public QParallelAnimationGroup{
+ Q_OBJECT
+private:
+ QWidget *planet;
+ QPropertyAnimation *orbit;
+ QSize range;
+ //QList<QPoint> path;
+ double radius;
+
+ void setupLoop(QPoint start, QPoint *ref){
+ //orbit->setStartValue(start);
+
+ //Used to find overall speed. Distance from the planet to the sun
+ radius = qSqrt( (qPow(start.x()-ref->x(),2) + qPow(start.y()-ref->y(),2) ));
+
+ //Number of frames in animation. Increase for smother motion
+ double step = 300.0;
+
+ //Random values that give the eliptical pattern to the orbit. Between 0.4 and 2.3
+ double xrand = 0.4; //(qrand()%10+4)/10.0;
+ double yrand = 0.4; //(qrand()%10+4)/10.0;
+
+ double theta = 1.5707963;
+ //double theta = aTan((start.x() - ref->x())/(start.y() - ref->y()));
+ QMatrix rotation = QMatrix(qCos(theta), qSin(theta), -qSin(theta), qCos(theta), -ref->x(), -ref->y());
+ qDebug() << rotation;
+ //qDebug() << "Starting Point" << start;
+ //qDebug() << "Angle" << theta;
+ //qDebug() << "Distance" << radius;
+ //qDebug() << "Center" << *ref;
+
+ QPoint firstP = (QPoint(ref->x() + xrand*start.x()*(qCos(0/step) -qSin(0/step)), ref->y() + yrand*start.y()*(qCos(0/step) -qSin(0/step))));
+ QPoint rotFP = rotation.map(firstP);
+ qDebug() << "First Point" << firstP;
+ qDebug() << "Rotation by Matrix" << rotFP;
+ QPoint lastP = (QPoint(ref->x() + xrand*start.x()*(qCos(PI/step) -qSin(PI/step)), ref->y() + yrand*start.y()*(qCos(PI/step) -qSin(PI/step))));
+ orbit->setKeyValueAt(0, firstP);
+ orbit->setKeyValueAt(1, lastP);
+ //path.push_back(firstP);
+
+ //Loops through all steps and creates all the points of the orbit
+ for(int i=1; i<step; i++) {
+ //Calculates the new point, including gravitational pull and eccentricity. Goes from 0 to 2PI in steps.
+ double newX = ref->x() + xrand*start.x()*(qCos((PI*i)/step) - qSin((PI*i)/step));
+ double newY = ref->y() + yrand*start.y()*(qSin((PI*i)/step) + qCos((PI*i)/step));
+
+ //Creates a new point and creates a key as part of the animation
+ QPoint newLoc = (QPoint(newX, newY));
+ orbit->setKeyValueAt(i/step, newLoc);
+ //path.push_back(newLoc);
+ }
+ //Sets the time for a full orbit. Increasing makes the orbit slower.
+ //path.push_back(lastP);
+ }
+private slots:
+ /*void LoopChanged(int loop){
+ //Adjust the orbit animation a bit
+ if(loop >= 0) {
+ orbit->setStartValue(orbit->endValue()); //start at the previous end point
+ orbit->setEndValue(path.at(loop%1000));
+ orbit->setDuration(10);
+ }
+ }*/
+ void stopped(){ planet->hide();}
+
+public:
+ Grav(QWidget *parent) : QParallelAnimationGroup(parent){
+ planet = new QWidget(parent);
+ range = parent->size();
+ QPoint center = QRect(QPoint(0,0), parent->size()).center();;
+
+ //Creates a random planet size. Between 12 and 45 pixels
+ int planet_radius = qRound(1.75* ((qrand()%20)+7) );
+
+ //Creates a random color in RGB, then creates a circular gradient
+ QString color = "rgba(" + QString::number(qrand() % 256) + ", " + QString::number(qrand() % 256) + ", " + QString::number(qrand() % 256);
+ QString style = "background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 " + color+
+ ", 255)" + " , stop:0.83871 " + color + ", 140)" + " , stop:0.99 rgba(0, 0, 0, 255), stop:1 transparent);";
+ planet->setStyleSheet(style);
+
+ //setup the orbit animation
+ orbit = new QPropertyAnimation(planet);
+ orbit->setPropertyName("pos");
+ orbit->setTargetObject(planet);
+
+ //Creates the random position of the planet, making sure it isn't too close to the sun
+ QRect invalid = QRect(center+QPoint(-50,-50), center+QPoint(50,50));
+ QPoint tmp = center;
+ while(invalid.contains(tmp)){
+ int randwidth = qrand()%(range.width() - 2*planet_radius) + planet_radius;
+ int randheight = qrand()%(range.height()- 2*planet_radius) + planet_radius;
+ tmp = QPoint(randwidth, randheight);
+ }
+
+ //Creates all frames for the animation
+ setupLoop(tmp, &center);
+ this->addAnimation(orbit);
+ planet->show();
+
+ //Ensures the screensaver will not stop until the user wishes to login or it times out
+ this->setLoopCount(3); //number of orbits
+ orbit->setDuration( qrand() %1000 + 19000); //20 second orbits
+ //orbit->setEndValue(path.at(0));
+ //LoopChanged(0); //load initial values
+
+ //Sets the initial size and location of the planet
+ planet->setGeometry(QRect(orbit->startValue().toPoint(), QSize(planet_radius, planet_radius)));
+ //connect(this, SIGNAL(currentLoopChanged(int)), this, SLOT(LoopChanged(int)) );
+ connect(this, SIGNAL(finished()), this, SLOT(stopped()) );
+ }
+ ~Grav(){}
+
+};
+
+class GravAnimation : public BaseAnimGroup{
+ Q_OBJECT
+private:
+ QList<Grav*> planets;
+ QWidget *sun;
+ QPropertyAnimation *wobble;
+
+private slots:
+ void checkFinished(){
+ int running = 0;
+ for(int i=0; i<this->animationCount(); i++){
+ if(this->animationAt(i)->state()==QAbstractAnimation::Running){ running++; }
+ }
+ if(running<=1){ wobble->stop(); emit wobble->finished();}
+ }
+
+public:
+ GravAnimation(QWidget *parent) : BaseAnimGroup(parent){}
+ ~GravAnimation(){
+ sun->deleteLater();
+ while(planets.length()>0){ planets.takeAt(0)->deleteLater(); }
+ }
+
+ void LoadAnimations(){
+ //Creates the sun, which is a thin shell with a gradient from green to yellow
+ sun = new QWidget(canvas);
+ QPoint center = QRect(QPoint(0,0), canvas->size()).center();
+ QString sunstyle = QStringLiteral("background-color:qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, ") +
+ QStringLiteral("stop:0 rgba(0, 0, 0, 0), stop:0.38 rgba(0, 0, 0, 0), stop:0.4 rgba(82, 121, 76, 33), stop:0.5 rgba(159, 235, 148, 64), ") +
+ QStringLiteral("stop:0.6 rgba(255, 238, 150, 129), stop:0.7 rgba(0, 0, 0, 0));");
+ sun->setStyleSheet(sunstyle);
+
+ //Creates the sun's pulsing animation
+ wobble = new QPropertyAnimation(sun);
+ wobble->setPropertyName("geometry");
+ wobble->setTargetObject(sun);
+ QRect initgeom = QRect(center-QPoint(30,30), QSize(60, 60));
+ wobble->setStartValue(initgeom);
+ wobble->setKeyValueAt(0, initgeom ); //starting point
+ wobble->setKeyValueAt(1, initgeom ); //starting point
+ wobble->setKeyValueAt(0.5, QRect(center-QPoint(45,45), QSize(90, 90))); //starting point
+ wobble->setDuration(2000);
+ wobble->setLoopCount(-1);
+ this->addAnimation(wobble);
+ sun->show();
+ sun->setGeometry(initgeom);
+
+ //Gives the screensaver a black background
+ //canvas->setStyleSheet("background: black;");
+
+ //Pulls number of planets from settings, with 10 as default
+ int number = readSetting("planets/number",qrand()%5+3).toInt();
+
+ //Loops through all planets and sets up the animations, then adds them to the base group and vector, which
+ //qDebug() << "Starting planets";
+ for(int i=0; i<number; i++){
+ Grav *tmp = new Grav(canvas);
+ this->addAnimation(tmp);
+ connect(tmp, SIGNAL(finished()), this, SLOT(checkFinished()));
+ planets << tmp;
+ }
+ }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/ImageSlideshow.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/ImageSlideshow.h
new file mode 100644
index 00000000..81bc2b35
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/ImageSlideshow.h
@@ -0,0 +1,165 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_IMAGESLIDESHOW_ANIMATION_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_IMAGESLIDESHOW_ANIMATION_H
+
+#include "global-includes.h"
+#include "BaseAnimGroup.h"
+
+class ImageSlideshow: public QParallelAnimationGroup{
+ Q_OBJECT
+private:
+ QLabel *image;
+ QPropertyAnimation *bounce, *fading;
+ QPixmap pixmap;
+ QStringList imageFiles;
+ QString imagePath, scriptPath, curpixmap;
+ QSize screenSize;
+ bool animate, scriptLoad;
+
+private:
+ void setupAnimation() {
+ //Choose between starting from top or bottom at random
+ if(qrand() % 2) {
+ bounce->setKeyValueAt(0, QPoint(0,screenSize.height()-image->height()));
+ bounce->setKeyValueAt(0.25, QPoint((screenSize.width()-image->width())/2,0));
+ bounce->setKeyValueAt(0.5, QPoint(screenSize.width()-image->width(),screenSize.height()-image->height()));
+ bounce->setKeyValueAt(0.75, QPoint((screenSize.width()-image->width())/2,0));
+ bounce->setKeyValueAt(1, QPoint(0,screenSize.height()-image->height()));
+ }else{
+ bounce->setKeyValueAt(0, QPoint(0,0));
+ bounce->setKeyValueAt(0.25, QPoint((screenSize.width()-image->width())/2,screenSize.height()-image->height()));
+ bounce->setKeyValueAt(0.5, QPoint(screenSize.width()-image->width(),0));
+ bounce->setKeyValueAt(0.75, QPoint((screenSize.width()-image->width())/2,screenSize.height()-image->height()));
+ bounce->setKeyValueAt(1, QPoint(0,0));
+ }
+ }
+
+ void chooseImage() {
+ /*if(scriptLoad){
+ QProcess process;
+ process.start("/home/zwelch/test.sh");
+ process.waitForFinished(1000);
+ QByteArray output = process.readAllStandardOutput();
+ //qDebug() << output;
+ //pixmap.load(randomFile);
+ }else{*/
+ //File Load
+ QString randomFile = curpixmap;
+ if(imageFiles.size()>1 || curpixmap.isEmpty()){
+ while(curpixmap==randomFile){ randomFile = imagePath+imageFiles[qrand() % imageFiles.size()]; }
+ }
+ if(curpixmap!=randomFile){
+ curpixmap = randomFile; //save this for later
+ //no need to load the new file or change the label
+ pixmap.load(randomFile);
+ //If the image is larger than the screen, then shrink the image down to 3/4 it's size (so there's still some bounce)
+ //Scale the pixmap to keep the aspect ratio instead of resizing the label itself
+ if(pixmap.width() >= (screenSize.width()-10) || pixmap.height() >= (screenSize.height()-10) ){
+ pixmap = pixmap.scaled(screenSize*(3.0/4.0), Qt::KeepAspectRatio);
+ }
+ //Set pixmap to the image label
+ image->setPixmap(pixmap);
+ image->resize(pixmap.size());
+ }
+ //}
+
+ }
+
+private slots:
+ void LoopChanged(){
+ //Load a new random image. Resize the label based on the image's size
+ chooseImage();
+ setupAnimation();
+ }
+ void stopped(){ image->hide();}
+
+public:
+ ImageSlideshow(QWidget *parent, QString path, bool animate, bool scriptLoad, QString scriptPath) : QParallelAnimationGroup(parent){
+ imagePath = path;
+ image = new QLabel(parent);
+ screenSize = parent->size();
+ this->animate = animate;
+ this->scriptLoad = scriptLoad;
+ this->scriptPath = scriptPath;
+
+ //Generate the list of files in the directory
+ imageFiles = QDir(imagePath).entryList(QDir::Files);
+ //Ensure all the files are actually images
+ for(int i=0; i<imageFiles.length(); i++){
+ if(QImageReader::imageFormat(imagePath+"/"+imageFiles[i]).isEmpty()){ imageFiles.removeAt(i); i--; }
+ }
+ if(imageFiles.empty()){
+ qDebug() << "Current image file path has no files.";
+ image->setText("No image files found:\n"+imagePath);
+ }else{
+ //Change some default settings for the image. If scaledContents is false, the image will be cut off if resized
+ image->setScaledContents(true);
+ image->setAlignment(Qt::AlignHCenter);
+ //Load a random initial image
+ chooseImage();
+ }
+
+ //Create the animation that moves the image across the screen
+ bounce = new QPropertyAnimation(image, "pos", parent);
+
+ //Add the animation that fades the image in and out
+ QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(parent);
+ image->setGraphicsEffect(eff);
+ fading = new QPropertyAnimation(eff,"opacity");
+ fading->setKeyValueAt(0, 0);
+ fading->setKeyValueAt(0.20, 1);
+ fading->setKeyValueAt(0.80, 1);
+ fading->setKeyValueAt(1, 0);
+ this->addAnimation(fading);
+
+ setupAnimation();
+ image->show();
+ //Only add the animation if set in the configuration file
+ if(animate)
+ this->addAnimation(bounce);
+ else
+ //If no animation, center the image in the middle of the screen
+ image->move(QPoint((parent->width()-image->width())/2,(parent->height()-image->height())/2));
+
+ //Loop through 15 times for a total for 2 minutes
+ this->setLoopCount(15);
+ bounce->setDuration(8000);
+ fading->setDuration(8000);
+
+ connect(this, SIGNAL(currentLoopChanged(int)), this, SLOT(LoopChanged()) );
+ connect(this, SIGNAL(finished()), this, SLOT(stopped()) );
+ }
+ ~ImageSlideshow(){}
+
+};
+
+class ImageAnimation: public BaseAnimGroup{
+ Q_OBJECT
+public:
+ ImageAnimation(QWidget *parent) : BaseAnimGroup(parent){}
+ ~ImageAnimation(){
+ this->stop();
+ }
+
+ void LoadAnimations(){
+ canvas->setStyleSheet("background: black;");
+ //Load the path of the images from the configuration file (default /usr/local/backgrounds/)
+ QString imagePath = readSetting("path", LOS::LuminaShare()+"../wallpapers/").toString();
+ //Load whether to animate the image (default true)
+ bool animate = readSetting("animate", true).toBool();
+ bool scriptLoad = readSetting("scriptLoad", true).toBool();
+ QString scriptPath;
+ if(scriptLoad){
+ scriptPath = readSetting("scriptPath", "/usr/local/backgrounds/script.sh").toString();
+ }
+ ImageSlideshow *tmp = new ImageSlideshow(canvas, imagePath, animate, scriptLoad, scriptPath);
+ this->addAnimation(tmp);
+ }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/SampleAnimation.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/SampleAnimation.h
new file mode 100644
index 00000000..c7a8b237
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/SampleAnimation.h
@@ -0,0 +1,45 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class is the sample plugin for a ScreenSaver animation
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_SAMPLE_ANIMATION_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_SAMPLE_ANIMATION_H
+
+#include "global-includes.h"
+#include "BaseAnimGroup.h"
+
+class SampleAnimation : public BaseAnimGroup{
+ Q_OBJECT
+private:
+ QWidget *ball;
+
+public:
+ SampleAnimation(QWidget *parent) : BaseAnimGroup(parent){}
+ ~SampleAnimation(){ this->stop(); delete ball; }
+
+ void LoadAnimations(){
+ //qDebug() << "Loading Sample Animation";
+ ball = new QWidget(canvas);
+ //This creates a red "ball" on the widget which is going to expand/contract in the center of the screen
+ ball->setStyleSheet("background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.341, fy:0.796, stop:0.00531915 rgba(107, 10, 10, 255), stop:0.521277 rgba(170, 10, 10, 255), stop:0.957447 rgba(200, 0, 0, 255), stop:0.994681 rgba(0, 0, 0, 225), stop:1 rgba(255, 255, 255, 0));");
+ //Now setup the movements
+ QPropertyAnimation *move = new QPropertyAnimation(ball,"geometry");
+ QPoint ctr(canvas->width()/2, canvas->height()/2);
+ QRect initgeom(ctr-QPoint(12,12), QSize(24,24) );
+ move->setKeyValueAt(0, initgeom ); //starting point
+ move->setKeyValueAt(1, initgeom ); //ending point (same as start for continuity)
+ int size = canvas->width();
+ if(size > canvas->height()){ size = canvas->height(); }
+ move->setKeyValueAt(0.5, QRect(ctr-QPoint(size/2, size/2), QSize(size,size))); //touch the edge of the screen
+ move->setDuration(10000); //10 seconds
+ this->addAnimation(move);
+ this->setLoopCount(10); //repeat 10 times
+ ball->show();
+ }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/Text.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/Text.h
new file mode 100644
index 00000000..bdde5ba2
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/Text.h
@@ -0,0 +1,100 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_TEXT_ANIMATION_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_TEXT_ANIMATION_H
+
+#include "global-includes.h"
+#include "BaseAnimGroup.h"
+#include <QParallelAnimationGroup>
+#include <QtMath>
+
+#include <unistd.h>
+
+class Text: public QParallelAnimationGroup{
+ Q_OBJECT
+private:
+ QLabel *text;
+ QPropertyAnimation *movement;
+ QSize range;
+ QPoint v;
+ bool bounce;
+
+private slots:
+ void LoopChanged(){
+ movement->setStartValue(movement->endValue());
+ QPoint currLoc = movement->startValue().toPoint();
+ bounce = !(currLoc.y() < 100 or currLoc.y() > range.height()-100 or currLoc.x() > range.width()-100 or currLoc.x() < 100);
+ if((currLoc.y() < 10 or currLoc.y() > range.height()-40) and !bounce) {
+ v.setY((v.y() * -1) + (qrand() % 20 - 10));
+ }else if((currLoc.x() > range.width()-10 or currLoc.x() < 10) and !bounce) {
+ v.setX((v.x() * -1) + (qrand() % 20 - 10));
+ }
+ currLoc.setX(currLoc.x() + v.x());
+ currLoc.setY(currLoc.y() + v.y());
+ movement->setEndValue(currLoc);
+ }
+ void stopped(){ qDebug() << "Text Stopped"; text->hide();}
+
+public:
+ Text(QWidget *parent, QString display) : QParallelAnimationGroup(parent){
+ text = new QLabel(parent);
+ range = parent->size();
+ QPoint center = QRect( QPoint(0,0), parent->size()).center();
+
+ QString color = "rgba(" + QString::number(qrand() % 206 + 50) + ", " + QString::number(qrand() % 206 + 50) + ", " + QString::number(qrand() % 206 + 50);
+ text->setStyleSheet("QLabel {background-color: transparent; color: " + color + "); }");
+ text->setFont(QFont("Courier", 24, QFont::Bold));
+ text->setText(display);
+ QFontMetrics metrics(text->font());
+ text->setMinimumSize(QSize( metrics.horizontalAdvance(text->text())+10, metrics.height()*text->text().count("\n") +10));
+
+ movement = new QPropertyAnimation(text);
+ movement->setPropertyName("pos");
+ movement->setTargetObject(text);
+
+ this->addAnimation(movement);
+ text->show();
+ v.setX((qrand() % 100 + 50) * qPow(-1, qrand() % 2));
+ v.setY((qrand() % 100 + 50) * qPow(-1, qrand() % 2));
+ movement->setStartValue(center);
+ //Ensures the screensaver will not stop until the user wishes to login or it times out
+ this->setLoopCount(200); //number of wall bounces
+ movement->setDuration(200);
+ movement->setEndValue(QPoint(qrand() % (int)range.height(), qrand() % range.width()));
+ LoopChanged(); //load initial values
+
+ connect(this, SIGNAL(currentLoopChanged(int)), this, SLOT(LoopChanged()) );
+ connect(this, SIGNAL(finished()), this, SLOT(stopped()) );
+ }
+ ~Text(){}
+
+};
+
+class TextAnimation : public BaseAnimGroup{
+ Q_OBJECT
+public:
+ TextAnimation(QWidget *parent) : BaseAnimGroup(parent){}
+ ~TextAnimation(){
+ this->stop();
+ }
+
+ void LoadAnimations(){
+ canvas->setStyleSheet("background: black;");
+ //Read off the text that needs to be displayed
+ QString textToShow = readSetting("text", "").toString();
+ if(textToShow.isEmpty()){
+ char hname[300];
+ gethostname(hname, 300);
+ textToShow = QString::fromLocal8Bit(hname);
+ }
+ // Now create the animation
+ Text *tmp = new Text(canvas, textToShow);
+ this->addAnimation(tmp);
+ }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/VideoSlideshow.h b/src-qt5/core/lumina-desktop/src-screensaver/animations/VideoSlideshow.h
new file mode 100644
index 00000000..358b4bfb
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/VideoSlideshow.h
@@ -0,0 +1,85 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_VIDEOSLIDESHOW_ANIMATION_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_VIDEOSLIDESHOW_ANIMATION_H
+
+#include "global-includes.h"
+#include "BaseAnimGroup.h"
+
+class VideoAnimation: public BaseAnimGroup{
+ Q_OBJECT
+private:
+ QString videoPath, singleVideo;
+ QVideoWidget *videoWidget;
+ QMediaPlayer *video;
+ QStringList videoFiles;
+ bool multiple;
+
+private slots:
+
+public:
+ VideoAnimation(QWidget *parent) : BaseAnimGroup(parent){}
+
+ ~VideoAnimation(){
+ this->stop();
+ }
+
+ void LoadAnimations(){
+ canvas->setStyleSheet("background: black;");
+
+ //Load the path of the videos from the configuration file (default /usr/local/videos/)
+ videoPath = readSetting("path","/usr/local/videos").toString();
+ singleVideo = readSetting("videoLocation","").toString();
+ multiple = readSetting("multiple",true).toBool();
+ if(!videoPath.endsWith("/")){ videoPath.append("/"); }
+
+ //Set whether to copy videos on two monitors or play different videos
+ //multimonitor = settings->value("videoSlideshow/multimonitor",true).toBool();
+
+ //Set up the VideoWidget
+ video = new QMediaPlayer(canvas, QMediaPlayer::VideoSurface);
+ videoWidget = new QVideoWidget(canvas);
+ video->setVideoOutput(videoWidget);
+ videoWidget->setGeometry(QRect(QPoint(0,0), canvas->size()));
+
+ //Generate the list of files in the directory
+ videoFiles = QDir(videoPath).entryList(QDir::Files);
+ if(videoFiles.empty()){
+ qDebug() << "Current video file path has no files:" << videoPath;
+ return;
+ }
+
+ if(singleVideo.isNull())
+ singleVideo = videoPath+videoFiles[0];
+
+ //Loading a random file from a directory
+ QDesktopWidget *dw = new QDesktopWidget();
+ QMediaPlaylist *playlist = new QMediaPlaylist();
+ if(multiple) {
+ for(int i = 0; i < videoFiles.size(); i++){
+ playlist->addMedia(QUrl::fromLocalFile(videoPath+videoFiles[i]));
+ }
+ playlist->shuffle();
+ }else{
+ playlist->addMedia(QUrl::fromLocalFile(singleVideo));
+ playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
+ }
+ videoWidget->show();
+ if(multiple)
+ video->setPlaylist(playlist);
+
+ //Only play sound for one monitor to prevent messed up audio
+ if(dw->screenNumber(canvas) == 0)
+ video->setVolume(100);
+ else
+ video->setVolume(0);
+
+ video->play();
+ }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/animations/animations.pri b/src-qt5/core/lumina-desktop/src-screensaver/animations/animations.pri
new file mode 100644
index 00000000..fdc75717
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/animations/animations.pri
@@ -0,0 +1,10 @@
+SOURCES += $$PWD/BaseAnimGroup.cpp
+
+HEADERS += $$PWD/BaseAnimGroup.h \
+ $$PWD/SampleAnimation.h \
+ $${PWD}/Fireflies.h \
+ $${PWD}/Grav.h \
+ $${PWD}/ImageSlideshow.h \
+ $${PWD}/VideoSlideshow.h \
+ $${PWD}/Text.h
+#FORMS +=
diff --git a/src-qt5/core/lumina-desktop/src-screensaver/screensaver.pri b/src-qt5/core/lumina-desktop/src-screensaver/screensaver.pri
new file mode 100644
index 00000000..92cc7bd2
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/src-screensaver/screensaver.pri
@@ -0,0 +1,15 @@
+SOURCES *= $${PWD}/LLockScreen.cpp \
+ $${PWD}/LScreenSaver.cpp \
+ $${PWD}/SSBaseWidget.cpp
+
+HEADERS *= $${PWD}/LLockScreen.h \
+ $${PWD}/LScreenSaver.h \
+ $${PWD}/SSBaseWidget.h
+
+FORMS *= $${PWD}/LLockScreen.ui
+
+#update the includepath so we can just (#include <LScreenSaver.h>) as needed without paths
+INCLUDEPATH *= $${PWD}
+
+#Now include all the screensaver animations/options
+#include(animations/animations.pri)
diff --git a/src-qt5/core/lumina-pingcursor/lumina-pingcursor.pro b/src-qt5/core/lumina-pingcursor/lumina-pingcursor.pro
new file mode 100644
index 00000000..5609a35b
--- /dev/null
+++ b/src-qt5/core/lumina-pingcursor/lumina-pingcursor.pro
@@ -0,0 +1,14 @@
+include("$${PWD}/../../OS-detect.pri")
+
+QT += core gui
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+
+TARGET = lumina-pingcursor
+target.path = $${L_BINDIR}
+
+TEMPLATE = app
+
+SOURCES += main.cpp
+
+INSTALLS += target
diff --git a/src-qt5/core/lumina-pingcursor/main.cpp b/src-qt5/core/lumina-pingcursor/main.cpp
new file mode 100644
index 00000000..6e332398
--- /dev/null
+++ b/src-qt5/core/lumina-pingcursor/main.cpp
@@ -0,0 +1,44 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2020, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+
+#include <QApplication>
+#include <QPixmap>
+#include <QLabel>
+#include <QDateTime>
+#include <QPoint>
+#include <QScreen>
+#include <QDesktopWidget>
+#include <QPropertyAnimation>
+#include <QThread>
+
+int main(int argc, char **argv){
+ //Setup the application
+ QApplication App(argc, argv);
+ App.setAttribute(Qt::AA_UseHighDpiPixmaps);
+ //Display the OSD
+ QLabel splash(0, Qt::Window | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::NoDropShadowWindowHint);
+ splash.setWindowTitle("");
+ splash.resize(100,100);
+ QWidget overlay( &splash );
+ overlay.setStyleSheet("margin: 0px; border: none; background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 0, 0, 0), stop:0.52 rgba(0, 0, 0, 0), stop:0.565 rgba(82, 121, 76, 33), stop:0.65 rgba(159, 235, 148, 64), stop:0.721925 rgba(255, 238, 150, 129), stop:0.77 rgba(130, 205, 47, 204), stop:0.89 rgba(100, 128, 255, 64), stop:1 rgba(0, 0, 0, 0));");
+ overlay.setGeometry(QRect(0,0,100,100));
+ //Make sure it is centered on the current screen
+ QPoint center = QCursor::pos();
+ splash.move(center.x()-(splash.size().width()/2), center.y()-(splash.size().height()/2));
+ splash.setPixmap(QApplication::screens().at(0)->grabWindow(QApplication::desktop()->winId(), splash.x(), splash.y(), 100,100) );
+ splash.show();
+ QPropertyAnimation anim(&splash,"windowOpacity");
+ anim.setDuration(1200);
+ anim.setStartValue(1);
+ anim.setKeyValueAt(0.30, 0); anim.setKeyValueAt(0.31, 1);
+ anim.setKeyValueAt(0.60, 0); anim.setKeyValueAt(0.61, 1);
+ anim.setEndValue(0);
+ anim.start();
+ while(anim.state() != QAbstractAnimation::Stopped){ QThread::msleep(20); App.processEvents(); } //60 fps
+ splash.hide();
+ return 0;
+}
diff --git a/src-qt5/core/lumina-session/session.cpp b/src-qt5/core/lumina-session/session.cpp
index 6115c365..cba855c9 100644
--- a/src-qt5/core/lumina-session/session.cpp
+++ b/src-qt5/core/lumina-session/session.cpp
@@ -100,7 +100,7 @@ void LSession::procFinished(){
//Note about compton: It does not like running multiple sessions under the *same user*
// (even on different displays). Run a blanket killall on it when closing down so that
// any other Lumina sessions will automatically restart compton on that specific display
- QProcess::execute("killall compton");
+ QProcess::execute("pkill compton"); //More OS's have pkill instead of killall
QCoreApplication::exit(0);
}else{
//Make sure we restart the process as needed
@@ -151,10 +151,16 @@ void LSession::setupCompositor(bool force){
//Compositing manager
QSettings settings("lumina-desktop","sessionsettings");
if(settings.value("enableCompositing",false).toBool() || force){
- if(LUtils::isValidBinary("compton")){
+ if(LUtils::isValidBinary("picom")){
+ //New name for compton - removed the "-d" startup option (finally reads DISPLAY instead) (May 2020)
+ //Always use the GLX backend for picom - the xrender and hybrid backends cause lots of flickering
+ startProcess("compositing","picom --backend glx --config "+set, QStringList() << set);
+
+ }else if(LUtils::isValidBinary("compton")){
QString disp = getenv("DISPLAY");
//Always use the GLX backend for compton - the xrender and hybrid backends cause lots of flickering
startProcess("compositing","compton --backend glx -d "+disp+" --config "+set, QStringList() << set);
+
}else if(LUtils::isValidBinary("xcompmgr") && !settings.value("compositingWithGpuAccelOnly",true).toBool() ){
startProcess("compositing","xcompmgr");
}
@@ -196,12 +202,12 @@ void LSession::start(bool unified){
startProcess("wm", WM);
}
//Compositing manager
- setupCompositor();
+ setupCompositor(true);
//Desktop Next
LSingleApplication::removeLocks("lumina-desktop");
startProcess("runtime","lumina-desktop");
//ScreenSaver
- if(LUtils::isValidBinary("xscreensaver")){ startProcess("screensaver","xscreensaver -no-splash"); }
+ //if(LUtils::isValidBinary("xscreensaver")){ startProcess("screensaver","xscreensaver -no-splash"); }
}else{
//unified process
setupCompositor(true); //required for Lumina 2
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp
index 9ffe39f8..b03647f4 100644
--- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp
@@ -194,6 +194,10 @@ bool lthemeengine::setCursorTheme(QString cursorname){
else{ info << "[Icon Theme]" << newval; } //entire section missing from file
}
//Now save the file
+ if( !QFile::exists(QDir::homePath()+"/.icons/default") ){
+ //Need to create the directory first
+ QDir().mkpath(QDir::homePath()+"/.icons/default");
+ }
QFile file(QDir::homePath()+"/.icons/default/index.theme");
bool ok = false;
if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){
diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp
index 0aedb1a0..ed3ca2c3 100644
--- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp
+++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp
@@ -34,13 +34,17 @@ PlainTextEditor::PlainTextEditor(QSettings *set, QWidget *parent) : QPlainTextEd
//this->setObjectName("PlainTextEditor");
//this->setStyleSheet("QPlainTextEdit#PlainTextEditor{ }");
SYNTAX = new Custom_Syntax(settings, this->document());
+ FTIMER = new QTimer(this);
+ FTIMER->setInterval(1000);
+ FTIMER->setSingleShot(true);
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(LNW_updateWidth()) );
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(LNW_highlightLine()) );
connect(this, SIGNAL(updateRequest(const QRect&, int)), this, SLOT(LNW_update(const QRect&, int)) );
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(checkMatchChar()) );
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(cursorMoved()) );
connect(this, SIGNAL(textChanged()), this, SLOT(textChanged()) );
- connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(fileChanged()) );
+ connect(watcher, SIGNAL(fileChanged(const QString&)), FTIMER, SLOT(start()) );
+ connect(FTIMER, SIGNAL(timeout()), this, SLOT(fileChanged()));
LNW_updateWidth();
LNW_highlightLine();
}
diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h
index 8f174d4b..8f2d7e98 100644
--- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h
+++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h
@@ -55,6 +55,7 @@ private:
QString lastSaveContents;
QFileSystemWatcher *watcher;
QList<Word*> wordList;
+ QTimer *FTIMER;
//Syntax Highlighting class
Custom_Syntax *SYNTAX;
//Hunspell *hunspell;
diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h
index f7321869..4ce2424c 100644
--- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h
+++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h
@@ -85,62 +85,42 @@ public:
void setupDocument(QPlainTextEdit *edit){ syntax.SetupDocument(edit); } //simple redirect for the function in the currently-loaded rules
protected:
+
void highlightBlock(const QString &text){
+ QTextCharFormat defaultFormat;
//qDebug() << "Highlight Block:" << text;
- //Now look for any multi-line patterns (starting/continuing/ending)
+ //Now finish any multi-line patterns
int start = 0;
int splitactive = previousBlockState();
if(splitactive>syntax.rules.length()-1){ splitactive = -1; } //just in case
- while(start>=0 && start<=text.length()-1){
- //qDebug() << "split check:" << start << splitactive;
- if(splitactive>=0){
- //Find the end of the current rule
- int end = syntax.rules[splitactive].endPattern.indexIn(text, start);
- if(end==-1){
- //qDebug() << "Highlight to end of line:" << text << start;
- //rule did not finish - apply to all
- if(start>0){ setFormat(start-1, text.length()-start+1, syntax.rules[splitactive].format); }
- else{ setFormat(start, text.length()-start, syntax.rules[splitactive].format); }
- break; //stop looking for more multi-line patterns
- }else{
- //Found end point within the same line
- //qDebug() << "Highlight to particular point:" << text << start << end;
- int len = end-start+syntax.rules[splitactive].endPattern.matchedLength();
- if(start>0){ start--; len++; } //need to include the first character as well
- setFormat(start, len , syntax.rules[splitactive].format);
- start+=len; //move pointer to the end of handled range
- splitactive = -1; //done with this rule
- }
- } //end check for end match
- //Look for the start of any new split rules
- //qDebug() << "Loop over multi-line rules";
- for(int i=0; i<syntax.rules.length() && splitactive<0; i++){
- //qDebug() << "Check Rule:" << i << syntax.rules[i].startPattern << syntax.rules[i].endPattern;
- if(syntax.rules[i].startPattern.isEmpty()){ continue; }
- //qDebug() << "Look for start of split rule:" << syntax.rules[i].startPattern << splitactive;
- int newstart = syntax.rules[i].startPattern.indexIn(text,start);
- if(newstart>=start){
- //qDebug() << "Got Start of split rule:" << start << newstart << text;
- splitactive = i;
- start = newstart+1;
- if(start>=text.length()-1){
- //qDebug() << "Special case: start now greater than line length";
- //Need to apply highlighting to this section too - start matches the end of the line
- setFormat(start-1, text.length()-start+1, syntax.rules[splitactive].format);
- }
- }
+ //qDebug() << "split check:" << start << splitactive;
+ if(splitactive>=0){
+ //Find the end of the current rule
+ int end = syntax.rules[splitactive].endPattern.indexIn(text, start);
+ if(end==-1){
+ //qDebug() << "Highlight to end of line:" << text << start;
+ //rule did not finish - apply to all
+ if(start>0){ setFormat(start-1, text.length()-start+1, syntax.rules[splitactive].format); }
+ else{ setFormat(start, text.length()-start, syntax.rules[splitactive].format); }
+ }else{
+ //Found end point within the same line
+ //qDebug() << "Highlight to particular point:" << text << start << end;
+ int len = end-start+syntax.rules[splitactive].endPattern.matchedLength();
+ if(start>0){ start--; len++; } //need to include the first character as well
+ setFormat(start, len , syntax.rules[splitactive].format);
+ start+=len; //move pointer to the end of handled range
+ splitactive = -1; //done with this rule
}
- if(splitactive<0){ break; } //no other rules found - go ahead and exit the loop
- } //end scan over line length and multi-line formats
+ } //end check for end of pre-existing multi-line block match
+ setCurrentBlockState(splitactive); //tag this block as continuing as well
- setCurrentBlockState(splitactive);
- //Do all the single-line patterns
- for(int i=0; i<syntax.rules.length(); i++){
- if(syntax.rules[i].pattern.isEmpty()){ continue; } //not a single-line rule
+ //Do all the single-line patterns
+ for(int i=0; i<syntax.rules.length() && splitactive<0; i++){
+ if(syntax.rules[i].pattern.isEmpty()){ continue; } //not a single-line rule
QRegExp patt(syntax.rules[i].pattern); //need a copy of the rule's pattern (will be changing it below)
int index = patt.indexIn(text);
- if(splitactive>=0 || index<start){ continue; } //skip this one - falls within a multi-line pattern above
+ if( index<start ){ continue; } //skip this one - falls within a multi-line pattern above
while(index>=0){
int len = patt.matchedLength();
if(format(index)==currentBlock().charFormat()){ setFormat(index, len, syntax.rules[i].format); } //only apply highlighting if not within a section already
@@ -148,10 +128,37 @@ protected:
}
}//end loop over normal (single-line) patterns
+ //Look for the start of any new split rules
+ //qDebug() << "Loop over multi-line rules";
+ for(int i=0; i<syntax.rules.length() && splitactive<0; i++){
+ //qDebug() << "Check Rule:" << i << syntax.rules[i].startPattern << syntax.rules[i].endPattern;
+ if(syntax.rules[i].startPattern.isEmpty()){ continue; }
+ //qDebug() << "Look for start of split rule:" << syntax.rules[i].startPattern << splitactive;
+ int newstart = syntax.rules[i].startPattern.indexIn(text,start);
+ if(newstart>=start && (format(newstart) == defaultFormat) ){ //only start multi-line formatting if it is not already contained in a single-line formatting
+ //qDebug() << "Got Start of split rule:" << start << newstart << text << (format(newstart) != defaultFormat);
+ splitactive = i;
+ start = newstart+1;
+ int end = syntax.rules[splitactive].endPattern.indexIn(text, start);
+ if(end>0){ //end of multi-line comment in the same block
+ setFormat(start-1, end-start+1, syntax.rules[splitactive].format);
+ start = end+1;
+ }else{
+ setCurrentBlockState(splitactive);
+ }
+ if(start>=text.length()-1 || splitactive>=0){
+ //qDebug() << "Special case: start now greater than line length";
+ //Need to apply highlighting to this section too - start matches the end of the line
+ setFormat(start-1, text.length()-start+1, syntax.rules[splitactive].format);
+ break; //this goes to the end of the text block
+ }
+ }
+ }
+
//Now go through and apply any document-wide formatting rules
- QTextCharFormat fmt;
- fmt.setBackground( QColor( settings->value("colors/bracket-missing").toString() ) );
- int max = syntax.char_limit();
+ QTextCharFormat fmt;
+ fmt.setBackground( QColor( settings->value("colors/bracket-missing").toString() ) );
+ int max = syntax.char_limit();
if(max >= 0 && ( (text.length()+(text.count("\t")*(syntax.tab_length()-1)) )> max) ) {
//Line longer than it should be - highlight the offending characters
//Need to be careful about where tabs show up in the line
@@ -159,7 +166,7 @@ protected:
for(int i=0; i<text.length() and len<=max; i++){
len += (text[i]=='\t') ? syntax.tab_length() : 1;
if(len>max)
- setFormat(i, text.length()-i, fmt);
+ setFormat(i, text.length()-i, fmt);
}
}
if(syntax.highlight_excess_whitespace()){
diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax
index f2256731..6ca832e9 100644
--- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax
+++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax
@@ -9,7 +9,7 @@
"meta": {
"name": "Shell",
"file_suffix": ["sh"],
- "first_line_match":["#!/bin/sh", "#!/sbin/openrc-run"]
+ "first_line_match":["#!/bin/sh", "#!/bin/bash","#!/bin/env bash","#!/sbin/openrc-run"]
},
"format": {
"line_wrap": false,
diff --git a/src-qt5/src-cpp/plugins-screensaver.cpp b/src-qt5/src-cpp/plugins-screensaver.cpp
index 6370b068..09779bc5 100644
--- a/src-qt5/src-cpp/plugins-screensaver.cpp
+++ b/src-qt5/src-cpp/plugins-screensaver.cpp
@@ -19,6 +19,7 @@ SSPlugin::~SSPlugin(){
bool SSPlugin::isValid(){
if(data.isEmpty()){ return false; }
+ if( data.value("disabled").toBool(false) ){ return false; } //Skip any plugin with "disabled" = true
bool ok = data.contains("name") && data.contains("qml") && data.contains("description");
ok &= containsDefault("name");
ok &= containsDefault("description");
bgstack15