aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/lumina-desktop-unified/src-WM
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/lumina-desktop-unified/src-WM')
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/DEPENDENCIES17
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/GlobalDefines.h74
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.cpp102
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.h42
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.ui144
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.cpp181
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.h59
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LWindow.cpp474
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LWindow.h114
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.cpp186
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.h40
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.cpp204
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.h130
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.cpp83
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.h55
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/WMSession.cpp62
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/WMSession.h42
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.cpp27
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.h37
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/animations/SampleAnimation.h45
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/animations/animations.pri6
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/lumina-wm.pro107
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-WM/main.cpp56
23 files changed, 2287 insertions, 0 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/DEPENDENCIES b/src-qt5/core/lumina-desktop-unified/src-WM/DEPENDENCIES
new file mode 100644
index 00000000..fa0ce486
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/DEPENDENCIES
@@ -0,0 +1,17 @@
+Most dependencies required to build Lumina are listed in the
+DEPENDENCIES file in the directory above this one. The following
+are dependencies specific to Lumina's window manager.
+
+
+FreeBSD/TrueOS
+=======================
+
+
+
+
+Linux (Debian/Ubuntu)
+=======================
+
+libxcb-screensaver0-dev
+
+
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/GlobalDefines.h b/src-qt5/core/lumina-desktop-unified/src-WM/GlobalDefines.h
new file mode 100644
index 00000000..3ec278ac
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/GlobalDefines.h
@@ -0,0 +1,74 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// Global defines and enumerations for the window manager
+//===========================================
+#ifndef _LUMINA_WINDOW_MANAGER_GLOBAL_DEFINES_H
+#define _LUMINA_WINDOW_MANAGER_GLOBAL_DEFINES_H
+
+//Qt includes
+#include <QObject>
+#include <QFrame>
+#include <QLabel>
+#include <QToolButton>
+#include <QMenu>
+#include <QHBoxLayout>
+#include <QMouseEvent>
+#include <QAction>
+#include <QPoint>
+#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 <QWindow>
+#include <QWidget>
+#include <QBackingStore>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QSettings>
+#include <QHostInfo>
+#include <QDesktopWidget>
+#include <QStyleOption>
+#include <QThread>
+
+// libLumina includes
+#include <LuminaX11.h>
+#include <LuminaXDG.h>
+#include <LuminaOS.h>
+#include <LuminaThemes.h>
+#include <LuminaUtils.h>
+#include <LuminaSingleApplication.h>
+
+//XCB Includes
+#include <xcb/xcb.h>
+#include <xcb/xproto.h>
+#include <xcb/damage.h>
+#include <xcb/xcb_atom.h>
+#include <xcb/xcb_aux.h> //included in libxcb-util.so
+
+#define ANIMTIME 80 //animation time in milliseconds
+//Global flags/structures
+namespace LWM{
+ //Flags/enumerations
+ enum WindowAction{MoveResize, Show, Hide, TryClose, Closed, WA_NONE};
+
+ //Data structures
+ extern LXCB *SYSTEM;
+};
+
+
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.cpp
new file mode 100644
index 00000000..4cc6d68b
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.cpp
@@ -0,0 +1,102 @@
+//===========================================
+// 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 WAITMINS 1
+#define DEBUG 1
+
+LLockScreen::LLockScreen(QWidget *parent) : QWidget(parent), ui(new Ui::LLockScreen()){
+ ui->setupUi(this);
+ waittime = new QTimer(this);
+ waittime->setInterval(WAITMINS*60000); //(too many attempts in short time)
+ 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(); }
+}
+
+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();
+}
+
+// =================
+// PRIVATE SLOTS
+// =================
+void LLockScreen::UpdateLockInfo(){
+ QString info;
+ /*if(triesleft>0 && triesleft<NUMTRIES ){
+ if(triesleft==1){info = tr("1 Attempt Left"); }
+ else{info = QString(tr("%1 Attempts Left")).arg(QString::number(triesleft)); }
+ }else*/
+ 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();
+ bool ok = (LUtils::runCmd("lumina-checkpass", QStringList() << pass) == 0);
+ if(ok){
+ emit ScreenUnlocked();
+ this->setEnabled(true);
+ }else{
+ triesleft--;
+ if(triesleft>0){
+ this->setEnabled(true);
+ }else{
+ waittime->start();
+ refreshtime->start();
+ }
+ ui->line_password->setFocus();
+ }
+ UpdateLockInfo();
+
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.h b/src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.h
new file mode 100644
index 00000000..040499c1
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/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 "GlobalDefines.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-unified/src-WM/LLockScreen.ui b/src-qt5/core/lumina-desktop-unified/src-WM/LLockScreen.ui
new file mode 100644
index 00000000..7f0b45b8
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/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-unified/src-WM/LScreenSaver.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.cpp
new file mode 100644
index 00000000..0c92784e
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.cpp
@@ -0,0 +1,181 @@
+//===========================================
+// 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>
+
+#define DEBUG 1
+
+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);
+
+ LOCKER = new LLockScreen(this);
+ LOCKER->hide();
+ settings = new QSettings("lumina-desktop","lumina-screensaver",this);
+ SSRunning = SSLocked = updating = false;
+ this->setObjectName("LSCREENSAVERBASE");
+ this->setStyleSheet("LScreenSaver#LSCREENSAVERBASE{ background: grey; }");
+ 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(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) ){ starttimer->start(); } //time to SS start
+ 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
+ starttimer->start();
+}
+
+void LScreenSaver::reloadSettings(){
+ settings->sync();
+ starttimer->setInterval( settings->value("timedelaymin",10).toInt() * 60000 );
+ locktimer->setInterval( settings->value("lockdelaymin",1).toInt() * 60000 );
+ hidetimer->setInterval( settings->value("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::ShowScreenSaver(){
+ if(DEBUG){ qDebug() << "Showing Screen Saver:" << QDateTime::currentDateTime().toString(); }
+ SSRunning = true;
+ updating = true;
+ //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, settings);
+ 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
+ BASES[i]->setPlugin(settings->value("screenplugin"+QString::number(i+1), settings->value("defaultscreenplugin","random").toString() ).toString() );
+ }
+ //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();
+ }
+ 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::desktop()->screenGeometry(QCursor::pos()).center();
+ LOCKER->resize(LOCKER->sizeHint());
+ LOCKER->move(ctr - QPoint(LOCKER->width()/2, LOCKER->height()/2) );
+ LOCKER->show();
+ //Start the timer for hiding the lock screen due to inactivity
+ UpdateTimers();
+}
+
+void LScreenSaver::HideScreenSaver(){
+ if(DEBUG){ qDebug() << "Hiding Screen Saver:" << QDateTime::currentDateTime().toString(); }
+ SSRunning = false;
+ if(cBright>0){ LOS::setScreenBrightness(cBright); } //return to current brightness
+ if(!SSLocked){
+ this->hide();
+ emit ClosingScreenSaver();
+ }
+ for(int i=0; i<BASES.length(); i++){
+ BASES[i]->hide();
+ BASES[i]->stopPainting();
+ }
+ 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;
+ LOCKER->LoadSystemDetails();
+ UpdateTimers();
+}
+
+void LScreenSaver::SSFinished(){
+ if(DEBUG){ qDebug() << "Screensaver Finished:" << QDateTime::currentDateTime().toString(); }
+ SSLocked = false;
+ HideLockScreen();
+ HideScreenSaver();
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.h b/src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.h
new file mode 100644
index 00000000..5119d8b1
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LScreenSaver.h
@@ -0,0 +1,59 @@
+//===========================================
+// 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 "GlobalDefines.h"
+
+#include "SSBaseWidget.h"
+#include "LLockScreen.h"
+
+class LScreenSaver : public QWidget{
+ Q_OBJECT
+public:
+ LScreenSaver();
+ ~LScreenSaver();
+
+ bool isLocked();
+
+private:
+ QTimer *starttimer, *locktimer, *hidetimer;
+ QSettings *settings;
+ QList<SSBaseWidget*> BASES;
+ LLockScreen *LOCKER;
+ int cBright;
+ bool SSRunning, SSLocked, updating;
+
+ void UpdateTimers();
+
+public slots:
+ void start();
+ void reloadSettings();
+ void newInputEvent();
+ void LockScreenNow();
+
+private slots:
+ void ShowScreenSaver();
+ void ShowLockScreen();
+ void HideScreenSaver();
+ void HideLockScreen();
+
+ void LockScreen();
+ void SSFinished();
+
+signals:
+ void StartingScreenSaver();
+ void ClosingScreenSaver();
+
+protected:
+ void mouseMoveEvent(QMouseEvent*){
+ QTimer::singleShot(0,this, SLOT(newInputEvent()));
+ }
+
+};
+
+#endif \ No newline at end of file
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LWindow.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/LWindow.cpp
new file mode 100644
index 00000000..84ff2ffd
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LWindow.cpp
@@ -0,0 +1,474 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LWindow.h"
+
+LWindowFrame::LWindowFrame(WId client, QWidget *parent) : QFrame(parent, Qt::X11BypassWindowManagerHint){
+ activeState = LWindowFrame::Normal;
+ CID = client;
+ lastAction = LWM::WA_NONE;
+ Closing = false;
+ //qDebug() << "New Window:" << CID << "Frame:" << this->winId();
+ this->setMouseTracking(true); //need this to determine mouse location when not clicked
+ this->setObjectName("LWindowFrame");
+ this->setStyleSheet("LWindowFrame#LWindowFrame{ border: 2px solid white; border-radius:3px; } QWidget#TitleBar{background: grey; } QLabel{ color: black; }");
+ InitWindow(); //initially create all the child widgets
+ //LWM::SYSTEM->setupEventsForFrame(this->winId());
+ updateAppearance(); //this loads the appearance based on window/theme settings
+ //QApplication::processEvents();
+ //Now set the frame size on this window
+ SyncSize();
+ SyncText();
+ this->show();
+}
+
+LWindowFrame::~LWindowFrame(){
+}
+
+// =================
+// PRIVATE
+// =================
+void LWindowFrame::InitWindow(){
+ anim = new QPropertyAnimation(this); //For simple window animations
+ anim->setTargetObject(this);
+ anim->setDuration(ANIMTIME); //In milliseconds
+ connect(anim, SIGNAL(finished()), this, SLOT(finishedAnimation()) );
+ titleBar = new QLabel(this); //This is the "container" for all the title buttons/widgets
+ titleBar->setObjectName("TitleBar");
+ titleBar->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
+ titleBar->setFocusPolicy(Qt::NoFocus);
+ titleBar->setCursor(Qt::ArrowCursor);
+ title = new QLabel(this); //Shows the window title/text
+ title->setObjectName("Title");
+ title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ title->setCursor(Qt::ArrowCursor);
+ title->setFocusPolicy(Qt::NoFocus);
+ icon = new QLabel(this); //Contains the window icon
+ icon->setObjectName("Icon");
+ icon->setCursor(Qt::ArrowCursor);
+ icon->setFocusPolicy(Qt::NoFocus);
+ minB = new QToolButton(this); //Minimize Button
+ minB->setObjectName("Minimize");
+ minB->setCursor(Qt::ArrowCursor);
+ minB->setFocusPolicy(Qt::NoFocus);
+ connect(minB, SIGNAL(clicked()), this, SLOT(minClicked()) );
+ maxB = new QToolButton(this); //Maximize Button
+ maxB->setObjectName("Maximize");
+ maxB->setCursor(Qt::ArrowCursor);
+ maxB->setFocusPolicy(Qt::NoFocus);
+ connect(maxB, SIGNAL(clicked()), this, SLOT(maxClicked()) );
+ closeB = new QToolButton(this);
+ closeB->setObjectName("Close");
+ closeB->setCursor(Qt::ArrowCursor);
+ closeB->setFocusPolicy(Qt::NoFocus);
+ connect(closeB, SIGNAL(clicked()), this, SLOT(closeClicked()) );
+ otherB = new QToolButton(this); //Button to place any other actions
+ otherB->setObjectName("Options");
+ otherB->setCursor(Qt::ArrowCursor);
+ otherB->setPopupMode(QToolButton::InstantPopup);
+ otherB->setStyleSheet("QToolButton::menu-indicator{ image: none; }");
+ otherB->setFocusPolicy(Qt::NoFocus);
+ otherM = new QMenu(this); //menu of "other" actions for the window
+ otherB->setMenu(otherM);
+ connect(otherM, SIGNAL(triggered(QAction*)), this, SLOT(otherClicked(QAction*)) );
+ //Now assemble the titlebar
+ QHBoxLayout *HL = new QHBoxLayout(this);
+ HL->setContentsMargins(0,0,0,0);
+ HL->addWidget(otherB);
+ HL->addWidget(icon);
+ HL->addWidget(title);
+ HL->addWidget(minB);
+ HL->addWidget(maxB);
+ HL->addWidget(closeB);
+ titleBar->setLayout(HL);
+ QVBoxLayout *VL = new QVBoxLayout(this);
+ this->setLayout(VL);
+ //The WinWidget container appears shifted right/down by 1 pixel for some reason
+ // Adjust the margins to account for this variation
+ VL->setContentsMargins(1,1,2,2);
+ VL->setSpacing(0);
+ //Have the window take the same initial size of the client window
+ QRect geom = LWM::SYSTEM->WM_Window_Geom(CID);
+ qDebug() << " - Load Size Hints" << "initial size:" << geom.size();
+ icccm_size_hints SH = LWM::SYSTEM->WM_ICCCM_GetNormalHints(CID);
+ qDebug() << " - - Got Normal Hints";
+ if(!SH.isValid()){ SH = LWM::SYSTEM->WM_ICCCM_GetSizeHints(CID); }
+ qDebug() << " - - Start resizing...";
+ if(SH.base_width>geom.width() && SH.base_height>geom.height()){ this->resize(SH.base_width, SH.base_height); }
+ else if(SH.min_width>geom.width() && SH.min_height>geom.height()){ this->resize(SH.min_width, SH.min_height); }
+ else if(SH.width>geom.width() && SH.height>geom.height()){ this->resize(SH.width, SH.height); }
+ else if(geom.isNull()){ this->resize(100,80); }
+ else{ this->resize( geom.size() ); }
+ qDebug() << " - done";
+
+ //Now embed the native window into the frame
+ WIN = QWindow::fromWinId(CID);
+ WinWidget = QWidget::createWindowContainer( WIN, this);
+ WinWidget->setCursor(Qt::ArrowCursor); //this is just a fallback - the window itself will adjust it
+ //WINBACK = new QBackingStore(WIN); //create a data backup for the widget
+
+ //Now assemble te initial layout for the window (all while still invisible)
+ /*VL->addWidget(titleBar);
+ VL->addWidget(WinWidget);
+ VL->setStretch(1,1);*/
+}
+
+LWindowFrame::ModState LWindowFrame::getStateAtPoint(QPoint pt, bool setoffset){
+ //Note: pt should be in widget-relative coordinates, not global
+ if(!this->layout()->geometry().contains(pt)){
+ //above the frame itself - need to figure out which quadrant it is in (8-directions)
+ if(pt.y() < 3){
+ //One of the top options
+ if(pt.x() < 3){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
+ return ResizeTopLeft;
+ }else if(pt.x() > (this->width()-3)){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(pt.y()); } //difference from top-right corner
+ return ResizeTopRight;
+ }else{
+ if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter)
+ return ResizeTop;
+ }
+ }else if(pt.y() > (this->height()-3) ){
+ //One of the bottom options
+ if(pt.x() < 3){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
+ return ResizeBottomLeft;
+ }else if(pt.x() > (this->width()-3)){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-right corner
+ return ResizeBottomRight;
+ }else{
+ if(setoffset){ offset.setX(0); offset.setY(this->height() - pt.y()); } //difference from bottom edge (X does not matter)
+ return ResizeBottom;
+ }
+ }else{
+ //One of the side options
+ if(pt.x() < 3){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter)
+ return ResizeLeft;
+ }else if(pt.x() > (this->width()-3) ){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(0); } //difference from right edge (Y does not matter)
+ return ResizeRight;
+ }else{
+ return Normal;
+ }
+ }
+ }
+ return Normal;
+}
+
+void LWindowFrame::setMouseCursor(ModState state, bool override){
+ Qt::CursorShape shape;
+ switch(state){
+ case Normal:
+ shape = Qt::ArrowCursor;
+ break;
+ case Move:
+ shape = Qt::SizeAllCursor;
+ break;
+ case ResizeTop:
+ shape = Qt::SizeVerCursor;
+ break;
+ case ResizeTopRight:
+ shape = Qt::SizeBDiagCursor;
+ break;
+ case ResizeRight:
+ shape = Qt::SizeHorCursor;
+ break;
+ case ResizeBottomRight:
+ shape = Qt::SizeFDiagCursor;
+ break;
+ case ResizeBottom:
+ shape = Qt::SizeVerCursor;
+ break;
+ case ResizeBottomLeft:
+ shape = Qt::SizeBDiagCursor;
+ break;
+ case ResizeLeft:
+ shape = Qt::SizeHorCursor;
+ break;
+ case ResizeTopLeft:
+ shape = Qt::SizeFDiagCursor;
+ break;
+ }
+ if(override){
+ QApplication::setOverrideCursor(QCursor(shape));
+ }else{
+ this->setCursor(shape);
+ }
+}
+
+// ==========================
+// WINDOW INTERACTIONS
+//==========================
+void LWindowFrame::SyncSize(bool fromwin){
+ //sync the window/frame geometries (generally only done before embedding the client window)
+ int frame = this->frameWidth();
+ int TH = titleBar->height();
+ //Now load the information about the window and adjust the frame to match
+ if(fromwin){ lastGeom = LWM::SYSTEM->WM_Window_Geom(CID); }
+ else{ lastGeom = this->geometry(); }
+ qDebug() << "Initial Size:" << lastGeom << frame << TH;
+ //Add in the frame size
+ lastGeom.moveTop(lastGeom.y()-frame-TH);
+ lastGeom.setHeight(lastGeom.height()+(2*frame)+TH);
+ lastGeom.moveLeft(lastGeom.x()-frame);
+ lastGeom.setWidth( lastGeom.width()+(2*frame));
+ QList<unsigned int> margins;
+ margins << frame << frame << frame+TH << frame; //L/R/Top/Bottom
+ qDebug() << " - With Frame:" << lastGeom;
+ //Now adjust for a out-of-bounds location
+ if(lastGeom.x() < 0){ lastGeom.moveLeft(0); }
+ if(lastGeom.y() < 0){ lastGeom.moveTop(0); }
+ qDebug() << " - Adjusted:" << lastGeom;
+ this->setGeometry(lastGeom);
+ LWM::SYSTEM->WM_Set_Frame_Extents(CID, margins);
+}
+
+void LWindowFrame::SyncText(){
+ QString txt = WIN->title();
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowName(CID); }
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->OldWindowName(CID); }
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowVisibleName(CID); }
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowIconName(CID); }
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowVisibleIconName(CID); }
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->WM_ICCCM_GetClass(CID); }
+ title->setText(txt);
+}
+
+// SIMPLE ANIMATIONS
+void LWindowFrame::showAnimation(LWM::WindowAction act){
+ bool useanimation = (act!=lastAction);
+ if(anim->state()==QAbstractAnimation::Running){
+ qDebug() << "New Animation Event:" << act;
+ return;
+ }
+ //Setup the animation routine
+ if(act==LWM::Show){
+ if(useanimation){
+ lastGeom = this->geometry();
+ //Expand out from center point
+ anim->setPropertyName("geometry");
+ anim->setStartValue( QRect(lastGeom.center(), QSize(0,0) ) );
+ anim->setEndValue( this->geometry() );
+ //Fade in gradually
+ //anim->setPropertyName("windowOpacity");
+ //anim->setStartValue( 0.0 );
+ //anim->setEndValue( 1.0 );
+ }else{
+ ShowClient(true);
+ this->raise();
+ this->show(); //just show it right away
+ }
+
+ }else if(act==LWM::Hide){
+ if(useanimation){
+ //Collapse in on center point
+ lastGeom = this->geometry();
+ anim->setPropertyName("geometry");
+ anim->setStartValue( QRect(this->geometry()) );
+ anim->setEndValue( QRect(this->geometry().center(), QSize(0,0) ) );
+ }else{
+ this->hide(); //just hide it right away
+ }
+ }else if(act==LWM::Closed){
+ //Need to clean up the container widget first to prevent XCB errors
+ //qDebug() << "Window Closed:" << WIN->winId() << CID;
+ if(useanimation){
+ //Collapse in on center line
+ lastGeom = this->geometry();
+ anim->setPropertyName("geometry");
+ anim->setStartValue( QRect(this->geometry()) );
+ anim->setEndValue( QRect(this->geometry().x(), this->geometry().center().y(), this->width(), 0 ) );
+ }else{
+ CloseAll(); //just hide it right away
+ }
+ }
+ if(useanimation){
+ ShowClient(false);
+ this->show();
+ qDebug() << " - Starting Animation:" << act;
+ lastAction = act;
+ anim->start();
+ };
+}
+
+void LWindowFrame::ShowClient(bool show){
+ if(show && this->layout()->indexOf(WinWidget)<0 && !Closing){
+ while(this->layout()->count()>0){ this->layout()->removeItem(0); }
+ this->layout()->addWidget(titleBar);
+ this->layout()->setAlignment(titleBar, Qt::AlignTop);
+ this->layout()->addWidget(WinWidget);
+ static_cast<QVBoxLayout*>(this->layout())->setStretch(1,1);
+ LWM::SYSTEM->WM_ShowWindow(CID);
+ }else if( !show && this->layout()->indexOf(WinWidget)>=0){
+ LWM::SYSTEM->WM_HideWindow(CID);
+ this->layout()->removeWidget(WinWidget);
+ }
+}
+
+void LWindowFrame::finishedAnimation(){
+ //Also set any final values
+ qDebug() << " - Finished Animation:" << lastAction;
+ switch(lastAction){
+ case LWM::Show:
+ ShowClient(true);
+ break;
+ case LWM::Closed:
+ case LWM::Hide:
+ this->lower();
+ this->hide();
+ LWM::SYSTEM->WM_HideWindow(this->winId());
+ default:
+ break;
+ }
+ if(Closing){
+ qDebug() << "Emitting finished signal";
+ emit Finished();
+ }
+}
+
+// =================
+// PUBLIC SLOTS
+// =================
+void LWindowFrame::updateAppearance(){
+ //Reload any button icons and such
+ minB->setIcon(LXDG::findIcon("window-suppressed",""));
+ maxB->setIcon(LXDG::findIcon("view-fullscreen",""));
+ closeB->setIcon(LXDG::findIcon("application-exit",""));
+ otherB->setIcon(LXDG::findIcon("configure",""));
+}
+
+void LWindowFrame::windowChanged(LWM::WindowAction act){
+ //A window property was changed - update accordingly
+ switch(act){
+ case LWM::Closed:
+ Closing = true;
+ case LWM::Hide:
+ case LWM::Show:
+ showAnimation(act);
+ break;
+ case LWM::MoveResize:
+ //Re-adjust to the new position/size of the window
+ SyncSize(true);
+ break;
+ default:
+ break; //do nothing
+ }
+}
+// =================
+// PRIVATE SLOTS
+// =================
+void LWindowFrame::closeClicked(){
+ qDebug() << "Closing Window" << LWM::SYSTEM->WM_ICCCM_GetClass(CID);
+ //First try the close event to let the client app do cleanup/etc
+ LWM::SYSTEM->WM_CloseWindow(CID);
+}
+
+void LWindowFrame::minClicked(){
+ qDebug() << "Minimize Window";
+ windowChanged(LWM::Hide);
+}
+
+void LWindowFrame::maxClicked(){
+ if(normalGeom.isNull()){
+ qDebug() << "Maximize Window";
+ normalGeom = this->geometry(); //save for later
+ this->showMaximized();
+ }else{
+ qDebug() << "Restore Window";
+ this->showNormal();
+ this->setGeometry(normalGeom);
+ normalGeom = QRect(); //clear it
+ }
+}
+
+void LWindowFrame::otherClicked(QAction* act){
+ QString action = act->whatsThis();
+}
+
+void LWindowFrame::CloseAll(){
+ qDebug() << " - Closing Frame";
+ this->hide();
+ emit Finished();
+}
+// =====================
+// PROTECTED
+// =====================
+void LWindowFrame::mousePressEvent(QMouseEvent *ev){
+ qDebug() << "Frame Mouse Press Event";
+ offset.setX(0); offset.setY(0);
+ if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse
+ this->activateWindow();
+ LWM::SYSTEM->WM_Set_Active_Window(CID);
+ if(this->childAt(ev->pos())!=0){
+ //Check for any non-left-click event and skip it
+ if(ev->button()!=Qt::LeftButton){ return; }
+ activeState = Move;
+ offset.setX(ev->pos().x()); offset.setY(ev->pos().y());
+ }else{
+ //Clicked on the frame somewhere
+ activeState = getStateAtPoint(ev->pos(), true); //also have it set the offset variable
+ }
+ setMouseCursor(activeState, true); //this one is an override cursor
+
+}
+
+void LWindowFrame::mouseMoveEvent(QMouseEvent *ev){
+ ev->accept();
+ if(activeState == Normal){
+ setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
+
+ }else{
+ //Currently in a modification state
+ QRect geom = this->geometry();
+ switch(activeState){
+ case Move:
+ geom.moveTopLeft(ev->globalPos()-offset); //will not change size
+ break;
+ case ResizeTop:
+ geom.setTop(ev->globalPos().y()-offset.y());
+ break;
+ case ResizeTopRight:
+ geom.setTopRight(ev->globalPos()-offset);
+ break;
+ case ResizeRight:
+ geom.setRight(ev->globalPos().x()-offset.x());
+ break;
+ case ResizeBottomRight:
+ geom.setBottomRight(ev->globalPos()-offset);
+ break;
+ case ResizeBottom:
+ geom.setBottom(ev->globalPos().y()-offset.y());
+ break;
+ case ResizeBottomLeft:
+ geom.setBottomLeft(ev->globalPos()-offset);
+ break;
+ case ResizeLeft:
+ geom.setLeft(ev->globalPos().x()-offset.x());
+ break;
+ case ResizeTopLeft:
+ geom.setTopLeft(ev->globalPos()-offset);
+ break;
+ default:
+ break;
+ }
+ this->setGeometry(geom);
+ }
+}
+
+void LWindowFrame::mouseReleaseEvent(QMouseEvent *ev){
+ //Check for a right-click event
+ qDebug() << "Frame Mouse Release Event";
+ ev->accept();
+ if( (activeState==Normal) && (this->childAt(ev->pos())==titleBar) && (ev->button()==Qt::RightButton) ){
+ otherM->popup(ev->globalPos());
+ return;
+ }
+ activeState = Normal;
+ QApplication::restoreOverrideCursor();
+ setMouseCursor( getStateAtPoint(ev->pos()) );
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LWindow.h b/src-qt5/core/lumina-desktop-unified/src-WM/LWindow.h
new file mode 100644
index 00000000..ceefca83
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LWindow.h
@@ -0,0 +1,114 @@
+//===========================================
+// 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_WINDOW_FRAME_H
+#define _LUMINA_DESKTOP_WINDOW_FRAME_H
+
+#include "GlobalDefines.h"
+
+class LWindowFrame : public QFrame{
+ Q_OBJECT
+public:
+ LWindowFrame(WId client, QWidget *parent = 0); //MUST have a valid client window
+ ~LWindowFrame();
+
+private:
+ void InitWindow(); //Initialize all the internal widgets
+
+ //Window status
+ enum ModState{Normal, Move, ResizeTop, ResizeTopRight, ResizeRight, ResizeBottomRight, ResizeBottom, ResizeBottomLeft, ResizeLeft, ResizeTopLeft};
+ ModState activeState;
+ QPoint offset; //needed for movement calculations (offset from mouse click to movement point)
+ //Functions for getting/setting state
+ ModState getStateAtPoint(QPoint pt, bool setoffset = false); //generally used for mouse location detection
+ void setMouseCursor(ModState, bool override = false); //Update the mouse cursor based on state
+
+ //General Properties/Modifications
+ WId CID; //Client ID
+ QWindow *WIN; //Embedded window container
+ QWidget *WinWidget;
+ bool Closing;
+ LWM::WindowAction lastAction;
+ //QBackingStore *WINBACK;
+ void SyncSize(bool fromwin = false); //sync the window/frame geometries
+ void SyncText();
+
+ //Window Frame Widgets/Items
+ QLabel *titleBar, *title, *icon;
+ QToolButton *minB, *maxB, *closeB, *otherB;
+ QMenu *otherM; //menu of "other" actions for the window
+ QRect normalGeom; //used for restoring back to original size after maximization/fullscreen
+
+ //Animations
+ QPropertyAnimation *anim; //used for appear/disappear animations
+ QRect lastGeom; //used for appear/disappear animations
+ void showAnimation(LWM::WindowAction); //sets lastAction
+ void ShowClient(bool show);
+
+public slots:
+ //These slots are generally used for the outside event watcher to prod for changes
+ void updateAppearance(); //reload the theme and change styling as necessary
+ void windowChanged(LWM::WindowAction);
+
+private slots:
+ void finishedAnimation(); //uses lastAction
+ void closeClicked();
+ void minClicked();
+ void maxClicked();
+ void otherClicked(QAction*);
+
+ void CloseAll();
+
+protected:
+ void mousePressEvent(QMouseEvent*);
+ void mouseMoveEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent*);
+
+signals:
+ void Finished(); //This means the window is completely finished (with animations and such) and should be removed from any lists
+
+};
+
+class LWindow : public QObject{
+ Q_OBJECT
+signals:
+ void Finished(WId client); //ready to be removed
+private:
+ WId CID;
+ LWindowFrame *FID;
+ bool needsFrame(QList<LXCB::WINDOWTYPE> list){
+ if(list.isEmpty()){ return !LWM::SYSTEM->WM_ICCCM_GetClass(CID).contains("Lumina-DE"); } //assume a normal window (fallback)
+ return !(list.contains(LXCB::T_DESKTOP) || list.contains(LXCB::T_DOCK) || list.contains(LXCB::T_TOOLBAR) \
+ || list.contains(LXCB::T_SPLASH) || list.contains(LXCB::T_DROPDOWN_MENU) \
+ || list.contains(LXCB::T_TOOLTIP) || list.contains(LXCB::T_POPUP_MENU) || list.contains(LXCB::T_TOOLTIP) \
+ || list.contains(LXCB::T_COMBO) || list.contains(LXCB::T_DND) );
+ }
+private slots:
+ void frameclosed(){
+ qDebug() << " - Window got frame closed signal";
+ //FID->close();
+ //delete FID;
+ emit Finished(CID);
+ }
+public:
+ LWindow(WId client){
+ FID= 0;
+ CID = client;
+ if( needsFrame(LWM::SYSTEM->WM_Get_Window_Type(CID)) ){
+ FID = new LWindowFrame(CID);
+ connect(FID, SIGNAL(Finished()), this, SLOT(frameclosed()) );
+ }
+ }
+ ~LWindow(){
+ if(FID!=0){delete FID;}
+ }
+
+ WId clientID(){ return CID; }
+ bool hasFrame(){ return FID!=0; }
+ LWindowFrame* frame(){ return FID; }
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.cpp
new file mode 100644
index 00000000..14ce6897
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.cpp
@@ -0,0 +1,186 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LWindowManager.h"
+
+#define DEBUG 1
+
+LWindowManager::LWindowManager(){
+
+}
+
+LWindowManager::~LWindowManager(){
+
+}
+
+bool LWindowManager::start(){
+ //Setup the initial screen/session values
+ LWM::SYSTEM->WM_Set_Root_Supported();
+ LWM::SYSTEM->WM_SetNumber_Desktops(1);
+ LWM::SYSTEM->WM_Set_Current_Desktop(0);
+ LWM::SYSTEM->WM_Set_Desktop_Names(QStringList() << "one");
+ QRect totgeom;
+ QList<QPoint> viewports;
+ QList<QRect> geoms;
+ for(int i=0; i<QApplication::desktop()->screenCount(); i++){
+ geoms << QApplication::desktop()->screen(i)->geometry();
+ viewports << QPoint(0,0);
+ totgeom = QApplication::desktop()->screen(i)->geometry();
+ }
+ LWM::SYSTEM->WM_Set_Desktop_Geometry(totgeom.size());
+ LWM::SYSTEM->WM_Set_Desktop_Viewport(viewports);
+ LWM::SYSTEM->WM_Set_Workarea(geoms);
+ //Should probably do a quick loop over any existing windows with the root as parent (just in case)
+ QList<WId> initial = LWM::SYSTEM->WM_RootWindows();
+ for(int i=0; i<initial.length(); i++){
+ NewWindow(initial[i], false); //These ones did not explicitly request to be mapped
+ }
+ RestackWindows();
+ return true;
+}
+
+void LWindowManager::stop(){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->hasFrame()){
+ LWM::SYSTEM->UnembedWindow(WINS[i]->clientID());
+ WINS[i]->frame()->close();
+ }
+ }
+}
+//===============
+// PUBLIC SLOTS
+//===============
+void LWindowManager::NewWindow(WId win, bool requested){
+ //Verify that this window can/should be managed first
+ //if(DEBUG){ qDebug() << "New Window:" << LWM::SYSTEM->WM_ICCCM_GetClass(win); }
+ QString wclass = LWM::SYSTEM->WM_ICCCM_GetClass(win);
+ if( wclass.contains("lumina-wm",Qt::CaseInsensitive) ){ return; } //just in case: prevent recursion
+ else{
+ bool ok = (wclass.isEmpty() ? false : LWM::SYSTEM->WM_ManageWindow(win, requested) );
+ if(!ok){
+ //See if this window is just a transient pointing to some other window
+ WId tran = LWM::SYSTEM->WM_ICCCM_GetTransientFor(win);
+ if(tran!=win && tran!=0){
+ win = tran;
+ ok = LWM::SYSTEM->WM_ManageWindow(win);
+ }
+ }
+ if(!ok){ return; }
+ }
+ if(DEBUG){ qDebug() << "New Managed Window:" << LWM::SYSTEM->WM_ICCCM_GetClass(win); }
+ LWM::SYSTEM->WM_Set_Active_Window(win);
+ LWindow *lwin = new LWindow(win);
+ connect(lwin, SIGNAL(Finished(WId)), this, SLOT(FinishedWindow(WId)) );
+ WINS << lwin;
+ if(lwin->hasFrame()){
+ lwin->frame()->windowChanged(LWM::Show); //Make sure to show it right away
+ }else{
+ LWM::SYSTEM->WM_ShowWindow(win); //just map the window right now
+ }
+}
+
+void LWindowManager::ClosedWindow(WId win){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->clientID()==win){
+ qDebug() << " - Closed Window";
+ if(WINS[i]->hasFrame()){ WINS[i]->frame()->windowChanged(LWM::Closed); } //do any animations/cleanup
+ else{ FinishedWindow(win); }
+ break;
+ }
+ }
+}
+
+void LWindowManager::ModifyWindow(WId win, LWM::WindowAction act){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->clientID()==win){
+ if(WINS[i]->hasFrame()){ WINS[i]->frame()->windowChanged(act); }
+ return;
+ }
+ }
+ //If it gets this far - it is an unmanaged window
+ if(act==LWM::Show){
+ NewWindow(win);
+ }
+ RestackWindows();
+}
+
+void LWindowManager::RestackWindows(){
+ Stack_Desktop.clear(); Stack_Below.clear(); Stack_Normal.clear(); Stack_Above.clear(); Stack_Fullscreen.clear();
+ QList<WId> currwins;
+ int cwork = LWM::SYSTEM->WM_Get_Current_Desktop();
+ int winwork = -1;
+ QList<LXCB::WINDOWSTATE> states;
+ QList<LXCB::WINDOWTYPE> types;
+ for(int i=0; i<WINS.length(); i++){
+ //Only show windows on the current desktop
+ winwork = LWM::SYSTEM->WM_Get_Desktop(WINS[i]->clientID());
+ states = LWM::SYSTEM->WM_Get_Window_States(WINS[i]->clientID());
+ types = LWM::SYSTEM->WM_Get_Window_Type(WINS[i]->clientID());
+ WId id = WINS[i]->clientID();
+ if(WINS[i]->hasFrame()){ id = WINS[i]->frame()->winId(); }
+ if(winwork<0 || winwork == cwork || states.contains(LXCB::S_STICKY) ){
+ //Now check the state/type and put it in the proper stack
+ currwins << WINS[i]->clientID(); //add this to the overall "age" list
+ //Now add it to the proper stack
+ if(types.contains(LXCB::T_DESKTOP)){ Stack_Desktop << id; }
+ else if(states.contains(LXCB::S_BELOW)){ Stack_Below << id; }
+ else if(types.contains(LXCB::T_DOCK) || states.contains(LXCB::S_ABOVE) ){ Stack_Above << id; }
+ else if(states.contains(LXCB::S_FULLSCREEN)){ Stack_Fullscreen << id; }
+ else{ Stack_Normal << id; }
+ }
+ }
+ //Active Window management
+ WId active = LWM::SYSTEM->WM_Get_Active_Window();
+ if(Stack_Desktop.contains(active)){ Stack_Desktop.removeAll(active); Stack_Desktop << active; }
+ else if(Stack_Below.contains(active)){ Stack_Below.removeAll(active); Stack_Below << active; }
+ else if(Stack_Normal.contains(active)){ Stack_Normal.removeAll(active); Stack_Normal << active; }
+ else if(Stack_Above.contains(active)){ Stack_Above.removeAll(active); Stack_Above << active; }
+ else if(Stack_Fullscreen.contains(active)){ Stack_Fullscreen.removeAll(active); Stack_Fullscreen << active; }
+
+ //Now set the root properties for these lists
+ LWM::SYSTEM->WM_Set_Client_List(currwins, false); //age-ordered version
+ LWM::SYSTEM->WM_Set_Client_List(QList<WId>() << Stack_Desktop << Stack_Below << Stack_Normal << Stack_Above << Stack_Fullscreen, true); //stacking order version
+ //Now re-paint (in order) the windows
+ RepaintWindows();
+}
+
+void LWindowManager::RepaintWindows(){
+ //Go through all the current windows (in stacking order) and re-paint them
+ for(int i=0; i<Stack_Desktop.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Desktop[i]);
+ }
+ for(int i=0; i<Stack_Below.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Below[i]);
+ }
+ for(int i=0; i<Stack_Normal.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Normal[i]);
+ }
+ for(int i=0; i<Stack_Above.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Above[i]);
+ }
+ for(int i=0; i<Stack_Fullscreen.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Fullscreen[i]);
+ }
+}
+
+//=================
+// PRIVATE SLOTS
+//=================
+void LWindowManager::FinishedWindow(WId win){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->clientID() == win){
+ qDebug() << " - Finished Window";
+ if(win == LWM::SYSTEM->WM_Get_Active_Window()){
+ if(i==0 && WINS.length()>1){ LWM::SYSTEM->WM_Set_Active_Window(WINS[i+1]->clientID()); }
+ else if(i>0){ LWM::SYSTEM->WM_Set_Active_Window(WINS[i-1]->clientID()); }
+ else{ LWM::SYSTEM->WM_Set_Active_Window( QX11Info::appRootWindow()); }
+ }
+ delete WINS.takeAt(i); break;
+ }
+ }
+ //Now update the list of clients
+ RestackWindows();
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.h b/src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.h
new file mode 100644
index 00000000..203efa1b
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LWindowManager.h
@@ -0,0 +1,40 @@
+//===========================================
+// 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_WINDOW_MANAGER_MAIN_CLASS_H
+#define _LUMINA_DESKTOP_WINDOW_MANAGER_MAIN_CLASS_H
+
+#include "GlobalDefines.h"
+#include "LWindow.h"
+
+class LWindowManager : public QObject{
+ Q_OBJECT
+public:
+ LWindowManager();
+ ~LWindowManager();
+
+ bool start();
+ void stop();
+
+private:
+ QList<LWindow*> WINS;
+ QList<WId> Stack_Desktop, Stack_Below, Stack_Normal, Stack_Above, Stack_Fullscreen;
+public slots:
+ void NewWindow(WId win, bool requested = true);
+ void ClosedWindow(WId win);
+ void ModifyWindow(WId win, LWM::WindowAction act);
+
+ void RestackWindows();
+ void RepaintWindows();
+
+private slots:
+ void FinishedWindow(WId win); //This is used for LWindow connections/animations
+
+signals:
+ void NewFullScreenWindows(QList<WId>);
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.cpp
new file mode 100644
index 00000000..abbe5a5a
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.cpp
@@ -0,0 +1,204 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LXcbEventFilter.h"
+
+//==================================================
+// NOTE: All the XCB interactions and atoms are accessed via:
+// LWM::SYSTEM->EWMH.(atom name)
+// LWM::SYSTEM->(do something)
+// (LWM::SYSTEM is the global XCB structure)
+//==================================================
+
+#include <LuminaX11.h>
+#include <QDebug>
+
+//#include <xcb/screensaver.h>
+
+#define DEBUG 1
+// Also keep the root window/screen around for use in the filters
+namespace L_XCB{
+ xcb_screen_t *root_screen;
+ xcb_window_t root;
+}
+
+//Constructor for the Event Filter wrapper
+EventFilter::EventFilter() : QObject(){
+ EF = new XCBEventFilter(this);
+ L_XCB::root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
+ L_XCB::root = L_XCB::root_screen->root;
+ SSLocked = false;
+ WMFlag = 0;
+}
+
+void EventFilter::start(){
+ if(DEBUG){ qDebug() << " - Install event filter..."; }
+ QCoreApplication::instance()->installNativeEventFilter(EF);
+ if(DEBUG){ qDebug() << " - Run request check..."; }
+ if(!LWM::SYSTEM->setupEventsForRoot()){
+ qCritical() << "[ERROR] Unable to setup WM event retrieval. Is another WM running?";
+ exit(1);
+ }
+ if(DEBUG){ qDebug() << " - Create WM ID Window"; }
+ WMFlag = LWM::SYSTEM->WM_CreateWindow();
+ LWM::SYSTEM->setupEventsForRoot(WMFlag);
+ LWM::SYSTEM->WM_Set_Supporting_WM(WMFlag);
+ QCoreApplication::instance()->flush();
+}
+
+//Constructor for the XCB event filter
+XCBEventFilter::XCBEventFilter(EventFilter *parent) : QAbstractNativeEventFilter(){
+ obj = parent;
+ InitAtoms();
+}
+
+//This function format taken directly from the Qt5.3 documentation
+bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
+{
+ //if(stopping){ return false; } //don't do any parsing
+ //qDebug() << "New Event";
+ bool stopevent = false;
+ if(eventType=="xcb_generic_event_t"){
+ //Convert to known event type (for X11 systems)
+ xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
+ //Now parse the event and emit signals as necessary
+ switch( ev->response_type & ~0x80){
+//==============================
+// INTERACTIVITY EVENTS
+//==============================
+ case XCB_KEY_PRESS:
+ //This is a keyboard key press
+ //qDebug() << "Key Press Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_key_press_event_t *) ev)->root ); //use the main "root" window - not the child widget
+ break;
+ case XCB_KEY_RELEASE:
+ //This is a keyboard key release
+ //qDebug() << "Key Release Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_key_release_event_t *) ev)->root ); //use the main "root" window - not the child widget
+ break;
+ case XCB_BUTTON_PRESS:
+ //This is a mouse button press
+ //qDebug() << "Button Press Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_button_press_event_t *) ev)->root ); //use the main "root" window - not the child widget
+ if(!stopevent){
+ //Activate the window right now if needed
+ if(LWM::SYSTEM->WM_Get_Active_Window()!=((xcb_button_press_event_t *) ev)->root){
+ LWM::SYSTEM->WM_Set_Active_Window( ((xcb_button_press_event_t *) ev)->root);
+ }
+ }
+ break;
+ case XCB_BUTTON_RELEASE:
+ //This is a mouse button release
+ //qDebug() << "Button Release Event";
+ //xcb_button_release_event_t *tmp = (xcb_button_release_event_t *)ev;
+ stopevent = BlockInputEvent( ((xcb_button_release_event_t *) ev)->root ); //use the main "root" window - not the child widget
+ break;
+ case XCB_MOTION_NOTIFY:
+ //This is a mouse movement event
+ //qDebug() << "Motion Notify Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_motion_notify_event_t *) ev)->root ); //use the main "root" window - not the child widget);
+ break;
+ case XCB_ENTER_NOTIFY:
+ //This is a mouse movement event when mouse goes over a new window
+ //qDebug() << "Enter Notify Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_enter_notify_event_t *) ev)->root );
+ break;
+ case XCB_LEAVE_NOTIFY:
+ //This is a mouse movement event when mouse goes leaves a window
+ //qDebug() << "Leave Notify Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent();
+ break;
+//==============================
+ case XCB_EXPOSE:
+ //qDebug() << "Expose Notify Event:";
+ //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
+ break;
+//==============================
+ case XCB_MAP_NOTIFY:
+ break; //This is just a notification that a window was mapped - nothing needs to change here
+ case XCB_MAP_REQUEST:
+ qDebug() << "Window Map Request Event";
+ obj->emit ModifyWindow( ((xcb_map_request_event_t *) ev)->window, LWM::Show);
+ break;
+//==============================
+ case XCB_CREATE_NOTIFY:
+ qDebug() << "Window Create Event";
+ break;
+//==============================
+ case XCB_UNMAP_NOTIFY:
+ qDebug() << "Window Unmap Event";
+ obj->emit ModifyWindow( ((xcb_unmap_notify_event_t *)ev)->window, LWM::Hide);
+ break;
+//==============================
+ case XCB_DESTROY_NOTIFY:
+ qDebug() << "Window Closed Event";
+ obj->emit WindowClosed( ((xcb_destroy_notify_event_t *) ev)->window );
+ break;
+//==============================
+ case XCB_FOCUS_IN:
+ //qDebug() << "Focus In Event:";
+ break;
+//==============================
+ case XCB_FOCUS_OUT:
+ //qDebug() << "Focus Out Event:";
+ break;
+//==============================
+ case XCB_PROPERTY_NOTIFY:
+ //qDebug() << "Property Notify Event:";
+ //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
+ break;
+//==============================
+ case XCB_CLIENT_MESSAGE:
+ //qDebug() << "Client Message Event";
+ //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
+ break;
+//==============================
+ case XCB_CONFIGURE_NOTIFY:
+ //qDebug() << "Configure Notify Event";
+ break;
+//==============================
+ case XCB_CONFIGURE_REQUEST:
+ //qDebug() << "Configure Request Event";
+ break;
+//==============================
+ case XCB_SELECTION_CLEAR:
+ //qDebug() << "Selection Clear Event";
+ break;
+//==============================
+ case 85: //not sure what event this is - but it seems to come up very often (just hide the notice)
+ case 0:
+ case XCB_GE_GENERIC:
+ break; //generic event - don't do anything special
+ default:
+ qDebug() << "Default Event:" << (ev->response_type & ~0x80);
+//==============================
+ }
+ }
+ return false;
+ //never stop event handling (this will not impact the X events themselves - just the internal screensaver/WM/widgets)
+}
+
+bool XCBEventFilter::BlockInputEvent(WId win){
+ //Checks the current state of the WM and sets the stop flag as needed
+ // - Always let the screensaver know about the event first (need to reset timers and such)
+ obj->emit NewInputEvent();
+ // - Check the state of the screensaver
+ if(obj->SSLocked){ qDebug() << "SS Locked"; return true; }
+ // - Check the state of any fullscreen apps
+ else if( win!=0 && !obj->FS_WINS.isEmpty()){
+ if(!obj->FS_WINS.contains(win) ){
+ //If this event is for an app underneath a fullscreen window - stop it
+ if(obj->FS_WINS.length() == QApplication::desktop()->screenCount()){ qDebug() << "Screens Covered"; return true; } //all screens covered right now
+ }
+ }
+ return false;
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.h b/src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.h
new file mode 100644
index 00000000..b68eedf5
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/LXcbEventFilter.h
@@ -0,0 +1,130 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2012, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class provides the XCB ->Xlib conversion necessary for Qt5 usage
+//===========================================
+#ifndef _LUMINA_DESKTOP_XCB_FILTER_H
+#define _LUMINA_DESKTOP_XCB_FILTER_H
+
+#include "GlobalDefines.h"
+
+
+/*
+List of XCB response types (since almost impossible to find good docs on XCB)
+switch (xcb_generic_event_t*->response_type & ~0x80)
+case values:
+XCB_KEY_[PRESS | RELEASE]
+XCB_BUTTON_[PRESS | RELEASE]
+XCB_MOTION_NOTIFY
+XCB_ENTER_NOTIFY
+XCB_LEAVE_NOTIFY
+XCB_FOCUS_[IN | OUT]
+XCB_KEYMAP_NOTIFY
+XCB_EXPOSE
+XCB_GRAPHICS_EXPOSURE
+XCB_VISIBILITY_NOTIFY
+XCB_CREATE_NOTIFY
+XCB_DESTROY_NOTIFY
+XCB_UNMAP_NOTIFY
+XCB_MAP_[NOTIFY | REQUEST]
+XCB_REPARENT_NOTIFY
+XCB_CONFIGURE_[NOTIFY | REQUEST]
+XCB_GRAVITY_NOTIFY
+XCB_RESIZE_REQUEST
+XCB_CIRCULATE_[NOTIFY | REQUEST]
+XCB_PROPERTY_NOTIFY
+XCB_SELECTION_[CLEAR | REQUEST | NOTIFY]
+XCB_COLORMAP_NOTIFY
+XCB_CLIENT_MESSAGE
+*/
+
+//SYSTEM TRAY STANDARD DEFINITIONS
+//#define SYSTEM_TRAY_REQUEST_DOCK 0
+//#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+//#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+
+class EventFilter : public QObject{
+ Q_OBJECT
+private:
+ QAbstractNativeEventFilter* EF;
+ WId WMFlag; //used to flag a running WM process
+
+public:
+ EventFilter();
+ ~EventFilter(){}
+
+ void start();
+
+ //Public variables for the event filter to use/check
+ QList<WId> FS_WINS; //Full-screen windows (1 per monitor) - used for hiding non-app events as needed
+ bool SSLocked;
+
+public slots:
+ void StartedSS(){ SSLocked = true; }
+ void StoppedSS(){ SSLocked = false; }
+ void FullScreenChanged(QList<WId> fslist){ FS_WINS = fslist; }
+
+signals:
+ void NewInputEvent();
+ void NewManagedWindow(WId);
+ void WindowClosed(WId);
+ void ModifyWindow(WId win, LWM::WindowAction);
+};
+
+class XCBEventFilter : public QAbstractNativeEventFilter{
+public:
+ XCBEventFilter(EventFilter *parent);
+ ~XCBEventFilter(){}
+
+ virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *);
+
+private:
+ EventFilter *obj;
+ QList<xcb_atom_t> WinNotifyAtoms, SysNotifyAtoms;
+
+ void InitAtoms(){
+ //Initialize any special atoms that we need to save/use regularly
+ //NOTE: All the EWMH atoms are already saved globally in LWM::SYSTEM->EWMH
+ WinNotifyAtoms.clear();
+ WinNotifyAtoms << LWM::SYSTEM->EWMH._NET_WM_NAME \
+ << LWM::SYSTEM->EWMH._NET_WM_VISIBLE_NAME \
+ << LWM::SYSTEM->EWMH._NET_WM_ICON_NAME \
+ << LWM::SYSTEM->EWMH._NET_WM_VISIBLE_ICON_NAME \
+ << LWM::SYSTEM->EWMH._NET_WM_ICON \
+ << LWM::SYSTEM->EWMH._NET_WM_ICON_GEOMETRY;
+
+ SysNotifyAtoms.clear();
+ SysNotifyAtoms << LWM::SYSTEM->EWMH._NET_CLIENT_LIST \
+ << LWM::SYSTEM->EWMH._NET_CLIENT_LIST_STACKING \
+ << LWM::SYSTEM->EWMH._NET_CURRENT_DESKTOP \
+ << LWM::SYSTEM->EWMH._NET_WM_STATE \
+ << LWM::SYSTEM->EWMH._NET_ACTIVE_WINDOW \
+ << LWM::SYSTEM->EWMH._NET_WM_ICON \
+ << LWM::SYSTEM->EWMH._NET_WM_ICON_GEOMETRY;
+
+ }
+
+ bool BlockInputEvent(WId win = 0); //Checks the current state of the WM and sets the stop flag as needed
+
+ //Longer Event handling functions
+ //bool ParseKeyPressEvent();
+ //bool ParseKeyReleaseEvent();
+ //bool ParseButtonPressEvent();
+ //bool ParseButtonReleaseEvent();
+ //bool ParseMotionEvent();
+ //bool ParsePropertyEvent();
+ //bool ParseClientMessageEvent();
+ //bool ParseDestroyEvent();
+ //bool ParseConfigureEvent();
+ //bool ParseKeySelectionClearEvent();
+
+
+
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.cpp
new file mode 100644
index 00000000..83b82ff8
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.cpp
@@ -0,0 +1,83 @@
+//===========================================
+// 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"
+
+#define DEBUG 1
+
+static QStringList validPlugs;
+// ========
+// PUBLIC
+// ========
+SSBaseWidget::SSBaseWidget(QWidget *parent, QSettings *set) : QWidget(parent){
+ if(validPlugs.isEmpty()){ validPlugs << "none"; } //add more later
+ settings = set; //needed to pass along for plugins to read any special options/settings
+ this->setObjectName("LuminaBaseSSWidget");
+ ANIM = 0;
+ this->setMouseTracking(true);
+}
+
+SSBaseWidget::~SSBaseWidget(){
+ if(ANIM!=0){ this->stopPainting(); }
+}
+
+void SSBaseWidget::setPlugin(QString plug){
+ plug = plug.toLower();
+ if(validPlugs.contains(plug) || plug=="random"){ plugType = plug; }
+ else{ plugType = "none"; }
+}
+
+// =============
+// PUBLIC SLOTS
+// =============
+void SSBaseWidget::startPainting(){
+ cplug = plugType;
+ //free up any old animation instance
+ if(ANIM!=0){
+ ANIM->stop(); ANIM->clear();
+ delete ANIM; ANIM = 0;
+ }
+ //If a random plugin - grab one of the known plugins
+ if(cplug=="random"){
+ QStringList valid = BaseAnimGroup::KnownAnimations();
+ if(valid.isEmpty()){ cplug = "none"; } //no known plugins
+ else{ cplug = valid[ qrand()%valid.length() ]; } //grab a random plugin
+ }
+ if(DEBUG){ qDebug() << " - Screen Saver:" << cplug; }
+ //Now list all the various plugins and start them appropriately
+ QString style;
+ if(cplug=="none"){
+ style = "background: transparent;"; //show the underlying black parent widget
+ }else{
+ style = "background: black;";
+ }
+ this->setStyleSheet("QWidget#LuminaBaseSSWidget{ "+style+"}");
+ this->repaint();
+ //If not a stylesheet-based plugin - set it here
+ if(cplug!="none"){
+ ANIM = BaseAnimGroup::NewAnimation(cplug, this, settings);
+ connect(ANIM, SIGNAL(finished()), this, SLOT(startPainting()) ); //repeat the plugin as needed
+ ANIM->LoadAnimations();
+ }
+ //Now start the animation(s)
+ if(ANIM!=0){
+ //if(DEBUG){ qDebug() << " - Starting SS Plugin:" << cplug << ANIM->animationCount() << ANIM->duration() << ANIM->loopCount(); }
+ if(ANIM->animationCount()>0){
+ if(DEBUG){ qDebug() << " - Starting SS Plugin:" << cplug << ANIM->animationCount() << ANIM->duration() << ANIM->loopCount(); }
+ ANIM->start();
+ }
+ }
+}
+
+void SSBaseWidget::stopPainting(){
+ if(ANIM!=0){
+ ANIM->stop();
+ ANIM->clear();
+ delete ANIM;
+ ANIM = 0;
+ }
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.h b/src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.h
new file mode 100644
index 00000000..a6574679
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/SSBaseWidget.h
@@ -0,0 +1,55 @@
+//===========================================
+// 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 "GlobalDefines.h"
+#include "animations/BaseAnimGroup.h"
+
+class SSBaseWidget : public QWidget{
+ Q_OBJECT
+public:
+ SSBaseWidget(QWidget *parent, QSettings *set);
+ ~SSBaseWidget();
+
+ void setPlugin(QString);
+
+public slots:
+ void startPainting();
+ void stopPainting();
+
+private:
+ QString plugType, cplug; //type of custom painting to do
+ BaseAnimGroup *ANIM;
+ QSettings *settings;
+
+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();
+ }
+ void paintEvent(QPaintEvent*){
+ QStyleOption opt;
+ opt.init(this);
+ QPainter p(this);
+ style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+ }
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/WMSession.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/WMSession.cpp
new file mode 100644
index 00000000..4a7c6e02
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/WMSession.cpp
@@ -0,0 +1,62 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "WMSession.h"
+
+#define DEBUG 1
+// ==========
+// PUBLIC
+// ==========
+WMSession::WMSession(){
+ if(DEBUG){ qDebug() << "Creating Event Filter..."; }
+ EFILTER = new EventFilter();
+ if(DEBUG){ qDebug() << "Creating Screen Saver..."; }
+ SS = new LScreenSaver();
+ if(DEBUG){ qDebug() << "Creating Window Manager..."; }
+ WM = new LWindowManager();
+ EVThread = new QThread();
+ EFILTER->moveToThread(EVThread);
+ //Setup connections
+ connect(EFILTER, SIGNAL(NewInputEvent()), SS, SLOT(newInputEvent()) );
+ connect(EFILTER, SIGNAL(NewManagedWindow(WId)), WM, SLOT(NewWindow(WId)) );
+ connect(EFILTER, SIGNAL(WindowClosed(WId)), WM, SLOT(ClosedWindow(WId)) );
+ connect(EFILTER, SIGNAL(ModifyWindow(WId, LWM::WindowAction)), WM, SLOT(ModifyWindow(WId,LWM::WindowAction)) );
+ connect(SS, SIGNAL(StartingScreenSaver()), EFILTER, SLOT(StartedSS()) );
+ connect(SS, SIGNAL(ClosingScreenSaver()), EFILTER, SLOT(StoppedSS()) );
+ connect(WM, SIGNAL(NewFullScreenWindows(QList<WId>)), EFILTER, SLOT(FullScreenChanged(QList<WId>)) );
+}
+
+WMSession::~WMSession(){
+}
+
+void WMSession::start(bool SSONLY){
+ //Get the screensaver initialized/ready
+ if(DEBUG){ qDebug() << "Starting Screen Saver..."; }
+ SS->start();
+ if(SSONLY){ return; }
+ //Now start pulling/filtering events
+ if(DEBUG){ qDebug() << "Starting Window Manager..."; }
+ WM->start();
+ if(DEBUG){ qDebug() << "Starting Event Filter..."; }
+ EVThread->start();
+ EFILTER->start();
+ if(DEBUG){ qDebug() << "Done Starting WM session..."; }
+}
+
+// ==========
+// Public Slots
+// ==========
+void WMSession::reloadIcons(){
+
+}
+
+void WMSession::newInputsAvailable(QStringList inputs){
+ for(int i=0; i<inputs.length(); i++){
+ if(inputs[i]=="--lock-now" || inputs[i]=="--test-ss"){
+ QTimer::singleShot(0,SS, SLOT(LockScreenNow()) );
+ }
+ }
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/WMSession.h b/src-qt5/core/lumina-desktop-unified/src-WM/WMSession.h
new file mode 100644
index 00000000..5b511326
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/WMSession.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_WINDOW_MANAGER_SESSION_H
+#define _LUMINA_DESKTOP_WINDOW_MANAGER_SESSION_H
+
+#include "GlobalDefines.h"
+
+#include "LScreenSaver.h"
+#include "LXcbEventFilter.h"
+#include "LWindowManager.h"
+
+class WMSession : public QObject{
+ Q_OBJECT
+public:
+ WMSession();
+ ~WMSession();
+
+ void start(bool SSONLY = false);
+
+private:
+ //XCB Event Watcher
+ EventFilter *EFILTER;
+ //ScreenSaver
+ LScreenSaver *SS;
+ //Window Manager
+ LWindowManager *WM;
+
+ QThread *EVThread; //X Event thread
+
+public slots:
+ void reloadIcons();
+ void newInputsAvailable(QStringList);
+
+private slots:
+
+};
+
+#endif \ No newline at end of file
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.cpp
new file mode 100644
index 00000000..1e55dc76
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.cpp
@@ -0,0 +1,27 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, 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"
+
+//==============================
+// PLUGIN LOADING/LISTING
+//==============================
+BaseAnimGroup* BaseAnimGroup::NewAnimation(QString type, QWidget *parent, QSettings *set){
+ //This is where we place all the known plugin ID's, and load the associated subclass
+ if(type == "sample"){
+ return (new SampleAnimation(parent, set));
+ }else{
+ //Unknown screensaver, return a blank animation group
+ return (new BaseAnimGroup(parent, set));
+ }
+}
+
+QStringList BaseAnimGroup::KnownAnimations(){
+ return (QStringList() << "sample");
+} \ No newline at end of file
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.h b/src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.h
new file mode 100644
index 00000000..dd7269d4
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/animations/BaseAnimGroup.h
@@ -0,0 +1,37 @@
+//===========================================
+// 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 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 "GlobalDefines.h"
+
+class BaseAnimGroup : public QParallelAnimationGroup{
+ Q_OBJECT
+public:
+ QWidget *canvas;
+ QSettings *settings;
+
+ virtual void LoadAnimations(){} //This is the main function which needs to be subclassed
+
+ BaseAnimGroup(QWidget *parent, QSettings *set){
+ canvas = parent;
+ settings = set;
+ }
+ ~BaseAnimGroup(){}
+
+ //==============================
+ // PLUGIN LOADING/LISTING (Change in the .cpp file)
+ //==============================
+ static BaseAnimGroup* NewAnimation(QString type, QWidget *parent, QSettings *set);
+ static QStringList KnownAnimations();
+
+};
+
+#endif \ No newline at end of file
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/animations/SampleAnimation.h b/src-qt5/core/lumina-desktop-unified/src-WM/animations/SampleAnimation.h
new file mode 100644
index 00000000..e0f11ba5
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/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 "GlobalDefines.h"
+#include "BaseAnimGroup.h"
+
+class SampleAnimation : public BaseAnimGroup{
+ Q_OBJECT
+private:
+ QWidget *ball;
+
+public:
+ SampleAnimation(QWidget *parent, QSettings *set) : BaseAnimGroup(parent, set){}
+ ~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-unified/src-WM/animations/animations.pri b/src-qt5/core/lumina-desktop-unified/src-WM/animations/animations.pri
new file mode 100644
index 00000000..5473d4e1
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/animations/animations.pri
@@ -0,0 +1,6 @@
+SOURCES += $$PWD/BaseAnimGroup.cpp
+
+HEADERS += $$PWD/BaseAnimGroup.h \
+ $$PWD/SampleAnimation.h
+
+FORMS += \ No newline at end of file
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/lumina-wm.pro b/src-qt5/core/lumina-desktop-unified/src-WM/lumina-wm.pro
new file mode 100644
index 00000000..928f8744
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/lumina-wm.pro
@@ -0,0 +1,107 @@
+include("$${PWD}/../../OS-detect.pri")
+
+QT += core gui network
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras
+
+TARGET = lumina-wm
+target.path = $${L_BINDIR}
+
+LIBS += -lLuminaUtils -lxcb -lxcb-damage -lxcb-composite -lxcb-screensaver -lxcb-util
+
+DEPENDPATH += ../libLumina
+
+SOURCES += main.cpp \
+ WMSession.cpp \
+ LScreenSaver.cpp \
+ SSBaseWidget.cpp \
+ LLockScreen.cpp \
+ LXcbEventFilter.cpp \
+ LWindow.cpp \
+ LWindowManager.cpp
+
+
+HEADERS += GlobalDefines.h \
+ WMSession.h \
+ LScreenSaver.h \
+ SSBaseWidget.h \
+ LLockScreen.h \
+ LXcbEventFilter.h \
+ LWindow.h \
+ LWindowManager.h
+
+FORMS += LLockScreen.ui
+
+#Now add in all the screensaver animation plugins
+include(animations/animations.pri)
+
+TRANSLATIONS = i18n/lumina-wm_af.ts \
+ i18n/lumina-wm_ar.ts \
+ i18n/lumina-wm_az.ts \
+ i18n/lumina-wm_bg.ts \
+ i18n/lumina-wm_bn.ts \
+ i18n/lumina-wm_bs.ts \
+ i18n/lumina-wm_ca.ts \
+ i18n/lumina-wm_cs.ts \
+ i18n/lumina-wm_cy.ts \
+ i18n/lumina-wm_da.ts \
+ i18n/lumina-wm_de.ts \
+ i18n/lumina-wm_el.ts \
+ i18n/lumina-wm_en_GB.ts \
+ i18n/lumina-wm_en_ZA.ts \
+ i18n/lumina-wm_es.ts \
+ i18n/lumina-wm_et.ts \
+ i18n/lumina-wm_eu.ts \
+ i18n/lumina-wm_fa.ts \
+ i18n/lumina-wm_fi.ts \
+ i18n/lumina-wm_fr.ts \
+ i18n/lumina-wm_fr_CA.ts \
+ i18n/lumina-wm_gl.ts \
+ i18n/lumina-wm_he.ts \
+ i18n/lumina-wm_hi.ts \
+ i18n/lumina-wm_hr.ts \
+ i18n/lumina-wm_hu.ts \
+ i18n/lumina-wm_id.ts \
+ i18n/lumina-wm_is.ts \
+ i18n/lumina-wm_it.ts \
+ i18n/lumina-wm_ja.ts \
+ i18n/lumina-wm_ka.ts \
+ i18n/lumina-wm_ko.ts \
+ i18n/lumina-wm_lt.ts \
+ i18n/lumina-wm_lv.ts \
+ i18n/lumina-wm_mk.ts \
+ i18n/lumina-wm_mn.ts \
+ i18n/lumina-wm_ms.ts \
+ i18n/lumina-wm_mt.ts \
+ i18n/lumina-wm_nb.ts \
+ i18n/lumina-wm_nl.ts \
+ i18n/lumina-wm_pa.ts \
+ i18n/lumina-wm_pl.ts \
+ i18n/lumina-wm_pt.ts \
+ i18n/lumina-wm_pt_BR.ts \
+ i18n/lumina-wm_ro.ts \
+ i18n/lumina-wm_ru.ts \
+ i18n/lumina-wm_sk.ts \
+ i18n/lumina-wm_sl.ts \
+ i18n/lumina-wm_sr.ts \
+ i18n/lumina-wm_sv.ts \
+ i18n/lumina-wm_sw.ts \
+ i18n/lumina-wm_ta.ts \
+ i18n/lumina-wm_tg.ts \
+ i18n/lumina-wm_th.ts \
+ i18n/lumina-wm_tr.ts \
+ i18n/lumina-wm_uk.ts \
+ i18n/lumina-wm_uz.ts \
+ i18n/lumina-wm_vi.ts \
+ i18n/lumina-wm_zh_CN.ts \
+ i18n/lumina-wm_zh_HK.ts \
+ i18n/lumina-wm_zh_TW.ts \
+ i18n/lumina-wm_zu.ts
+
+dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/
+dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/
+
+INSTALLS += target
+
+WITH_I18N{
+ INSTALLS += dotrans
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-WM/main.cpp b/src-qt5/core/lumina-desktop-unified/src-WM/main.cpp
new file mode 100644
index 00000000..02e48b7b
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-WM/main.cpp
@@ -0,0 +1,56 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+
+#include "GlobalDefines.h"
+//Initialize any global structures here
+LXCB *LWM::SYSTEM = 0;
+
+//Local includes
+#include "WMSession.h"
+#include "LWindow.h"
+#include <QDialog>
+
+
+//#define DEBUG 0
+int main(int argc, char ** argv)
+{
+ qDebug() << "Starting lumina-wm...";
+ LTHEME::LoadCustomEnvSettings();
+ LSingleApplication a(argc, argv, "lumina-wm");
+ if(!a.isPrimaryProcess()){ return 0; } //Inputs forwarded on to the primary already
+ LuminaThemeEngine themes(&a);
+
+ //Setup the global structures
+ LWM::SYSTEM = new LXCB();
+ if( a.inputlist.contains("--test-win") ){
+ //Simple override to test out the window class
+ qDebug() << "Starting window test...";
+ QLabel dlg(0, Qt::Window | Qt::BypassWindowManagerHint); //this test should be ignored by the current WM
+ dlg.setText("Sample Window");
+ dlg.setWindowTitle("Test");
+ dlg.resize(200,100);
+ dlg.setStyleSheet("background: rgba(255,255,255,100); color: black;");
+ dlg.move(100,100);
+ dlg.show();
+ //dlg.move(100,100);
+ qDebug() << " - Loading window frame...";
+ LWindow win(dlg.winId()); //have it wrap around the dialog
+ qDebug() << " - Show frame...";
+ win.frame()->windowChanged(LWM::Show);
+ qDebug() << " - Start event loop...";
+ a.setQuitOnLastWindowClosed(true);
+ return a.exec();
+ }
+ WMSession w;
+ w.start(a.inputlist.contains("--test-ss"));
+ QObject::connect(&themes, SIGNAL(updateIcons()), &w, SLOT(reloadIcons()) );
+ QObject::connect(&a, SIGNAL(InputsAvailable(QStringList)), &w, SLOT(newInputsAvailable(QStringList)) );
+ if(!a.inputlist.isEmpty()){ w.newInputsAvailable(a.inputlist); }
+ int retCode = a.exec();
+
+ return retCode;
+}
bgstack15