aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina')
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.cpp57
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.h8
-rw-r--r--src-qt5/core/libLumina/ExternalProcess.h22
-rw-r--r--src-qt5/core/libLumina/LDesktopUtils.cpp127
-rw-r--r--src-qt5/core/libLumina/LDesktopUtils.h6
-rw-r--r--src-qt5/core/libLumina/LDesktopUtils.pri2
-rw-r--r--src-qt5/core/libLumina/LFileInfo.cpp184
-rw-r--r--src-qt5/core/libLumina/LFileInfo.h62
-rw-r--r--src-qt5/core/libLumina/LIconCache.cpp23
-rw-r--r--src-qt5/core/libLumina/LIconCache.h4
-rw-r--r--src-qt5/core/libLumina/LUtils.cpp109
-rw-r--r--src-qt5/core/libLumina/LUtils.h12
-rw-r--r--src-qt5/core/libLumina/LUtils.pri10
-rw-r--r--src-qt5/core/libLumina/LVideoLabel.cpp122
-rw-r--r--src-qt5/core/libLumina/LVideoLabel.h42
-rw-r--r--src-qt5/core/libLumina/LVideoLabel.pri13
-rw-r--r--src-qt5/core/libLumina/LVideoSurface.cpp60
-rw-r--r--src-qt5/core/libLumina/LVideoSurface.h26
-rw-r--r--src-qt5/core/libLumina/LVideoSurface.pri9
-rw-r--r--src-qt5/core/libLumina/LVideoWidget.cpp38
-rw-r--r--src-qt5/core/libLumina/LVideoWidget.h22
-rw-r--r--src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp82
-rw-r--r--src-qt5/core/libLumina/LuminaOS.h14
-rw-r--r--src-qt5/core/libLumina/LuminaSingleApplication.cpp16
-rw-r--r--src-qt5/core/libLumina/LuminaThemes.cpp169
-rw-r--r--src-qt5/core/libLumina/LuminaThemes.h11
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.cpp230
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.h16
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.pri8
-rw-r--r--src-qt5/core/libLumina/NativeEmbedWidget.cpp253
-rw-r--r--src-qt5/core/libLumina/NativeEmbedWidget.h63
-rw-r--r--src-qt5/core/libLumina/NativeEventFilter.cpp297
-rw-r--r--src-qt5/core/libLumina/NativeEventFilter.h70
-rw-r--r--src-qt5/core/libLumina/NativeKeyToQt.cpp528
-rw-r--r--src-qt5/core/libLumina/NativeWindow.cpp119
-rw-r--r--src-qt5/core/libLumina/NativeWindow.h117
-rw-r--r--src-qt5/core/libLumina/NativeWindow.pri17
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.cpp900
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.h138
-rw-r--r--src-qt5/core/libLumina/OSInterface-template.cpp100
-rw-r--r--src-qt5/core/libLumina/OSInterface.h136
-rw-r--r--src-qt5/core/libLumina/ResizeMenu.cpp18
-rw-r--r--src-qt5/core/libLumina/ResizeMenu.h5
-rw-r--r--src-qt5/core/libLumina/RootWindow-mgmt.cpp49
-rw-r--r--src-qt5/core/libLumina/XDGMime.cpp3
-rw-r--r--src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp (renamed from src-qt5/core/libLumina/RootSubWindow-animations.cpp)27
-rw-r--r--src-qt5/core/libLumina/obsolete/RootSubWindow.cpp (renamed from src-qt5/core/libLumina/RootSubWindow.cpp)174
-rw-r--r--src-qt5/core/libLumina/obsolete/RootSubWindow.h (renamed from src-qt5/core/libLumina/RootSubWindow.h)16
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp95
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow.cpp (renamed from src-qt5/core/libLumina/RootWindow.cpp)66
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow.h (renamed from src-qt5/core/libLumina/RootWindow.h)14
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow.pri (renamed from src-qt5/core/libLumina/RootWindow.pri)0
52 files changed, 1569 insertions, 3140 deletions
diff --git a/src-qt5/core/libLumina/DesktopSettings.cpp b/src-qt5/core/libLumina/DesktopSettings.cpp
index 8bda1ac5..f1c74bc5 100644
--- a/src-qt5/core/libLumina/DesktopSettings.cpp
+++ b/src-qt5/core/libLumina/DesktopSettings.cpp
@@ -56,11 +56,19 @@ void DesktopSettings::stop(){
}
//Main Read/Write functions
+QList< DesktopSettings::File > DesktopSettings::writableFiles(){
+ QList< DesktopSettings::File > tmp;
+ if(runmode!=DesktopSettings::SystemFull){ tmp = filesForRunMode(runmode); }
+ return tmp;
+}
+
QVariant DesktopSettings::value(DesktopSettings::File file, QString variable, QVariant defaultvalue){
if(!files.contains(file)){ return defaultvalue; }
for(int i=0; i<files[file].length(); i++){
+ //qDebug() << "Look for Settings value:" << variable << files[file];
if( settings.contains(files[file][i])){ //make sure this file is in the settings hash
if(settings[files[file][i]]->contains(variable)){ //if this file does not have the variable - go to the next one
+ //qDebug() << " - Found Setting in File:" << files[file][i];
return settings[files[file][i]]->value(variable, defaultvalue);
}
}
@@ -118,7 +126,7 @@ void DesktopSettings::parseSystemSettings(){
QString defMode = settings[path]->value("default_mode","fulluser").toString().toLower();
if(defMode=="fullsystem"){ runmode= DesktopSettings::SystemFull; }
else if(defMode=="staticinterface"){ runmode = DesktopSettings::SystemInterface; }
-
+ else{ runmode = DesktopSettings::UserFull; }
//Now determine the runmode for this user
struct passwd *pw = getpwuid(getuid());
if(pw!=0){
@@ -178,25 +186,29 @@ void DesktopSettings::locateFiles(){
systemdirs << QString(getenv("XDG_CONFIG_DIRS")).split(":") << QString(getenv("XDG_DATA_DIRS")).split(":");
//Load all the user-level files for this run mode
QList< DesktopSettings::File > tmp;
- if(runmode == DesktopSettings::UserFull){ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Keys << DesktopSettings::Theme; }
- else if(runmode == DesktopSettings::SystemInterface){ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Keys << DesktopSettings::Theme; }
- for(int i=0; i<tmp.length(); i++){
- QString path = userdir+rel_path(tmp[i]);
- touchFile(path);
- files.insert(tmp[i], QStringList() << path);
- settings.insert(path, new QSettings(path, QSettings::IniFormat, this) );
- watcher->addPath(path);
+ if(runmode!=DesktopSettings::SystemFull){
+ //Load the user-level files
+ tmp= filesForRunMode(runmode);
+ for(int i=0; i<tmp.length(); i++){
+ QString path = userdir+rel_path(tmp[i]);
+ touchFile(path);
+ files.insert(tmp[i], QStringList() << path);
+ settings.insert(path, new QSettings(path, QSettings::IniFormat, this) );
+ watcher->addPath(path);
+ }
}
//Now load all the system-level files
- tmp.clear();
- tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Keys << DesktopSettings::Theme;
+ tmp = filesForRunMode(DesktopSettings::SystemFull);
for(int i=0; i<systemdirs.length(); i++){
if(systemdirs[i].endsWith("/xdg")){ systemdirs[i] = systemdirs[i].section("/",0,-2); }
if( !QFile::exists(systemdirs[i]+"/lumina-desktop") ){ continue; }
for(int j=0; j<tmp.length(); j++){
QString path = systemdirs[i]+rel_path(tmp[j]);
if(QFile::exists(path)){
- files.insert(tmp[j], QStringList() << path);
+ QStringList filepaths;
+ if(files.contains(tmp[j])){ filepaths = files[tmp[j]]; }
+ filepaths << path; //add this file to the end of the list for this type of settings file
+ files.insert(tmp[j], filepaths);
settings.insert(path, new QSettings(path, QSettings::IniFormat, this) );
watcher->addPath(path);
}
@@ -219,6 +231,17 @@ void DesktopSettings::touchFile(QString path){
}
}
+QList< DesktopSettings::File > DesktopSettings::filesForRunMode(RunMode mode){
+ // Note that the "System" file is always ignored here - that is specially loaded
+ QList< DesktopSettings::File > tmp;
+ if(mode == DesktopSettings::UserFull || mode == DesktopSettings::SystemFull){
+ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Panels << DesktopSettings::Plugins << DesktopSettings::Keys << DesktopSettings::ContextMenu << DesktopSettings::Animation << DesktopSettings::ScreenSaver << DesktopSettings::WM;
+ }else if(runmode == DesktopSettings::SystemInterface){
+ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session;
+ }
+ return tmp;
+}
+
QString DesktopSettings::rel_path(DesktopSettings::File file){
QString name;
switch(file){
@@ -236,10 +259,16 @@ QString DesktopSettings::rel_path(DesktopSettings::File file){
name="contextmenu"; break;
case DesktopSettings::Keys:
name="keys"; break;
- case DesktopSettings::Theme:
- name="theme"; break;
case DesktopSettings::Animation:
name="animations"; break;
+ case DesktopSettings::Panels:
+ name="panels"; break;
+ case DesktopSettings::Plugins:
+ name="plugins"; break;
+ case DesktopSettings::ScreenSaver:
+ name="screensaver"; break;
+ case DesktopSettings::WM:
+ name="windows"; break;
}
return FILEPREFIX+name+".conf";
}
diff --git a/src-qt5/core/libLumina/DesktopSettings.h b/src-qt5/core/libLumina/DesktopSettings.h
index dcb10bb6..efb3776e 100644
--- a/src-qt5/core/libLumina/DesktopSettings.h
+++ b/src-qt5/core/libLumina/DesktopSettings.h
@@ -25,7 +25,8 @@
class DesktopSettings : public QObject{
Q_OBJECT
public:
- enum File{ System, Favorites, Environment, Session, Desktop, ContextMenu, Keys, Theme, Animation };
+ enum File{ System, Favorites, Environment, Session, Desktop, Panels, Plugins, ContextMenu, Keys, Animation, ScreenSaver, WM};
+ //Changes to this enum need to be added to the "filesForRunMode()" and "rel_path()" functions as well
DesktopSettings(QObject *parent = 0);
~DesktopSettings();
@@ -37,6 +38,7 @@ public:
void stop();
//Main Read/Write functions
+ QList< DesktopSettings::File > writableFiles(); //return the list of all writable files
QVariant value(DesktopSettings::File, QString variable, QVariant defaultvalue);
bool setValue(DesktopSettings::File, QString variable, QVariant value);
QStringList keys(DesktopSettings::File); //return a list of all variables which are available in this file
@@ -51,9 +53,13 @@ private:
QHash< DesktopSettings::File, QStringList > files; //location hash for where files are actually located on disk
QHash< QString, QSettings*> settings; //location hash for the settings files themselves
+ //Functions
void parseSystemSettings(); //run at start - determine the RunMode for this user/session
void locateFiles(); //run at start - finds the locations of the various files (based on RunMode)
void touchFile(QString path); //used to create an empty file so it can be watched for changes later
+
+ //The two functions which define the public "File" enumeration (both need updates when the enum changes)
+ QList< DesktopSettings::File > filesForRunMode(RunMode mode);
QString rel_path(DesktopSettings::File); //return the relative file path (starting with "/")
private slots:
diff --git a/src-qt5/core/libLumina/ExternalProcess.h b/src-qt5/core/libLumina/ExternalProcess.h
index b1e56af8..e75d6108 100644
--- a/src-qt5/core/libLumina/ExternalProcess.h
+++ b/src-qt5/core/libLumina/ExternalProcess.h
@@ -15,26 +15,31 @@
#include <QString>
#include <QTimer>
#include <QApplication>
+#include <QDebug>
class ExternalProcess : public QProcess{
Q_OBJECT
private:
bool cursorRestored;
+ QString logoutput;
private slots:
void resetCursor(){
+ //qDebug() << "External Process: Reset Mouse Cursor =" << !cursorRestored;
if(!cursorRestored){
QApplication::restoreOverrideCursor();
cursorRestored = true;
}
}
void processStarting(){
+ //qDebug() << "Starting External Process: Mouse Notification =" << !cursorRestored;
if(!cursorRestored){
- QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
- QTimer::singleShot(15000, this, SLOT(resetCursor()) );
+ QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) );
+ QTimer::singleShot(3000, this, SLOT(resetCursor()) );
}
}
void processFinished(){
+ //qDebug() << "External Process Finished: Reset Mouse Cursor =" << !cursorRestored;
if(!cursorRestored){
QApplication::restoreOverrideCursor();
cursorRestored = true;
@@ -42,6 +47,9 @@ private slots:
//Clean up this object
this->deleteLater();
}
+ void updateLog(){
+ logoutput.append( QString(this->readAllStandardOutput()) );
+ }
public:
ExternalProcess(QString logfile = "", bool manageCursors = false) : QProcess(){
@@ -49,10 +57,13 @@ public:
cursorRestored = !manageCursors;
if(logfile.isEmpty()){
this->setStandardOutputFile(QProcess::nullDevice());
+ }else if(logfile=="stdout"){
+ connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(updateLog()) );
}else{
this->setStandardOutputFile(logfile);
}
//Setup the connection for automatic cleanup
+ connect(this, SIGNAL(started()), this, SLOT(processStarting()) );
connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished()) );
}
@@ -62,7 +73,12 @@ public:
}*/
}
- static void launch(QString program, QStringList args = QStringList(), bool manageCursors = false){
+ QString log(){
+ //NOTE: This will only contain output if the "stdout" argument is used as the logfile
+ return logoutput;
+ }
+
+ static void launch(QString program, QStringList args = QStringList(), bool manageCursors = true){
//Quick launch of a process with logging disabled and automatic cleanup
ExternalProcess *tmp = new ExternalProcess("", manageCursors);
if(args.isEmpty()){ tmp->start(program); }
diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp
index b79f777d..5595532a 100644
--- a/src-qt5/core/libLumina/LDesktopUtils.cpp
+++ b/src-qt5/core/libLumina/LDesktopUtils.cpp
@@ -13,10 +13,8 @@
#include "LuminaThemes.h"
-static QStringList fav;
-
QString LDesktopUtils::LuminaDesktopVersion(){
- QString ver = "1.3.2";
+ QString ver = "1.4.1";
#ifdef GIT_VERSION
ver.append( QString(" (Git Revision: %1)").arg(GIT_VERSION) );
#endif
@@ -80,22 +78,23 @@ QStringList LDesktopUtils::infoQuickPlugin(QString ID){ //Returns: [Name, Descri
}
QStringList LDesktopUtils::listFavorites(){
- static QDateTime lastRead;
- QDateTime cur = QDateTime::currentDateTime();
- if(lastRead.isNull() || lastRead<QFileInfo( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list").lastModified()){
+ //static QDateTime lastRead;
+ QStringList fav;
+ //QDateTime cur = QDateTime::currentDateTime();
+ //if(lastRead.isNull() || fav.isEmpty() || lastRead<QFileInfo( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list").lastModified()){
fav = LUtils::readFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list");
fav.removeAll(""); //remove any empty lines
fav.removeDuplicates();
- lastRead = cur;
- }
-
+ //lastRead = cur;
+ //}
return fav;
}
bool LDesktopUtils::saveFavorites(QStringList list){
list.removeDuplicates();
+ //qDebug() << "Save Favorites:" << list;
bool ok = LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list", list, true);
- if(ok){ fav = list; } //also save internally in case of rapid write/read of the file
+ //if(ok){ fav = list; } //also save internally in case of rapid write/read of the file
return ok;
}
@@ -116,11 +115,13 @@ bool LDesktopUtils::addFavorite(QString path, QString name){
else{ type = LXDG::findAppMimeForFile(path); }
//Assign a name if none given
if(name.isEmpty()){ name = info.fileName(); }
+ //qDebug() << "Add Favorite:" << path << type << name;
//Now add it to the list
QStringList favs = LDesktopUtils::listFavorites();
+ //qDebug() << "Current Favorites:" << favs;
bool found = false;
for(int i=0; i<favs.length(); i++){
- if(favs[i].endsWith("::::"+path)){ favs[i] = name+"::::"+type+"::::"+path; }
+ if(favs[i].endsWith("::::"+path)){ favs[i] = name+"::::"+type+"::::"+path; found = true; }
}
if(!found){ favs << name+"::::"+type+"::::"+path; }
return LDesktopUtils::saveFavorites(favs);
@@ -143,6 +144,15 @@ void LDesktopUtils::upgradeFavorites(int){ //fromoldversionnumber
void LDesktopUtils::LoadSystemDefaults(bool skipOS){
//Will create the Lumina configuration files based on the current system template (if any)
qDebug() << "Loading System Defaults";
+ //Ensure that the settings directory exists
+ QString setdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop";
+ if(!QFile::exists(setdir)){
+ QDir dir;
+ dir.mkpath(setdir);
+ }
+
+ bool skipmime = QFile::exists( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-mimapps.list" );
+ //qDebug() << " - Skipping mimetype default apps" << skipmime;
QStringList sysDefaults;
if(!skipOS){ sysDefaults = LUtils::readFile(LOS::AppPrefix()+"etc/luminaDesktop.conf"); }
if(sysDefaults.isEmpty() && !skipOS){ sysDefaults = LUtils::readFile(LOS::AppPrefix()+"etc/luminaDesktop.conf.dist"); }
@@ -153,8 +163,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
if(sysDefaults.isEmpty()){ sysDefaults = LUtils::readFile(LOS::LuminaShare()+"luminaDesktop.conf"); }
//Find the number of the left-most desktop screen
QString screen = "0";
- QDesktopWidget *desk =QApplication::desktop();
QRect screenGeom;
+ QDesktopWidget *desk =QApplication::desktop();
for(int i=0; i<desk->screenCount(); i++){
if(desk->screenGeometry(i).x()==0){
screen = QString::number(i);
@@ -185,6 +195,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
if(var.endsWith("_ifexists") ){
var = var.remove("_ifexists"); //remove this flag from the variable
//Check if the value exists (absolute path only)
+ val = LUtils::AppToAbsolute(val);
+ //qDebug() << "Checking if favorite app exists:" << val;
if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist
}
@@ -193,18 +205,18 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
if(var=="session_enablenumlock"){ sset = "EnableNumlock="+ istrue; }
else if(var=="session_playloginaudio"){ sset = "PlayStartupAudio="+istrue; }
else if(var=="session_playlogoutaudio"){ sset = "PlayLogoutAudio="+istrue; }
- else if(var=="session_default_terminal"){
+ else if(var=="session_default_terminal" && !skipmime){
LXDG::setDefaultAppForMime("application/terminal", val);
//sset = "default-terminal="+val;
- }else if(var=="session_default_filemanager"){
+ }else if(var=="session_default_filemanager" && !skipmime){
LXDG::setDefaultAppForMime("inode/directory", val);
//sset = "default-filemanager="+val;
//loset = "directory="+val;
- }else if(var=="session_default_webbrowser"){
+ }else if(var=="session_default_webbrowser" && !skipmime){
//loset = "webbrowser="+val;
LXDG::setDefaultAppForMime("x-scheme-handler/http", val);
LXDG::setDefaultAppForMime("x-scheme-handler/https", val);
- }else if(var=="session_default_email"){
+ }else if(var=="session_default_email" && !skipmime){
LXDG::setDefaultAppForMime("application/email",val);
//loset = "email="+val;
}
@@ -225,24 +237,27 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
// -- MIMETYPE DEFAULTS --
tmp = sysDefaults.filter("mime_default_");
- for(int i=0; i<tmp.length(); i++){
+ for(int i=0; i<tmp.length() && !skipmime; i++){
if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; }
QString var = tmp[i].section("=",0,0).toLower().simplified();
QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
+ qDebug() << "Mime entry:" << var << val;
if(val.isEmpty()){ continue; }
QString istrue = (val.toLower()=="true") ? "true": "false";
//Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while
if(var.contains(".")){ var.replace(".","_"); }
//Now parse the variable and put the value in the proper file
- val = LUtils::AppToAbsolute(val);
//Special handling for values which need to exist first
if(var.endsWith("_ifexists") ){
var = var.remove("_ifexists"); //remove this flag from the variable
+ val = LUtils::AppToAbsolute(val);
+ //qDebug() << "Checking if Mime app exists:" << val;
//Check if the value exists (absolute path only)
if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist
}
//Now turn this variable into the mimetype only
var = var.section("_default_",1,-1);
+ //qDebug() << " - Set Default Mime:" << var << val;
LXDG::setDefaultAppForMime(var, val);
}
@@ -324,6 +339,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
tmp = sysDefaults.filter("favorites_");
if(tmp.isEmpty()){ tmp = sysDefaults.filter("favorites."); }
for(int i=0; i<tmp.length(); i++){
+ //qDebug() << "Found Favorite Entry:" << tmp[i];
if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; }
QString var = tmp[i].section("=",0,0).toLower().simplified();
QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
@@ -332,11 +348,21 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
//Now parse the variable and put the value in the proper file
qDebug() << "Favorite entry:" << var << val;
val = LUtils::AppToAbsolute(val); //turn any relative files into absolute
- if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:"; LDesktopUtils::addFavorite(val); }
+ if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:" << val; LDesktopUtils::addFavorite(val); }
else if(var=="favorites_add"){ qDebug() << " - Adding:"; LDesktopUtils::addFavorite(val); }
else if(var=="favorites_remove"){ qDebug() << " - Removing:"; LDesktopUtils::removeFavorite(val); }
}
+ tmp = sysDefaults.filter("desktoplinks_");
+ QString desktopFolder = QDir::homePath()+"/Desktop/"; //need to make this translatable and dynamic later
+ for(int i=0; i<tmp.length(); i++){
+ if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; }
+ QString var = tmp[i].section("=",0,0).toLower().simplified();
+ QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
+ val = LUtils::AppToAbsolute(val); //turn any relative files into absolute
+ if(var=="desktoplinks_add" && QFile::exists(val) && !QFile::exists(desktopFolder+val.section("/",-1)) ){ QFile::link(val, desktopFolder+val.section("/",-1)); }
+ }
+
// -- QUICKLAUNCH --
tmp = sysDefaults.filter("quicklaunch_");
if(tmp.isEmpty()){ tmp = sysDefaults.filter("quicklaunch."); }
@@ -373,6 +399,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
if(var.contains(".")){ var.replace(".","_"); }
//Now parse the variable and put the value in the proper file
if(var=="theme_themefile"){ themesettings[0] = val; }
+ else if(var=="theme_styles"){ LTHEME::setCurrentStyles( val.split(",",QString::SkipEmptyParts) ); }
else if(var=="theme_colorfile"){ themesettings[1] = val; }
else if(var=="theme_iconset"){ themesettings[2] = val; }
else if(var=="theme_font"){ themesettings[3] = val; }
@@ -389,7 +416,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QStringList syscolors = LTHEME::availableSystemColors();
//theme file
//qDebug() << "Detected Themes/colors:" << systhemes << syscolors;
- if( !themesettings[0].startsWith("/") || !QFile::exists(themesettings[0]) || !themesettings[0].endsWith(".qss.template")){
+ if( !themesettings[0].startsWith("/") || !QFile::exists(themesettings[0]) || !themesettings[0].endsWith(".qss")){
themesettings[0] = themesettings[0].section(".qss",0,0).simplified();
for(int i=0; i<systhemes.length(); i++){
if(systhemes[i].startsWith(themesettings[0]+"::::",Qt::CaseInsensitive)){
@@ -399,9 +426,9 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
}
}
//color file
- if( !themesettings[1].startsWith("/") || !QFile::exists(themesettings[1]) || !themesettings[1].endsWith(".qss.colors") ){
+ if( !themesettings[1].startsWith("/") || !QFile::exists(themesettings[1]) || !themesettings[1].endsWith(".conf") ){
//Remove any extra/invalid extension
- themesettings[1] = themesettings[1].section(".qss",0,0).simplified();
+ themesettings[1] = themesettings[1].section(".conf",0,0).simplified();
for(int i=0; i<syscolors.length(); i++){
if(syscolors[i].startsWith(themesettings[1]+"::::",Qt::CaseInsensitive)){
themesettings[1] = syscolors[i].section("::::",1,1); //Replace with the full path
@@ -409,17 +436,14 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
}
}
}
+
}
//qDebug() << " - Final Theme Color:" << themesettings[1];
- //Ensure that the settings directory exists
- QString setdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop";
- if(!QFile::exists(setdir)){
- QDir dir;
- dir.mkpath(setdir);
- }
//Now save the settings files
- if(setTheme){ LTHEME::setCurrentSettings( themesettings[0], themesettings[1], themesettings[2], themesettings[3], themesettings[4]); }
+ if(setTheme){
+ LTHEME::setCurrentSettings( themesettings[0], themesettings[1], themesettings[2], themesettings[3], themesettings[4]);
+ }
LUtils::writeFile(setdir+"/sessionsettings.conf", sesset, true);
LUtils::writeFile(setdir+"/desktopsettings.conf", deskset, true);
@@ -441,12 +465,14 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
}
-bool LDesktopUtils::checkUserFiles(QString lastversion){
+bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){
+ //WARNING: Make sure you create a QApplication instance before calling this function!!!
+
//internal version conversion examples:
// [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001]
//returns true if something changed
int oldversion = LDesktopUtils::VersionStringToNumber(lastversion);
- int nversion = LDesktopUtils::VersionStringToNumber(QApplication::applicationVersion());
+ int nversion = LDesktopUtils::VersionStringToNumber(currentversion);
bool newversion = ( oldversion < nversion ); //increasing version number
bool newrelease = ( lastversion.contains("-devel", Qt::CaseInsensitive) && QApplication::applicationVersion().contains("-release", Qt::CaseInsensitive) ); //Moving from devel to release
@@ -488,6 +514,43 @@ bool LDesktopUtils::checkUserFiles(QString lastversion){
}
LUtils::writeFile(dset, DS, true);
}
+ if(oldversion<1003004){
+ //Lumina 1.3.4 - Migrate theme settings from old format to the new theme engine format
+ QString themefile = QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/lthemeengine.conf";
+ if(!QFile::exists(themefile)){
+ QDir dir;
+ dir.mkpath(themefile.section("/",0,-2)); //make sure the main directory exists first
+ //Need to migrate theme settings from the old location to the new one
+ QSettings newtheme(themefile, QSettings::NativeFormat);
+ qDebug() << "Migrating Theme settings:" << newtheme.fileName();
+ QStringList oldtheme = LUtils::readFile( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themesettings.cfg" );
+ //Find the system install location for the theme engine for use later
+ QString enginedir = LOS::LuminaShare()+"/../lthemeengine/";
+ //Find/match the icon theme
+ QString tmp = oldtheme.filter("ICONTHEME=").join("\n").section("=",1,-1).section("\n",0,0).simplified();
+ if(tmp.isEmpty()){ tmp = "material-design-light"; } //unknown Icon theme - use the default "light" version
+ newtheme.setValue("Appearance/icon_theme",tmp);
+ //Quick detect/adjust of the tone of the color theme based on the icons/colors (no 1-to-1 color theme matching between systems)
+ bool isdarktheme = tmp.contains("dark");
+ isdarktheme = isdarktheme || oldtheme.filter("COLORFILE=").join("\n").section("=",1,-1).section("\n",0,0).contains("DarkGlass");
+ //Quick adjust for the material-design icon theme to make it match the current dark/light theme
+ if(tmp.contains("material-design")){
+ newtheme.setValue("Appearance/icon_theme", QString("material-design-")+ (isdarktheme ? "dark" : "light") );
+ }
+ if(isdarktheme){
+ newtheme.setValue("Appearance/custom_palette", true);
+ newtheme.setValue("Appearance/color_scheme_path", enginedir+"colors/darker.conf");
+ newtheme.setValue("Interface/desktop_stylesheets", QStringList() << enginedir+"desktop_qss/DarkGlass.qss");
+ }else{
+ newtheme.setValue("Appearance/custom_palette", true);
+ newtheme.setValue("Appearance/color_scheme_path", enginedir+"colors/airy.conf");
+ newtheme.setValue("Interface/desktop_stylesheets", QStringList() << enginedir+"desktop_qss/Glass.qss");
+ }
+ newtheme.setValue("Appearance/style", "Fusion");
+ newtheme.setValue("Interface/stylesheets", QStringList() << enginedir+"qss/tooltip-simple.qss" << enginedir+"qss/scrollbar-simple.qss" << enginedir+"qss/sliders-simple.qss" << enginedir+"qss/traynotification-simple.qss");
+ newtheme.sync(); //flush this to file right now
+ } //end check for theme file existance
+ }
//Check the fluxbox configuration files
dset = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/";
@@ -515,7 +578,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion){
}
int LDesktopUtils::VersionStringToNumber(QString version){
- version = version.section("-",0,0); //trim any extra labels off the end
+ version = version.section("_",0,0).section("-",0,0); //trim any extra labels off the end
int maj, mid, min; //major/middle/minor version numbers (<Major>.<Middle>.<Minor>)
maj = mid = min = 0;
bool ok = true;
diff --git a/src-qt5/core/libLumina/LDesktopUtils.h b/src-qt5/core/libLumina/LDesktopUtils.h
index b21bc78a..b0ce6ba5 100644
--- a/src-qt5/core/libLumina/LDesktopUtils.h
+++ b/src-qt5/core/libLumina/LDesktopUtils.h
@@ -30,7 +30,7 @@ public:
static QString findQuickPluginFile(QString ID);
static QStringList listQuickPlugins(); //List of valid ID's
static QStringList infoQuickPlugin(QString ID); //Returns: [Name, Description, Icon]
-
+
//Various functions for the favorites sub-system
// Formatting Note: "<name>::::[dir/app/<mimetype>]::::<path>"
// the <name> field might not be used for "app" flagged entries
@@ -40,10 +40,10 @@ public:
static bool addFavorite(QString path, QString name = "");
static void removeFavorite(QString path);
static void upgradeFavorites(int fromoldversionnumber);
-
+
//Load the default setup for the system
static void LoadSystemDefaults(bool skipOS = false);
- static bool checkUserFiles(QString lastversion); //returns true if something changed
+ static bool checkUserFiles(QString lastversion, QString currentversion); //returns true if something changed
static int VersionStringToNumber(QString version); //convert the lumina version string to a number for comparisons
//Migrating desktop settings from one ID to another
diff --git a/src-qt5/core/libLumina/LDesktopUtils.pri b/src-qt5/core/libLumina/LDesktopUtils.pri
index 80bbcfa8..ebfa89f4 100644
--- a/src-qt5/core/libLumina/LDesktopUtils.pri
+++ b/src-qt5/core/libLumina/LDesktopUtils.pri
@@ -5,3 +5,5 @@ INCLUDEPATH *= ${PWD}
#Now the other dependendies of it
include(LUtils.pri)
+include(LuminaThemes.pri)
+include(LuminaXDG.pri)
diff --git a/src-qt5/core/libLumina/LFileInfo.cpp b/src-qt5/core/libLumina/LFileInfo.cpp
new file mode 100644
index 00000000..e7d2b71a
--- /dev/null
+++ b/src-qt5/core/libLumina/LFileInfo.cpp
@@ -0,0 +1,184 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2013-2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LFileInfo.h"
+#include <LUtils.h>
+
+LFileInfo::LFileInfo() : QFileInfo(){
+ desk = 0;
+}
+
+LFileInfo::LFileInfo(QString filepath) : QFileInfo(){ //overloaded contructor
+ desk = 0;
+ this->setFile(filepath);
+ loadExtraInfo();
+}
+
+LFileInfo::LFileInfo(QFileInfo info) : QFileInfo(){ //overloaded contructor
+ desk = 0;
+ this->swap(info); //use the given QFileInfo without re-loading it
+ loadExtraInfo();
+}
+LFileInfo::~LFileInfo(){
+ if(desk!=0){ desk->deleteLater(); }
+}
+
+//Need some extra information not usually available by a QFileInfo
+void LFileInfo::loadExtraInfo(){
+ if(desk!=0){ desk->deleteLater(); }
+ desk = 0;
+ //Now load the extra information
+ if(this->absoluteFilePath().startsWith("/net/") || this->isDir() ){
+ mime = "inode/directory";
+ //Special directory icons
+ QString name = this->fileName().toLower();
+ if(name=="desktop"){ icon = "user-desktop"; }
+ else if(name=="tmp"){ icon = "folder-temp"; }
+ else if(name=="video" || name=="videos"){ icon = "folder-video"; }
+ else if(name=="music" || name=="audio"){ icon = "folder-sound"; }
+ else if(name=="projects" || name=="devel"){ icon = "folder-development"; }
+ else if(name=="notes"){ icon = "folder-txt"; }
+ else if(name=="downloads"){ icon = "folder-downloads"; }
+ else if(name=="documents"){ icon = "folder-documents"; }
+ else if(name=="images" || name=="pictures"){ icon = "folder-image"; }
+ else if(this->absoluteFilePath().startsWith("/net/")){ icon = "folder-remote"; }
+ else if( !this->isReadable() ){ icon = "folder-locked"; }
+ }else if( this->suffix()=="desktop"){
+ mime = "application/x-desktop";
+ icon = "application-x-desktop"; //default value
+ desk = new XDGDesktop(this->absoluteFilePath(), 0);
+ if(desk->type!=XDGDesktop::BAD){
+ //use the specific desktop file info (if possible)
+ if(!desk->icon.isEmpty()){ icon = desk->icon; }
+ }
+ }else{
+ //Generic file, just determine the mimetype
+ mime = LXDG::findAppMimeForFile(this->fileName());
+ }
+}
+
+bool LFileInfo::zfsAvailable(){
+ static unsigned int avail = 2;
+ if(avail == 2){ avail = (LUtils::isValidBinary("zfs") ? 0 : 1); }
+ return (avail == 0);
+}
+
+void LFileInfo::getZfsDataset(){
+ if(zfs_ds.isEmpty()){
+ //First run - need to probe the current directory
+ bool ok = false;
+ //Use the "atime" property for this check - been around since the earliest versions of ZFS and should take no time to probe
+ QString out = LUtils::runCommand(ok, "zfs", QStringList() << "get" << "-H" << "atime" << this->canonicalFilePath() );
+ if(!ok){ zfs_ds = "."; } //just something that is not empty - but is clearly not a valid dataset
+ else{ zfs_ds = out.section("\n",0,0).section("\t",0,0).simplified(); }
+ //qDebug() << "Found Dataset:" << zfs_ds << out << ok;
+ }
+}
+
+bool LFileInfo::goodZfsDataset(){
+ if(!zfsAvailable()){ return false; }
+ getZfsDataset(); //ensure this field is populated
+ if(zfs_ds=="." || zfs_ds.isEmpty()){ return false; }
+ return true;
+}
+
+//Functions for accessing the extra information
+// -- Return the mimetype for the file
+QString LFileInfo::mimetype(){
+ if(mime=="inode/directory"){ return ""; }
+ else{ return mime; }
+}
+
+// -- Return the icon to use for this file
+QString LFileInfo::iconfile(){
+ if(!icon.isEmpty()){
+ return icon;
+ }else if(!mime.isEmpty()){
+ QString tmp = mime;
+ tmp.replace("/","-");
+ return tmp;
+ }else if(this->isExecutable()){
+ return "application-x-executable";
+ }
+ return ""; //Fall back to nothing
+}
+
+// -- Check if this is an XDG desktop file
+bool LFileInfo::isDesktopFile(){
+ if(desk==0){ return false; }
+ return (!desk->filePath.isEmpty());
+}
+
+// -- Allow access to the XDG desktop data structure
+XDGDesktop* LFileInfo::XDG(){
+ return desk;
+}
+
+// -- Check if this is a readable video file (for thumbnail support)
+bool LFileInfo::isVideo(){
+ if(!mime.startsWith("video/")){ return false; }
+ //Check the hardcoded list of known supported video formats to see if the thumbnail can be generated
+ return ( !LUtils::videoExtensions().filter(this->suffix().toLower()).isEmpty() );
+}
+
+// -- Check if this is a readable image file
+bool LFileInfo::isImage(){
+ if(!mime.startsWith("image/")){ return false; } //quick return for non-image files
+ //Check the Qt subsystems to see if this image file can be read
+ return ( !LUtils::imageExtensions().filter(this->suffix().toLower()).isEmpty() );
+}
+
+bool LFileInfo::isAVFile(){
+ return (mime.startsWith("audio/") || mime.startsWith("video/") );
+}
+
+bool LFileInfo::isZfsDataset(){
+ if(!goodZfsDataset()){ return false; }
+ return ( ("/"+zfs_ds.section("/",1,-1)) == this->canonicalFilePath());
+}
+
+QString LFileInfo::zfsPool(){
+ if(!goodZfsDataset()){ return ""; }
+ return zfs_ds.section("/",0,0);
+}
+
+QStringList LFileInfo::zfsSnapshots(){
+ if(!goodZfsDataset()){ return QStringList(); }
+ QString relpath = this->canonicalFilePath().remove(0, QString("/"+zfs_ds.section("/",1,-1)).length() );
+ //qDebug() << "Got Relative path:" << zfs_ds << this->canonicalFilePath() << relpath;
+ QDir dir("/"+zfs_ds.section("/",1,-1)+"/.zfs/snapshot/");
+ QStringList snaps = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time);
+ for(int i=0; i<snaps.length(); i++){
+ if( QFile::exists(dir.absoluteFilePath(snaps[i])+relpath) ){ snaps[i].append("::::" + dir.absoluteFilePath(snaps[i])+relpath ); }
+ else{ snaps.removeAt(i); i--; }
+ }
+ return snaps;
+}
+
+QJsonObject LFileInfo::zfsProperties(){
+ QJsonObject props;
+ if(!goodZfsDataset()){ return props; }
+ bool ok = false;
+ QStringList out = LUtils::runCommand(ok, "zfs", QStringList() << "get" << "-H" << "all" << zfs_ds).split("\n");
+ //Note: Formating of zfs output: tab-delimited, with columns [dataset, property, value, source]
+ for(int i=0; i<out.length() && ok; i++){
+ if(out[i].simplified().isEmpty()){ continue; }
+ QJsonObject prop;
+ prop.insert("property", out[i].section("\t",1,1).simplified());
+ prop.insert("value", out[i].section("\t",2,2).simplified());
+ prop.insert("source", out[i].section("\t",3,-1).simplified());
+ props.insert(prop.value("property").toString(), prop);
+ }
+ return props;
+}
+
+bool LFileInfo::zfsSetProperty(QString property, QString value){
+ if(!goodZfsDataset()){ return false; }
+ bool ok = false;
+ QString info = LUtils::runCommand(ok, "zfs", QStringList() << "set" << property+"="+value << zfs_ds);
+ if(!ok){ qDebug() << "Error Setting ZFS Property:" << property+"="+value << info; }
+ return ok;
+}
diff --git a/src-qt5/core/libLumina/LFileInfo.h b/src-qt5/core/libLumina/LFileInfo.h
new file mode 100644
index 00000000..df1abb65
--- /dev/null
+++ b/src-qt5/core/libLumina/LFileInfo.h
@@ -0,0 +1,62 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2013-2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// File Information simplification class (combine QFileInfo with XDGDesktop)
+// Need some extra information not usually available by a QFileInfo
+// ========================
+#ifndef _LUMINA_LIBRARY_FILE_INFO_H
+#define _LUMINA_LIBRARY_FILE_INFO_H
+
+#include <LuminaXDG.h>
+#include <QString>
+#include <QFileInfo>
+#include <QJsonObject>
+
+class LFileInfo : public QFileInfo{
+private:
+ QString mime, icon, zfs_ds;
+ XDGDesktop *desk;
+
+ void loadExtraInfo();
+ bool zfsAvailable();
+ void getZfsDataset(); //note: only run this if "zfsAvailable" is true
+ bool goodZfsDataset(); //simplification of the two functions above
+
+public:
+ //Couple overloaded contructors
+ LFileInfo();
+ LFileInfo(QString filepath);
+ LFileInfo(QFileInfo info);
+ ~LFileInfo();
+
+ //Functions for accessing the extra information
+ // -- Return the mimetype for the file
+ QString mimetype();
+
+ // -- Return the icon file to use for this file
+ QString iconfile(); //Note: This string is auto-formatted for use in the LXDG::findIcon() routine.
+
+ // -- Check if this is an XDG desktop file
+ bool isDesktopFile();
+
+ // -- Allow access to the internal XDG desktop data structure
+ XDGDesktop* XDG();
+
+ //Other file type identification routines
+ bool isImage(); //Is a readable image file (for thumbnail support)
+ bool isVideo(); //Is a readable video file (for thumbnail support)
+ bool isAVFile(); //Is an audio/video file
+
+ bool isZfsDataset();
+ QString zfsPool();
+ QStringList zfsSnapshots(); //Format: "snapshot name::::path/to/snapshot"
+ QJsonObject zfsProperties();
+ bool zfsSetProperty(QString property, QString value);
+
+};
+typedef QList<LFileInfo> LFileInfoList;
+
+#endif
diff --git a/src-qt5/core/libLumina/LIconCache.cpp b/src-qt5/core/libLumina/LIconCache.cpp
index 70c360fb..84428546 100644
--- a/src-qt5/core/libLumina/LIconCache.cpp
+++ b/src-qt5/core/libLumina/LIconCache.cpp
@@ -184,6 +184,27 @@ void LIconCache::loadIcon(QLabel *label, QString icon, bool noThumb){
if(needload){ startReadFile(icon, idata.fullpath); }
}
+void LIconCache::loadIcon(QMenu *action, QString icon, bool noThumb){
+ if(icon.isEmpty()){ return; }
+ if(isThemeIcon(icon)){
+ action->setIcon( iconFromTheme(icon));
+ return ;
+ }
+ //See if the icon has already been loaded into the HASH
+ bool needload = !HASH.contains(icon);
+ if(!needload){
+ if(!noThumb && !HASH[icon].thumbnail.isNull()){ action->setIcon( HASH[icon].thumbnail ); return; }
+ else if(!HASH[icon].icon.isNull()){ action->setIcon( HASH[icon].icon ); return; }
+ }
+ //Need to load the icon
+ icon_data idata;
+ if(HASH.contains(icon)){ idata = HASH.value(icon); }
+ else { idata = createData(icon); }
+ idata.pendingMenus << QPointer<QMenu>(action); //save this button for later
+ HASH.insert(icon, idata);
+ if(needload){ startReadFile(icon, idata.fullpath); }
+}
+
void LIconCache::clearIconTheme(){
//use when the icon theme changes to refresh all requested icons
QStringList keys = HASH.keys();
@@ -282,6 +303,8 @@ void LIconCache::startReadFile(QString id, QString path){
idat.pendingLabels.clear();
for(int i=0; i<idat.pendingActions.length(); i++){ if(!idat.pendingActions[i].isNull()){ idat.pendingActions[i]->setIcon(idat.icon); } }
idat.pendingActions.clear();
+ for(int i=0; i<idat.pendingMenus.length(); i++){ if(!idat.pendingMenus[i].isNull()){ idat.pendingMenus[i]->setIcon(idat.icon); } }
+ idat.pendingMenus.clear();
//Now update the hash and let the world know it is available now
HASH.insert(id, idat);
this->emit IconAvailable(id);
diff --git a/src-qt5/core/libLumina/LIconCache.h b/src-qt5/core/libLumina/LIconCache.h
index 428ffcab..691d328c 100644
--- a/src-qt5/core/libLumina/LIconCache.h
+++ b/src-qt5/core/libLumina/LIconCache.h
@@ -4,7 +4,7 @@
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
-// This is a simple class for loading/serving icon files
+// This is a simple class for loading/serving icon files
// from the icon theme or local filesystem
//===========================================
#include <QHash>
@@ -26,6 +26,7 @@ struct icon_data{
QList<QPointer<QLabel> > pendingLabels;
QList<QPointer<QAbstractButton> > pendingButtons;
QList<QPointer<QAction> > pendingActions;
+ QList<QPointer<QMenu> > pendingMenus;
QIcon icon;
QIcon thumbnail;
};
@@ -50,6 +51,7 @@ public:
void loadIcon(QAbstractButton *button, QString icon, bool noThumb = false);
void loadIcon(QLabel *label, QString icon, bool noThumb = false);
void loadIcon(QAction *action, QString icon, bool noThumb = false);
+ void loadIcon(QMenu *action, QString icon, bool noThumb = false);
QIcon loadIcon(QString icon, bool noThumb = false); //generic loading routine - does not background the loading of icons when not in the cache
diff --git a/src-qt5/core/libLumina/LUtils.cpp b/src-qt5/core/libLumina/LUtils.cpp
index fa0173dc..3d3c878a 100644
--- a/src-qt5/core/libLumina/LUtils.cpp
+++ b/src-qt5/core/libLumina/LUtils.cpp
@@ -14,7 +14,7 @@
#include <unistd.h>
-inline QStringList ProcessRun(QString cmd, QStringList args){
+/*inline QStringList ProcessRun(QString cmd, QStringList args){
//Assemble outputs
QStringList out; out << "1" << ""; //error code, string output
QProcess proc;
@@ -26,7 +26,7 @@ inline QStringList ProcessRun(QString cmd, QStringList args){
if(args.isEmpty()){
proc.start(cmd, QIODevice::ReadOnly);
}else{
- proc.start(cmd,args ,QIODevice::ReadOnly);
+ proc.start(cmd,args ,QIODevice::ReadOnly);
}
QString info;
while(!proc.waitForFinished(1000)){
@@ -37,52 +37,59 @@ inline QStringList ProcessRun(QString cmd, QStringList args){
}
out[0] = QString::number(proc.exitCode());
out[1] = info+QString(proc.readAllStandardOutput());
- return out;
-}
+ return out;
+}*/
+
//=============
// LUtils Functions
//=============
-int LUtils::runCmd(QString cmd, QStringList args){
- /*QProcess proc;
- proc.setProcessChannelMode(QProcess::MergedChannels);
- if(args.isEmpty()){
- proc.start(cmd);
- }else{
- proc.start(cmd, args);
+QString LUtils::runCommand(bool &success, QString command, QStringList arguments, QString workdir, QStringList env){
+ QProcess proc;
+ proc.setProcessChannelMode(QProcess::MergedChannels); //need output
+ //First setup the process environment as necessary
+ QProcessEnvironment PE = QProcessEnvironment::systemEnvironment();
+ if(!env.isEmpty()){
+ for(int i=0; i<env.length(); i++){
+ if(!env[i].contains("=")){ continue; }
+ PE.insert(env[i].section("=",0,0), env[i].section("=",1,100));
+ }
+ }
+ proc.setProcessEnvironment(PE);
+ //if a working directory is specified, check it and use it
+ if(!workdir.isEmpty()){
+ proc.setWorkingDirectory(workdir);
}
- //if(!proc.waitForStarted(30000)){ return 1; } //process never started - max wait of 30 seconds
- while(!proc.waitForFinished(300)){
+ //Now run the command (with any optional arguments)
+ if(arguments.isEmpty()){ proc.start(command); }
+ else{ proc.start(command, arguments); }
+ //Wait for the process to finish (but don't block the event loop)
+ QString info;
+ while(!proc.waitForFinished(1000)){
if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal
- QCoreApplication::processEvents();
+ QString tmp = proc.readAllStandardOutput();
+ if(tmp.isEmpty()){ proc.terminate(); }
+ else{ info.append(tmp); }
}
- int ret = proc.exitCode();
- return ret;*/
- QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args);
- return future.result()[0].toInt(); //turn it back into an integer return code
-
+ info.append(proc.readAllStandardOutput()); //make sure we don't miss anything in the output
+ success = (proc.exitCode()==0); //return success/failure
+ return info;
+}
+
+int LUtils::runCmd(QString cmd, QStringList args){
+ bool success;
+ LUtils::runCommand(success, cmd, args);
+ return success;
+
+ /*QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args);
+ return future.result()[0].toInt(); //turn it back into an integer return code*/
}
QStringList LUtils::getCmdOutput(QString cmd, QStringList args){
- /*QProcess proc;
- QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
- env.insert("LANG", "C");
- env.insert("LC_MESSAGES", "C");
- proc.setProcessEnvironment(env);
- proc.setProcessChannelMode(QProcess::MergedChannels);
- if(args.isEmpty()){
- proc.start(cmd);
- }else{
- proc.start(cmd,args);
- }
- //if(!proc.waitForStarted(30000)){ return QStringList(); } //process never started - max wait of 30 seconds
- while(!proc.waitForFinished(300)){
- if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal
- QCoreApplication::processEvents();
- }
- QStringList out = QString(proc.readAllStandardOutput()).split("\n");
- return out;*/
- QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args);
- return future.result()[1].split("\n"); //Split the return message into lines
+ bool success;
+ QString log = LUtils::runCommand(success, cmd, args);
+ return log.split("\n");
+ /*QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args);
+ return future.result()[1].split("\n"); //Split the return message into lines*/
}
QStringList LUtils::readFile(QString filepath){
@@ -114,11 +121,15 @@ bool LUtils::writeFile(QString filepath, QStringList contents, bool overwrite){
}
bool LUtils::isValidBinary(QString& bin){
+ //Trim off any quotes
+ if(bin.startsWith("\"") && bin.endsWith("\"")){ bin.chop(1); bin = bin.remove(0,1); }
+ if(bin.startsWith("\'") && bin.endsWith("\'")){ bin.chop(1); bin = bin.remove(0,1); }
+ //Now look for relative/absolute path
if(!bin.startsWith("/")){
//Relative path: search for it on the current "PATH" settings
QStringList paths = QString(qgetenv("PATH")).split(":");
for(int i=0; i<paths.length(); i++){
- if(QFile::exists(paths[i]+"/"+bin)){ bin = paths[i]+"/"+bin; break;}
+ if(QFile::exists(paths[i]+"/"+bin)){ bin = paths[i]+"/"+bin; break;}
}
}
//bin should be the full path by now
@@ -150,7 +161,7 @@ QSettings* LUtils::openSettings(QString org, QString name, QObject *parent){
}else{
return (new QSettings(filepath, QSettings::IniFormat, parent));
}
-
+
}
QStringList LUtils::systemApplicationDirs(){
@@ -164,7 +175,7 @@ QStringList LUtils::systemApplicationDirs(){
for(int i=0; i<appDirs.length(); i++){
if( QFile::exists(appDirs[i]+"/applications") ){
out << appDirs[i]+"/applications";
- //Also check any subdirs within this directory
+ //Also check any subdirs within this directory
// (looking at you KDE - stick to the standards!!)
out << LUtils::listSubDirectories(appDirs[i]+"/applications");
}
@@ -197,7 +208,7 @@ QString LUtils::GenerateOpenTerminalExec(QString term, QString dirpath){
}else if(term=="konsole" || term == "qterminal"){
exec = term+" --workdir \""+dirpath+"\"";
}else{
- //-e is the parameter for most of the terminal appliction to execute an external command.
+ //-e is the parameter for most of the terminal appliction to execute an external command.
//In this case we start a shell in the selected directory
//Need the user's shell first
QString shell = QString(getenv("SHELL"));
@@ -253,12 +264,18 @@ QString LUtils::AppToAbsolute(QString path){
return path;
}
+QStringList LUtils::videoExtensions() {
+ static QStringList vidExtensions;
+ vidExtensions << "avi" << "mkv" << "mp4" << "mov" << "webm" << "wmv";
+ return vidExtensions;
+}
+
QStringList LUtils::imageExtensions(bool wildcards){
//Note that all the image extensions are lowercase!!
static QStringList imgExtensions;
if(imgExtensions.isEmpty()){
QList<QByteArray> fmt = QImageReader::supportedImageFormats();
- for(int i=0; i<fmt.length(); i++){
+ for(int i=0; i<fmt.length(); i++){
if(wildcards){ imgExtensions << "*."+QString::fromLocal8Bit(fmt[i]); }
else{ imgExtensions << QString::fromLocal8Bit(fmt[i]); }
}
@@ -308,7 +325,7 @@ QStringList LUtils::imageExtensions(bool wildcards){
qDebug() << "Loading System Encoding:" << langEnc;
}
//Load current encoding for this locale
- QTextCodec::setCodecForLocale( QTextCodec::codecForName(langEnc.toUtf8()) );
+ QTextCodec::setCodecForLocale( QTextCodec::codecForName(langEnc.toUtf8()) );
return cTrans;
}
@@ -379,7 +396,7 @@ void LUtils::setLocaleEnv(QString lang, QString msg, QString time, QString num,Q
else{
if(!ctype.contains(".")){ ctype.append(".UTF-8"); }
setenv("LC_CTYPE",ctype.toUtf8(),1);
- }
+ }
}
QString LUtils::currentLocale(){
diff --git a/src-qt5/core/libLumina/LUtils.h b/src-qt5/core/libLumina/LUtils.h
index 4ad05ca1..ee04c023 100644
--- a/src-qt5/core/libLumina/LUtils.h
+++ b/src-qt5/core/libLumina/LUtils.h
@@ -30,6 +30,9 @@
class LUtils{
public:
+ //Run an external command and return output & exit code
+ static QString runCommand(bool &success, QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList());
+
//Run an external command and return the exit code
static int runCmd(QString cmd, QStringList args = QStringList());
//Run an external command and return any text output (one line per entry)
@@ -55,7 +58,7 @@ public:
//Create the exec string to open a terminal in a particular directory
static QString GenerateOpenTerminalExec(QString term, QString dirpath);
-
+
//List all the sub-directories of a parent dir (recursive)
static QStringList listSubDirectories(QString dir, bool recursive = true);
@@ -65,18 +68,19 @@ public:
//Get the list of all file extensions which Qt can read (lowercase)
static QStringList imageExtensions(bool wildcards = false);
-
+ static QStringList videoExtensions();
+
//Load a translation file for a Lumina Project
static QTranslator* LoadTranslation(QApplication *app, QString appname, QString locale = "", QTranslator *cTrans = 0);
//Other localization shortcuts
static QStringList knownLocales(); //Note: This only lists locales known to Lumina (so the i18n files need to be installed)
static void setLocaleEnv(QString lang, QString msg="", QString time="", QString num="" ,QString money="",QString collate="", QString ctype="");
static QString currentLocale();
-
+
//Number format conversions
static double DisplaySizeToBytes(QString num); //Turn a display size (like 50M or 50KB) into a double for calculations (bytes)
static QString BytesToDisplaySize(qint64 bytes); //convert into a readable size (like 50M or 50KB)
-
+
static QString SecondsToDisplay(int secs); //convert into a readable time
};
#endif
diff --git a/src-qt5/core/libLumina/LUtils.pri b/src-qt5/core/libLumina/LUtils.pri
index 6ce0839c..da5a78d5 100644
--- a/src-qt5/core/libLumina/LUtils.pri
+++ b/src-qt5/core/libLumina/LUtils.pri
@@ -15,8 +15,7 @@ GIT_VERSION=$$system(git describe --always)
#DEFINES += BUILD_DATE='"\\\"$$system(date)\\\""'
#LuminaOS files
-HEADERS *= $${PWD}/LuminaOS.h \
- $${PWD}/OSInterface.h
+HEADERS *= $${PWD}/LuminaOS.h
# LuminaOS support functions (or fall back to generic one)
exists($${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp){
@@ -26,13 +25,6 @@ exists($${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp){
}else{
SOURCES *= $${PWD}/LuminaOS-template.cpp
}
-exists($${PWD}/OSInterface-$${LINUX_DISTRO}.cpp){
- SOURCES *= $${PWD}/OSInterface-$${LINUX_DISTRO}.cpp
-}else:exists($${PWD}/OSInterface-$${OS}.cpp){
- SOURCES *= $${PWD}/OSInterface-$${OS}.cpp
-}else{
- SOURCES *= $${PWD}/OSInterface-template.cpp
-}
#LUtils Files
SOURCES *= $${PWD}/LUtils.cpp
diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp
new file mode 100644
index 00000000..93e95afd
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoLabel.cpp
@@ -0,0 +1,122 @@
+#include "LVideoLabel.h"
+#include <LuminaXDG.h>
+#include <QCoreApplication>
+#include <QTimer>
+
+LVideoLabel::LVideoLabel(QString file, bool icons, QWidget *parent) : QLabel(parent) {
+ thumbnail = QPixmap();
+ entered = false;
+ this->icons = icons;
+ filepath = file;
+ defaultThumbnail = LXDG::findIcon("media-playback-start", "").pixmap(256,256);
+ QTimer::singleShot(qrand()%10, this, SLOT(initializeBackend()) );
+}
+
+LVideoLabel::~LVideoLabel() {
+ mediaPlayer->deleteLater();
+ surface->deleteLater();
+}
+
+void LVideoLabel::initializeBackend(){
+ mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface);
+ surface = new LVideoSurface(this);
+ mediaPlayer->setVideoOutput(surface);
+ mediaPlayer->setPlaybackRate(3);
+ mediaPlayer->setMuted(true);
+
+ this->setPixmap(defaultThumbnail.scaled(this->size(),Qt::IgnoreAspectRatio));
+ mediaPlayer->setMedia(QUrl::fromLocalFile(filepath));
+
+ this->connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap)));
+ this->connect(mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(stateChanged(QMediaPlayer::State)));
+ this->connect(mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus)));
+ this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver()));
+
+ //QTimer::singleShot( qrand()%100,mediaPlayer, SLOT(play()) );
+ //mediaPlayer->play();
+}
+
+void LVideoLabel::enableIcons() {
+ this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio));
+ icons = true;
+}
+
+void LVideoLabel::disableIcons() {
+ this->setPixmap(defaultThumbnail.scaled(this->size(),Qt::IgnoreAspectRatio));
+ icons = false;
+}
+
+void LVideoLabel::stopVideo(QPixmap pix) {
+ if(!entered) {
+ emit frameReceived(pix);
+ if(thumbnail.isNull())
+ thumbnail = pix;
+ if(icons)
+ this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio));
+ mediaPlayer->pause();
+ }else {
+ if(icons)
+ this->setPixmap(pix.scaled(this->size(),Qt::IgnoreAspectRatio));
+ }
+}
+
+void LVideoLabel::stateChanged(QMediaPlayer::State state) {
+ //qDebug() << state;
+}
+
+void LVideoLabel::setDuration(QMediaPlayer::MediaStatus status) {
+ //qDebug() << status;
+ if(status == QMediaPlayer::BufferedMedia && !entered) { //Set duration in the middle to capture the thumbnail
+ mediaPlayer->setPosition(mediaPlayer->duration() / 2);
+ mediaPlayer->play();
+ }else if(status == QMediaPlayer::EndOfMedia && entered) { //Loop back to the beginning if playback started and at the end of the video
+ mediaPlayer->setPosition(0);
+ mediaPlayer->play();
+ }else if(status == QMediaPlayer::InvalidMedia){
+ mediaPlayer->stop();
+ QTimer::singleShot(qrand()%100, mediaPlayer, SLOT(play())); //mediaPlayer->play();
+ }/*else if(status == QMediaPlayer::LoadingMedia) {
+ mediaPlayer->pause();
+ QTimer timer;
+ timer.setSingleShot(true);
+ timer.setInterval(300);
+ timer.start();
+ qDebug() << "Timer Started" << timer.remainingTime();
+ while(timer.isActive()) QCoreApplication::processEvents(QEventLoop::AllEvents, 5);
+ qDebug() << "Timer Finished" << timer.remainingTime();
+ mediaPlayer->setPosition(0);
+ mediaPlayer->play();
+ }*/
+}
+
+void LVideoLabel::resizeEvent(QResizeEvent *event) {
+ //Resize the current pixmap to match the new size
+ if(!thumbnail.isNull()){
+ if(icons)
+ this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio));
+ else
+ this->setPixmap(defaultThumbnail.scaled(this->size(),Qt::IgnoreAspectRatio));
+ }
+ QLabel::resizeEvent(event);
+}
+
+//Start playing the video from the beginning when the mouse enters the label
+void LVideoLabel::enterEvent(QEvent *event) {
+ if(icons) {
+ entered=true;
+ emit rollOver();
+ mediaPlayer->setPosition(0);
+ mediaPlayer->play();
+ }
+ QWidget::enterEvent(event);
+}
+
+//Stop the video and set the thumbnail back to the middle of the video when the mouse leaves the label
+void LVideoLabel::leaveEvent(QEvent *event) {
+ if(icons) {
+ entered=false;
+ mediaPlayer->setPosition(mediaPlayer->duration() / 2);
+ emit rollOver();
+ }
+ QWidget::leaveEvent(event);
+}
diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h
new file mode 100644
index 00000000..56defb6a
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoLabel.h
@@ -0,0 +1,42 @@
+#ifndef LVIDEOLABEL_H
+#define LVIDEOLABEL_H
+
+#include <QLabel>
+#include <QMediaPlayer>
+#include <QTimer>
+#include <QResizeEvent>
+#include "LVideoSurface.h"
+
+class LVideoLabel : public QLabel{
+ Q_OBJECT
+ public:
+ LVideoLabel(QString, bool, QWidget* parent=NULL);
+ ~LVideoLabel();
+ void enableIcons();
+ void disableIcons();
+
+ protected:
+ void enterEvent(QEvent*);
+ void leaveEvent(QEvent*);
+ void resizeEvent(QResizeEvent*);
+
+ signals:
+ void rollOver();
+ void frameReceived(QPixmap);
+
+ private slots:
+ void initializeBackend();
+ void stopVideo(QPixmap);
+ void setDuration(QMediaPlayer::MediaStatus);
+ void stateChanged(QMediaPlayer::State);
+
+ private:
+ QMediaPlayer *mediaPlayer;
+ LVideoSurface *surface;
+ QPixmap thumbnail;
+ QPixmap defaultThumbnail;
+ bool entered;
+ bool icons;
+ QString filepath;
+};
+#endif
diff --git a/src-qt5/core/libLumina/LVideoLabel.pri b/src-qt5/core/libLumina/LVideoLabel.pri
new file mode 100644
index 00000000..06395c8d
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoLabel.pri
@@ -0,0 +1,13 @@
+QT *= multimedia
+
+HEADERS *= $${PWD}/LVideoLabel.h
+HEADERS *= $${PWD}/LVideoSurface.h
+HEADERS *= $${PWD}/LVideoWidget.h
+SOURCES *= $${PWD}/LVideoLabel.cpp
+SOURCES *= $${PWD}/LVideoSurface.cpp
+SOURCES *= $${PWD}/LVideoWidget.cpp
+
+INCLUDEPATH *= ${PWD}
+
+#Now the other dependendies of it
+#include(LUtils.pri)
diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp
new file mode 100644
index 00000000..3aaa81f0
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoSurface.cpp
@@ -0,0 +1,60 @@
+#include "LVideoSurface.h"
+#include <QDebug>
+
+LVideoSurface::LVideoSurface(QObject *parent) : QAbstractVideoSurface(parent) {
+ frameImage = QPixmap();
+ entered = false;
+}
+
+bool LVideoSurface::present(const QVideoFrame &frame) {
+ //qDebug() << surfaceFormat().frameSize() << frame.size();
+ if(!frameImage.isNull() && !entered) {
+ emit frameReceived(frameImage);
+ return true;
+ }
+
+ if(frame.isValid()) {
+ //qDebug() << "Recording Frame";
+ //qDebug() << surfaceFormat().frameSize() << frame.size();
+ QVideoFrame icon(frame);
+ icon.map(QAbstractVideoBuffer::ReadOnly);
+ QImage img(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()));
+
+ if((frameImage.isNull() && !entered) or entered)
+ frameImage = QPixmap::fromImage(img.copy(img.rect()));
+
+ icon.unmap();
+ emit frameReceived(frameImage);
+ return true;
+ }
+ return false;
+}
+
+QList<QVideoFrame::PixelFormat> LVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const {
+ Q_UNUSED(type);
+ return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB32 << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555 << QVideoFrame::Format_BGRA32 << QVideoFrame::Format_BGR32;
+}
+
+void LVideoSurface::stop() {
+ QAbstractVideoSurface::stop();
+}
+
+void LVideoSurface::switchRollOver() {
+ entered = !entered;
+}
+
+bool LVideoSurface::start(const QVideoSurfaceFormat &format) {
+ const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ const QSize size = format.frameSize();
+
+ //QVideoSurfaceFormat newFormat = format;
+ //Shrink the frames passed through the format to a smaller, thumbnail appropriate size and increase the frame rate
+ //newFormat.setFrameSize(258,258);
+ //newFormat.setFrameRate(90);
+
+ if (imageFormat != QImage::Format_Invalid && !size.isEmpty())
+ QAbstractVideoSurface::start(format);
+
+ return (imageFormat != QImage::Format_Invalid && !size.isEmpty());
+}
diff --git a/src-qt5/core/libLumina/LVideoSurface.h b/src-qt5/core/libLumina/LVideoSurface.h
new file mode 100644
index 00000000..7a3dcaad
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoSurface.h
@@ -0,0 +1,26 @@
+#ifndef LVIDEOSURFACE_H
+#define LVIDEOSURFACE_H
+
+#include <QAbstractVideoSurface>
+#include <QVideoSurfaceFormat>
+#include <QPixmap>
+#include <QDebug>
+
+class LVideoSurface : public QAbstractVideoSurface {
+ Q_OBJECT
+
+ public:
+ LVideoSurface(QObject *parent=0);
+ virtual bool present(const QVideoFrame&);
+ virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType) const;
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+ signals:
+ void frameReceived(QPixmap);
+ public slots:
+ void switchRollOver();
+ private:
+ QPixmap frameImage;
+ bool entered;
+};
+#endif
diff --git a/src-qt5/core/libLumina/LVideoSurface.pri b/src-qt5/core/libLumina/LVideoSurface.pri
new file mode 100644
index 00000000..469b8c93
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoSurface.pri
@@ -0,0 +1,9 @@
+QT *= multimedia
+
+HEADERS *= $${PWD}/LVideoSurface.h
+SOURCES *= $${PWD}/LVideoSurface.cpp
+
+INCLUDEPATH *= ${PWD}
+
+#Now the other dependendies of it
+#include(LUtils.pri)
diff --git a/src-qt5/core/libLumina/LVideoWidget.cpp b/src-qt5/core/libLumina/LVideoWidget.cpp
new file mode 100644
index 00000000..f1f74414
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoWidget.cpp
@@ -0,0 +1,38 @@
+#include "LVideoWidget.h"
+
+LVideoWidget::LVideoWidget(QString file, QSize iconSize, bool icons, QWidget *parent) : QWidget(parent) {
+ iconLabel = new LVideoLabel(file, icons, parent);
+ textLabel = new QLabel(parent);
+
+ layout = new QHBoxLayout(this);
+ layout->setAlignment(Qt::AlignLeft | Qt::AlignCenter);
+ layout->setContentsMargins(5,5,5,5);
+ layout->setStretchFactor(textLabel, 1); //make sure this always occupies all extra space
+
+ textLabel->setText(file.section("/", -1));
+ iconLabel->setGeometry(QRect(QPoint(0,0), iconSize));
+ iconLabel->setFixedSize(iconSize);
+ iconLabel->setVisible(true);
+ textLabel->setVisible(true);
+
+ layout->addWidget(iconLabel);
+ layout->addWidget(textLabel);
+}
+
+LVideoWidget::~LVideoWidget() {
+ delete iconLabel;
+ delete textLabel;
+ delete layout;
+}
+
+void LVideoWidget::setIconSize(QSize iconSize) {
+ iconLabel->setFixedSize(iconSize);
+}
+
+void LVideoWidget::enableIcons() {
+ iconLabel->enableIcons();
+}
+
+void LVideoWidget::disableIcons() {
+ iconLabel->disableIcons();
+}
diff --git a/src-qt5/core/libLumina/LVideoWidget.h b/src-qt5/core/libLumina/LVideoWidget.h
new file mode 100644
index 00000000..610fd9e5
--- /dev/null
+++ b/src-qt5/core/libLumina/LVideoWidget.h
@@ -0,0 +1,22 @@
+#ifndef LVIDEOWIDGET_H
+#define LVIDEOWIDGET_H
+
+#include "LVideoLabel.h"
+#include <QHBoxLayout>
+#include <QResizeEvent>
+
+class LVideoWidget : public QWidget {
+ Q_OBJECT
+ public:
+ LVideoWidget(QString, QSize, bool icons, QWidget* parent=NULL);
+ ~LVideoWidget();
+ void setIconSize(QSize);
+ void disableIcons();
+ void enableIcons();
+
+ private:
+ LVideoLabel *iconLabel;
+ QLabel *textLabel;
+ QHBoxLayout *layout;
+};
+#endif
diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp
index b9346565..1ee8fb8a 100644
--- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp
@@ -27,12 +27,12 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
QString LOS::ControlPanelShortcut(){ return "/usr/local/share/applications/pccontrol.desktop"; } //system control panel
QString LOS::AppStoreShortcut(){ return "/usr/local/share/applications/appcafe.desktop"; } //graphical app/pkg manager
//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
-QStringList LOS::RSSFeeds(){
+QStringList LOS::RSSFeeds(){
QStringList feeds;
feeds << "FreeBSD News Feed::::https://www.freebsd.org/news/rss.xml";
- feeds << "TrueOS News Feed::::http://www.trueos.org/?feed=rss2";
+ feeds << "TrueOS News Feed::::http://www.trueos.org/feed/";
return feeds;
- }
+ }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
@@ -59,6 +59,25 @@ QStringList LOS::ExternalDevicePaths(){
i--;
}
}
+ //Also add info about anything in the "/media" directory
+ QDir media("/media");
+ QFileInfoList list = media.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Type | QDir::Name);
+ //qDebug() << "Media files found:" << list.length();
+ for(int i=0; i<list.length(); i++){
+ //qDebug() << "Found media entry:" << list[i].fileName();
+ if(list[i].isDir()){
+ devs << "UNKNOWN::::::::/media/"+list[i].fileName();
+ }else if(list[i].fileName().endsWith(".desktop")){
+ QString type = list[i].fileName().section(".desktop",0,-2);
+ //Determine the type of hardware device based on the dev node
+ if(type.startsWith("da")){ type = "USB"; }
+ else if(type.startsWith("ada")){ type = "HDRIVE"; }
+ else if(type.startsWith("mmsd")){ type = "SDCARD"; }
+ else if(type.startsWith("cd")||type.startsWith("acd")){ type="DVD"; }
+ else{ type = "UNKNOWN"; }
+ devs << type+"::::::::/media/"+list[i].fileName();
+ }
+ }
return devs;
}
@@ -66,7 +85,7 @@ QStringList LOS::ExternalDevicePaths(){
int LOS::ScreenBrightness(){
//First run a quick check to ensure this is not a VirtualBox VM (no brightness control)
static int goodsys = -1; //This will not change over time - only check/set once
- if(goodsys<0){
+ if(goodsys<0){
//Make sure we are not running in VirtualBox (does not work in a VM)
QStringList info = LUtils::getCmdOutput("pciconf -lv");
if( info.filter("VirtualBox", Qt::CaseInsensitive).isEmpty() ){ goodsys = 1; }
@@ -84,8 +103,8 @@ int LOS::ScreenBrightness(){
}
}
//If it gets to this point, then we have a valid (but new) installation
- if(screenbrightness<0){ screenbrightness = 100; } //default value for systems
- return screenbrightness;
+ if(screenbrightness<0){ screenbrightness = 100; } //default value for systems
+ return screenbrightness;
}
//Set screen brightness
@@ -98,12 +117,12 @@ void LOS::setScreenBrightness(int percent){
bool success = false;
// - try hardware setting first (TrueOS || or intel_backlight)
bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty();
- if( LUtils::isValidBinary("pc-sysconfig") && !remoteSession){
+ /*if( LUtils::isValidBinary("pc-sysconfig") && !remoteSession){
//Use TrueOS tool (direct sysctl control)
QString ret = LUtils::getCmdOutput("pc-sysconfig", QStringList() <<"setscreenbrightness "+QString::number(percent)).join("");
success = ret.toLower().contains("success");
qDebug() << "Set hardware brightness:" << percent << success;
- }
+ }*/
if( !success && LUtils::isValidBinary("intel_backlight") && !remoteSession){
//Use the intel_backlight utility (only for Intel mobo/hardware?)
if(0== LUtils::runCmd("intel_backlight", QStringList() <<QString::number(percent)) ){
@@ -130,10 +149,10 @@ int LOS::audioVolume(){ //Returns: audio volume as a percentage (0-100, with -1
if(out < 0){
//First time session check: Load the last setting for this user
QString info = LUtils::readFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentvolume").join("");
- if(!info.isEmpty()){
- out = info.simplified().toInt();
+ if(!info.isEmpty()){
+ out = info.simplified().toInt();
audiovolume = out; //reset this internal flag
- return out;
+ return out;
}
}
bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty();
@@ -154,7 +173,7 @@ int LOS::audioVolume(){ //Returns: audio volume as a percentage (0-100, with -1
//Volume changed by other utility: adjust the saved value as well
LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentvolume", QStringList() << QString::number(out), true);
}
- audiovolume = out;
+ audiovolume = out;
}
}
return out;
@@ -203,7 +222,7 @@ void LOS::changeAudioVolume(int percentdiff){
//Run Command
LUtils::runCmd("mixer vol "+QString::number(L)+":"+QString::number(R));
}
- }
+ }
}
//Check if a graphical audio mixer is installed
@@ -229,7 +248,7 @@ bool LOS::systemPerformingUpdates(){
//Return the details of any updates which are waiting to apply on shutdown
QString LOS::systemPendingUpdates(){
- if(QFile::exists("/tmp/.rebootRequired")){ return LUtils::readFile("/tmp/.rebootRequired").join("\n"); }
+ if(QFile::exists("/tmp/.trueos-update-staged")){ return LUtils::readFile("/tmp/.trueos-update-staged").join("\n"); }
else{ return ""; }
}
@@ -241,24 +260,31 @@ void LOS::systemShutdown(bool skipupdates){ //start poweroff sequence
//System Restart
void LOS::systemRestart(bool skipupdates){ //start reboot sequence
- if(skipupdates){QProcess::startDetached("shutdown -ro now"); }
- else{ QProcess::startDetached("shutdown -r now"); }
+ bool activeupdates = (LUtils::getCmdOutput("sysrc -n trueos_active_update").join("").simplified()=="YES");
+ if(skipupdates){
+ QProcess::startDetached("shutdown -ro now");
+ }else{
+ if(activeupdates && LUtils::isValidBinary("pc-updatemanager") && LOS::systemPendingUpdates().isEmpty()){ QProcess::startDetached("pc-updatemanager startupdate"); }
+ else{ QProcess::startDetached("shutdown -r now"); }
+ }
}
//Check for suspend support
bool LOS::systemCanSuspend(){
- //This will only function on TrueOS
- //(permissions issues on standard FreeBSD unless setup a special way)
- bool ok = QFile::exists("/usr/local/bin/pc-sysconfig");
+ QString state = LUtils::getCmdOutput("sysctl -n hw.acpi.suspend_state").join("").simplified();
+ bool ok = LUtils::getCmdOutput("sysctl -n hw.acpi.supported_sleep_state").join("").split(" ",QString::SkipEmptyParts).contains(state);
+ /*bool ok = QFile::exists("/usr/local/bin/pc-sysconfig");
if(ok){
ok = LUtils::getCmdOutput("pc-sysconfig systemcansuspend").join("").toLower().contains("true");
- }
+ }*/
return ok;
}
//Put the system into the suspend state
void LOS::systemSuspend(){
- QProcess::startDetached("pc-sysconfig suspendsystem");
+ QString state = LUtils::getCmdOutput("sysctl -n hw.acpi.suspend_state").join("").simplified();
+ //QProcess::startDetached("pc-sysconfig suspendsystem");
+ QProcess::startDetached("acpiconf", QStringList() << "-s" << state );
}
//Battery Availability
@@ -270,8 +296,8 @@ bool LOS::hasBattery(){
//Battery Charge Level
int LOS::batteryCharge(){ //Returns: percent charge (0-100), anything outside that range is counted as an error
int charge = LUtils::getCmdOutput("apm -l").join("").toInt();
- if(charge > 100){ charge = -1; } //invalid charge
- return charge;
+ if(charge > 100){ charge = -1; } //invalid charge
+ return charge;
}
//Battery Charging State
@@ -309,11 +335,11 @@ QString LOS::FileSystemCapacity(QString dir) { //Return: percentage capacity as
QStringList LOS::CPUTemperatures(){ //Returns: List containing the temperature of any CPU's ("50C" for example)
static QStringList vars = QStringList();
QStringList temps;
- if(vars.isEmpty()){
+ if(vars.isEmpty()){
temps = LUtils::getCmdOutput("sysctl -i dev.cpu").filter(".temperature:"); //try direct readings first
if(temps.isEmpty()){ temps = LUtils::getCmdOutput("sysctl -i hw.acpi").filter(".temperature:"); } // then try acpi values
}else{ temps = LUtils::getCmdOutput("sysctl "+vars.join(" ")); vars.clear(); }
-
+
temps.sort();
for(int i=0; i<temps.length(); i++){
if(temps[i].contains(".acpi.") || temps[i].contains(".cpu")){
@@ -364,7 +390,7 @@ int LOS::CPUUsagePercent(){ //Returns: Overall percentage of the amount of CPU c
tot += 100.0L - ( (100.0L*result[i].toLong())/sum ); //remember IDLE is the last of the five values per CPU
}
return qRound(tot/cpnum);
-
+
}
int LOS::MemoryUsagePercent(){
@@ -388,14 +414,14 @@ QStringList LOS::DiskUsage(){ //Returns: List of current read/write stats for ea
info[i].replace("\t"," ");
if(i==1){ labs = info[i].split(" ", QString::SkipEmptyParts); }//the labels for each column
else{
- QStringList data = info[i].split(" ",QString::SkipEmptyParts); //data[0] is always the device
+ QStringList data = info[i].split(" ",QString::SkipEmptyParts); //data[0] is always the device
//qDebug() << "Data Line:" << data;
if(data.length()>2 && labs.length()>2){
out << fmt.arg(data[0], data[1]+" "+labs[1], data[2]+" "+labs[2]);
}
}
}
-
+
return out;
}
diff --git a/src-qt5/core/libLumina/LuminaOS.h b/src-qt5/core/libLumina/LuminaOS.h
index e7a72129..98137816 100644
--- a/src-qt5/core/libLumina/LuminaOS.h
+++ b/src-qt5/core/libLumina/LuminaOS.h
@@ -5,8 +5,8 @@
// See the LICENSE file for full details
//===========================================
// This is the main interface for any OS-specific system calls
-// To port Lumina to a different operating system, just create a file
-// called "LuminaOS-<Operating System>.cpp", and use that file in
+// To port Lumina to a different operating system, just create a file
+// called "LuminaOS-<Operating System>.cpp", and use that file in
// the project (libLumina.pro) instead of LuminaOS-FreeBSD.cpp
//===========================================
#ifndef _LUMINA_LIBRARY_OS_H
@@ -23,7 +23,7 @@
class LOS{
public:
//Return the name of the OS being used
- static QString OSName();
+ static QString OSName();
//OS-specific prefix(s)
static QString LuminaShare(); //Install dir for Lumina share files
@@ -34,7 +34,7 @@ public:
static QString ControlPanelShortcut();
static QString AppStoreShortcut();
- //OS-specific RSS feeds
+ //OS-specific RSS feeds
static QStringList RSSFeeds(); //Return Format: QStringList[ <name>::::<url> ];
//Scan for mounted external devices
@@ -81,13 +81,13 @@ public:
static bool batteryIsCharging();
//Battery Time Remaining
static int batterySecondsLeft(); //Returns: estimated number of seconds remaining
-
+
//Get the checksum for a file
static QStringList Checksums(QStringList filepaths); //Return: checksum of each input file (same order)
-
+
//Get the filesystem capacity
static QString FileSystemCapacity(QString dir) ; //Return: percentage capacity as give by the df command
-
+
//System CPU Information
static QStringList CPUTemperatures(); //Returns: List containing the temperature of any CPU's ("50C" for example)
static int CPUUsagePercent(); //Returns: Overall percentage of the amount of CPU cycles in use (-1 for errors)
diff --git a/src-qt5/core/libLumina/LuminaSingleApplication.cpp b/src-qt5/core/libLumina/LuminaSingleApplication.cpp
index 86248666..6107aff8 100644
--- a/src-qt5/core/libLumina/LuminaSingleApplication.cpp
+++ b/src-qt5/core/libLumina/LuminaSingleApplication.cpp
@@ -11,7 +11,7 @@
#include <QDebug>
#include <QX11Info>
-#include <unistd.h> //for getlogin()
+#include <unistd.h> //for getuid()
LSingleApplication::LSingleApplication(int &argc, char **argv, QString appname) : QApplication(argc, argv){
//Load the proper translation systems
@@ -19,7 +19,7 @@ LSingleApplication::LSingleApplication(int &argc, char **argv, QString appname)
if(appname!="lumina-desktop"){ cTrans = LUtils::LoadTranslation(this, appname); }//save the translator for later
//Initialize a couple convenience internal variables
cfile = QDir::tempPath()+"/.LSingleApp-%1-%2-%3";
- QString username = QString(getlogin());
+ QString username = QString::number(getuid());
//For locking the process use the official process name - not the user input (no masking)
appname = this->applicationName();
cfile = cfile.arg( username, appname, QString::number(QX11Info::appScreen()) );
@@ -107,17 +107,17 @@ void LSingleApplication::PerformLockChecks(){
QLocalSocket socket(this);
socket.connectToServer(cfile);
socket.waitForConnected();
- if(!socket.isValid() || socket.state()!=QLocalSocket::ConnectedState){
+ if(!socket.isValid() || socket.state()!=QLocalSocket::ConnectedState){
//error - could not forward info for some reason
qDebug() << " - Could not connect to locking process: exiting...";
- exit(1);
- }
-
- qDebug() << " - Forwarding inputs to locking process and closing down this instance...";
+ exit(1);
+ }
+
+ qDebug() << " - Forwarding inputs to locking process and closing down this instance...";
socket.write( inputlist.join("::::").toLocal8Bit() );
socket.waitForDisconnected(500); //max out at 1/2 second (only hits this if no inputs)
}
-
+
}
//New messages detected
diff --git a/src-qt5/core/libLumina/LuminaThemes.cpp b/src-qt5/core/libLumina/LuminaThemes.cpp
index 85d43925..03524941 100644
--- a/src-qt5/core/libLumina/LuminaThemes.cpp
+++ b/src-qt5/core/libLumina/LuminaThemes.cpp
@@ -23,46 +23,67 @@
//#include "qxcbcursor.h" //needed to prod Qt to refresh the mouse cursor theme
//#include <QCursor>
-QStringList LTHEME::availableSystemThemes(){
+QStringList LTHEME::availableSystemThemes(){
//returns: [name::::path] for each item
- QDir dir(LOS::LuminaShare()+"themes");
- QStringList list = dir.entryList(QStringList() <<"*.qss.template", QDir::Files, QDir::Name);
+ QDir dir(LOS::LuminaShare()+"../lthemeengine/desktop_qss");
+ QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name);
for(int i=0; i<list.length(); i++){
//Format the output entry [<name>::::<fullpath>]
- list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]);
+ list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]);
}
- return list;
+ return list;
+}
+
+QStringList LTHEME::availableSystemStyles(){
+ //returns: [name::::path] for each item
+ QDir dir(LOS::LuminaShare()+"../lthemeengine/qss");
+ QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name);
+ for(int i=0; i<list.length(); i++){
+ //Format the output entry [<name>::::<fullpath>]
+ list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]);
+ }
+ return list;
}
QStringList LTHEME::availableLocalThemes(){ //returns: [name::::path] for each item
- QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes");
- QStringList list = dir.entryList(QStringList() <<"*.qss.template", QDir::Files, QDir::Name);
+ QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/desktop_qss");
+ QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name);
for(int i=0; i<list.length(); i++){
//Format the output entry [<name>::::<fullpath>]
- list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]);
+ list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]);
+ }
+ return list;
+}
+
+QStringList LTHEME::availableLocalStyles(){ //returns: [name::::path] for each item
+ QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/qss");
+ QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name);
+ for(int i=0; i<list.length(); i++){
+ //Format the output entry [<name>::::<fullpath>]
+ list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]);
}
return list;
}
QStringList LTHEME::availableSystemColors(){ //returns: [name::::path] for each item
//returns: [name::::path] for each item
- QDir dir(LOS::LuminaShare()+"colors");
- QStringList list = dir.entryList(QStringList() <<"*.qss.colors", QDir::Files, QDir::Name);
+ QDir dir(LOS::LuminaShare()+"../lthemeengine/colors");
+ QStringList list = dir.entryList(QStringList() <<"*.conf", QDir::Files, QDir::Name);
for(int i=0; i<list.length(); i++){
//Format the output entry [<name>::::<fullpath>]
- list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]);
+ list[i] = list[i].section(".conf",0,0)+"::::"+dir.absoluteFilePath(list[i]);
}
- return list;
+ return list;
}
QStringList LTHEME::availableLocalColors(){ //returns: [name::::path] for each item
- QDir dir(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors");
- QStringList list = dir.entryList(QStringList() <<"*.qss.colors", QDir::Files, QDir::Name);
+ QDir dir(QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/colors");
+ QStringList list = dir.entryList(QStringList() <<"*.conf", QDir::Files, QDir::Name);
for(int i=0; i<list.length(); i++){
//Format the output entry [<name>::::<fullpath>]
- list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]);
+ list[i] = list[i].section(".conf",0,0)+"::::"+dir.absoluteFilePath(list[i]);
}
- return list;
+ return list;
}
QStringList LTHEME::availableSystemIcons(){ //returns: [name] for each item
@@ -72,7 +93,7 @@ QStringList LTHEME::availableSystemIcons(){ //returns: [name] for each item
xdd << QString(getenv("XDG_DATA_DIRS")).split(":");
for(int i=0; i<xdd.length(); i++){
if(QFile::exists(xdd[i]+"/icons")){
- paths << xdd[i]+"/icons";
+ paths << xdd[i]+"/icons";
}
}
//Now get all the icon themes in these directories
@@ -83,8 +104,8 @@ QStringList LTHEME::availableSystemIcons(){ //returns: [name] for each item
tmpthemes = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
for(int j=0; j<tmpthemes.length(); j++){
if(tmpthemes[j].startsWith("default")){ continue; }
- if(QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/index.theme")) ||
- QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/index.desktop")) ){ themes << tmpthemes[j]; }
+ if( (QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/index.theme")) ||
+ QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/index.desktop")) ) ){ themes << tmpthemes[j]; }
}
}
}
@@ -92,34 +113,51 @@ QStringList LTHEME::availableSystemIcons(){ //returns: [name] for each item
themes.sort();
return themes;
}
-
+
QStringList LTHEME::availableSystemCursors(){ //returns: [name] for each item
- QStringList paths; paths << LOS::SysPrefix()+"lib/X11/icons/" << LOS::AppPrefix()+"lib/X11/icons/";
- QStringList out;
+ QStringList paths;
+ paths << QDir::homePath()+"/.icons";
+ QStringList xdd = QString(getenv("XDG_DATA_HOME")).split(":");
+ xdd << QString(getenv("XDG_DATA_DIRS")).split(":");
+ for(int i=0; i<xdd.length(); i++){
+ if(QFile::exists(xdd[i]+"/icons")){
+ paths << xdd[i]+"/icons";
+ }
+ }
+ //Now get all the icon themes in these directories
+ QStringList themes, tmpthemes;
+ QDir dir;
for(int i=0; i<paths.length(); i++){
- if( !QFile::exists(paths[i]) ){ continue; }
- QDir dir(paths[i]);
- QStringList tmp = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
- for(int j=0; j<tmp.length(); j++){
- if(QFile::exists(paths[i]+tmp[j]+"/cursors")){
- out << tmp[j]; //good theme - save it to the output list
- }
+ if(dir.cd(paths[i])){
+ tmpthemes = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
+ for(int j=0; j<tmpthemes.length(); j++){
+ if(tmpthemes[j].startsWith("default")){ continue; }
+ if( QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/cursors")) ){ themes << tmpthemes[j]; }
+ }
}
}
- return out;
+ themes.removeDuplicates();
+ themes.sort();
+ return themes;
}
//Save a new theme/color file
bool LTHEME::saveLocalTheme(QString name, QStringList contents){
- QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes/";
- if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); }
- return LUtils::writeFile(localdir+name+".qss.template", contents, true);
+ Q_UNUSED(name);
+ Q_UNUSED(contents);
+ return false; //old format - do not use!!
+ //QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes/";
+ //if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); }
+ //return LUtils::writeFile(localdir+name+".qss.template", contents, true);
}
bool LTHEME::saveLocalColors(QString name, QStringList contents){
- QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors/";
- if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); }
- return LUtils::writeFile(localdir+name+".qss.colors", contents, true);
+ Q_UNUSED(name);
+ Q_UNUSED(contents);
+ return false; //old format - do not use!!
+ // QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors/";
+ //if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); }
+ //return LUtils::writeFile(localdir+name+".qss.colors", contents, true);
}
//Return the currently selected Theme/Colors/Icons
@@ -129,21 +167,23 @@ QStringList LTHEME::currentSettings(){ //returns [theme path, colorspath, iconsn
for(int i=0; i<settings.length(); i++){
if(settings[i].startsWith("THEMEFILE=")){ out[0] = settings[i].section("=",1,1).simplified(); }
else if(settings[i].startsWith("COLORFILE=")){ out[1] = settings[i].section("=",1,1).simplified(); }
- else if(settings[i].startsWith("ICONTHEME=")){ out[2] = settings[i].section("=",1,1).simplified(); }
+ //else if(settings[i].startsWith("ICONTHEME=")){ out[2] = settings[i].section("=",1,1).simplified(); }
else if(settings[i].startsWith("FONTFAMILY=")){ out[3] = settings[i].section("=",1,1).simplified(); }
else if(settings[i].startsWith("FONTSIZE=")){ out[4] = settings[i].section("=",1,1).simplified(); }
}
+ QSettings engineset("lthemeengine","lthemeengine");
+ out[2]=engineset.value("Appearance/icon_theme", "material-design-light").toString();
bool nofile = settings.isEmpty();
if(out[0].isEmpty() || !QFile::exists(out[0]) ){ out[0] = LOS::LuminaShare()+"themes/Lumina-default.qss.template"; }
if(out[1].isEmpty() || !QFile::exists(out[1]) ){ out[1] = LOS::LuminaShare()+"colors/Lumina-Glass.qss.colors"; }
if(out[3].isEmpty()){ out[3] = QFont().defaultFamily(); }
- if(out[4].isEmpty()){
+ if(out[4].isEmpty()){
int num = QFont().pointSize(); out[4] = QString::number(num)+"pt"; //Check point size first
if(num<0){ num = QFont().pixelSize(); out[4] = QString::number(num)+"px";} //Now check pixel size
if(num<0){ out[4] = "9pt"; } //Now hard-code a fallback (just in case)
}
if(nofile){ setCurrentSettings(out[0], out[1], out[2], out[3], out[4]); }
-
+
return out;
}
@@ -167,17 +207,25 @@ QString LTHEME::currentCursor(){
//Change the current Theme/Colors/Icons
bool LTHEME::setCurrentSettings(QString themepath, QString colorpath, QString iconname, QString font, QString fontsize){
- QIcon::setThemeName(iconname);
- //Now save the theme settings file
- QStringList contents;
+ Q_UNUSED(font);
+ Q_UNUSED(fontsize);
+ //QIcon::setThemeName(iconname);
+ //Save these settings into the theme engine settings
+ QSettings engineset("lthemeengine","lthemeengine");
+ engineset.setValue("Appearance/icon_theme", iconname);
+ engineset.setValue("Appearance/custom_palette", QFile::exists(colorpath) );
+ engineset.setValue("Appearance/color_scheme_path", colorpath);
+ engineset.setValue("Interface/desktop_stylesheets", QStringList() << themepath);
+ return true;
+ //Now save the theme settings file
+ /*QStringList contents;
contents << "THEMEFILE="+themepath;
contents << "COLORFILE="+colorpath;
contents << "ICONTHEME="+iconname;
contents << "FONTFAMILY="+font;
contents << "FONTSIZE="+fontsize;
bool ok = LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themesettings.cfg", contents, true);
-
- return ok;
+ return ok;*/
}
//Change the current Cursor Theme
@@ -195,13 +243,13 @@ bool LTHEME::setCursorTheme(QString cursorname){
bool changed = false;
QString newval = "Inherits="+cursorname;
for(int i=0; i<info.length() && !changed; i++){
- if(info[i]=="[Icon Theme]"){
+ if(info[i]=="[Icon Theme]"){
insection = true;
- }else if( info[i].startsWith("[") && insection){
+ }else if( info[i].startsWith("[") && insection){
//Section does not have the setting - add it
- info.insert(i, newval);
+ info.insert(i, newval);
changed =true;
- }else if( info[i].startsWith("[") ){
+ }else if( info[i].startsWith("[") ){
insection = false;
}else if(insection && info[i].startsWith("Inherits=")){
info[i] = newval; //replace the current setting
@@ -217,6 +265,23 @@ bool LTHEME::setCursorTheme(QString cursorname){
return LUtils::writeFile(QDir::homePath()+"/.icons/default/index.theme", info, true);
}
+bool LTHEME::setCurrentStyles(QStringList paths){
+ //Verify that the paths are all absolute paths, otherwise scan/replace with absolute paths
+ QStringList avail = LTHEME::availableSystemStyles();
+ for(int i=0; i<paths.length(); i++){
+ paths[i] = paths[i].simplified();
+ if(paths[i].startsWith("/")){ continue; } //already an absolute path
+ for(int j=0; j<avail.length(); j++){
+ if(avail[j].startsWith(paths[i].section("/",-1).section(".qss",0,0)+"::::") ){ paths[i] = avail[j].section("::::",1,-1); break; }
+ }
+ }
+ //ordered by priority: lowest -> highest
+ QSettings engineset("lthemeengine","lthemeengine");
+ engineset.setValue("Interface/stylesheets",paths);
+ engineset.sync();
+ return true;
+}
+
//Return the complete stylesheet for a given theme/colors
QString LTHEME::assembleStyleSheet(QString themepath, QString colorpath, QString font, QString fontsize){
QString stylesheet = LUtils::readFile(themepath).join("\n");
@@ -280,13 +345,13 @@ QStringList LTHEME::cursorInformation(QString name){
}
}
return out;
-}
+}
QStringList LTHEME::CustomEnvSettings(bool useronly){ //view all the key=value settings
QStringList newinfo;
if(!useronly){
QStringList sysfiles; sysfiles << L_ETCDIR+"/lumina_environment.conf" << LOS::LuminaShare()+"lumina_environment.conf";
- for(int i=0; i<sysfiles.length() && newinfo.isEmpty(); i++){
+ for(int i=0; i<sysfiles.length() && newinfo.isEmpty(); i++){
newinfo << LUtils::readFile(sysfiles[i]);
}
}
@@ -313,10 +378,10 @@ void LTHEME::LoadCustomEnvSettings(){
setenv(info[i].section("=",0,0).toLocal8Bit(), info[i].section("=",1,100).simplified().toLocal8Bit(), 1);
}
}
-
+
}
-bool LTHEME::setCustomEnvSetting(QString var, QString val){
+bool LTHEME::setCustomEnvSetting(QString var, QString val){
//variable/value pair (use an empty val to clear it)
QStringList info = LTHEME::CustomEnvSettings(true); //user only
bool changed = false;
diff --git a/src-qt5/core/libLumina/LuminaThemes.h b/src-qt5/core/libLumina/LuminaThemes.h
index 39602f58..133bd04d 100644
--- a/src-qt5/core/libLumina/LuminaThemes.h
+++ b/src-qt5/core/libLumina/LuminaThemes.h
@@ -25,7 +25,9 @@ class LTHEME{
public:
//Read the Themes/Colors/Icons that are available on the system
static QStringList availableSystemThemes();//returns: [name::::path] for each item
+ static QStringList availableSystemStyles();//returns: [name::::path] for each item
static QStringList availableLocalThemes(); //returns: [name::::path] for each item
+ static QStringList availableLocalStyles(); //returns: [name::::path] for each item
static QStringList availableSystemColors(); //returns: [name::::path] for each item
static QStringList availableLocalColors(); //returns: [name::::path] for each item
static QStringList availableSystemIcons(); //returns: [name] for each item
@@ -34,7 +36,7 @@ public:
//Save a new theme/color file
static bool saveLocalTheme(QString name, QStringList contents);
static bool saveLocalColors(QString name, QStringList contents);
-
+
//Return the currently selected Theme/Colors/Icons
static QStringList currentSettings(); //returns [theme path, colorspath, iconsname, font, fontsize]
static QString currentCursor(); //returns: current cursor theme name
@@ -42,19 +44,20 @@ public:
//Change the current Theme/Colors/Icons
static bool setCurrentSettings(QString themepath, QString colorpath, QString iconname, QString font, QString fontsize);
static bool setCursorTheme(QString cursorname);
+ static bool setCurrentStyles(QStringList paths); //ordered by priority: lowest -> highest
//Return the complete stylesheet for a given theme/colors
static QString assembleStyleSheet(QString themepath, QString colorpath, QString font, QString fontsize);
-
+
//Additional info for a cursor theme
static QStringList cursorInformation(QString name); //returns: [Name, Comment, Sample Image File]
-
+
//Environment settings
static QStringList CustomEnvSettings(bool useronly = false); //view all the key=value settings
static void LoadCustomEnvSettings(); //will push the custom settings into the environment (recommended before loading the initial QApplication)
static bool setCustomEnvSetting(QString var, QString val); //variable/value pair (use an empty val to clear it)
static QString readCustomEnvSetting(QString var);
-
+
};
// Qt Style override to allow custom themeing/colors
diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp
index 01b3305e..e1c582d9 100644
--- a/src-qt5/core/libLumina/LuminaXDG.cpp
+++ b/src-qt5/core/libLumina/LuminaXDG.cpp
@@ -44,7 +44,7 @@ void XDGDesktop::sync(){
//Get the current localization code
type = XDGDesktop::APP; //assume this initially if we read the file properly
QString lang = QLocale::system().name(); //lang code
- QString slang = lang.section("_",0,0); //short lang code
+ QString slang = lang.section("_",0,0); //short lang code
//Now start looping over the information
XDGDesktopAction CDA; //current desktop action
bool insection=false;
@@ -53,14 +53,14 @@ void XDGDesktop::sync(){
QString line = file[i];
//if(filePath.contains("pcbsd")){ qDebug() << " - Check Line:" << line << inaction << insection; }
//Check if this is the end of a section
- if(line.startsWith("[") && inaction){
+ if(line.startsWith("[") && inaction){
insection=false; inaction=false;
//Add the current Action structure to the main desktop structure if appropriate
if(!CDA.ID.isEmpty()){ actions << CDA; CDA = XDGDesktopAction(); }
}else if(line.startsWith("[")){ insection=false; inaction = false; }
//Now check if this is the beginning of a section
if(line=="[Desktop Entry]"){ insection=true; continue; }
- else if(line.startsWith("[Desktop Action ")){
+ else if(line.startsWith("[Desktop Action ")){
//Grab the ID of the action out of the label
CDA.ID = line.section("]",0,0).section("Desktop Action",1,1).simplified();
inaction = true;
@@ -72,27 +72,28 @@ void XDGDesktop::sync(){
QString loc = var.section("[",1,1).section("]",0,0).simplified(); // localization
var = var.section("[",0,0).simplified(); //remove the localization
QString val = line.section("=",1,50).simplified();
+ if( val.count("\"")==2 && val.startsWith("\"") && val.endsWith("\"")){ val.chop(1); val = val.remove(0,1); } //remove the starting/ending quotes
//-------------------
- if(var=="Name"){
+ if(var=="Name"){
if(insection){
- if(name.isEmpty() && loc.isEmpty()){ name = val; }
- else if(name.isEmpty() && loc==slang){ name = val; } //short locale code
- else if(loc == lang){ name = val; }
+ if(loc==slang){ name = val;} //short locale code
+ else if(loc==lang){ name = val;}
+ else if(name.isEmpty() && loc.isEmpty()){ /*qDebug() << "Empty" << val;*/ name = val; }
}else if(inaction){
if(CDA.name.isEmpty() && loc.isEmpty()){ CDA.name = val; }
else if(CDA.name.isEmpty() && loc==slang){ CDA.name = val; } //short locale code
- else if(loc == lang){ CDA.name = val; }
+ else if(loc == lang){ CDA.name = val; }
}
//hasName = true;
- }else if(var=="GenericName" && insection){
+ }else if(var=="GenericName" && insection){
if(genericName.isEmpty() && loc.isEmpty()){ genericName = val; }
else if(genericName.isEmpty() && loc==slang){ genericName = val; } //short locale code
else if(loc == lang){ genericName = val; }
- }else if(var=="Comment" && insection){
+ }else if(var=="Comment" && insection){
if(comment.isEmpty() && loc.isEmpty()){ comment = val; }
else if(comment.isEmpty() && loc==slang){ comment = val; } //short locale code
else if(loc == lang){ comment = val; }
- }else if(var=="Icon"){
+ }else if(var=="Icon"){
if(insection){
if(icon.isEmpty() && loc.isEmpty()){ icon = val; }
else if(icon.isEmpty() && loc==slang){ icon = val; } //short locale code
@@ -107,7 +108,7 @@ void XDGDesktop::sync(){
else if(var=="Exec"){
if(insection && exec.isEmpty() ){ exec = val; }
else if(inaction && CDA.exec.isEmpty() ){ CDA.exec = val; }
- }
+ }
else if( (var=="Path") && (path.isEmpty() ) && insection){ path = val; }
else if(var=="NoDisplay" && !isHidden && insection){ isHidden = (val.toLower()=="true"); }
else if(var=="Hidden" && !isHidden && insection){ isHidden = (val.toLower()=="true"); }
@@ -117,7 +118,7 @@ void XDGDesktop::sync(){
else if(var=="Terminal" && insection){ useTerminal= (val.toLower()=="true"); }
else if(var=="Actions" && insection){ actionList = val.split(";",QString::SkipEmptyParts); }
else if(var=="MimeType" && insection){ mimeList = val.split(";",QString::SkipEmptyParts); }
- else if(var=="Keywords" && insection){
+ else if(var=="Keywords" && insection){
if(keyList.isEmpty() && loc.isEmpty()){ keyList = val.split(";",QString::SkipEmptyParts); }
else if(loc == lang){ keyList = val.split(";",QString::SkipEmptyParts); }
}
@@ -136,7 +137,7 @@ void XDGDesktop::sync(){
file.clear(); //done with contents of file
//If there are OnlyShowIn desktops listed, add them to the name
if( !showInList.isEmpty() && !showInList.contains("Lumina", Qt::CaseInsensitive) ){
- name.append(" ("+showInList.join(", ")+")");
+ name.append(" ("+showInList.join(", ")+")");
}
//Quick fix for showing "wine" applications (which quite often don't list a category, or have other differences)
if(catList.isEmpty() && filePath.contains("/wine/")){
@@ -164,7 +165,7 @@ bool XDGDesktop::isValid(bool showAll){
//if(DEBUG){ qDebug() << "[LXDG] Check File validity:" << dFile.name << dFile.filePath; }
switch (type){
case XDGDesktop::BAD:
- ok=false;
+ ok=false;
//if(DEBUG){ qDebug() << " - Bad file type"; }
break;
case XDGDesktop::APP:
@@ -182,7 +183,7 @@ bool XDGDesktop::isValid(bool showAll){
break;
default:
ok=false;
- //if(DEBUG){ qDebug() << " - Unknown file type"; }
+ //if(DEBUG){ qDebug() << " - Unknown file type"; }
}
if(!showAll){
QString cdesk = getenv("XDG_CURRENT_DESKTOP");
@@ -206,7 +207,7 @@ QString XDGDesktop::getDesktopExec(QString ActionID){
}
}
}
-
+
if(out.isEmpty()){ return ""; }
else if(useTerminal){
//Get the currently default terminal
@@ -222,7 +223,7 @@ QString XDGDesktop::getDesktopExec(QString ActionID){
}
//Now perform any of the XDG flag substitutions as appropriate (9/2014 standards)
if(out.contains("%i") && !icon.isEmpty() ){ out.replace("%i", "--icon \""+icon+"\""); }
- if(out.contains("%c")){
+ if(out.contains("%c")){
if(!name.isEmpty()){ out.replace("%c", "\""+name+"\""); }
else if(!genericName.isEmpty()){ out.replace("%c", "\""+genericName+"\""); }
else{ out.replace("%c", "\""+filePath.section("/",-1).section(".desktop",0,0)+"\""); }
@@ -236,8 +237,9 @@ QString XDGDesktop::generateExec(QStringList inputfiles, QString ActionID){
//Does the app need the input files in URL or File syntax?
bool URLsyntax = (exec.contains("%u") || exec.contains("%U"));
//Adjust the input file formats as needed
+ //qDebug() << "Got inputfiles:" << inputfiles << URLsyntax;
for(int i=0; i<inputfiles.length(); i++){
- bool url = inputfiles[i].contains("://") || inputfiles[i].startsWith("www") || QUrl(inputfiles[i]).isValid();
+ bool url = inputfiles[i].startsWith("www") || inputfiles[i].contains("://");
//Run it through the QUrl class to catch/fix any URL syntax issues
if(URLsyntax){
if(inputfiles[i].startsWith("mailto:") ){} //don't touch this syntax - already formatted
@@ -245,22 +247,25 @@ QString XDGDesktop::generateExec(QStringList inputfiles, QString ActionID){
else{ inputfiles[i] = QUrl::fromLocalFile(inputfiles[i]).url(); }
}else{
//if(inputfiles[i].startsWith("mailto:") ){} //don't touch this syntax - already formatted
+ //qDebug() << "Need local format:" << inputfiles[i] << url;
if(url){ inputfiles[i] = QUrl(inputfiles[i]).toLocalFile(); }
- else{ inputfiles[i] = QUrl::fromLocalFile(inputfiles[i]).toLocalFile(); }
+ else{ inputfiles[i] = inputfiles[i]; } //QUrl::fromLocalFile(inputfiles[i]).toLocalFile(); }
}
}
+ inputfiles.removeAll(""); //just in case any empty ones get through
//Now to the exec replacements as needed
- if(exec.contains("%f")){
+ //qDebug() << "Generate Exec:" << exec << inputfiles;
+ if(exec.contains("%f")){
if(inputfiles.isEmpty()){ exec.replace("%f",""); }
else{ exec.replace("%f", "\""+inputfiles.first()+"\""); } //Note: can only take one input
- }else if(exec.contains("%F")){
+ }else if(exec.contains("%F")){
if(inputfiles.isEmpty()){ exec.replace("%F",""); }
else{ exec.replace("%F", "\""+inputfiles.join("\" \"")+"\""); }
}
- if(exec.contains("%u")){
+ if(exec.contains("%u")){
if(inputfiles.isEmpty()){ exec.replace("%u",""); }
else{ exec.replace("%u", "\""+inputfiles.first()+"\""); } //Note: can only take one input
- }else if(exec.contains("%U")){
+ }else if(exec.contains("%U")){
if(inputfiles.isEmpty()){ exec.replace("%U",""); }
else{ exec.replace("%U", "\""+inputfiles.join("\" \"")+"\""); }
}
@@ -281,7 +286,7 @@ bool XDGDesktop::saveDesktopFile(bool merge){
info = LUtils::readFile(filePath);
//set a couple flags based on the contents before we start iterating through
// - determine if a translated field was changed (need to remove all the now-invalid translations)
- bool clearName, clearComment, clearGName;
+ bool clearName, clearComment, clearGName;
QString tmp = "";
if(!info.filter("Name=").isEmpty()){ tmp = info.filter("Name=").first().section("=",1,50); }
clearName=(tmp!=name);
@@ -294,13 +299,13 @@ bool XDGDesktop::saveDesktopFile(bool merge){
//Now start iterating through the file and changing fields as necessary
bool insection = false;
for(int i=0; i<info.length(); i++){
- if(info[i]=="[Desktop Entry]"){
- insection = true;
+ if(info[i]=="[Desktop Entry]"){
+ insection = true;
continue;
- }else if(info[i].startsWith("[")){
+ }else if(info[i].startsWith("[")){
if(insection){ insertloc = i; } //save this location for later insertions
- insection = false;
- continue;
+ insection = false;
+ continue;
}
if(!insection || info[i].isEmpty() || info[i].section("#",0,0).simplified().isEmpty()){ continue; }
QString var = info[i].section("=",0,0);
@@ -331,25 +336,25 @@ bool XDGDesktop::saveDesktopFile(bool merge){
else if(var=="OnlyShowIn"){ info[i] = var+"="+showInList.join(";"); showInList.clear(); }
else if(var=="NotShowIn"){ info[i] = var+"="+notShowInList.join(";"); notShowInList.clear(); }
else if(var=="URL"){ info[i] = var+"="+url; url.clear(); }
-
+
// --BOOLIAN VALUES--
- else if(var=="Hidden"){
+ else if(var=="Hidden"){
if(!autofile){ info.removeAt(i); i--; continue; }
else{ info[i] = var+"="+(isHidden ? "true": "false"); isHidden=false;}
- }else if(var=="NoDisplay"){
+ }else if(var=="NoDisplay"){
if(autofile){ info.removeAt(i); i--; continue; }
else{ info[i] = var+"="+(isHidden ? "true": "false"); isHidden=false;}
- }else if(var=="Terminal"){
+ }else if(var=="Terminal"){
info[i] = var+"="+(useTerminal ? "true": "false"); useTerminal=false;
- }else if(var=="StartupNotify"){
+ }else if(var=="StartupNotify"){
info[i] = var+"="+(startupNotify ? "true": "false"); startupNotify=false;
}
// Remove any lines that have been un-set or removed from the file
if(info[i].section("=",1,50).simplified().isEmpty()){ info.removeAt(i); i--; }
}
-
+
}else{
- //Just write a new file and overwrite any old one
+ //Just write a new file and overwrite any old one
// (pre-set some values here which are always required)
info << "[Desktop Entry]";
info << "Version=1.0";
@@ -357,7 +362,7 @@ bool XDGDesktop::saveDesktopFile(bool merge){
else if(type==XDGDesktop::LINK){ info << "Type=Link"; }
else if(type==XDGDesktop::DIR){ info << "Type=Dir"; }
}
-
+
if(insertloc<0){ insertloc = info.size(); }//put it at the end
//Now add in any items that did not exist in the original file
if( !exec.isEmpty() ){ info.insert(insertloc,"Exec="+exec); }
@@ -379,7 +384,7 @@ bool XDGDesktop::saveDesktopFile(bool merge){
else if(isHidden){ info.insert(insertloc,"NoDisplay=true"); }
if( useTerminal){ info.insert(insertloc,"Terminal=true"); }
if( startupNotify ){ info.insert(insertloc,"StartupNotify=true"); }
-
+
//Now save the file
return LUtils::writeFile(filePath, info, true);
}
@@ -409,7 +414,7 @@ bool XDGDesktop::setAutoStarted(bool autostart){
}
}
//Make sure the user-autostart dir is specified, and clean the app structure as necessary
- if( !filePath.startsWith(upath) && autostart){
+ if( !filePath.startsWith(upath) && autostart){
//Some other non-override autostart file - set it up to open with lumina-open
if(!filePath.endsWith(".desktop")){
exec = "lumina-open \""+filePath+"\"";
@@ -444,6 +449,39 @@ bool XDGDesktop::setAutoStarted(bool autostart){
return saved;
}
+void XDGDesktop::addToMenu(QMenu *topmenu){
+ if(!this->isValid()){ return; }
+ if(actions.isEmpty()){
+ //Just a single entry point - no extra actions
+ QAction *act = new QAction(this->name, topmenu);
+ act->setIcon(LXDG::findIcon(this->icon, ""));
+ act->setToolTip(this->comment);
+ act->setWhatsThis(this->filePath);
+ topmenu->addAction(act);
+ }else{
+ //This app has additional actions - make this a sub menu
+ // - first the main menu/action
+ QMenu *submenu = new QMenu(this->name, topmenu);
+ submenu->setIcon( LXDG::findIcon(this->icon,"") );
+ //This is the normal behavior - not a special sub-action (although it needs to be at the top of the new menu)
+ QAction *act = new QAction(this->name, submenu);
+ act->setIcon(LXDG::findIcon(this->icon, ""));
+ act->setToolTip(this->comment);
+ act->setWhatsThis(this->filePath);
+ submenu->addAction(act);
+ //Now add entries for every sub-action listed
+ for(int sa=0; sa<this->actions.length(); sa++){
+ QAction *sact = new QAction( this->actions[sa].name, this);
+ sact->setIcon(LXDG::findIcon( this->actions[sa].icon, this->icon));
+ sact->setToolTip(this->comment);
+ sact->setWhatsThis("-action \""+this->actions[sa].ID+"\" \""+this->filePath+"\"");
+ submenu->addAction(sact);
+ }
+ topmenu->addMenu(submenu);
+ }
+}
+
+
//====XDGDesktopList Functions ====
XDGDesktopList::XDGDesktopList(QObject *parent, bool watchdirs) : QObject(parent){
synctimer = new QTimer(this); //interval set automatically based on changes/interactions
@@ -462,6 +500,14 @@ XDGDesktopList::~XDGDesktopList(){
//nothing special to do here
}
+XDGDesktopList* XDGDesktopList::instance(){
+ static XDGDesktopList *APPLIST = 0;
+ if(APPLIST==0){
+ APPLIST = new XDGDesktopList(0, true);
+ }
+ return APPLIST;
+}
+
void XDGDesktopList::watcherChanged(){
if(synctimer->isActive()){ synctimer->stop(); }
synctimer->setInterval(1000); //1 second delay before check kicks off
@@ -484,7 +530,7 @@ void XDGDesktopList::updateList(){
apps = dir.entryList(QStringList() << "*.desktop",QDir::Files, QDir::Name);
for(int a=0; a<apps.length(); a++){
path = dir.absoluteFilePath(apps[a]);
- if(files.contains(path) && (files.value(path)->lastRead>QFileInfo(path).lastModified()) ){
+ if(files.contains(path) && (files.value(path)->lastRead>QFileInfo(path).lastModified()) ){
//Re-use previous data for this file (nothing changed)
found << files[path]->name; //keep track of which files were already found
}else{
@@ -503,7 +549,7 @@ void XDGDesktopList::updateList(){
} //end loop over apps
} //end loop over appDirs
//Save the extra info to the internal lists
- if(!firstrun){
+ if(!firstrun){
removedApps = oldkeys;//files which were removed
newApps = newfiles; //files which were added
}
@@ -539,12 +585,58 @@ QList<XDGDesktop*> XDGDesktopList::apps(bool showAll, bool showHidden){
return out;
}
+XDGDesktop* XDGDesktopList::findAppFile(QString filename){
+ QStringList keys = files.keys().filter(filename);
+ QString chk = filename.section("/",-1);
+ for(int i=0; i<keys.length(); i++){
+ if(keys[i] == filename || keys[i].endsWith("/"+chk)){ return files[keys[i]]; }
+ }
+ //No matches
+ return 0;
+}
+
+void XDGDesktopList::populateMenu(QMenu *topmenu, bool byCategory){
+ topmenu->clear();
+ if(byCategory){
+ QHash<QString, QList<XDGDesktop*> > APPS = LXDG::sortDesktopCats( this->apps(false,false) );
+ QStringList cats = APPS.keys();
+ cats.sort(); //make sure they are alphabetical
+ for(int i=0; i<cats.length(); i++){
+ //Make sure they are translated and have the right icons
+ QString name, icon;
+ if(cats[i]=="All"){continue; } //skip this listing for the menu
+ else if(cats[i] == "Multimedia"){ name = tr("Multimedia"); icon = "applications-multimedia"; }
+ else if(cats[i] == "Development"){ name = tr("Development"); icon = "applications-development"; }
+ else if(cats[i] == "Education"){ name = tr("Education"); icon = "applications-education"; }
+ else if(cats[i] == "Game"){ name = tr("Games"); icon = "applications-games"; }
+ else if(cats[i] == "Graphics"){ name = tr("Graphics"); icon = "applications-graphics"; }
+ else if(cats[i] == "Network"){ name = tr("Network"); icon = "applications-internet"; }
+ else if(cats[i] == "Office"){ name = tr("Office"); icon = "applications-office"; }
+ else if(cats[i] == "Science"){ name = tr("Science"); icon = "applications-science"; }
+ else if(cats[i] == "Settings"){ name = tr("Settings"); icon = "preferences-system"; }
+ else if(cats[i] == "System"){ name = tr("System"); icon = "applications-system"; }
+ else if(cats[i] == "Utility"){ name = tr("Utility"); icon = "applications-utilities"; }
+ else if(cats[i] == "Wine"){ name = tr("Wine"); icon = "wine"; }
+ else{ name = tr("Unsorted"); icon = "applications-other"; }
+
+ QMenu *menu = new QMenu(name, topmenu);
+ menu->setIcon(LXDG::findIcon(icon,""));
+ QList<XDGDesktop*> appL = APPS.value(cats[i]);
+ for( int a=0; a<appL.length(); a++){ appL[a]->addToMenu(menu); }
+ topmenu->addMenu(menu);
+ } //end loop over cats
+ }else{
+ QList<XDGDesktop*> APPS = this->apps(false, false);
+ for(int i=0; i<APPS.length(); i++){ APPS[i]->addToMenu(topmenu); }
+ }
+}
+
//==== LFileInfo Functions ====
//Need some extra information not usually available by a QFileInfo
-void LFileInfo::loadExtraInfo(){
+/*void LFileInfo::loadExtraInfo(){
desk = 0;
//Now load the extra information
- if(this->isDir()){
+ if( this->suffix().isEmpty() && (this->absoluteFilePath().startsWith("/net/") || this->isDir()) ){
mime = "inode/directory";
//Special directory icons
QString name = this->fileName().toLower();
@@ -557,6 +649,7 @@ void LFileInfo::loadExtraInfo(){
else if(name=="downloads"){ icon = "folder-downloads"; }
else if(name=="documents"){ icon = "folder-documents"; }
else if(name=="images" || name=="pictures"){ icon = "folder-image"; }
+ else if(this->absoluteFilePath().startsWith("/net/")){ icon = "folder-shared"; }
else if( !this->isReadable() ){ icon = "folder-locked"; }
}else if( this->suffix()=="desktop"){
mime = "application/x-desktop";
@@ -577,11 +670,11 @@ LFileInfo::LFileInfo(){
LFileInfo::LFileInfo(QString filepath){ //overloaded contructor
this->setFile(filepath);
loadExtraInfo();
-}
+}
LFileInfo::LFileInfo(QFileInfo info){ //overloaded contructor
this->swap(info); //use the given QFileInfo without re-loading it
loadExtraInfo();
-}
+}
//Functions for accessing the extra information
// -- Return the mimetype for the file
@@ -596,7 +689,7 @@ QString LFileInfo::iconfile(){
return icon;
}else{
if(!mime.isEmpty()){
- QString tmp = mime;
+ QString tmp = mime;
tmp.replace("/","-");
return tmp;
}else if(this->isExecutable()){
@@ -609,7 +702,7 @@ QString LFileInfo::iconfile(){
// -- Check if this is an XDG desktop file
bool LFileInfo::isDesktopFile(){
if(desk==0){ return false; }
- return (!desk->filePath.isEmpty());
+ return (!desk->filePath.isEmpty());
}
// -- Allow access to the XDG desktop data structure
@@ -617,7 +710,14 @@ XDGDesktop* LFileInfo::XDG(){
return desk;
}
-// -- Check if this is a readable image file (for thumbnail support)
+// -- Check if this is a readable video file (for thumbnail support)
+bool LFileInfo::isVideo(){
+ if(!mime.startsWith("video/")){ return false; }
+ //Check the hardcoded list of known supported video formats to see if the thumbnail can be generated
+ return ( !LUtils::videoExtensions().filter(this->suffix().toLower()).isEmpty() );
+}
+
+// -- Check if this is a readable image file
bool LFileInfo::isImage(){
if(!mime.startsWith("image/")){ return false; } //quick return for non-image files
//Check the Qt subsystems to see if this image file can be read
@@ -626,17 +726,20 @@ bool LFileInfo::isImage(){
bool LFileInfo::isAVFile(){
return (mime.startsWith("audio/") || mime.startsWith("video/") );
-}
+}*/
//==== LXDG Functions ====
bool LXDG::checkExec(QString exec){
//Return true(good) or false(bad)
+ //Check for quotes around the exec, and remove them as needed
+ if(exec.startsWith("\"") && exec.count("\"")>=2){ exec = exec.section("\"",1,1).simplified(); }
+ if(exec.startsWith("\'") && exec.count("\'")>=2){ exec = exec.section("\'",1,1).simplified(); }
if(exec.startsWith("/")){ return QFile::exists(exec); }
else{
QStringList paths = QString(getenv("PATH")).split(":");
for(int i=0; i<paths.length(); i++){
- if(QFile::exists(paths[i]+"/"+exec)){ return true; }
+ if(QFile::exists(paths[i]+"/"+exec)){ return true; }
}
}
return false; //could not find the executable in the current path(s)
@@ -653,7 +756,7 @@ QStringList LXDG::systemApplicationDirs(){
for(int i=0; i<appDirs.length(); i++){
if( QFile::exists(appDirs[i]+"/applications") ){
out << appDirs[i]+"/applications";
- //Also check any subdirs within this directory
+ //Also check any subdirs within this directory
// (looking at you KDE - stick to the standards!!)
out << LUtils::listSubDirectories(appDirs[i]+"/applications");
}
@@ -750,7 +853,7 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){
QIcon tmp;
if(!iconName.contains("libreoffice")){ //libreoffice is stupid - their svg icons are un-renderable with Qt
tmp = QIcon::fromTheme(iconName);
- if(tmp.isNull()){ tmp = QIcon::fromTheme(fallback); }
+ //if(tmp.isNull()){ tmp = QIcon::fromTheme(fallback); }
}
if(!tmp.isNull()){ return tmp; } //found one in the theme
@@ -797,7 +900,7 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){
fall << getChildIconDirs(paths[i]+"hicolor"); //XDG fallback (apps add to this)
}
//Now load all the icon theme dependencies in order (Theme1 -> Theme2 -> Theme3 -> Fallback)
-
+
//fall << LOS::AppPrefix()+"share/pixmaps"; //always use this as well as a final fallback
QDir::setSearchPaths("icontheme", theme);
QDir::setSearchPaths("default", oxy);
@@ -832,7 +935,7 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){
//simple PNG image - load directly into the QIcon structure
ico.addFile(srch[i]+":"+iconName+".png");
}
-
+
}
//If still no icon found, look for any image format in the "pixmaps" directory
if(ico.isNull()){
@@ -852,13 +955,13 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){
break;
}
}
-
+
}
}
//Use the fallback icon if necessary
if(ico.isNull() ){
if(!fallback.isEmpty()){ ico = LXDG::findIcon(fallback,""); }
- else if(iconName.contains("-x-") && !iconName.endsWith("-x-generic")){
+ else if(iconName.contains("-x-") && !iconName.endsWith("-x-generic")){
//mimetype - try to use the generic type icon
ico = LXDG::findIcon(iconName.section("-x-",0,0)+"-x-generic", "");
}
@@ -875,7 +978,7 @@ QStringList LXDG::getChildIconDirs(QString parent){
QDir D(parent);
QStringList out;
QStringList dirs = D.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
- if(!dirs.isEmpty() && (dirs.contains("32x32") || dirs.contains("scalable")) ){
+ if(!dirs.isEmpty() && (dirs.contains("32x32") || dirs.contains("scalable")) ){
//Need to sort these directories by image size
//qDebug() << " - Parent:" << parent << "Dirs:" << dirs;
for(int i=0; i<dirs.length(); i++){
@@ -923,7 +1026,7 @@ QStringList LXDG::systemMimeDirs(){
QStringList out;
for(int i=0; i<appDirs.length(); i++){
if( QFile::exists(appDirs[i]+"/mime") ){
- out << appDirs[i]+"/mime";
+ out << appDirs[i]+"/mime";
}
}
return out;
@@ -934,7 +1037,7 @@ QIcon LXDG::findMimeIcon(QString extension){
QString mime = LXDG::findAppMimeForFile(extension);
if(mime.isEmpty()){ mime = LXDG::findAppMimeForFile(extension.toLower()); }
mime.replace("/","-"); //translate to icon mime name
- if(!mime.isEmpty()){ ico = LXDG::findIcon(mime, "unknown");} //use the "unknown" mimetype icon as fallback
+ if(!mime.isEmpty()){ ico = LXDG::findIcon(mime, "unknown");} //use the "unknown" mimetype icon as fallback
if(ico.isNull()){ ico = LXDG::findIcon("unknown",""); } //just in case
return ico;
}
@@ -956,8 +1059,8 @@ while(mimes.isEmpty()){
return extension;
}
//Look for globs at the end of the filename
- if(!extension.isEmpty()){
- mimes = mimefull.filter(":*."+extension);
+ if(!extension.isEmpty()){
+ mimes = mimefull.filter(":*."+extension);
//If nothing found, try a case-insensitive search
if(mimes.isEmpty()){ mimes = mimefull.filter(":*."+extension, Qt::CaseInsensitive); }
//Now ensure that the filter was accurate (*.<extention>.<something> will still be caught)
@@ -968,7 +1071,7 @@ while(mimes.isEmpty()){
}
}
//Look for globs at the start of the filename
- if(mimes.isEmpty()){
+ if(mimes.isEmpty()){
mimes = mimefull.filter(":"+filename.left(2)); //look for the first 2 characters initially
//Note: This initial filter will only work if the wildcard (*) is not within the first 2 characters of the pattern
//Now ensure that the filter was accurate
@@ -1191,6 +1294,7 @@ QStringList LXDG::findAvailableAppsForMime(QString mime){
}
void LXDG::setDefaultAppForMime(QString mime, QString app){
+ //qDebug() << "Set Default App For Mime:" << mime << app;
QString filepath = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-mimeapps.list";
QStringList cinfo = LUtils::readFile(filepath);
//If this is a new file, make sure to add the header appropriately
diff --git a/src-qt5/core/libLumina/LuminaXDG.h b/src-qt5/core/libLumina/LuminaXDG.h
index cc250c7e..066f0462 100644
--- a/src-qt5/core/libLumina/LuminaXDG.h
+++ b/src-qt5/core/libLumina/LuminaXDG.h
@@ -28,7 +28,8 @@
#include <QTextStream>
#include <QDateTime>
#include <QDebug>
-
+#include <QMenu>
+#include <QAction>
// ======================
// FreeDesktop Desktop Actions Framework (data structure)
@@ -82,6 +83,9 @@ public:
bool saveDesktopFile(bool merge = true); //This will use the "filePath" variable for where to save the file
bool setAutoStarted(bool autostart = true);
+
+ //Create a menu entry for this application
+ void addToMenu(QMenu*);
};
// ========================
@@ -93,8 +97,13 @@ public:
//Functions
XDGDesktopList(QObject *parent = 0, bool watchdirs = false);
~XDGDesktopList();
+
+ static XDGDesktopList* instance();
+
//Main Interface functions
QList<XDGDesktop*> apps(bool showAll, bool showHidden); //showAll: include invalid files, showHidden: include NoShow/Hidden files
+ XDGDesktop* findAppFile(QString filename);
+ void populateMenu(QMenu *, bool byCategory = true);
//Administration variables (not typically used directly)
QDateTime lastCheck;
@@ -119,7 +128,7 @@ signals:
// File Information simplification class (combine QFileInfo with XDGDesktop)
// Need some extra information not usually available by a QFileInfo
// ========================
-class LFileInfo : public QFileInfo{
+/*class LFileInfo : public QFileInfo{
private:
QString mime, icon;
XDGDesktop *desk;
@@ -150,9 +159,10 @@ public:
//Other file type identification routines
bool isImage(); //Is a readable image file (for thumbnail support)
+ bool isVideo(); //Is a readable video file (for thumbnail support)
bool isAVFile(); //Is an audio/video file
};
-typedef QList<LFileInfo> LFileInfoList;
+typedef QList<LFileInfo> LFileInfoList;*/
// ================================
// Collection of FreeDesktop standards interaction routines
diff --git a/src-qt5/core/libLumina/LuminaXDG.pri b/src-qt5/core/libLumina/LuminaXDG.pri
index 6f3a2b7c..1a8a8368 100644
--- a/src-qt5/core/libLumina/LuminaXDG.pri
+++ b/src-qt5/core/libLumina/LuminaXDG.pri
@@ -1,10 +1,12 @@
QT *= multimedia svg
#LUtils Files
-SOURCES *= $${PWD}/LuminaXDG.cpp
-HEADERS *= $${PWD}/LuminaXDG.h
+SOURCES *= $${PWD}/LuminaXDG.cpp \
+ $${PWD}/LFileInfo.cpp
+HEADERS *= $${PWD}/LuminaXDG.h \
+ $${PWD}/LFileInfo.h
-INCLUDEPATH *= ${PWD}
+INCLUDEPATH *= $${PWD}
#include LUtils and LuminaOS
include(LUtils.pri)
diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.cpp b/src-qt5/core/libLumina/NativeEmbedWidget.cpp
deleted file mode 100644
index 487d1040..00000000
--- a/src-qt5/core/libLumina/NativeEmbedWidget.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include "NativeEmbedWidget.h"
-
-#include <QPainter>
-#include <QX11Info>
-#include <QDebug>
-
-#include <xcb/xproto.h>
-#include <xcb/xcb_aux.h>
-#include <xcb/xcb_image.h>
-#include <xcb/composite.h>
-#include <X11/extensions/Xdamage.h>
-
-#define DISABLE_COMPOSITING true
-
-#define NORMAL_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_BUTTON_MOTION | \
- XCB_EVENT_MASK_EXPOSURE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_ENTER_WINDOW| \
- XCB_EVENT_MASK_PROPERTY_CHANGE)
-
-
-inline void registerClientEvents(WId id){
- uint32_t value_list[1] = {NORMAL_WIN_EVENT_MASK};
- xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list);
-}
-
-// ============
-// PRIVATE
-// ============
-//Simplification functions for the XCB/XLib interactions
-void NativeEmbedWidget::syncWinSize(QSize sz){
- if(WIN==0 ){ return; }
- else if(!sz.isValid()){ sz = this->size(); } //use the current widget size
- //qDebug() << "Sync Window Size:" << sz;
- if(sz == winSize){ return; } //no change
- const uint32_t valList[2] = {(uint32_t) sz.width(), (uint32_t) sz.height()};
- const uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
- xcb_configure_window(QX11Info::connection(), WIN->id(), mask, valList);
- winSize = sz; //save this for checking later
-}
-
-void NativeEmbedWidget::syncWidgetSize(QSize sz){
- //qDebug() << "Sync Widget Size:" << sz;
- this->resize(sz);
-}
-
-void NativeEmbedWidget::hideWindow(){
- xcb_unmap_window(QX11Info::connection(), WIN->id());
-}
-
-void NativeEmbedWidget::showWindow(){
- xcb_map_window(QX11Info::connection(), WIN->id());
- QTimer::singleShot(0,this, SLOT(repaintWindow()));
-}
-
-QImage NativeEmbedWidget::windowImage(QRect geom){
- //Pull the XCB pixmap out of the compositing layer
- xcb_pixmap_t pix = xcb_generate_id(QX11Info::connection());
- xcb_composite_name_window_pixmap(QX11Info::connection(), WIN->id(), pix);
- if(pix==0){ qDebug() << "Got blank pixmap!"; return QImage(); }
-
- //Convert this pixmap into a QImage
- xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, geom.x(), geom.y(), geom.width(), geom.height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP);
- if(ximg == 0){ qDebug() << "Got blank image!"; return QImage(); }
- QImage img(ximg->data, ximg->width, ximg->height, ximg->stride, QImage::Format_ARGB32_Premultiplied);
- img = img.copy(); //detach this image from the XCB data structures
- xcb_image_destroy(ximg);
-
- //Cleanup the XCB data structures
- xcb_free_pixmap(QX11Info::connection(), pix);
-
- return img;
-
-}
-
-// ============
-// PUBLIC
-// ============
-NativeEmbedWidget::NativeEmbedWidget(QWidget *parent) : QWidget(parent){
- WIN = 0; //nothing embedded yet
- paused = false;
- //this->setSizeIncrement(2,2);
-}
-
-bool NativeEmbedWidget::embedWindow(NativeWindow *window){
- WIN = window;
- //PIXBACK = xcb_generate_id(QX11Info::connection());
- xcb_reparent_window(QX11Info::connection(), WIN->id(), this->winId(), 0, 0);
- //Now send the embed event to the app
- //qDebug() << " - send _XEMBED event";
- /*xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = WIN->id();
- event.type = obj->ATOMS["_XEMBED"]; //_XEMBED
- event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY
- event.data.data32[2] = 0;
- event.data.data32[3] = this->winId(); //WID of the container
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- */
- //Now setup any redirects and return
- if(!DISABLE_COMPOSITING){
- xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]);
- xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]);
-
- //Now create/register the damage handler
- // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore)
- // -- Retested 6/29/17 (no change) Ken Moore
- //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer
- //xcb_damage_create(QX11Info::connection(), dmgID, WIN->id(), XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
- // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself).
- Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles);
-
- WIN->addDamageID( (uint) dmgID); //save this for later
- }
- WIN->addFrameWinID(this->winId());
- connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change
-
- registerClientEvents(WIN->id());
- registerClientEvents(this->winId());
- qDebug() << "Events Registered:" << WIN->id() << this->winId();
- return true;
-}
-
-bool NativeEmbedWidget::detachWindow(){
- xcb_reparent_window(QX11Info::connection(), WIN->id(), QX11Info::appRootWindow(), -1, -1);
- WIN = 0;
- return true;
-}
-
-bool NativeEmbedWidget::isEmbedded(){
- return (WIN!=0);
-}
-
-// ==============
-// PUBLIC SLOTS
-// ==============
-//Pause/resume
-void NativeEmbedWidget::pause(){
- if(winImage.isNull()){ repaintWindow(); } //make sure we have one image already cached first
- paused = true;
-}
-
-void NativeEmbedWidget::resume(){
- paused = false;
- //syncWinSize();
- //showWindow();
- repaintWindow(); //update the cached image right away
-}
-
-void NativeEmbedWidget::resyncWindow(){
- if(WIN==0){ return; }
- /*return; //skip the stuff below (not working)
- QRect geom = WIN->geometry();
- //Send an artificial configureNotify event to the window with the global position/size included
- xcb_configure_notify_event_t event;
- event.x = geom.x() + this->pos().x();
- event.y = geom.y() + this->pos().y();
- event.width = this->width();
- event.height = this->height();
- event.border_width = 0;
- event.above_sibling = XCB_NONE;
- event.override_redirect = false;
- event.window = WIN->id();
- event.event = WIN->id();
- event.response_type = XCB_CONFIGURE_NOTIFY;
- xcb_send_event(QX11Info::connection(), false, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, (const char *) &event);
- */
- //Just jitter the window size by 1 pixel really quick so the window knows to update it's geometry
- QSize sz = this->size();
- uint32_t valList[2] = {(uint32_t) sz.width()-1, (uint32_t) sz.height()};
- uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
- xcb_configure_window(QX11Info::connection(), WIN->id(), mask, valList);
- xcb_flush(QX11Info::connection());
- valList[0] = (uint32_t) sz.width();
- xcb_configure_window(QX11Info::connection(), WIN->id(), mask, valList);
- xcb_flush(QX11Info::connection());
- syncWinSize();
- QTimer::singleShot(10, this, SLOT(repaintWindow()) );
-}
-
-void NativeEmbedWidget::repaintWindow(){
- if(DISABLE_COMPOSITING){ return; }
- //qDebug() << "Update Window Image:" << !paused;
- if(paused){ return; }
- QImage tmp = windowImage( QRect(QPoint(0,0), this->size()) );
- if(!tmp.isNull()){
- winImage = tmp;
- }else{ qDebug() << "Got Null Image!!"; }
- this->parentWidget()->update();
-}
-// ==============
-// PROTECTED
-// ==============
-void NativeEmbedWidget::resizeEvent(QResizeEvent *ev){
- QWidget::resizeEvent(ev);
- if(WIN!=0){
- syncWinSize(ev->size());
- } //syncronize the window with the new widget size
-}
-
-void NativeEmbedWidget::showEvent(QShowEvent *ev){
- if(WIN!=0){ showWindow(); }
- QWidget::showEvent(ev);
-}
-
-void NativeEmbedWidget::hideEvent(QHideEvent *ev){
- if(WIN!=0){ hideWindow(); }
- QWidget::hideEvent(ev);
-}
-
-void NativeEmbedWidget::paintEvent(QPaintEvent *ev){
- if(WIN==0 || DISABLE_COMPOSITING){ QWidget::paintEvent(ev); return; }
- else if( winImage.isNull() ){ /*QTimer::singleShot(0, this, SLOT(repaintWindow()) );*/ return; }
- else if(paused){ return; }
- //else if(this->size()!=winSize){ QTimer::singleShot(0,this, SLOT(syncWinSize())); return; } //do not paint here - waiting to re-sync the sizes
- //else if(this->size() != winImage.size()){ QTimer::singleShot(0, this, SLOT(repaintWindow()) ); return; }
- //Need to paint the image from the window onto the widget as an overlay
- QRect geom = ev->rect(); //atomic updates
- geom.adjust(-10,-10,10,10); //add an additional few pixels in each direction to be painted
- geom = geom.intersected(QRect(0,0,this->width(), this->height())); //ensure intersection with actual window
- if( !QRect(QPoint(0,0),winImage.size()).contains(geom) ){ QTimer::singleShot(0,this, SLOT(repaintWindow()) );return; }
- QPainter P(this);
- P.setClipping(true);
- P.setClipRect(0,0,this->width(), this->height());
- //qDebug() << "Paint Embed Window:" << geom << winImage.size();
- if(winImage.size() == this->size()){
- P.drawImage( geom , winImage, geom, Qt::NoOpaqueDetection); //1-to-1 mapping
- //Note: Qt::NoOpaqueDetection Speeds up the paint by bypassing the checks to see if there are [semi-]transparent pixels
- // Since this is an embedded image - we fully expect there to be transparency all/most of the time.
- }else{
- P.drawImage( geom , winImage);
- }
- //else{ QImage scaled = winImage.scaled(geom.size()); P.drawImage(geom, scaled); }
- //P.drawImage( geom , winImage, geom, Qt::NoOpaqueDetection); //1-to-1 mapping
- //Note: Qt::NoOpaqueDetection Speeds up the paint by bypassing the checks to see if there are [semi-]transparent pixels
- // Since this is an embedded image - we fully expect there to be transparency all/most of the time.
-
-}
diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.h b/src-qt5/core/libLumina/NativeEmbedWidget.h
deleted file mode 100644
index 65e03c51..00000000
--- a/src-qt5/core/libLumina/NativeEmbedWidget.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This is a container object for embedding a native window into a QWidget
-// and maintaining a 1-to-1 mapping of sizing and other properties
-// while also providing compositing effects between the two windows
-//===========================================
-#ifndef _LUMINA_NATIVE_EMBED_WIDGET_H
-#define _LUMINA_NATIVE_EMBED_WIDGET_H
-
-#include "NativeWindow.h"
-#include <QWidget>
-#include <QTimer>
-#include <QResizeEvent>
-#include <QShowEvent>
-#include <QHideEvent>
-#include <QPaintEvent>
-
-class NativeEmbedWidget : public QWidget{
- Q_OBJECT
-private:
- NativeWindow *WIN;
- QSize winSize;
- QImage winImage;
- bool paused;
-
-private slots:
- //Simplification functions
- void syncWinSize(QSize sz = QSize());
- void syncWidgetSize(QSize sz);
- void hideWindow();
- void showWindow();
- QImage windowImage(QRect geom);
-
-
-public:
- NativeEmbedWidget(QWidget *parent);
-
- bool embedWindow(NativeWindow *window);
- bool detachWindow();
- bool isEmbedded(); //status of the embed
-
-
-
-public slots:
- //Pause/resume
- void pause();
- void resume();
-
- void resyncWindow();
- void repaintWindow();
-
-protected:
- void resizeEvent(QResizeEvent *ev);
- void showEvent(QShowEvent *ev);
- void hideEvent(QHideEvent *ev);
- void paintEvent(QPaintEvent *ev);
-};
-
-#endif
diff --git a/src-qt5/core/libLumina/NativeEventFilter.cpp b/src-qt5/core/libLumina/NativeEventFilter.cpp
deleted file mode 100644
index 354dbe76..00000000
--- a/src-qt5/core/libLumina/NativeEventFilter.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-//===========================================
-// Lumina-desktop source code
-// Copyright (c) 2015-2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include "NativeEventFilter.h"
-#include <QCoreApplication>
-#include <QDebug>
-
-//#include <xcb/xcb_aux.h>
-//#include <xcb/damage.h>
-
-//==================================================
-// NOTE: All the XCB interactions and atoms are accessed via:
-// obj->XCB->EWMH.(atom name)
-// obj->XCB->(do something)
-//==================================================
-
-/*
-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
-
-//#include <LuminaX11.h>
-#include <QX11Info>
-#include <xcb/xcb_ewmh.h>
-#include <xcb/xcb_keysyms.h>
-#include <xcb/damage.h>
-
-#define DEBUG 0
-
-//Special objects/variables for XCB parsing
-static xcb_ewmh_connection_t EWMH;
-//static LXCB *XCB = 0;
-static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE = 0;
-
-inline void ParsePropertyEvent(xcb_property_notify_event_t *ev, NativeEventFilter *obj){
- qDebug() << "Got Property Event:" << ev->window << ev->atom;
- NativeWindow::Property prop = NativeWindow::None;
- //Now determine which properties are getting changed, and update the native window as appropriate
- if(ev->atom == EWMH._NET_WM_NAME){ prop = NativeWindow::Title; }
- else if(ev->atom == EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; }
- else if(ev->atom == EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; }
- else if(ev->atom == EWMH._NET_WM_DESKTOP){ prop = NativeWindow::Workspace; }
- else if(ev->atom == EWMH._NET_WM_WINDOW_TYPE ){ prop = NativeWindow::WinTypes; }
- else if( ev->atom == EWMH._NET_WM_STATE){ prop = NativeWindow::States; }
- //Send out the signal if necessary
- if(prop!=NativeWindow::None){
- //if(DEBUG){
- qDebug() << "Detected Property Change:" << ev->window << prop;
- //}
- obj->emit WindowPropertyChanged(ev->window, prop);
- }else{
- //qDebug() << "Unknown Property Change:" << ev->window << ev->atom;
- }
-}
-
-inline void ParseClientMessageEvent(xcb_client_message_event_t *ev, NativeEventFilter *obj){
- NativeWindow::Property prop = NativeWindow::None;
- QVariant val;
- if(ev->type==EWMH._NET_WM_NAME){ prop = NativeWindow::Title; }
- else if(ev->type==EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; }
- else if(ev->type==EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; }
- else if(ev->type==EWMH._NET_WM_DESKTOP){
- prop = NativeWindow::Workspace;
- val = QVariant( (int) ev->data.data32[0] );
- }else if(ev->type==EWMH._NET_WM_WINDOW_TYPE){ prop = NativeWindow::WinTypes; }
- else if(ev->type==EWMH._NET_WM_STATE){ prop = NativeWindow::States; }
-
- if(prop!=NativeWindow::None){
- //if(DEBUG){
- qDebug() << "Detected Property Change Request:" << ev->window << prop; //}
- if(val.isNull()){ obj->emit WindowPropertyChanged(ev->window, prop); }
- else{ obj->emit RequestWindowPropertyChange(ev->window, prop, val); }
- }
-
-}
-
-
-//Constructor for the Event Filter wrapper
-NativeEventFilter::NativeEventFilter() : QObject(){
- EF = new EventFilter(this);
- if(EWMH.nb_screens <=0){
- xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH);
- if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){
- qDebug() << "Error with XCB atom initializations";
- }
- }
- if(_NET_SYSTEM_TRAY_OPCODE==0){
- //_NET_SYSTEM_TRAY_OPCODE
- xcb_intern_atom_cookie_t cookie = xcb_intern_atom(QX11Info::connection(), 0, 23,"_NET_SYSTEM_TRAY_OPCODE");
- xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(QX11Info::connection(), cookie, NULL);
- if(r){
- _NET_SYSTEM_TRAY_OPCODE = r->atom;
- free(r);
- }
- }
-}
-
-void NativeEventFilter::start(){
- if(DEBUG){ qDebug() << " - Install event filter..."; }
- QCoreApplication::instance()->installNativeEventFilter(EF);
- if(DEBUG){ qDebug() << " - Run request check..."; }
-
-}
-
-void NativeEventFilter::stop(){
- QCoreApplication::instance()->installNativeEventFilter(0);
-}
-
-//=============================
-// EventFilter Class
-//=============================
-
-//Constructor for the XCB event filter
-EventFilter::EventFilter(NativeEventFilter *parent) : QAbstractNativeEventFilter(){
- obj = parent;
-}
-
-//This function format taken directly from the Qt5.3 documentation
-bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *){
- //qDebug() << "New Event";
- 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 KeyPressed( ((xcb_key_press_event_t *) ev)->detail, ((xcb_key_press_event_t *) ev)->root );
- break;
- case XCB_KEY_RELEASE:
- //This is a keyboard key release
- //qDebug() << "Key Release Event";
- obj->emit KeyReleased( ((xcb_key_release_event_t *) ev)->detail, ((xcb_key_release_event_t *) ev)->root );
- break;
- case XCB_BUTTON_PRESS:
- //This is a mouse button press
- //qDebug() << "Button Press Event";
- obj->emit MousePressed( ((xcb_button_press_event_t *) ev)->detail, ((xcb_button_press_event_t *) ev)->root );
- break;
- case XCB_BUTTON_RELEASE:
- //This is a mouse button release
- //qDebug() << "Button Release Event";
- obj->emit MouseReleased( ((xcb_button_release_event_t *) ev)->detail, ((xcb_button_release_event_t *) ev)->root );
- break;
- case XCB_MOTION_NOTIFY:
- //This is a mouse movement event
- if(DEBUG){ qDebug() << "Motion Notify Event"; }
- obj->emit MouseMovement();
- break;
- case XCB_ENTER_NOTIFY:
- //This is a mouse movement event when mouse goes over a new window
- //qDebug() << "Enter Notify Event";
- obj->emit MouseEnterWindow( ((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 MouseLeaveWindow( ((xcb_leave_notify_event_t *) ev)->root );
- break;
-//==============================
- case XCB_EXPOSE:
- //qDebug() << "Expose Notify Event:";
- //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
- break;
-//==============================
- case XCB_MAP_NOTIFY:
- //qDebug() << "Window Map Event:" << ((xcb_map_notify_event_t *)ev)->window;
- obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, true);
- 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 WindowCreated( ((xcb_map_request_event_t *) ev)->window );
- break;
-//==============================
- case XCB_CREATE_NOTIFY:
- //qDebug() << "Window Create Event";
- break;
-//==============================
- case XCB_UNMAP_NOTIFY:
- //qDebug() << "Window Unmap Event:" << ((xcb_unmap_notify_event_t *)ev)->window;
- obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, false);
- break;
-//==============================
- case XCB_DESTROY_NOTIFY:
- //qDebug() << "Window Closed Event:" << ((xcb_destroy_notify_event_t *)ev)->window;
- obj->emit WindowDestroyed( ((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:";
- ParsePropertyEvent((xcb_property_notify_event_t*)ev, obj);
- break;
-//==============================
- case XCB_CLIENT_MESSAGE:
- //qDebug() << "Client Message Event";
- //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
- if( ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){
- //data32[0] is timestamp, [1] is opcode, [2] is window handle
- if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){
- obj->emit TrayWindowCreated( ((xcb_client_message_event_t*)ev)->data.data32[2] );
- //addTrayApp( ((xcb_client_message_event_t*)ev)->data.data32[2] );
- }
- //Ignore the System Tray messages at the moment
- }else if(((xcb_client_message_event_t*)ev)->window != QX11Info::appRootWindow()){
- ParseClientMessageEvent((xcb_client_message_event_t*)ev, obj);
- }
- break;
-//==============================
- case XCB_CONFIGURE_NOTIFY:
- //qDebug() << "Configure Notify Event";
- /*obj->emit WindowPropertiesChanged( ((xcb_configure_notify_event_t*)ev)->window,
- QList<NativeWindow::Property>() << NativeWindow::GlobalPos << NativeWindow::Size,
- QList<QVariant>() << QPoint(((xcb_configure_notify_event_t*)ev)->x, ((xcb_configure_notify_event_t*)ev)->y) <<
- QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );*/
- obj->emit WindowPropertyChanged( ((xcb_configure_notify_event_t*)ev)->window, NativeWindow::Size,
- QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );
- break;
-//==============================
- case XCB_CONFIGURE_REQUEST:
- //qDebug() << "Configure Request Event";
- obj->emit RequestWindowPropertiesChange( ((xcb_configure_request_event_t*)ev)->window,
- QList<NativeWindow::Property>() << NativeWindow::GlobalPos << NativeWindow::Size,
- QList<QVariant>() << QPoint(((xcb_configure_request_event_t*)ev)->x, ((xcb_configure_request_event_t*)ev)->y) <<
- QSize(((xcb_configure_request_event_t*)ev)->width, ((xcb_configure_request_event_t*)ev)->height) );
- break;
-//==============================
- case XCB_RESIZE_REQUEST:
- //qDebug() << "Resize Request Event";
- obj->emit RequestWindowPropertyChange( ((xcb_resize_request_event_t*)ev)->window,
- NativeWindow::Size, QSize(((xcb_resize_request_event_t*)ev)->width, ((xcb_resize_request_event_t*)ev)->height) );
- 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:
- //if( (ev->response_type & ~0x80)==TrayDmgID){
- obj->emit PossibleDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable );
- //checkDamageID( ((xcb_damage_notify_event_t*)ev)->drawable );
- //}else{
- //qDebug() << "Default Event:" << (ev->response_type & ~0x80);
- //}
-//==============================
- }
- }
- return false;
- //never stop event handling (this will not impact the X events themselves - just the internal Qt application)
-}
diff --git a/src-qt5/core/libLumina/NativeEventFilter.h b/src-qt5/core/libLumina/NativeEventFilter.h
deleted file mode 100644
index 2b184f99..00000000
--- a/src-qt5/core/libLumina/NativeEventFilter.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2012-2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This class provides the XCB event handling/registrations that are needed
-//===========================================
-#ifndef _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H
-#define _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H
-
-#include <QAbstractNativeEventFilter>
-#include <QObject>
-#include <QByteArray>
-
-#include "NativeWindow.h"
-
-
-class NativeEventFilter : public QObject{
- Q_OBJECT
-private:
- QAbstractNativeEventFilter* EF;
- WId WMFlag; //used to flag a running WM process
-
-public:
- NativeEventFilter();
- ~NativeEventFilter(){}
-
- void start();
- void stop();
-
-signals:
- //Window Signals
- void WindowCreated(WId);
- void WindowDestroyed(WId);
- void WindowPropertyChanged(WId, NativeWindow::Property);
- void WindowPropertyChanged(WId, NativeWindow::Property, QVariant);
- void WindowPropertiesChanged(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void RequestWindowPropertyChange(WId, NativeWindow::Property, QVariant);
- void RequestWindowPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>);
-
- //System Tray Signals
- void TrayWindowCreated(WId);
- void TrayWindowDestroyed(WId);
-
- //Miscellaneos Signals
- void PossibleDamageEvent(WId);
-
- //Input Event Signals
- void KeyPressed(int, WId);
- void KeyReleased(int, WId);
- void MousePressed(int, WId);
- void MouseReleased(int, WId);
- void MouseMovement();
- void MouseEnterWindow(WId);
- void MouseLeaveWindow(WId);
-};
-
-class EventFilter : public QAbstractNativeEventFilter{
-public:
- EventFilter(NativeEventFilter *parent);
- ~EventFilter(){}
-
- virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *);
-
-private:
- NativeEventFilter *obj;
-};
-
-#endif
diff --git a/src-qt5/core/libLumina/NativeKeyToQt.cpp b/src-qt5/core/libLumina/NativeKeyToQt.cpp
deleted file mode 100644
index 06056be7..00000000
--- a/src-qt5/core/libLumina/NativeKeyToQt.cpp
+++ /dev/null
@@ -1,528 +0,0 @@
-
-#include <NativeWindowSystem.h>
-
-#include <QKeySequence>
-#include <QX11Info>
-
-// XCB/X11 Includes
-#define XK_MISCELLANY
-#define XK_XKB_KEYS
-#define XK_LATIN1
-#define XK_LATIN2
-#define XK_LATIN3
-#define XK_LATIN4
-#define XK_LATIN8
-#define XK_LATIN9
-//NOTE: Look at the keysymdef.h file for additional define/characters which we may need later
-#include <X11/keysymdef.h>
-#include <xcb/xcb_keysyms.h>
-
-
-//Small simplification functions
-Qt::Key NativeWindowSystem::KeycodeToQt(int keycode){
- static xcb_key_symbols_t *SYM = 0;
- if(SYM==0){ SYM = xcb_key_symbols_alloc(QX11Info::connection()); }
- xcb_keysym_t symbol = xcb_key_symbols_get_keysym(SYM, keycode,0);
- //not sure about the "column" input - we want raw keys though so ignore the "modified" key states (columns) for now
- //qDebug() << "Try to convert keycode to Qt::Key:" << keycode << symbol;
- //Now map this symbol to the appropriate Qt::Key enumeration
- switch(symbol){
- //FUNCTION KEYS
- case XK_F1: return Qt::Key_F1;
- case XK_F2: return Qt::Key_F2;
- case XK_F3: return Qt::Key_F3;
- case XK_F4: return Qt::Key_F4;
- case XK_F5: return Qt::Key_F5;
- case XK_F6: return Qt::Key_F6;
- case XK_F7: return Qt::Key_F7;
- case XK_F8: return Qt::Key_F8;
- case XK_F9: return Qt::Key_F9;
- case XK_F10: return Qt::Key_F10;
- case XK_F11: return Qt::Key_F11;
- case XK_F12: return Qt::Key_F12;
- case XK_F13: return Qt::Key_F13;
- case XK_F14: return Qt::Key_F14;
- case XK_F15: return Qt::Key_F15;
- case XK_F16: return Qt::Key_F16;
- case XK_F17: return Qt::Key_F17;
- case XK_F18: return Qt::Key_F18;
- case XK_F19: return Qt::Key_F19;
- case XK_F20: return Qt::Key_F20;
- case XK_F21: return Qt::Key_F21;
- case XK_F22: return Qt::Key_F22;
- case XK_F23: return Qt::Key_F23;
- case XK_F24: return Qt::Key_F24;
- case XK_F25: return Qt::Key_F25;
- case XK_F26: return Qt::Key_F26;
- case XK_F27: return Qt::Key_F27;
- case XK_F28: return Qt::Key_F28;
- case XK_F29: return Qt::Key_F29;
- case XK_F30: return Qt::Key_F30;
- case XK_F31: return Qt::Key_F31;
- case XK_F32: return Qt::Key_F32;
- case XK_F33: return Qt::Key_F33;
- case XK_F34: return Qt::Key_F34;
- case XK_F35: return Qt::Key_F35;
- //Miscellaneous Keys
- case XK_BackSpace: return Qt::Key_Backspace;
- case XK_Delete: return Qt::Key_Delete;
- //case XK_LineFeed: return Qt::Key_Backspace;
- case XK_Clear: return Qt::Key_Clear;
- case XK_Return: return Qt::Key_Return;
- case XK_Pause: return Qt::Key_Pause;
- case XK_Scroll_Lock: return Qt::Key_ScrollLock;
- case XK_Sys_Req: return Qt::Key_SysReq;
- case XK_Escape: return Qt::Key_Escape;
- case XK_Select: return Qt::Key_Select;
- case XK_Print: return Qt::Key_Print;
- //case XK_Execute: return Qt::Key_Execute;
- case XK_Insert: return Qt::Key_Insert;
- case XK_Undo: return Qt::Key_Undo;
- case XK_Redo: return Qt::Key_Redo;
- case XK_Menu: return Qt::Key_Menu;
- case XK_Find: return Qt::Key_Find;
- case XK_Cancel: return Qt::Key_Cancel;
- case XK_Help: return Qt::Key_Help;
- //case XK_Break: return Qt::Key_Break;
- //case XK_Mode_switch: return Qt::Key_Backspace;
- //case XK_script_switch: return Qt::Key_Backspace;
- case XK_Num_Lock: return Qt::Key_NumLock;
- //Cursor Controls
- case XK_Home: return Qt::Key_Home;
- case XK_Left: return Qt::Key_Left;
- case XK_Up: return Qt::Key_Up;
- case XK_Right: return Qt::Key_Right;
- case XK_Down: return Qt::Key_Down;
- //case XK_Prior: return Qt::Key_Backspace;
- case XK_Page_Up: return Qt::Key_PageUp;
- case XK_Page_Down: return Qt::Key_PageDown;
- //case XK_Next: return Qt::Key_Backspace;
- case XK_End: return Qt::Key_End;
- //case XK_Begin: return Qt::Key_Backspace;
- // Keypad Functions and numbers
- case XK_KP_Space: return Qt::Key_Space;
- case XK_KP_Tab: return Qt::Key_Tab;
- case XK_KP_Enter: return Qt::Key_Enter;
- case XK_KP_F1: return Qt::Key_F1;
- case XK_KP_F2: return Qt::Key_F2;
- case XK_KP_F3: return Qt::Key_F3;
- case XK_KP_F4: return Qt::Key_F4;
- case XK_KP_Home: return Qt::Key_Home;
- case XK_KP_Left: return Qt::Key_Left;
- case XK_KP_Up: return Qt::Key_Up;
- case XK_KP_Right: return Qt::Key_Right;
- case XK_KP_Down: return Qt::Key_Down;
- //case XK_KP_Prior: return Qt::Key_
- case XK_KP_Page_Up: return Qt::Key_PageUp;
- //case XK_KP_Next: return Qt::Key_
- case XK_KP_Page_Down: return Qt::Key_PageDown;
- case XK_KP_End: return Qt::Key_End;
- //case XK_KP_Begin: return Qt::Key_
- case XK_KP_Insert: return Qt::Key_Insert;
- case XK_KP_Delete: return Qt::Key_Delete;
- case XK_KP_Equal: return Qt::Key_Equal;
- case XK_KP_Multiply: return Qt::Key_Asterisk;
- case XK_KP_Add: return Qt::Key_Plus;
- case XK_KP_Separator: return Qt::Key_Comma; //X11 definitions say this is often comma
- case XK_KP_Subtract: return Qt::Key_Minus;
- case XK_KP_Decimal: return Qt::Key_Period;
- case XK_KP_Divide: return Qt::Key_Slash;
- case XK_KP_0: return Qt::Key_0;
- case XK_KP_1: return Qt::Key_1;
- case XK_KP_2: return Qt::Key_2;
- case XK_KP_3: return Qt::Key_3;
- case XK_KP_4: return Qt::Key_4;
- case XK_KP_5: return Qt::Key_5;
- case XK_KP_6: return Qt::Key_6;
- case XK_KP_7: return Qt::Key_7;
- case XK_KP_8: return Qt::Key_8;
- case XK_KP_9: return Qt::Key_9;
- // Modifier Keys
- case XK_Shift_L: return Qt::Key_Shift;
- case XK_Shift_R: return Qt::Key_Shift;
- case XK_Control_L: return Qt::Key_Control;
- case XK_Control_R: return Qt::Key_Control;
- case XK_Caps_Lock: return Qt::Key_CapsLock;
- //case XK_Shift_Lock: return Qt::Key_ShiftLock;
- case XK_Meta_L: return Qt::Key_Meta;
- case XK_Meta_R: return Qt::Key_Meta;
- case XK_Alt_L: return Qt::Key_Alt;
- case XK_Alt_R: return Qt::Key_Alt;
- case XK_Super_L: return Qt::Key_Super_L;
- case XK_Super_R: return Qt::Key_Super_R;
- case XK_Hyper_L: return Qt::Key_Hyper_L;
- case XK_Hyper_R: return Qt::Key_Hyper_R;
- case XK_space: return Qt::Key_Space;
- case XK_exclam: return Qt::Key_Exclam;
- case XK_quotedbl: return Qt::Key_QuoteDbl;
- case XK_numbersign: return Qt::Key_NumberSign;
- case XK_dollar: return Qt::Key_Dollar;
- case XK_percent: return Qt::Key_Percent;
- case XK_ampersand: return Qt::Key_Ampersand;
- case XK_apostrophe: return Qt::Key_Apostrophe;
- case XK_parenleft: return Qt::Key_ParenLeft;
- case XK_parenright: return Qt::Key_ParenRight;
- case XK_asterisk: return Qt::Key_Asterisk;
- case XK_plus: return Qt::Key_Plus;
- case XK_comma: return Qt::Key_Comma;
- case XK_minus: return Qt::Key_Minus;
- case XK_period: return Qt::Key_Period;
- case XK_slash: return Qt::Key_Slash;
- case XK_0: return Qt::Key_0;
- case XK_1: return Qt::Key_1;
- case XK_2: return Qt::Key_2;
- case XK_3: return Qt::Key_3;
- case XK_4: return Qt::Key_4;
- case XK_5: return Qt::Key_5;
- case XK_6: return Qt::Key_6;
- case XK_7: return Qt::Key_7;
- case XK_8: return Qt::Key_8;
- case XK_9: return Qt::Key_9;
- case XK_colon: return Qt::Key_Colon;
- case XK_semicolon: return Qt::Key_Semicolon;
- case XK_less: return Qt::Key_Less;
- case XK_equal: return Qt::Key_Equal;
- case XK_greater: return Qt::Key_Greater;
- case XK_question: return Qt::Key_Question;
- case XK_at: return Qt::Key_At;
- case XK_A: return Qt::Key_A;
- case XK_B: return Qt::Key_B;
- case XK_C: return Qt::Key_C;
- case XK_D: return Qt::Key_D;
- case XK_E: return Qt::Key_E;
- case XK_F: return Qt::Key_F;
- case XK_G: return Qt::Key_G;
- case XK_H: return Qt::Key_H;
- case XK_I: return Qt::Key_I;
- case XK_J: return Qt::Key_J;
- case XK_K: return Qt::Key_K;
- case XK_L: return Qt::Key_L;
- case XK_M: return Qt::Key_M;
- case XK_N: return Qt::Key_N;
- case XK_O: return Qt::Key_O;
- case XK_P: return Qt::Key_P;
- case XK_Q: return Qt::Key_Q;
- case XK_R: return Qt::Key_R;
- case XK_S: return Qt::Key_S;
- case XK_T: return Qt::Key_T;
- case XK_U: return Qt::Key_U;
- case XK_V: return Qt::Key_V;
- case XK_W: return Qt::Key_W;
- case XK_X: return Qt::Key_X;
- case XK_Y : return Qt::Key_Y;
- case XK_Z: return Qt::Key_Z;
- case XK_bracketleft: return Qt::Key_BracketLeft;
- case XK_backslash: return Qt::Key_Backslash;
- case XK_bracketright: return Qt::Key_BracketRight;
- case XK_asciicircum: return Qt::Key_AsciiCircum;
- case XK_underscore: return Qt::Key_Underscore;
- case XK_grave: return Qt::Key_Agrave;
- case XK_a: return Qt::Key_A;
- case XK_b: return Qt::Key_B;
- case XK_c: return Qt::Key_C;
- case XK_d: return Qt::Key_D;
- case XK_e: return Qt::Key_E;
- case XK_f : return Qt::Key_F;
- case XK_g: return Qt::Key_G;
- case XK_h: return Qt::Key_H;
- case XK_i: return Qt::Key_I;
- case XK_j: return Qt::Key_J;
- case XK_k: return Qt::Key_K;
- case XK_l: return Qt::Key_L;
- case XK_m: return Qt::Key_M;
- case XK_n: return Qt::Key_N;
- case XK_o: return Qt::Key_O;
- case XK_p: return Qt::Key_P;
- case XK_q: return Qt::Key_Q;
- case XK_r: return Qt::Key_R;
- case XK_s: return Qt::Key_S;
- case XK_t : return Qt::Key_T;
- case XK_u: return Qt::Key_U;
- case XK_v: return Qt::Key_V;
- case XK_w: return Qt::Key_W;
- case XK_x: return Qt::Key_X;
- case XK_y: return Qt::Key_Y;
- case XK_z: return Qt::Key_Z;
- case XK_braceleft: return Qt::Key_BraceLeft;
- case XK_bar: return Qt::Key_Bar;
- case XK_braceright: return Qt::Key_BraceRight;
- case XK_asciitilde: return Qt::Key_AsciiTilde;
-
- case XK_nobreakspace: return Qt::Key_nobreakspace;
- case XK_exclamdown: return Qt::Key_exclamdown;
- case XK_cent: return Qt::Key_cent;
- case XK_sterling: return Qt::Key_sterling;
- case XK_currency: return Qt::Key_currency;
- case XK_yen: return Qt::Key_yen;
- case XK_brokenbar: return Qt::Key_brokenbar;
- case XK_section: return Qt::Key_section;
- case XK_diaeresis: return Qt::Key_diaeresis;
- case XK_copyright: return Qt::Key_copyright;
- case XK_ordfeminine: return Qt::Key_ordfeminine;
- case XK_guillemotleft: return Qt::Key_guillemotleft;
- case XK_notsign: return Qt::Key_notsign;
- case XK_hyphen: return Qt::Key_hyphen;
- case XK_registered: return Qt::Key_registered;
- case XK_macron: return Qt::Key_macron;
- case XK_degree: return Qt::Key_degree;
- case XK_plusminus: return Qt::Key_plusminus;
- case XK_twosuperior: return Qt::Key_twosuperior;
- case XK_threesuperior: return Qt::Key_threesuperior;
- case XK_acute: return Qt::Key_acute;
- case XK_mu: return Qt::Key_mu;
- case XK_paragraph: return Qt::Key_paragraph;
- case XK_periodcentered: return Qt::Key_periodcentered;
- case XK_cedilla: return Qt::Key_cedilla;
- case XK_onesuperior: return Qt::Key_onesuperior;
- case XK_masculine: return Qt::Key_masculine;
- case XK_guillemotright: return Qt::Key_guillemotright;
- case XK_onequarter: return Qt::Key_onequarter;
- case XK_onehalf: return Qt::Key_onehalf;
- case XK_threequarters: return Qt::Key_threequarters;
- case XK_questiondown: return Qt::Key_questiondown;
- case XK_Agrave: return Qt::Key_Agrave;
- case XK_Aacute: return Qt::Key_Aacute;
- case XK_Acircumflex: return Qt::Key_Acircumflex;
- case XK_Atilde: return Qt::Key_Atilde;
- case XK_Adiaeresis: return Qt::Key_Adiaeresis;
- case XK_Aring: return Qt::Key_Aring;
- case XK_AE: return Qt::Key_AE;
- case XK_Ccedilla: return Qt::Key_Ccedilla;
- case XK_Egrave: return Qt::Key_Egrave;
- case XK_Eacute: return Qt::Key_Eacute;
- case XK_Ecircumflex: return Qt::Key_Ecircumflex;
- case XK_Ediaeresis: return Qt::Key_Ediaeresis;
- case XK_Igrave: return Qt::Key_Igrave;
- case XK_Iacute: return Qt::Key_Iacute;
- case XK_Icircumflex: return Qt::Key_Icircumflex;
- case XK_Idiaeresis: return Qt::Key_Idiaeresis;
- case XK_ETH: return Qt::Key_ETH;
- //case XK_Eth: return Qt::Key_Eth;
- case XK_Ntilde: return Qt::Key_Ntilde;
- case XK_Ograve: return Qt::Key_Ograve;
- case XK_Oacute: return Qt::Key_Oacute;
- case XK_Ocircumflex: return Qt::Key_Ocircumflex;
- case XK_Otilde: return Qt::Key_Otilde;
- case XK_Odiaeresis: return Qt::Key_Odiaeresis;
- case XK_multiply: return Qt::Key_multiply;
- //case XK_Oslash: return Qt::Key_AsciiTilde;
- case XK_Ooblique: return Qt::Key_Ooblique;
- case XK_Ugrave: return Qt::Key_Ugrave;
- case XK_Uacute: return Qt::Key_Uacute;
- case XK_Ucircumflex: return Qt::Key_Ucircumflex;
- case XK_Udiaeresis: return Qt::Key_Udiaeresis;
- case XK_Yacute: return Qt::Key_Yacute;
- case XK_THORN: return Qt::Key_THORN;
- //case XK_Thorn: return Qt::Key_AsciiTilde;
- case XK_ssharp: return Qt::Key_ssharp;
- /*case XK_agrave: return Qt::Key_AsciiTilde;
- case XK_aacute: return Qt::Key_AsciiTilde;
- case XK_acircumflex: return Qt::Key_AsciiTilde;
- case XK_atilde: return Qt::Key_AsciiTilde;
- case XK_adiaeresis: return Qt::Key_AsciiTilde;
- case XK_aring: return Qt::Key_AsciiTilde;
- case XK_ae: return Qt::Key_AsciiTilde;
- case XK_ccedilla: return Qt::Key_AsciiTilde;
- case XK_egrave: return Qt::Key_AsciiTilde;
- case XK_eacute: return Qt::Key_AsciiTilde;
- case XK_ecircumflex: return Qt::Key_AsciiTilde;
- case XK_ediaeresis: return Qt::Key_AsciiTilde;
- case XK_igrave: return Qt::Key_AsciiTilde;
- case XK_iacute: return Qt::Key_AsciiTilde;
- case XK_icircumflex: return Qt::Key_AsciiTilde;
- case XK_idiaeresis: return Qt::Key_AsciiTilde;
- case XK_eth: return Qt::Key_AsciiTilde;
- case XK_ntilde: return Qt::Key_AsciiTilde;
- case XK_ograve: return Qt::Key_AsciiTilde;
- case XK_oacute: return Qt::Key_AsciiTilde;
- case XK_ocircumflex: return Qt::Key_AsciiTilde;
- case XK_otilde: return Qt::Key_AsciiTilde;
- case XK_odiaeresis: return Qt::Key_AsciiTilde;
- case XK_division: return Qt::Key_AsciiTilde;
- case XK_oslash: return Qt::Key_AsciiTilde;
- case XK_ooblique: return Qt::Key_AsciiTilde;
- case XK_ugrave: return Qt::Key_AsciiTilde;
- case XK_uacute: return Qt::Key_AsciiTilde;
- case XK_ucircumflex: return Qt::Key_AsciiTilde;
- case XK_udiaeresis: return Qt::Key_AsciiTilde;
- case XK_yacute: return Qt::Key_AsciiTilde;
- case XK_thorn: return Qt::Key_AsciiTilde;
- case XK_ydiaeresis: return Qt::Key_AsciiTilde;
-
- case: XK_Agonek: return Qt::Key_AsciiTilde;
- case XK_breve: return Qt::Key_AsciiTilde;
- case XK_Lstroke: return Qt::Key_AsciiTilde;
- case XK_Lcaron: return Qt::Key_AsciiTilde;
- case XK_Sacute: return Qt::Key_AsciiTilde;
- case XK_Scaron: return Qt::Key_AsciiTilde;
- case XK_Scedilla: return Qt::Key_AsciiTilde;
- case XK_Tcaron: return Qt::Key_AsciiTilde;
- case XK_Zacute: return Qt::Key_AsciiTilde;
- case XK_Zcaron: return Qt::Key_AsciiTilde;
- case XK_Zabovedot: return Qt::Key_AsciiTilde;
- case XK_aogonek: return Qt::Key_AsciiTilde;
- case XK_ogonek: return Qt::Key_AsciiTilde;
- case XK_lstroke: return Qt::Key_AsciiTilde;
- case XK_lcaron: return Qt::Key_AsciiTilde;
- case XK_sacute: return Qt::Key_AsciiTilde;
- case XK_caron: return Qt::Key_AsciiTilde;
- case XK_scaron: return Qt::Key_AsciiTilde;
- case XK_scedilla: return Qt::Key_AsciiTilde;
- case XK_tcaron: return Qt::Key_AsciiTilde;
- case XK_zacute: return Qt::Key_AsciiTilde;
- case XK_doubleacute: return Qt::Key_AsciiTilde;
- case XK_zcaron: return Qt::Key_AsciiTilde;
- case XK_zabovedot: return Qt::Key_AsciiTilde;
- case XK_Racute: return Qt::Key_AsciiTilde;
- case XK_Abreve: return Qt::Key_AsciiTilde;
- case XK_Lacute: return Qt::Key_AsciiTilde;
- case XK_Cacute: return Qt::Key_AsciiTilde;
- case XK_Ccaron: return Qt::Key_AsciiTilde;
- case XK_Eogonek: return Qt::Key_AsciiTilde;
- case XK_Ecaron: return Qt::Key_AsciiTilde;
- case XK_Dcaron: return Qt::Key_AsciiTilde;
- case XK_Dstroke: return Qt::Key_AsciiTilde;
- case XK_Nacute: return Qt::Key_AsciiTilde;
- case XK_Ncaron: return Qt::Key_AsciiTilde;
- case XK_Odoubleacute: return Qt::Key_AsciiTilde;
- case XK_Rcaron: return Qt::Key_AsciiTilde;
- case XK_Uring: return Qt::Key_AsciiTilde;
- case XK_Udoubleacute: return Qt::Key_AsciiTilde;
- case XK_Tcedilla: return Qt::Key_AsciiTilde;
- case XK_racute: return Qt::Key_AsciiTilde;
- case XK_abreve: return Qt::Key_AsciiTilde;
- case XK_lacute: return Qt::Key_AsciiTilde;
- case XK_cacute: return Qt::Key_AsciiTilde;
- case XK_ccaron: return Qt::Key_AsciiTilde;
- case XK_eogonek: return Qt::Key_AsciiTilde;
- case XK_ecaron: return Qt::Key_AsciiTilde;
- case XK_dcaron: return Qt::Key_AsciiTilde;
- case XK_dstroke: return Qt::Key_AsciiTilde;
- case XK_nacute: return Qt::Key_AsciiTilde;
- case XK_ncaron: return Qt::Key_AsciiTilde;
- case XK_odoubleacute: return Qt::Key_AsciiTilde;
- case XK_rcaron: return Qt::Key_AsciiTilde;
- case XK_uring: return Qt::Key_AsciiTilde;
- case XK_udoubleacute: return Qt::Key_AsciiTilde;
- case XK_tcedilla: return Qt::Key_AsciiTilde;
- case XK_abovedot: return Qt::Key_AsciiTilde;
- case XK_Hstroke: return Qt::Key_AsciiTilde;
- case XK_Hcircumflex: return Qt::Key_AsciiTilde;
- case XK_Iabovedot: return Qt::Key_AsciiTilde;
- case XK_Gbreve: return Qt::Key_AsciiTilde;
- case XK_Jcircumflex: return Qt::Key_AsciiTilde;
- case XK_hstroke: return Qt::Key_AsciiTilde;
- case XK_hcircumflex: return Qt::Key_AsciiTilde;
- case XK_idotless: return Qt::Key_AsciiTilde;
- case XK_gbreve: return Qt::Key_AsciiTilde;
- case XK_jcircumflex: return Qt::Key_AsciiTilde;
- case XK_Cabovedot: return Qt::Key_AsciiTilde;
- case XK_Ccircumflex: return Qt::Key_AsciiTilde;
- case XK_Gabovedot: return Qt::Key_AsciiTilde;
- case XK_Gcircumflex: return Qt::Key_AsciiTilde;
- case XK_Ubreve: return Qt::Key_AsciiTilde;
- case XK_Scircumflex: return Qt::Key_AsciiTilde;
- case XK_cabovedot: return Qt::Key_AsciiTilde;
- case XK_ccircumflex: return Qt::Key_AsciiTilde;
- case XK_gabovedot: return Qt::Key_AsciiTilde;
- case XK_gcircumflex: return Qt::Key_AsciiTilde;
- case XK_ubreve: return Qt::Key_AsciiTilde;
- case XK_scircumflex: return Qt::Key_AsciiTilde;
- case XK_kra: return Qt::Key_AsciiTilde;
- case XK_kappa: return Qt::Key_AsciiTilde;
- case XK_Rcedilla: return Qt::Key_AsciiTilde;
- case XK_Itilde: return Qt::Key_AsciiTilde;
- case XK_Lcedilla: return Qt::Key_AsciiTilde;
- case XK_Emacron: return Qt::Key_AsciiTilde;
- case XK_Gcedilla: return Qt::Key_AsciiTilde;
- case XK_Tslash: return Qt::Key_AsciiTilde;
- case XK_rcedilla: return Qt::Key_AsciiTilde;
- case XK_itilde: return Qt::Key_AsciiTilde;
- case XK_lcedilla: return Qt::Key_AsciiTilde;
- case XK_emacron: return Qt::Key_AsciiTilde;
- case XK_gcedilla: return Qt::Key_AsciiTilde;
- case XK_tslash: return Qt::Key_AsciiTilde;
- case XK_ENG: return Qt::Key_AsciiTilde;
- case XK_eng: return Qt::Key_AsciiTilde;
- case XK_Amacron: return Qt::Key_AsciiTilde;
- case XK_Iogonek: return Qt::Key_AsciiTilde;
- case XK_Eabovedot: return Qt::Key_AsciiTilde;
- case XK_Imacron: return Qt::Key_AsciiTilde;
- case XK_Ncedilla: return Qt::Key_AsciiTilde;
- case XK_Omacron: return Qt::Key_AsciiTilde;
- case XK_Kcedilla: return Qt::Key_AsciiTilde;
- case XK_Uogonek: return Qt::Key_AsciiTilde;
- case XK_Utilde: return Qt::Key_AsciiTilde;
- case XK_Umacron: return Qt::Key_AsciiTilde;
- case XK_amacron: return Qt::Key_AsciiTilde;
- case XK_iogonek: return Qt::Key_AsciiTilde;
- case XK_eabovedot: return Qt::Key_AsciiTilde;
- case XK_imacron: return Qt::Key_AsciiTilde;
- case XK_ncedilla: return Qt::Key_AsciiTilde;
- case XK_omacron: return Qt::Key_AsciiTilde;
- case XK_kcedilla: return Qt::Key_AsciiTilde;
- case XK_uogonek: return Qt::Key_AsciiTilde;
- case XK_utilde: return Qt::Key_AsciiTilde;
- case XK_umacron: return Qt::Key_AsciiTilde;
- case XK_Wcircumflex: return Qt::Key_AsciiTilde;
- case XK_wcircumflex: return Qt::Key_AsciiTilde;
- case XK_Ycircumflex: return Qt::Key_AsciiTilde;
- case XK_ycircumflex: return Qt::Key_AsciiTilde;
- case XK_Babovedot: return Qt::Key_AsciiTilde;
- case XK_babovedot: return Qt::Key_AsciiTilde;
- case XK_Dabovedot: return Qt::Key_AsciiTilde;
- case XK_dabovedot: return Qt::Key_AsciiTilde;
- case XK_Fabovedot: return Qt::Key_AsciiTilde;
- case XK_fabovedot: return Qt::Key_AsciiTilde;
- case XK_Mabovedot: return Qt::Key_AsciiTilde;
- case XK_mabovedot: return Qt::Key_AsciiTilde;
- case XK_Pabovedot: return Qt::Key_AsciiTilde;
- case XK_pabovedot: return Qt::Key_AsciiTilde;
- case XK_Sabovedot: return Qt::Key_AsciiTilde;
- case XK_sabovedot: return Qt::Key_AsciiTilde;
- case XK_Tabovedot: return Qt::Key_AsciiTilde;
- case XK_tabovedot: return Qt::Key_AsciiTilde;
- case XK_Wgrave: return Qt::Key_AsciiTilde;
- case XK_wgrave: return Qt::Key_AsciiTilde;
- case XK_Wacute: return Qt::Key_AsciiTilde;
- case XK_wacute: return Qt::Key_AsciiTilde;
- case XK_Wdiaeresis: return Qt::Key_AsciiTilde;
- case XK_wdiaeresis: return Qt::Key_AsciiTilde;
- case XK_Ygrave: return Qt::Key_AsciiTilde;
- case XK_ygrave: return Qt::Key_AsciiTilde;
- case XK_OE: return Qt::Key_AsciiTilde;
- case XK_oe: return Qt::Key_AsciiTilde;
- case XK_Ydiaeresis: return Qt::Key_AsciiTilde;*/
- default:
- qDebug() << "Unknown Key";
- }
- qDebug() << " -- Simple Qt Map:" << (Qt::Key)(symbol);
- qDebug() << " -- Key Sequence Map:" << QKeySequence(symbol);
- qDebug() << " - Not implemented yet";
- return Qt::Key_unknown;
-}
-
-NativeWindowSystem::MouseButton NativeWindowSystem::MouseToQt(int keycode){
- switch(keycode){
- case 1:
- return NativeWindowSystem::LeftButton;
- case 3:
- return NativeWindowSystem::RightButton;
- case 2:
- return NativeWindowSystem::MidButton;
- case 4:
- return NativeWindowSystem::WheelUp;
- case 5:
- return NativeWindowSystem::WheelDown;
- case 6:
- return NativeWindowSystem::WheelLeft;
- case 7:
- return NativeWindowSystem::WheelRight;
- case 8:
- return NativeWindowSystem::BackButton; //Not sure if this is correct yet (1/27/17)
- case 9:
- return NativeWindowSystem::ForwardButton; //Not sure if this is correct yet (1/27/17)
- default:
- return NativeWindowSystem::NoButton;
- }
-}
diff --git a/src-qt5/core/libLumina/NativeWindow.cpp b/src-qt5/core/libLumina/NativeWindow.cpp
deleted file mode 100644
index 3c76ed00..00000000
--- a/src-qt5/core/libLumina/NativeWindow.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include "NativeWindow.h"
-
-#include <QDebug>
-
-// === PUBLIC ===
-NativeWindow::NativeWindow(WId id) : QObject(){
- winid = id;
- frameid = 0;
- dmgID = 0;
-}
-
-NativeWindow::~NativeWindow(){
- hash.clear();
-}
-
-void NativeWindow::addFrameWinID(WId fid){
- frameid = fid;
-}
-
-void NativeWindow::addDamageID(unsigned int dmg){
- dmgID = dmg;
-}
-
-bool NativeWindow::isRelatedTo(WId tmp){
- return (relatedTo.contains(tmp) || winid == tmp || frameid == tmp);
-}
-
-WId NativeWindow::id(){
- return winid;
-}
-
-WId NativeWindow::frameId(){
- return frameid;
-}
-
-unsigned int NativeWindow::damageId(){
- return dmgID;
-}
-
-QVariant NativeWindow::property(NativeWindow::Property prop){
- if(hash.contains(prop)){ return hash.value(prop); }
- else if(prop == NativeWindow::RelatedWindows){ return QVariant::fromValue(relatedTo); }
- return QVariant(); //null variant
-}
-
-void NativeWindow::setProperty(NativeWindow::Property prop, QVariant val, bool force){
- if(prop == NativeWindow::RelatedWindows){ relatedTo = val.value< QList<WId> >(); }
- else if(prop == NativeWindow::None || (!force && hash.value(prop)==val)){ return; }
- else{ hash.insert(prop, val); }
- emit PropertiesChanged(QList<NativeWindow::Property>() << prop, QList<QVariant>() << val);
-}
-
-void NativeWindow::setProperties(QList<NativeWindow::Property> props, QList<QVariant> vals, bool force){
- for(int i=0; i<props.length(); i++){
- if(i>=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property
- if(props[i] == NativeWindow::None || (!force && (hash.value(props[i]) == vals[i])) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value
- hash.insert(props[i], vals[i]);
- }
- emit PropertiesChanged(props, vals);
-}
-
-void NativeWindow::requestProperty(NativeWindow::Property prop, QVariant val, bool force){
- if(prop == NativeWindow::None || prop == NativeWindow::RelatedWindows || (!force && hash.value(prop)==val) ){ return; }
- emit RequestPropertiesChange(winid, QList<NativeWindow::Property>() << prop, QList<QVariant>() << val);
-}
-
-void NativeWindow::requestProperties(QList<NativeWindow::Property> props, QList<QVariant> vals, bool force){
- //Verify/adjust inputs as needed
- for(int i=0; i<props.length(); i++){
- if(i>=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property
- if(props[i] == NativeWindow::None || props[i] == NativeWindow::RelatedWindows || (!force && hash.value(props[i])==vals[i]) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value
- /*if( (props[i] == NativeWindow::Visible || props[i] == NativeWindow::Active) && frameid !=0){
- //These particular properties needs to change the frame - not the window itself
- emit RequestPropertiesChange(frameid, QList<NativeWindow::Property>() << props[i], QList<QVariant>() << vals[i]);
- props.removeAt(i); vals.removeAt(i); i--;
- }*/
- }
- emit RequestPropertiesChange(winid, props, vals);
-}
-
-QRect NativeWindow::geometry(){
- //Calculate the "full" geometry of the window + frame (if any)
- //Check that the size is between the min/max limitations
- QSize size = hash.value(NativeWindow::Size).toSize();
- QSize min = hash.value(NativeWindow::MinSize).toSize();
- QSize max = hash.value(NativeWindow::MaxSize).toSize();
- if(min.isValid() && min.width() > size.width() ){ size.setWidth(min.width()); }
- if(min.isValid() && min.height() > size.height()){ size.setHeight(min.height()); }
- if(max.isValid() && max.width() < size.width() && max.width()>min.width()){ size.setWidth(max.width()); }
- if(max.isValid() && max.height() < size.height() && max.height()>min.height()){ size.setHeight(max.height()); }
- //Assemble the full geometry
- QRect geom( hash.value(NativeWindow::GlobalPos).toPoint(), size );
- //Now adjust the window geom by the frame margins
- QList<int> frame = hash.value(NativeWindow::FrameExtents).value< QList<int> >(); //Left,Right,Top,Bottom
- //qDebug() << "Calculate Geometry:" << geom << frame;
- if(frame.length()==4){
- geom = geom.adjusted( -frame[0], -frame[2], frame[1], frame[3] );
- }
- //qDebug() << " - Total:" << geom;
- return geom;
-}
-// ==== PUBLIC SLOTS ===
-void NativeWindow::requestClose(){
- emit RequestClose(winid);
-}
-
-void NativeWindow::requestKill(){
- emit RequestKill(winid);
-}
-
-void NativeWindow::requestPing(){
- emit RequestPing(winid);
-}
diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h
deleted file mode 100644
index d04815ce..00000000
--- a/src-qt5/core/libLumina/NativeWindow.h
+++ /dev/null
@@ -1,117 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This is a container object for setting/announcing changes
-// in a native window's properties.
-// The WM will usually run the "setProperty" function on this object,
-// and any other classes/widgets which watch this window can act appropriatly after-the-fact
-// Non-WM classes should use the "Request" signals to ask the WM to do something, and listen for changes later
-//===========================================
-#ifndef _LUMINA_DESKTOP_NATIVE_WINDOW_H
-#define _LUMINA_DESKTOP_NATIVE_WINDOW_H
-
-#include <QString>
-#include <QRect>
-#include <QSize>
-#include <QObject>
-#include <QWindow>
-#include <QHash>
-#include <QVariant>
-
-class NativeWindow : public QObject{
- Q_OBJECT
-public:
- enum State{ S_MODAL, S_STICKY, S_MAX_VERT, S_MAX_HORZ, S_SHADED, S_SKIP_TASKBAR, S_SKIP_PAGER, S_HIDDEN, S_FULLSCREEN, S_ABOVE, S_BELOW, S_ATTENTION };
- enum Type{T_DESKTOP, T_DOCK, T_TOOLBAR, T_MENU, T_UTILITY, T_SPLASH, T_DIALOG, T_DROPDOWN_MENU, T_POPUP_MENU, T_TOOLTIP, T_NOTIFICATION, T_COMBO, T_DND, T_NORMAL };
- enum Action {A_MOVE, A_RESIZE, A_MINIMIZE, A_SHADE, A_STICK, A_MAX_VERT, A_MAX_HORZ, A_FULLSCREEN, A_CHANGE_DESKTOP, A_CLOSE, A_ABOVE, A_BELOW};
-
- enum Property{ /*QVariant Type*/
- None=0, /*null*/
- MinSize=1, /*QSize*/
- MaxSize=2, /*QSize*/
- Size=3, /*QSize*/
- GlobalPos=4, /*QPoint*/
- Title=5, /*QString*/
- ShortTitle=6, /*QString*/
- Icon=7, /*QIcon*/
- Name=8, /*QString*/
- Workspace=9, /*int*/
- States=10, /*QList<NativeWindow::State> : Current state of the window */
- WinTypes=11, /*QList<NativeWindow::Type> : Current type of window (typically does not change)*/
- WinActions=12, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/
- FrameExtents=13, /*QList<int> : [Left, Right, Top, Bottom] in pixels */
- RelatedWindows=14, /* QList<WId> - better to use the "isRelatedTo(WId)" function instead of reading this directly*/
- Active=15, /*bool*/
- Visible=16 /*bool*/
- };
-
- static QList<NativeWindow::Property> allProperties(){
- //Return all the available properties (excluding "None" and "FrameExtents" (WM control only) )
- QList<NativeWindow::Property> props;
- props << MinSize << MaxSize << Size << GlobalPos << Title << ShortTitle << Icon << Name << Workspace \
- << States << WinTypes << WinActions << RelatedWindows << Active << Visible;
- return props;
- };
-
- NativeWindow(WId id);
- ~NativeWindow();
-
- void addFrameWinID(WId);
- void addDamageID(unsigned int);
- bool isRelatedTo(WId);
-
- WId id();
- WId frameId();
- unsigned int damageId();
-
- //QWindow* window();
-
- QVariant property(NativeWindow::Property);
- void setProperty(NativeWindow::Property, QVariant, bool force = false);
- void setProperties(QList<NativeWindow::Property>, QList<QVariant>, bool force = false);
- void requestProperty(NativeWindow::Property, QVariant, bool force = false);
- void requestProperties(QList<NativeWindow::Property>, QList<QVariant>, bool force = false);
-
- QRect geometry(); //this returns the "full" geometry of the window (window + frame)
-
-public slots:
- void requestClose(); //ask the app to close the window (may/not depending on activity)
- void requestKill(); //ask the WM to kill the app associated with this window (harsh - only use if not responding)
- void requestPing(); //ask the app if it is still active (a WindowNotResponding signal will get sent out if there is no reply);
-
-private:
- QHash <NativeWindow::Property, QVariant> hash;
- //QWindow *WIN;
- WId winid, frameid;
- QList<WId> relatedTo;
- unsigned int dmgID;
-
-signals:
- //General Notifications
- void PropertiesChanged(QList<NativeWindow::Property>, QList<QVariant>);
- void RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void WindowClosed(WId);
- void WindowNotResponding(WId); //will be sent out if a window does not respond to a ping request
- void VisualChanged();
-
- //Action Requests (not automatically emitted - typically used to ask the WM to do something)
- //Note: "WId" should be the NativeWindow id()
- void RequestClose(WId); //Close the window
- void RequestKill(WId); //Kill the window/app (usually from being unresponsive)
- void RequestPing(WId); //Verify that the window is still active (such as not closing after a request
- void RequestReparent(WId, WId, QPoint); //client window, frame window, relative origin point in frame
- // System Tray Icon Embed/Unembed Requests
- //void RequestEmbed(WId, QWidget*);
- //void RequestUnEmbed(WId, QWidget*);
-};
-
-// Declare the enumerations as Qt MetaTypes
-Q_DECLARE_METATYPE(NativeWindow::Type);
-Q_DECLARE_METATYPE(NativeWindow::Action);
-Q_DECLARE_METATYPE(NativeWindow::State);
-Q_DECLARE_METATYPE(NativeWindow::Property);
-
-#endif
diff --git a/src-qt5/core/libLumina/NativeWindow.pri b/src-qt5/core/libLumina/NativeWindow.pri
deleted file mode 100644
index c2ac0137..00000000
--- a/src-qt5/core/libLumina/NativeWindow.pri
+++ /dev/null
@@ -1,17 +0,0 @@
-
-# Files
-QT *= x11extras
-LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lxcb-keysyms -lXdamage
-
-SOURCES *= $${PWD}/NativeWindow.cpp \
- $${PWD}/NativeWindowSystem.cpp \
- $${PWD}/NativeKeyToQt.cpp \
- $${PWD}/NativeEventFilter.cpp \
- $${PWD}/NativeEmbedWidget.cpp
-
-HEADERS *= $${PWD}/NativeWindow.h \
- $${PWD}/NativeWindowSystem.h \
- $${PWD}/NativeEventFilter.h \
- $${PWD}/NativeEmbedWidget.h
-
-INCLUDEPATH *= $${PWD}
diff --git a/src-qt5/core/libLumina/NativeWindowSystem.cpp b/src-qt5/core/libLumina/NativeWindowSystem.cpp
deleted file mode 100644
index 71e95a0e..00000000
--- a/src-qt5/core/libLumina/NativeWindowSystem.cpp
+++ /dev/null
@@ -1,900 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This is the XCB version of the NativeWindowSystem class,
-// used for interacting with the X11 display system on BSD/Linux/Unix systems
-//===========================================
-#include "NativeWindowSystem.h"
-
-//Additional Qt includes
-#include <QX11Info>
-#include <QDebug>
-#include <QApplication>
-#include <QScreen>
-#include <QFont>
-#include <QFontMetrics>
-#include <QKeySequence>
-
-
-//XCB Library includes
-#include <xcb/xcb.h>
-#include <xcb/xcb_atom.h>
-#include <xcb/xproto.h>
-#include <xcb/xcb_ewmh.h>
-#include <xcb/xcb_icccm.h>
-#include <xcb/xcb_image.h>
-#include <xcb/xcb_aux.h>
-#include <xcb/composite.h>
-#include <xcb/damage.h>
-
-//XLib includes (XCB Damage lib does not appear to register for damage events properly)
-#include <X11/extensions/Xdamage.h>
-
-//SYSTEM TRAY STANDARD DEFINITIONS
-#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
-#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
-#define SYSTEM_TRAY_REQUEST_DOCK 0
-#define SYSTEM_TRAY_BEGIN_MESSAGE 1
-#define SYSTEM_TRAY_CANCEL_MESSAGE 2
-
-#define URGENCYHINT (1L << 8) //For window urgency detection
-
-#define ROOT_WIN_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_FOCUS_CHANGE | \
- XCB_EVENT_MASK_ENTER_WINDOW)
-
-#define NORMAL_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_BUTTON_MOTION | \
- XCB_EVENT_MASK_EXPOSURE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_ENTER_WINDOW| \
- XCB_EVENT_MASK_PROPERTY_CHANGE)
-
-inline void registerClientEvents(WId id){
- uint32_t value_list[1] = {NORMAL_WIN_EVENT_MASK};
- xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list);
-}
-
-//Internal XCB private objects class
-class NativeWindowSystem::p_objects{
-public:
- xcb_ewmh_connection_t EWMH; //This is where all the screen info and atoms are located
- QHash<QString, xcb_atom_t> ATOMS;
- xcb_screen_t *root_screen;
- xcb_window_t root_window, wm_window, tray_window;
-
- //Functions for setting up these objects as needed
- bool init_ATOMS(){
- xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH);
- if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){
- qDebug() << "Error with XCB atom initializations";
- return false;
- }
-
- QStringList atoms;
- atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "_NET_WM_WINDOW_OPACITY"
- << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_XEMBED"
- << "_NET_SYSTEM_TRAY_VISUAL" << QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen()));
- //Create all the requests for the atoms
- QList<xcb_intern_atom_reply_t*> reply;
- for(int i=0; i<atoms.length(); i++){
- reply << xcb_intern_atom_reply(QX11Info::connection(), \
- xcb_intern_atom(QX11Info::connection(), 0, atoms[i].length(), atoms[i].toLocal8Bit()), NULL);
- }
- //Now evaluate all the requests and save the atoms
- for(int i=0; i<reply.length(); i++){ //NOTE: this will always be the same length as the "atoms" list
- if(reply[i]!=0){
- ATOMS.insert(atoms[i], reply[i]->atom);
- free(reply[i]); //done with this reply
- }else{
- //Invalid atom - could not be created
- qDebug() << "Could not initialize XCB atom:" << atoms[i];
- }
- } //loop over reply
- return (ATOMS.keys().length() == atoms.length());
- }
-
- WId getTransientFor(WId win){
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for_unchecked(QX11Info::connection(), win);
- xcb_window_t trans;
- if(1!= xcb_icccm_get_wm_transient_for_reply(QX11Info::connection(), cookie, &trans, NULL) ){
- return win; //error in fetching transient window ID (or none found)
- }else{
- return trans;
- }
-}
-
- bool register_wm(){
- uint32_t value_list[1] = {ROOT_WIN_EVENT_MASK};
- xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), root_window, XCB_CW_EVENT_MASK, value_list));
- if(status!=0){ return false; }
- uint32_t params[] = {1};
- wm_window = xcb_generate_id(QX11Info::connection()); //need a new ID
- xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
- wm_window, root_window, -1, -1, 1, 1, 0, \
- XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
- XCB_CW_OVERRIDE_REDIRECT, params);
- if(wm_window==0){ return false; }
- //Set the _NET_SUPPORTING_WM property on the root window first
- xcb_ewmh_set_supporting_wm_check(&EWMH, root_window, wm_window);
- //Also set this property on the child window (pointing to itself)
- xcb_ewmh_set_supporting_wm_check(&EWMH, wm_window, wm_window);
- //Now also setup the root event mask on the wm_window
- status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), wm_window, XCB_CW_EVENT_MASK, value_list));
- if(status!=0){ return false; }
- return true;
- }
-
- bool start_system_tray(){
- xcb_atom_t _NET_SYSTEM_TRAY_S = ATOMS.value( QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())) );
- //Make sure that there is no other system tray running
- xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
- xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
- if(ownreply == 0){
- qWarning() << " - Could not get owner selection reply";
- return false;
- }else if(ownreply->owner != 0){
- free(ownreply);
- qWarning() << " - An alternate system tray is currently in use";
- return false;
- }
- free(ownreply);
- //Now create the window to use (just offscreen)
- tray_window = xcb_generate_id(QX11Info::connection()); //need a new ID
- uint32_t params[] = {1};
- xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
- tray_window, root_screen->root, -1, -1, 1, 1, 0, \
- XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
- XCB_CW_OVERRIDE_REDIRECT, params);
- //Now register this widget as the system tray
- xcb_set_selection_owner(QX11Info::connection(), tray_window, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME);
- //Make sure that it was registered properly
- ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
- xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
- if(ownreply==0 || ownreply->owner != tray_window){
- if(ownreply!=0){ free(ownreply); }
- qWarning() << " - Could not register the system tray";
- xcb_destroy_window(QX11Info::connection(), tray_window);
- return false;
- }
- free(ownreply); //done with structure
- //Now register the orientation of the system tray
- uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
- xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \
- ATOMS.value("_NET_SYSTEM_TRAY_ORIENTATION"), XCB_ATOM_CARDINAL, 32, 1, &orient);
-
- //Now set the visual ID for the system tray (same as the root window, but TrueColor)
- xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32);
- if(type!=0){
- xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \
- ATOMS.value("_NET_SYSTEM_TRAY_VISUAL"), XCB_ATOM_VISUALID, 32, 1, &type->visual_id);
- }else{
- qWarning() << " - Could not set TrueColor visual for system tray";
- }
-
- //Finally, send out an X event letting others know that the system tray is up and running
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = root_screen->root;
- event.type = EWMH.MANAGER; //MANAGER atom
- event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom
- event.data.data32[2] = tray_window;
- event.data.data32[3] = 0;
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, root_screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- return true;
- }
-
-}; //end private objects class
-
-
-//inline functions for setting up the internal objects
-
-
-// === PUBLIC ===
-NativeWindowSystem::NativeWindowSystem() : QObject(){
- obj = 0;
- pingTimer = 0;
- screenLocked = false;
-}
-
-NativeWindowSystem::~NativeWindowSystem(){
- xcb_ewmh_connection_wipe(&(obj->EWMH));
- free(obj);
-}
-
-//Overarching start/stop functions
-bool NativeWindowSystem::start(){
- //Initialize the XCB/EWMH objects
- if(obj==0){
- obj = new p_objects(); //instantiate the private objects
- obj->wm_window = 0;
- obj->tray_window = 0;
- xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &obj->EWMH);
- if(!xcb_ewmh_init_atoms_replies(&obj->EWMH, cookie, NULL) ){
- qDebug() << "Error with XCB atom initializations";
- return false;
- }
- obj->root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
- obj->root_window = obj->root_screen->root; //simplification for later - minor duplication of memory (unsigned int)
- //Initialize all the extra atoms that the EWMH object does not have
- if( !obj->init_ATOMS() ){ return false; }
- } //Done with private object init
- bool ok = obj->register_wm();
- if(ok){
- setRoot_supportedActions();
- ok = obj->start_system_tray();
- }else{
- qWarning() << "Could not register the WM";
- }
- return ok;
-}
-
-void NativeWindowSystem::stop(){
-
-}
-
-// === PRIVATE ===
-NativeWindow* NativeWindowSystem::findWindow(WId id, bool checkRelated){
- //qDebug() << "Find Window:" << id;
- for(int i=0; i<NWindows.length(); i++){
- if(id==NWindows[i]->id() ){ return NWindows[i]; }
- else if(id==NWindows[i]->frameId() ){ qDebug() << "Matched Frame:" << id; return NWindows[i]; }
- //if(checkRelated && NWindows[i]->isRelatedTo(id)){ return NWindows[i]; }
- //else if(!checkRelated && id==NWindows[i]->id()){ return NWindows[i]; }
- }
- //Check to see if this is a transient for some other window
- if(checkRelated){
- //WId tid = obj->getTransientFor(id);
- //if(tid!=id){ return findWindow(tid, checkRelated); } //call it recursively as needed
- //qDebug() << " -- Could not find Window!";
- }
- return 0;
-}
-
-NativeWindow* NativeWindowSystem::findTrayWindow(WId id){
- for(int i=0; i<TWindows.length(); i++){
- if(TWindows[i]->isRelatedTo(id)){ return TWindows[i]; }
- }
- return 0;
-}
-
-void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){
- //Put the properties in logical groups as appropriate (some XCB calls return multiple properties)
- if(props.contains(NativeWindow::Title)){
- //Try the EWMH standards first
- // _NET_WM_NAME
- QString name;
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- if(name.isEmpty()){
- //_NET_WM_VISIBLE_NAME
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_visible_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- }
- if(name.isEmpty()){
- //Now try the ICCCM standard
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name_unchecked(QX11Info::connection(), win->id());
- xcb_icccm_get_text_property_reply_t reply;
- if(1 == xcb_icccm_get_wm_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){
- name = QString::fromLocal8Bit(reply.name, reply.name_len);
- xcb_icccm_get_text_property_reply_wipe(&reply);
- }
- }
- win->setProperty(NativeWindow::Title, name);
- } //end TITLE property
-
- if(props.contains(NativeWindow::ShortTitle)){
- //Try the EWMH standards first
- // _NET_WM_ICON_NAME
- QString name;
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- if(name.isEmpty()){
- //_NET_WM_VISIBLE_ICON_NAME
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_icon_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_visible_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- }
- if(name.isEmpty()){
- //Now try the ICCCM standard
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_icon_name_unchecked(QX11Info::connection(), win->id());
- xcb_icccm_get_text_property_reply_t reply;
- if(1 == xcb_icccm_get_wm_icon_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){
- name = QString::fromLocal8Bit(reply.name, reply.name_len);
- xcb_icccm_get_text_property_reply_wipe(&reply);
- }
- }
- win->setProperty(NativeWindow::ShortTitle, name);
- } //end SHORTTITLE property
-
- if(props.contains(NativeWindow::Icon)){
- //See if this is a tray icon first (different routine - entire app window is the icon)
- QIcon icon;
- if(win == findTrayWindow(win->id())){
- //Tray Icon Window
- QPixmap pix;
- //Get the current QScreen (for XCB->Qt conversion)
- QList<QScreen*> scrnlist = QApplication::screens();
- //Try to grab the given window directly with Qt
- for(int i=0; i<scrnlist.length() && pix.isNull(); i++){
- pix = scrnlist[i]->grabWindow(win->id());
- }
- icon.addPixmap(pix);
- }else{
- //Standard window
- //Fetch the _NET_WM_ICON for the window and return it as a QIcon
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_unchecked(&obj->EWMH, win->id());
- xcb_ewmh_get_wm_icon_reply_t reply;
- if(1 == xcb_ewmh_get_wm_icon_reply(&obj->EWMH, cookie, &reply, NULL)){
- xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply);
- //Just use the first
- bool done =false;
- while(!done){
- //Now convert the current data into a Qt image
- // - first 2 elements are width and height (removed via XCB functions)
- // - data in rows from left to right and top to bottom
- QImage image(iter.width, iter.height, QImage::Format_ARGB32); //initial setup
- uint* dat = iter.data;
- //dat+=2; //remember the first 2 element offset
- for(int i=0; i<image.byteCount()/4; ++i, ++dat){
- ((uint*)image.bits())[i] = *dat;
- }
- icon.addPixmap(QPixmap::fromImage(image)); //layer this pixmap onto the icon
- //Now see if there are any more icons available
- done = (iter.rem<1); //number of icons remaining
- if(!done){ xcb_ewmh_get_wm_icon_next(&iter); } //get the next icon data
- }
- xcb_ewmh_get_wm_icon_reply_wipe(&reply);
- }
- } //end type of window
- win->setProperty(NativeWindow::Icon, icon);
- } //end ICON property
-
- if(props.contains(NativeWindow::MinSize) || props.contains(NativeWindow::MaxSize)
- || props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){
- //Try the ICCCM "Normal Hints" structure first (newer spec?)
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_normal_hints_unchecked(QX11Info::connection(), win->id());
- xcb_size_hints_t reply;
- bool ok = false;
- if(1==xcb_icccm_get_wm_normal_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; }
- else{
- //Could not find normal hints, try the older "size hints" instead
- cookie = xcb_icccm_get_wm_size_hints_unchecked(QX11Info::connection(), win->id(), XCB_ATOM_WM_SIZE_HINTS);
- if(1==xcb_icccm_get_wm_size_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; }
- }
- if(ok){
- bool initsize = win->property(NativeWindow::Size).isNull(); //initial window size
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_POSITION)==XCB_ICCCM_SIZE_HINT_US_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_SIZE)==XCB_ICCCM_SIZE_HINT_US_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_POSITION)==XCB_ICCCM_SIZE_HINT_P_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_SIZE)==XCB_ICCCM_SIZE_HINT_P_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)==XCB_ICCCM_SIZE_HINT_P_MIN_SIZE ){ win->setProperty(NativeWindow::MinSize, QSize(reply.min_width, reply.min_height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)==XCB_ICCCM_SIZE_HINT_P_MAX_SIZE ){ win->setProperty(NativeWindow::MaxSize, QSize(reply.max_width, reply.max_height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_BASE_SIZE)==XCB_ICCCM_SIZE_HINT_BASE_SIZE && initsize ){ win->setProperty(NativeWindow::Size, QSize(reply.base_width, reply.base_height)); }
- //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)==XCB_ICCCM_SIZE_HINT_P_RESIZE_INC ){ hints.width_inc=reply.width_inc; hints.height_inc=reply.height_inc; }
- //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_ASPECT)==XCB_ICCCM_SIZE_HINT_P_ASPECT ){ hints.min_aspect_num=reply.min_aspect_num; hints.min_aspect_den=reply.min_aspect_den; hints.max_aspect_num=reply.max_aspect_num; hints.max_aspect_den=reply.max_aspect_den;}
- //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)==XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY ){ hints.win_gravity=reply.win_gravity; }
- }
- } //end of geometry properties
-
- if(props.contains(NativeWindow::Name)){
- //Put the app/class name here (much more static than the "Title" properties
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win->id());
- xcb_icccm_get_wm_class_reply_t reply;
- if(1 == xcb_icccm_get_wm_class_reply(QX11Info::connection(), cookie, &reply, NULL) ){
- //Returns: "<instance name>::::<class name>"
- win->setProperty(NativeWindow::Name, ( QString::fromLocal8Bit(reply.instance_name)+"::::"+QString::fromLocal8Bit(reply.class_name) ));
- xcb_icccm_get_wm_class_reply_wipe(&reply);
- }
- } //end NAME property
-
- if(props.contains(NativeWindow::Workspace)){
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&obj->EWMH, win->id());
- uint32_t num = 0;
- int wkspace = -1;
- if(1==xcb_ewmh_get_wm_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){
- if(num!=0xFFFFFFFF){ wkspace = num; }
- }/*else{
- //Error in fetching property (not set?)
- // - put it on the current screen
- out = WM_Get_Current_Desktop();
- }*/
- win->setProperty(NativeWindow::Workspace, wkspace);
- }
- if(props.contains(NativeWindow::FrameExtents)){
- //Just assign default values to this - need to automate it later
- //win->setProperty(NativeWindow::FrameExtents, QVariant::fromValue<QList<int> >(QList<int>() << 5 << 5 << 5+QFontMetrics(QFont()).height() << 5) );
- }
- if(props.contains(NativeWindow::RelatedWindows)){
- WId orig = win->id();
- WId tid = obj->getTransientFor(orig);
- QList<WId> list;
- while(tid != orig){
- list << tid;
- orig = tid;
- tid = obj->getTransientFor(orig);
- }
- win->setProperty(NativeWindow::RelatedWindows, QVariant::fromValue(list));
- }
- if(props.contains(NativeWindow::Visible)){
- xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), xcb_get_window_attributes(QX11Info::connection(), win->id()) , NULL);
- if(attr != 0){
- win->setProperty(NativeWindow::Visible, attr->map_state == XCB_MAP_STATE_VIEWABLE);
- free(attr);
- }
- }
- if(props.contains(NativeWindow::WinTypes)){
- QList< NativeWindow::Type> types;
- types << NativeWindow::T_NORMAL; //make this load appropriately later
- win->setProperty(NativeWindow::WinTypes, QVariant::fromValue< QList<NativeWindow::Type> >(types) );
- }
-}
-
-void NativeWindowSystem::ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList<QVariant> vals){
- if(props.length() == 0 || vals.length()!=props.length() || win ==0 ){ return; }
- //qDebug() << "Change Window Properties:" << props << vals;
- if(props.contains(NativeWindow::Title)){
-
- }
- if(props.contains(NativeWindow::ShortTitle)){
-
- }
- if(props.contains(NativeWindow::Icon)){
-
- }
- if(props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){
- xcb_configure_window_value_list_t valList;
- valList.x = 0; //Note that this is the relative position - should always be 0,0 relative to the embed widget
- valList.y = 0;
- QSize sz = win->property(NativeWindow::Size).toSize();
- if(props.contains(NativeWindow::Size)){
- sz = vals[ props.indexOf(NativeWindow::Size) ] .toSize();
- }
- valList.width = sz.width();
- valList.height = sz.height();
- /*if(props.contains(NativeWindow::GlobalPos)){
- QPoint pt = vals[ props.indexOf(NativeWindow::GlobalPos) ] .toPoint();
- valList.x = pt.x();
- valList.y = pt.y();
- }else{
- valList.x = win->property(NativeWindow::GlobalPos).toPoint().x();
- valList.y = win->property(NativeWindow::GlobalPos).toPoint().y();
- }*/
- uint16_t mask = 0;
- mask = mask | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;// | XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
- qDebug() << "Configure window Geometry:" << sz;
- xcb_configure_window_aux(QX11Info::connection(), win->id(), mask, &valList);
- }
- if(props.contains(NativeWindow::Name)){
-
- }
- if(props.contains(NativeWindow::Workspace)){
- int num = vals[ props.indexOf(NativeWindow::Workspace) ].toInt();
- xcb_ewmh_set_wm_desktop(&obj->EWMH, win->id(), (num<0 ? 0xFFFFFFFF : qAbs(num) ) );
- }
- if(props.contains(NativeWindow::RelatedWindows)){
-
- }
- if(props.contains(NativeWindow::Visible)){
- //qDebug() << "Check Window Visibility:" << vals[ props.indexOf(NativeWindow::Visible) ];
- if( vals[ props.indexOf(NativeWindow::Visible) ].toBool() ){
- //qDebug() << " - Map it!";
- xcb_map_window(QX11Info::connection(), win->id());
- }else{
- //qDebug() << " - Unmap it!";
- xcb_unmap_window(QX11Info::connection(), win->id());
- }
- }
- if(props.contains(NativeWindow::Active)){
- //Only one window can be "Active" at a time - so only do anything if this window wants to be active
- if(vals[props.indexOf(NativeWindow::Active)].toBool() ){
- xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), (win->frameId()==0 ?win->id() : win->frameId()));
- //Also send the active window a message to take input focus
- //Send the window a WM_TAKE_FOCUS message
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win->id();
- event.type = obj->ATOMS["WM_PROTOCOLS"];
- event.data.data32[0] = obj->ATOMS["WM_TAKE_FOCUS"];
- event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[2] = 0;
- event.data.data32[3] = 0;
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, win->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- xcb_flush(QX11Info::connection());
- }
- }
-
-}
-
-// === PUBLIC SLOTS ===
-//These are the slots which are typically only used by the desktop system itself or the NativeEventFilter
-void NativeWindowSystem::RegisterVirtualRoot(WId id){
- //Convert to XCB array
- xcb_window_t array[1];
- array[0] = id;
- //Set the property
- xcb_ewmh_set_virtual_roots(&obj->EWMH, QX11Info::appScreen(), 1, array);
-}
-
-void NativeWindowSystem::setRoot_supportedActions(){
-//NET_WM standards (ICCCM implied - no standard way to list those)
- xcb_atom_t list[] = {obj->EWMH._NET_WM_NAME,
- obj->EWMH._NET_WM_ICON,
- obj->EWMH._NET_WM_ICON_NAME,
- obj->EWMH._NET_WM_DESKTOP,
- obj->ATOMS["_NET_WM_WINDOW_OPACITY"],
- /*_NET_WINDOW_TYPE (and all the various types - 15 in total*/
- obj->EWMH._NET_WM_WINDOW_TYPE, obj->EWMH._NET_WM_WINDOW_TYPE_DESKTOP, obj->EWMH._NET_WM_WINDOW_TYPE_DOCK,
- obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, obj->EWMH._NET_WM_WINDOW_TYPE_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY,
- obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH, obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG, obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL,
- obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP,
- obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, obj->EWMH._NET_WM_WINDOW_TYPE_COMBO, obj->EWMH._NET_WM_WINDOW_TYPE_DND,
- };
- xcb_ewmh_set_supported(&obj->EWMH, QX11Info::appScreen(), 20,list);
-}
-
-void NativeWindowSystem::setRoot_numberOfWorkspaces(QStringList names){
- if(names.isEmpty()){ names << "one"; }
- //First set the overall number of workspaces
- xcb_ewmh_set_number_of_desktops(&obj->EWMH, QX11Info::appScreen(), names.length());
- //Now set the names for the workspaces
- //EWMH LIBRARY BROKEN - appears to be a mismatch in the function header (looking for a single char array, instead of a list of char arrays)
- // Ken Moore - 6/27/17
- /*
- char *array[ names.length() ];
- for(int i=0; i<names.length(); i++){array[i] = names[i].toUtf8().data(); } //Convert to an array of char arrays
- xcb_ewmh_set_desktop_names(&obj->EWMH, QX11Info::appScreen(), names.length(), array);
- */
-}
-
-void NativeWindowSystem::setRoot_currentWorkspace(int num){
- xcb_ewmh_set_current_desktop(&obj->EWMH, QX11Info::appScreen(), num);
-}
-
-void NativeWindowSystem::setRoot_clientList(QList<WId> list, bool stackorder){
- //convert the QList into a generic array
- xcb_window_t array[list.length()];
- for(int i=0; i<list.length(); i++){ array[i] = list[i]; }
- if(stackorder){
- xcb_ewmh_set_client_list_stacking(&obj->EWMH, QX11Info::appScreen(), list.length(), array);
- }else{
- xcb_ewmh_set_client_list(&obj->EWMH, QX11Info::appScreen(), list.length(), array);
- }
-}
-
-void NativeWindowSystem::setRoot_desktopGeometry(QRect geom){
- //This one is a combo function
- // This will set the "DESKTOP_VIEWPORT" property (point)
- // as well as the "DESKTOP_GEOMETRY" property (size)
- //Turn the QList into xcb_ewmh_coordinates_t*
- xcb_ewmh_coordinates_t array[1];
- array[0].x=geom.x(); array[0].y=geom.y();
- //Now set the property
- xcb_ewmh_set_desktop_viewport(&obj->EWMH, QX11Info::appScreen(), 1, array);
- xcb_ewmh_set_desktop_geometry(&obj->EWMH, QX11Info::appScreen(), geom.width(), geom.height());
-}
-
-void NativeWindowSystem::setRoot_desktopWorkarea(QList<QRect> list){
- //Convert to the XCB/EWMH data structures
- xcb_ewmh_geometry_t array[list.length()];
- for(int i=0; i<list.length(); i++){
- array[i].x = list[i].x(); array[i].y = list[i].y();
- array[i].width = list[i].width(); array[i].height = list[i].height();
- }
- //Now set the property
- xcb_ewmh_set_workarea(&obj->EWMH, QX11Info::appScreen(), list.length(), array);
-}
-
-void NativeWindowSystem::setRoot_activeWindow(WId win){
- xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win);
- //Also send the active window a message to take input focus
- //Send the window a WM_TAKE_FOCUS message
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win;
- event.type = obj->ATOMS["WM_PROTOCOLS"];
- event.data.data32[0] = obj->ATOMS["WM_TAKE_FOCUS"];
- event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[2] = 0;
- event.data.data32[3] = 0;
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- xcb_flush(QX11Info::connection());
-}
-
-int NativeWindowSystem::currentWorkspace(){
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop_unchecked(&obj->EWMH, QX11Info::appScreen());
- uint32_t num = 0;
- if(1==xcb_ewmh_get_current_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){
- return num;
- }else{
- return 0;
- }
-}
-
-//NativeWindowEventFilter interactions
-void NativeWindowSystem::NewWindowDetected(WId id){
- //Make sure this can be managed first
- if(findWindow(id, false) != 0){ qDebug() << "Window Already Managed!!!!"; findWindow(id,false)->setProperty(NativeWindow::Visible, true, true); return; } //already managed
- xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id);
- xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL);
- if(attr == 0){ return; } //could not get attributes of window
- if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage)
- free(attr);
- //Now go ahead and create/populate the container for this window
- NativeWindow *win = new NativeWindow(id);
- //Register for events from this window
- registerClientEvents(win->id());
- NWindows << win;
- UpdateWindowProperties(win, NativeWindow::allProperties());
- qDebug() << "New Window [& associated ID's]:" << win->id() << win->frameId() << win->property(NativeWindow::RelatedWindows);
- //Now setup the connections with this window
- connect(win, SIGNAL(RequestClose(WId)), this, SLOT(RequestClose(WId)) );
- connect(win, SIGNAL(RequestKill(WId)), this, SLOT(RequestKill(WId)) );
- connect(win, SIGNAL(RequestPing(WId)), this, SLOT(RequestPing(WId)) );
- connect(win, SIGNAL(RequestReparent(WId, WId, QPoint)), this, SLOT(RequestReparent(WId, WId, QPoint)) );
- connect(win, SIGNAL(RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>)), this, SLOT(RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>)) );
- emit NewWindowAvailable(win);
-}
-
-void NativeWindowSystem::NewTrayWindowDetected(WId id){
- //Make sure this can be managed first
- if(findTrayWindow(id) != 0){ return; } //already managed
- xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id);
- xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL);
- if(attr == 0){ return; } //could not get attributes of window
- if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage)
- free(attr);
- //Register for events from this window
- #define TRAY_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_BUTTON_MOTION | \
- XCB_EVENT_MASK_EXPOSURE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_ENTER_WINDOW)
-
- uint32_t value_list[1] = {TRAY_WIN_EVENT_MASK};
- xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list);
- //Now go ahead and create/populate the container for this window
- NativeWindow *win = new NativeWindow(id);
- TWindows << win;
- UpdateWindowProperties(win, NativeWindow::allProperties());
- emit NewTrayWindowAvailable(win);
-}
-
-void NativeWindowSystem::WindowCloseDetected(WId id){
- NativeWindow *win = findWindow(id, false);
- //qDebug() << "Got Window Closed" << id << win;
- //qDebug() << "Old Window List:" << NWindows.length();
- if(win!=0){
- NWindows.removeAll(win);
- //RequestReparent(id, QX11Info::appRootWindow(), QPoint(0,0));
- win->emit WindowClosed(id);
- //qDebug() << "Visible Window Closed!!!";
- //win->deleteLater();
- }else{
- win = findTrayWindow(id);
- if(win!=0){
- TWindows.removeAll(win);
- win->emit WindowClosed(id);
- win->deleteLater();
- }
- }
- //qDebug() << " - Now:" << NWindows.length();
-}
-
-void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop){
- //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves
- NativeWindow *win = findWindow(id, prop!=NativeWindow::Visible);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- UpdateWindowProperties(win, QList<NativeWindow::Property>() << prop);
- }
-}
-
-void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop, QVariant val){
- NativeWindow *win = findWindow(id,prop!=NativeWindow::Visible);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- win->setProperty(prop, val);
- }
-}
-
-void NativeWindowSystem::WindowPropertiesChanged(WId id, QList<NativeWindow::Property> props, QList<QVariant> vals){
- NativeWindow *win = findWindow(id);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- for(int i=0; i<props.length() && i<vals.length(); i++){ win->setProperty(props[i], vals[i]); }
- }
-}
-
-void NativeWindowSystem::RequestPropertyChange(WId id, NativeWindow::Property prop, QVariant val){
- //This is just a simplified version of the multiple-property function
- RequestPropertiesChange(id, QList<NativeWindow::Property>() << prop, QList<QVariant>() << val);
-}
-
-void NativeWindowSystem::RequestPropertiesChange(WId win, QList<NativeWindow::Property> props, QList<QVariant> vals){
- //Find the window object associated with this id
- bool istraywin = false; //just in case we care later if it is a tray window or a regular window
- NativeWindow *WIN = findWindow(win);
- if(WIN==0){ istraywin = true; WIN = findTrayWindow(win); }
- if(WIN==0){ return; } //invalid window ID - no longer available
- //Now make any changes as needed
- ChangeWindowProperties(WIN, props, vals);
-}
-
-void NativeWindowSystem::GotPong(WId id){
- if(waitingForPong.contains(id)){
- waitingForPong.remove(id);
- }
- if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); }
-}
-
-void NativeWindowSystem::NewKeyPress(int keycode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- Qt::Key key = KeycodeToQt(keycode);
- if(key!=Qt::Key_unknown){ emit KeyPressDetected(win, key); }
-}
-
-void NativeWindowSystem::NewKeyRelease(int keycode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- Qt::Key key = KeycodeToQt(keycode);
- if(key!=Qt::Key_unknown){ emit KeyReleaseDetected(win, key); }
-}
-
-void NativeWindowSystem::NewMousePress(int buttoncode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- emit MousePressDetected(win, MouseToQt(buttoncode));
-}
-
-void NativeWindowSystem::NewMouseRelease(int buttoncode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- emit MouseReleaseDetected(win, MouseToQt(buttoncode));
-}
-
-void NativeWindowSystem::CheckDamageID(WId win){
- for(int i=0; i<NWindows.length(); i++){
- if(NWindows[i]->damageId() == win || NWindows[i]->id() == win || NWindows[i]->frameId()==win){
- NWindows[i]->emit VisualChanged();
- //qDebug() << "Got DAMAGE Event";
- return;
- }
- }
- NativeWindow *WIN = findTrayWindow(win);
- if(WIN!=0){
- UpdateWindowProperties(WIN, QList<NativeWindow::Property>() << NativeWindow::Icon);
- }
-}
-
-// === PRIVATE SLOTS ===
-//These are the slots which are built-in and automatically connected when a new NativeWindow is created
-
-void NativeWindowSystem::RequestClose(WId win){
- //Send the window a WM_DELETE_WINDOW message
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win;
- event.type = obj->ATOMS.value("WM_PROTOCOLS");
- event.data.data32[0] = obj->ATOMS.value("WM_DELETE_WINDOW");
- event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[2] = 0;
- event.data.data32[3] = 0;
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- xcb_flush(QX11Info::connection());
-}
-
-void NativeWindowSystem::RequestKill(WId win){
- xcb_kill_client(QX11Info::connection(), win);
-}
-
-void NativeWindowSystem::RequestPing(WId win){
- waitingForPong.insert(win, QDateTime::currentDateTime().addSecs(5) );
- xcb_ewmh_send_wm_ping(&obj->EWMH, win, XCB_CURRENT_TIME);
- if(pingTimer==0){
- pingTimer = new QTimer(this);
- pingTimer->setInterval(2000); //2seconds
- connect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPings()) );
- }
- pingTimer->start();
-}
-
-void NativeWindowSystem::RequestReparent(WId win, WId container, QPoint relorigin){
- NativeWindow *WIN = findWindow(win);
- if(WIN==0){ return; } //could not find corresponding window structure
-//Reparent the window into the container
- xcb_reparent_window(QX11Info::connection(), win, container, relorigin.x(), relorigin.y());
- //xcb_map_window(QX11Info::connection(), win);
-
- //Now send the embed event to the app
- //qDebug() << " - send _XEMBED event";
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win;
- event.type = obj->ATOMS["_XEMBED"]; //_XEMBED
- event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY
- event.data.data32[2] = 0;
- event.data.data32[3] = container; //WID of the container
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
-
- //Now setup any redirects and return
- //this->SelectInput(win, true); //Notify of structure changes
- registerClientEvents(win);
- //xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]);
-
- //Now map the window (will be a transparent child of the container)
- xcb_map_window(QX11Info::connection(), win);
- xcb_map_window(QX11Info::connection(), container);
- //Now create/register the damage handler
- // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore)
- // -- Retested 6/29/17 (no change) Ken Moore
- //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer
- //xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
- // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself).
- Damage dmgID = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
- WIN->addDamageID( (uint) dmgID); //save this for later
- //qDebug() << " - Done";
- //return ( (uint) dmgID );
-}
-/*
- xcb_reparent_window(QX11Info::connection(), client, parent, relorigin.x(), relorigin.y());
-
- //Now ensure that we still get event for these windows
- registerClientEvents(client); //make sure we re-do this after reparenting
- registerClientEvents(parent);
- xcb_map_window(QX11Info::connection(), parent);
-}*/
diff --git a/src-qt5/core/libLumina/NativeWindowSystem.h b/src-qt5/core/libLumina/NativeWindowSystem.h
deleted file mode 100644
index 97208c2f..00000000
--- a/src-qt5/core/libLumina/NativeWindowSystem.h
+++ /dev/null
@@ -1,138 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This is a Qt5/Lumina wrapper around native graphics system calls
-// It is primarily designed around the creation/modification of instances of
-// the "NativeWindow" class for passing information around
-//===========================================
-#ifndef _LUMINA_NATIVE_WINDOW_SYSTEM_H
-#define _LUMINA_NATIVE_WINDOW_SYSTEM_H
-
-#include "NativeWindow.h"
-#include <QDateTime>
-#include <QTimer>
-#include <QDebug>
-
-class NativeWindowSystem : public QObject{
- Q_OBJECT
-private:
- QList<NativeWindow*> NWindows;
- QList<NativeWindow*> TWindows;
-
- //Simplifications to find an already-created window object
- NativeWindow* findWindow(WId id, bool checkRelated = true);
-
- NativeWindow* findTrayWindow(WId id);
-
- //Now define a simple private_objects class so that each implementation
- // has a storage container for defining/placing private objects as needed
- class p_objects;
- p_objects* obj;
-
- //Internal timers/variables for managing pings
- QTimer *pingTimer;
- QHash<WId, QDateTime> waitingForPong;
- void checkPings(){
- QDateTime cur = QDateTime::currentDateTime();
- QList<WId> waiting = waitingForPong.keys();
- for(int i=0; i<waiting.length(); i++){
- if(waitingForPong.value(waiting[i]) < cur){
- waitingForPong.remove(waiting[i]); //Timeout on this window
- if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); }
- NativeWindow *win = findWindow(waiting[i]);
- if(win==0){ win = findTrayWindow(waiting[i]); }
- if(win!=0){ win->emit WindowNotResponding(waiting[i]); }
- }
- }
- }
-
- // Since some properties may be easier to update in bulk
- // let the native system interaction do them in whatever logical groups are best
- void UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props);
- void ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList<QVariant> vals);
-
- //Generic private variables
- bool screenLocked;
-
-public:
- //enum Property{ None, CurrentWorkspace, Workspaces, VirtualRoots, WorkAreas };
- enum MouseButton{NoButton, LeftButton, RightButton, MidButton, BackButton, ForwardButton, TaskButton, WheelUp, WheelDown, WheelLeft, WheelRight};
-
- NativeWindowSystem();
- ~NativeWindowSystem();
-
- //Overarching start/stop functions
- bool start();
- void stop();
-
- //General-purpose listing functions
- QList<NativeWindow*> currentWindows(){ return NWindows; }
- QList<NativeWindow*> currentTrayWindows(){ return TWindows; }
-
- //Small simplification functions
- static Qt::Key KeycodeToQt(int keycode);
- static NativeWindowSystem::MouseButton MouseToQt(int button);
-
-public slots:
- //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter
-
- //This is called by the lock screen to keep the NWS aware of the current status
- // it is **NOT** the function to call for the user to actually lock the session (that is in the screensaver/lockscreen class)
- void ScreenLockChanged(bool lock){
- screenLocked = lock;
- }
-
- //Root Window property registrations
- void RegisterVirtualRoot(WId);
- void setRoot_supportedActions();
- void setRoot_numberOfWorkspaces(QStringList names);
- void setRoot_currentWorkspace(int);
- void setRoot_clientList(QList<WId>, bool stackorder = false);
- void setRoot_desktopGeometry(QRect);
- void setRoot_desktopWorkarea(QList<QRect>);
- void setRoot_activeWindow(WId);
-
- // - Workspaces
- int currentWorkspace();
- //void GoToWorkspace(int);
-
-
- //NativeWindowEventFilter interactions
- void NewWindowDetected(WId); //will automatically create the new NativeWindow object
- void NewTrayWindowDetected(WId); //will automatically create the new NativeWindow object
- void WindowCloseDetected(WId); //will update the lists and make changes if needed
- void WindowPropertyChanged(WId, NativeWindow::Property); //will rescan the window and update the object as needed
- void WindowPropertyChanged(WId, NativeWindow::Property, QVariant); //will save that property/value to the right object
- void WindowPropertiesChanged(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void RequestPropertyChange(WId, NativeWindow::Property, QVariant);
- void RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void GotPong(WId);
-
- void NewKeyPress(int keycode, WId win = 0);
- void NewKeyRelease(int keycode, WId win = 0);
- void NewMousePress(int buttoncode, WId win = 0);
- void NewMouseRelease(int buttoncode, WId win = 0);
- void CheckDamageID(WId);
-
-private slots:
- //These are the slots which are built-in and automatically connected when a new NativeWindow is created
- void RequestClose(WId);
- void RequestKill(WId);
- void RequestPing(WId);
- void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent
-
-signals:
- void NewWindowAvailable(NativeWindow*);
- void NewTrayWindowAvailable(NativeWindow*);
- void NewInputEvent(); //a mouse or keypress was detected (lock-state independent);
- void KeyPressDetected(WId, Qt::Key); //only emitted if lockstate = false
- void KeyReleaseDetected(WId, Qt::Key); //only emitted if lockstate = false
- void MousePressDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false
- void MouseReleaseDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false
-
-};
-
-#endif
diff --git a/src-qt5/core/libLumina/OSInterface-template.cpp b/src-qt5/core/libLumina/OSInterface-template.cpp
deleted file mode 100644
index 96b01e60..00000000
--- a/src-qt5/core/libLumina/OSInterface-template.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//===========================================
-// Lumina desktop source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include <OSInterface.h>
-
-//===========
-// PUBLIC
-//===========
-
-//Simple functions used to determine if the current OS supports using this class, and what levels of support
-QList<OSInterface::Interface> OSInterface::supportedNotifications(){
- //Which interfaces provide change notifications
- return QList< OSInterface::Interface >();
-}
-
-QList<OSInterface::Interface> OSInterface::supportedStatus(){
- //Which interfaces are available for "status" requests
- return QList< OSInterface::Interface >();
-}
-
-QList<OSInterface::Interface> OSInterface::supportedModify(){
- //Which interfaces are available for "modify" requests
- return QList< OSInterface::Interface >();
-}
-
-//Start/stop interface watchers/notifications (each only called once per session)
-void OSInterface::start(){
- //nothing to do
-}
-
-void OSInterface::stop(){
- //nothing to do
-}
-
-//Generic status update
-QList<QVariant> OSInterface::status(OSInterface::Interface){
- // ==== Interface status output lists ====
- // Battery: [ float (percent charge), bool (is Charging), double (seconds remaining) ];
- // Volume: [int (percent volume) ]
- // Devices: [ QStringList[ name, mountpoint, type (optional)] ] (List length depends on number of devices)
- // Network: [bool (network access available)]
- // PowerOff: [bool (can power off system)]
- // Reboot: [bool (can reboot system)]
- // Suspend: [bool (can suspend system)]
- // Updates: [bool (is updating), bool (reboot required)]
- // ==========
- return QList<QVariant>();
-}
-
-//Individual Interface interactions
-bool OSInterface::modify(OSInterface::Interface, QList<QVariant>){ //returns: success/failure
- // ==== Interface modification argument lists ====
- // Battery: <NO MODIFICATION>
- // Volume: [int (set percent volume) ]
- // Devices: <NO MODIFICATION>
- // Network: <NO MODIFICATION>
- // PowerOff: [bool (skip updates - optional)]
- // Reboot: [bool (skip updates - optional)]
- // Suspend: [] (No input arguments)
- // Updates: <NO MODIFICATION>
- // ==========
- return false;
-}
-
-//=================
-// PRIVATE SLOTS
-//=================
-//FileSystemWatcher slots
-void OSInterface::watcherFileChanged(QString){
-
-}
-
-void OSInterface::watcherDirChanged(QString){
-
-}
-
-//IO Device slots
-void OSInterface::iodeviceReadyRead(){
-
-}
-
-void OSInterface::iodeviceAboutToClose(){
-
-}
-
-//NetworkAccessManager slots
-void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility){
-
-}
-
-void OSInterface::netRequestFinished(QNetworkReply*){
-
-}
-
-void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){
-
-}
diff --git a/src-qt5/core/libLumina/OSInterface.h b/src-qt5/core/libLumina/OSInterface.h
deleted file mode 100644
index acbd5c38..00000000
--- a/src-qt5/core/libLumina/OSInterface.h
+++ /dev/null
@@ -1,136 +0,0 @@
-//===========================================
-// Lumina desktop source code
-// Copyright (c) 2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This is the main interface for any OS-specific system calls
-// To port Lumina to a different operating system, just create a file
-// called "OSInterface-<Operating System>.cpp"
-//===========================================
-#ifndef _LUMINA_LIBRARY_OS_INTERFACE_H
-#define _LUMINA_LIBRARY_OS_INTERFACE_H
-
-#include <QString>
-#include <QStringList>
-#include <QList>
-#include <QObject>
-#include <QVariant>
-#include <QHash>
-
-#include <QIODevice>
-#include <QFileSystemWatcher>
-#include <QNetworkAccessManager>
-#include <QNetworkReply>
-#include <QSslError>
-
-class OSInterface : public QObject{
- Q_OBJECT
-
-public:
- enum Interface{ Battery, Volume, Devices, Network, PowerOff, Reboot, Suspend, Updates };
-
-private slots:
- //FileSystemWatcher slots
- void watcherFileChanged(QString);
- void watcherDirChanged(QString);
- //IO Device slots
- void iodeviceReadyRead();
- void iodeviceAboutToClose();
- //NetworkAccessManager slots
- void netAccessChanged(QNetworkAccessManager::NetworkAccessibility);
- void netRequestFinished(QNetworkReply*);
- void netSslErrors(QNetworkReply*, const QList<QSslError>&);
-
-private:
- //Internal persistant data storage, OS-specific usage implementation
- QHash< OSInterface::Interface, QList<QVariant> > INFO;
-
- // ============
- // Internal possibilities for watching the system (OS-Specific usage/implementation)
- // ============
- //File System Watcher
- QFileSystemWatcher *watcher;
- //IO Device (QLocalSocket, QTcpConnection, QFile, etc)
- QIODevice *iodevice;
- //Network Access Manager (check network connectivity, etc)
- QNetworkAccessManager *netman;
-
- //Simplifications for connecting the various watcher objects to their respective slots
- void connectWatcher(){
- if(watcher==0){ return; }
- connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherFileChanged(QString)) );
- connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(watcherDirChanged(QString)) );
- }
- void connectIodevice(){
- if(iodevice==0){ return; }
- connect(iodevice, SIGNAL(readyRead()), this, SLOT(iodeviceReadyRead()) );
- }
- void connectNetman(){
- if(netman==0){ return; }
- connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(netAccessChanged(QNetworkAccessManager::NetworkAccessibility)) );
- connect(netman, SIGNAL(requestFinished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*)) );
- connect(netman, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(netSslErrors(QNetworkReply*, const QList<QSslError>&)) );
- }
-
-public:
- OSInterface(QObject *parent = 0) : QObject(parent){
- watcher = 0;
- iodevice = 0;
- netman = 0;
- }
- ~OSInterface(){
- if(watcher!=0){
- QStringList paths; paths << watcher->files() << watcher->directories();
- if(!paths.isEmpty()){ watcher->removePaths(paths); }
- watcher->deleteLater();
- }
- if(iodevice!=0){
- if(iodevice->isOpen()){ iodevice->close(); }
- iodevice->deleteLater();
- }
- if(netman!=0){
- netman->deleteLater();
- }
- }
-
- //Simple functions used to determine if the current OS supports using this class, and what levels of support
- QList<OSInterface::Interface> supportedNotifications(); //Which interfaces provide change notifications
- QList<OSInterface::Interface> supportedStatus(); //Which interfaces are available for "status" requests
- QList<OSInterface::Interface> supportedModify(); //Which interfaces are available for "modify" requests
-
- //Start/stop interface watchers/notifications (each only called once per session)
- void start();
- void stop();
-
- //Generic status update
- QList<QVariant> status(OSInterface::Interface);
- // ==== Interface status output lists ====
- // Battery: [ float (percent charge), bool (is Charging), double (seconds remaining) ];
- // Volume: [int (percent volume) ]
- // Devices: [ QStringList[ name, mountpoint, type (optional)] ] (List length depends on number of devices)
- // Network: [bool (network access available)]
- // PowerOff: [bool (can power off system)]
- // Reboot: [bool (can reboot system)]
- // Suspend: [bool (can suspend system)]
- // Updates: [bool (is updating), bool (reboot required)]
- // ==========
-
- //Individual Interface interactions
- bool modify(OSInterface::Interface, QList<QVariant> args); //returns: success/failure
- // ==== Interface modification argument lists ====
- // Battery: <NO MODIFICATION>
- // Volume: [int (set percent volume) ]
- // Devices: <NO MODIFICATION>
- // Network: <NO MODIFICATION>
- // PowerOff: [bool (skip updates - optional)]
- // Reboot: [bool (skip updates - optional)]
- // Suspend: [] (No input arguments)
- // Updates: <NO MODIFICATION>
- // ==========
-
-signals:
- void interfaceChanged(OSInterface::Interface);
-
-};
-#endif
diff --git a/src-qt5/core/libLumina/ResizeMenu.cpp b/src-qt5/core/libLumina/ResizeMenu.cpp
index 9f291134..cf5b124d 100644
--- a/src-qt5/core/libLumina/ResizeMenu.cpp
+++ b/src-qt5/core/libLumina/ResizeMenu.cpp
@@ -5,6 +5,7 @@
// See the LICENSE file for full details
//===========================================
#include "ResizeMenu.h"
+#include <QDebug>
// =======================
// RESIZEMENU CLASS
@@ -21,7 +22,7 @@ ResizeMenu::ResizeMenu(QWidget *parent) : QMenu(parent){
}
ResizeMenu::~ResizeMenu(){
-
+
}
void ResizeMenu::setContents(QWidget *con){
@@ -30,6 +31,15 @@ void ResizeMenu::setContents(QWidget *con){
this->addAction(cAct);
contents = con; //save for later
contents->setCursor(Qt::ArrowCursor);
+ resyncSize();
+}
+
+void ResizeMenu::resyncSize(){
+ if(contents==0){ return; }
+ qDebug() << "Resync Size:" << this->size() << contents->size();
+ this->resize(contents->size());
+ qDebug() << " - after menu resize:" << this->size() << contents->size();
+ emit MenuResized(this->size());
}
void ResizeMenu::mouseMoveEvent(QMouseEvent *ev){
@@ -46,21 +56,21 @@ void ResizeMenu::mouseMoveEvent(QMouseEvent *ev){
this->setGeometry(geom);
if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));}
handled = true;
- break;
+ break;
case BOTTOM:
if(gpos.y() <= geom.top()+1){ break; }
geom.setBottom( gpos.y());
this->setGeometry(geom);
if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));}
handled = true;
- break;
+ break;
case LEFT:
if(gpos.x() >= geom.right()-1){ break; }
geom.setLeft(gpos.x());
this->setGeometry(geom);
if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));}
handled = true;
- break;
+ break;
case RIGHT:
if(gpos.x() <= geom.left()+1){ break; }
geom.setRight(gpos.x());
diff --git a/src-qt5/core/libLumina/ResizeMenu.h b/src-qt5/core/libLumina/ResizeMenu.h
index ed909da3..029d2716 100644
--- a/src-qt5/core/libLumina/ResizeMenu.h
+++ b/src-qt5/core/libLumina/ResizeMenu.h
@@ -17,7 +17,7 @@
#include <QPoint>
//Special subclass for a menu which the user can grab the edges and resize as necessary
-// Note: Make sure that you don't set 0pixel contents margins on this menu
+// Note: Make sure that you don't set 0pixel contents margins on this menu
// - it needs at least 1 pixel margins for the user to be able to grab it
class ResizeMenu : public QMenu{
Q_OBJECT
@@ -26,13 +26,14 @@ public:
virtual ~ResizeMenu();
void setContents(QWidget *con);
+ void resyncSize();
private:
enum SideFlag{NONE, TOP, BOTTOM, LEFT, RIGHT};
SideFlag resizeSide;
QWidget *contents;
QWidgetAction *cAct;
-
+
private slots:
void clearFlags(){
resizeSide=NONE;
diff --git a/src-qt5/core/libLumina/RootWindow-mgmt.cpp b/src-qt5/core/libLumina/RootWindow-mgmt.cpp
deleted file mode 100644
index 00b3e336..00000000
--- a/src-qt5/core/libLumina/RootWindow-mgmt.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2016, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include "RootWindow.h"
-
-//Primary/private function
-void RootWindow::arrangeWindows(RootSubWindow *primary, QString type){
- if(primary==0){
- //Get the currently active window and treat that as the primary
-
- }
- //Now loop over the windows and arrange them as needed
-
-}
-
-// ================
-// Public slots for starting the arrangement routine(s) above
-// ================
-void RootWindow::ArrangeWindows(WId primary, QString type){
- RootSubWindow* win = windowForId(primary);
- if(type.isEmpty()){ type = ""; } //grab the default arrangement format
- arrangeWindows(win, type);
-}
-
-void RootWindow::TileWindows(WId primary, QString type){
- RootSubWindow* win = windowForId(primary);
- if(type.isEmpty()){ type = ""; } //grab the default arrangement format for tiling
- arrangeWindows(win, type);
-}
-
-void RootWindow::CheckWindowPosition(WId id, bool newwindow){
- //used after a "drop" to validate/snap/re-arrange window(s) as needed
- // if "newwindow" is true, then this is the first-placement routine for a window before it initially appears
- RootSubWindow* win = windowForId(id);
- if(win==0){ return; } //invalid window
- QRect geom = win->nativeWindow()->geometry();
- bool changed = false;
- //Make sure it is on the screen (quick check)
- if(geom.x() < 0){ changed = true; geom.moveLeft(0); }
- if(geom.y() < 0){ changed = true; geom.moveTop(0); }
- if(geom.width() < 20){ changed = true; geom.setWidth(100); }
- if(geom.height() < 20){ changed = true; geom.setHeight(100); }
- if(changed){ win->setGeometry(geom); }
- //Now run it through the window arrangement routine
- ArrangeWindows(id);
-}
diff --git a/src-qt5/core/libLumina/XDGMime.cpp b/src-qt5/core/libLumina/XDGMime.cpp
index 3983f6b5..cbbeff75 100644
--- a/src-qt5/core/libLumina/XDGMime.cpp
+++ b/src-qt5/core/libLumina/XDGMime.cpp
@@ -12,6 +12,9 @@ static QStringList mimeglobs;
static qint64 mimechecktime;
QString XDGMime::fromFileName(QString filename){
+ if(QFile::exists(filename) && QFileInfo(filename).isDir()){
+ return "inode/directory";
+ }
//Convert a filename into a mimetype
return findAppMimeForFile(filename.section("/",-1),false);
}
diff --git a/src-qt5/core/libLumina/RootSubWindow-animations.cpp b/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp
index ac813e3a..efab20fe 100644
--- a/src-qt5/core/libLumina/RootSubWindow-animations.cpp
+++ b/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp
@@ -11,16 +11,20 @@ QStringList RootSubWindow::validAnimations(NativeWindow::Property prop){
QStringList valid;
if(prop == NativeWindow::Visible){
valid << "zoom" << "wipe-center-vertical" << "wipe-center-horizontal" << "shade-top" << "shade-right" << "shade-left" << "shade-bottom";
+ }else if(prop == NativeWindow::Size){
+ //Note: this is used for pretty much all geometry changes to the window where it is visible both before/after animation
+ valid << "direct";
}
return valid;
}
void RootSubWindow::loadAnimation(QString name, NativeWindow::Property prop, QVariant nval){
+ if(anim->state()==QAbstractAnimation::Running){ return; } //already running
animResetProp.clear();
//Special case - random animation each time
if(name=="random"){
QStringList valid = validAnimations(prop);
- name = valid.at(qrand()%valid.length());
+ if(!valid.isEmpty()){ name = valid.at(qrand()%valid.length()); }
}
//Now setup the animation
if(prop == NativeWindow::Visible){
@@ -57,6 +61,7 @@ void RootSubWindow::loadAnimation(QString name, NativeWindow::Property prop, QVa
}
if(nval.toBool()){
this->setGeometry( anim->startValue().toRect() ); //ensure the window is the initial geom before it becomes visible
+ //QTimer::singleShot( anim->duration()+5, this, SLOT(activate()) );
}else{
QVariant tmp = anim->startValue();
anim->setStartValue(anim->endValue());
@@ -68,6 +73,19 @@ void RootSubWindow::loadAnimation(QString name, NativeWindow::Property prop, QVa
anim->start();
this->show();
} //end of Visibility animation
+ else if(prop == NativeWindow::Size){
+ //This is pretty much all geometry animations where the window is visible->visible
+ anim->setPropertyName("geometry");
+ anim->setStartValue(this->geometry());
+ anim->setEndValue(nval.toRect());
+ /*if(name==""){
+ // TO-DO modify the path from beginning->end somehow
+ }*/
+ // Now start the animation
+ WinWidget->pause();
+ anim->start();
+ this->show();
+ }
}
void RootSubWindow::animFinished(){
@@ -87,11 +105,12 @@ void RootSubWindow::animFinished(){
//qDebug() << "Sub Window geometry:" << clientg;
WIN->setProperties(QList< NativeWindow::Property>() << NativeWindow::Size << NativeWindow::GlobalPos,
QList<QVariant>() << clientg.size() << clientg.topLeft() );
- WinWidget->resyncWindow(); //also let the window know about the current geometry
}
}
+ WinWidget->resyncWindow(); //also let the window know about the current geometry
}
animResetProp = QVariant(); //clear the variable
- WinWidget->resume();
-
+ //QTimer::singleShot(10, WinWidget, SLOT(resume()) );
+ WinWidget->resume();
+ emit windowAnimFinished();
}
diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp
index 6341f923..5040f2f9 100644
--- a/src-qt5/core/libLumina/RootSubWindow.cpp
+++ b/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp
@@ -10,6 +10,7 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTimer>
+#include <QScreen>
#define WIN_BORDER 5
@@ -56,7 +57,7 @@ RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset
if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
return ResizeTopLeft;
}else if(pt.x() > (this->width()*4.0/5.0)){
- if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(pt.y()); } //difference from top-right corner
+ if(setoffset){ offset.setX(pt.x()-this->width()); 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)
@@ -65,13 +66,13 @@ RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset
}else if(pt.y() > (this->height()-WIN_BORDER) ){
//One of the bottom options
if(pt.x() < this->width()/5){
- if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner
return ResizeBottomLeft;
}else if(pt.x() > (this->width()*4.0/5.0)){
- if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-right corner
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //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)
+ if(setoffset){ offset.setX(0); offset.setY(pt.y()-this->height()); } //difference from bottom edge (X does not matter)
return ResizeBottom;
}
}else if(pt.x() < WIN_BORDER){
@@ -80,7 +81,7 @@ RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset
if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
return ResizeTopLeft;
}else if(pt.y() > (this->height()*4.0/5.0)){
- if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner
return ResizeBottomLeft;
}else{
if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter)
@@ -89,13 +90,13 @@ RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset
}else if(pt.x() > (this->width()-WIN_BORDER) ){
//Right side options
if(pt.y() < this->height()/5){
- if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(pt.y()); } //difference from top-right corner
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner
return ResizeTopRight;
}else if(pt.y() > (this->height()*4.0/5.0)){
- if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-right corner
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner
return ResizeBottomRight;
}else{
- if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(0); } //difference from right edge (Y does not matter)
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(0); } //difference from right edge (Y does not matter)
return ResizeRight;
}
}else{
@@ -186,12 +187,14 @@ void RootSubWindow::initWindowFrame(){
titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
mainLayout->addWidget(titleBar);
mainLayout->addWidget(WinWidget);
+ mainLayout->setAlignment(titleBar, Qt::AlignTop);
//Setup the cursors for the buttons
closeB->setCursor(Qt::ArrowCursor);
minB->setCursor(Qt::ArrowCursor);
maxB->setCursor(Qt::ArrowCursor);
- otherM->setCursor(Qt::ArrowCursor);
+ otherB->setCursor(Qt::ArrowCursor);
titleLabel->setCursor(Qt::ArrowCursor);
+ WinWidget->setCursor(Qt::ArrowCursor);
//Now all the stylesheet options
this->setObjectName("WindowFrame");
closeB->setObjectName("Button_Close");
@@ -239,6 +242,16 @@ void RootSubWindow::enableFrame(bool on){
WIN->setProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList<int> >(extents) ); //save to structure now
}
+void RootSubWindow::enableFrame(QList<NativeWindow::Type> types){
+ static QList<NativeWindow::Type> noframe;
+ if(noframe.isEmpty()){ noframe << NativeWindow::T_DESKTOP << NativeWindow::T_DOCK << NativeWindow::T_TOOLBAR << NativeWindow::T_MENU << NativeWindow::T_SPLASH << NativeWindow::T_DROPDOWN_MENU << NativeWindow::T_POPUP_MENU << NativeWindow::T_TOOLTIP << NativeWindow::T_NOTIFICATION << NativeWindow::T_COMBO << NativeWindow::T_DND; }
+ for(int i=0; i<types.length(); i++){
+ if(noframe.contains(types[i])){ enableFrame(false); return; }
+ }
+ enableFrame(true);
+ //Now make buttons visible as appropriate for the type
+ //NativeWindow::T_UTILITY, NativeWindow::T_DIALOG, , NativeWindow::T_NORMAL
+}
void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){
QList<QVariant> vals;
//Always ensure that visibility changes are evaluated last
@@ -277,12 +290,44 @@ void RootSubWindow::LoadAllProperties(){
//Button Actions - public so they can be tied to key shortcuts and stuff as well
void RootSubWindow::toggleMinimize(){
- WIN->setProperty(NativeWindow::Visible, false);
- QTimer::singleShot(2000, this, SLOT(toggleMaximize()) );
+ WIN->toggleVisibility();
}
void RootSubWindow::toggleMaximize(){
- WIN->setProperty(NativeWindow::Visible, true);
+ //Get the current screen that this window is on
+ QList<QScreen*> screens = QApplication::screens();
+ QRect rect;
+ int primaryscreen = 0; //fallback value
+ for(int i=0; i<screens.length(); i++){
+ QRect intersect = screens[i]->geometry().intersected(this->geometry());
+ if( (intersect.width()-rect.width() + intersect.height()-rect.height()) > 0){
+ rect = intersect;
+ primaryscreen = i;
+ }
+ }
+ //Now that we have the screen dimensions, lets check/change the window
+ rect = screens[primaryscreen]->availableGeometry();
+ QList< NativeWindow::State > states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State> >();
+ if(rect == this->geometry() || states.contains(NativeWindow::S_MAX_VERT) || states.contains(NativeWindow::S_MAX_HORZ)){
+ //Already maximized - try to restore it to the previous size/location
+ if(!lastMaxGeom.isNull()){
+ rect = lastMaxGeom;
+ }else{
+ // no last geometry - started out maximized?
+ // make it half the screen size and centered on the screen
+ QPoint center = rect.center();
+ rect.setWidth( rect.width()/2 );
+ rect.setHeight( rect.height()/2 );
+ rect.moveTopLeft( center - QPoint(rect.width()/2, rect.height()/2) );
+ }
+ lastMaxGeom = QRect(); //clear this saved geom
+ }else{
+ //Not maximized yet - go ahead and make it so
+ lastMaxGeom = this->geometry(); //save this for later;
+ }
+ //qDebug() << "Toggle Maximize:" << this->geometry() << rect;
+ QString anim_type = DesktopSettings::instance()->value(DesktopSettings::Animation, "window/move", "random").toString();
+ loadAnimation(anim_type, NativeWindow::Size, rect);
}
void RootSubWindow::triggerClose(){
@@ -290,11 +335,18 @@ void RootSubWindow::triggerClose(){
}
void RootSubWindow::toggleSticky(){
-
+ QList< NativeWindow::State> states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State > >();
+ if(states.contains(NativeWindow::S_STICKY)){
+ states.removeAll(NativeWindow::S_STICKY);
+ }else{
+ states << NativeWindow::S_STICKY;
+ }
+ WIN->requestProperty(NativeWindow::States, QVariant::fromValue<QList <NativeWindow::State> >(states) );
}
void RootSubWindow::activate(){
- WIN->requestProperty(NativeWindow::Active, true);
+ //WinWidget->raiseWindow();
+ WIN->requestProperty(NativeWindow::Active, true, true);
}
//Mouse Interactivity
@@ -309,13 +361,15 @@ void RootSubWindow::startMoving(){
activeState = Move;
offset = this->mapFromGlobal(curpt);
setMouseCursor(activeState, true); //this one is an override cursor
- //WinWidget->pause();
- //Also need to capture the mouse
+ WinWidget->pause();
this->grabMouse();
}
void RootSubWindow::startResizing(){
-
+ activeState = getStateAtPoint( this->mapFromGlobal(QCursor::pos()), true); //also have it set the offset variable
+ setMouseCursor(activeState, true); //this one is an override cursor
+ WinWidget->pause();
+ this->grabMouse();
}
// === PRIVATE SLOTS ===
@@ -325,9 +379,11 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
//qDebug() << "RootSubWindow: Property Changed:" << props[i] << vals[i];
switch(props[i]){
case NativeWindow::Visible:
- //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry();
- if(vals[i].toBool()){ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/appear", "random").toString(), NativeWindow::Visible, vals[i]); }
- else{ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/disappear", "random").toString(), NativeWindow::Visible, vals[i]); }
+ if(!WinWidget->isPaused() && (this->isVisible()!=vals[i].toBool()) && activeState==Normal ){
+ //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry();
+ if(vals[i].toBool()){ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/appear", "random").toString(), NativeWindow::Visible, vals[i]); }
+ else{ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/disappear", "random").toString(), NativeWindow::Visible, vals[i]); }
+ }
break;
case NativeWindow::Title:
titleLabel->setText(vals[i].toString());
@@ -338,6 +394,10 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
else{ otherB->setIcon(vals[i].value<QIcon>()); }
break;
case NativeWindow::GlobalPos:
+ if(vals[i].toPoint()!=QPoint(0,0)){
+ WinWidget->resyncWindow();
+ }
+ break;
case NativeWindow::Size:
//qDebug() << " - SIZE CHANGE";
if(WIN->property(NativeWindow::FrameExtents).isNull() && (i<props.indexOf(NativeWindow::FrameExtents)) ){
@@ -345,9 +405,11 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
props << props.takeAt(i);
vals << vals.takeAt(i);
i--;
- }else if(anim->state() != QPropertyAnimation::Running ){
- if(WIN->property(NativeWindow::Size).toSize() != WinWidget->size() && activeState==Normal ){
- this->setGeometry(WIN->geometry());
+ }else if(!WinWidget->isPaused() && activeState==Normal){
+ if(WIN->property(NativeWindow::Size).toSize() != WinWidget->size()){
+ //qDebug() << "Got Direct Geometry Change:" << WIN->geometry();
+ this->setGeometry( QRect(this->geometry().topLeft(), WIN->geometry().size()) );
+ WinWidget->resyncWindow();
}
}
break;
@@ -370,7 +432,7 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
WinWidget->setMaximumSize(vals[i].toSize());
break;
case NativeWindow::Active:
- //if(vals[i].toBool()){ WinWidget->setFocus(); }
+ if(vals[i].toBool()){ activate(); } //WinWidget->raiseWindow(); }
break;
/*case NativeWindow::FrameExtents:
qDebug() << " - FRAME CHANGE";
@@ -382,7 +444,8 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
mainLayout->setContentsMargins( vals[i].value< QList<int> >().at(0),vals[i].value< QList<int> >().at(2) - titleLabel->height(),vals[i].value< QList<int> >().at(1),vals[i].value< QList<int> >().at(3));
break;*/
case NativeWindow::WinTypes:
- enableFrame(vals[i].value< QList<NativeWindow::Type> >().contains(NativeWindow::T_NORMAL) );
+ //qDebug() << "Got Window Types:" << vals[i].value< QList<NativeWindow::Type> >();
+ enableFrame(vals[i].value< QList<NativeWindow::Type> >() );
break;
default:
qDebug() << "Window Property Unused:" << props[i] << vals[i];
@@ -394,27 +457,24 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
void RootSubWindow::mousePressEvent(QMouseEvent *ev){
activate();
this->raise();
+ QFrame::mousePressEvent(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->activate();
- 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
+ offset.setX(0); offset.setY(0);
+ if(ev->button()==Qt::LeftButton){
+ if(this->childAt(ev->pos())!=0){
+ //Clicked on the titlebar
+ startMoving();
+ }else{
+ //Clicked on the frame somewhere
+ startResizing();
+ }
}
- setMouseCursor(activeState, true); //this one is an override cursor
- //if(activeState!=Normal){WinWidget->pause(); }
- if(activeState!=Normal && activeState!=Move){WinWidget->pause(); }
- QFrame::mousePressEvent(ev);
+
}
void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
- activate(); //make sure this window is "Active"
+ QFrame::mouseMoveEvent(ev);
if(activeState == Normal){
setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
}else{
@@ -489,10 +549,15 @@ void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
break;
}
//if( (geom.width()%2==0 && geom.height()%2==0) || activeState==Move){
- this->setGeometry(geom);
+ //qDebug() << " Change Window:" << this->geometry() << geom;
+ if(activeState==Move){ this->setGeometry(geom); }
+ else{
+ //qDebug() << " Change Window Dimensions:" << this->geometry() << geom;
+ //qDebug() << " - Mouse Pos:" << ev->globalPos() << ev->pos() << "Offset" << offset;
+ this->setGeometry(geom);
+ }
//}
}
- QFrame::mouseMoveEvent(ev);
}
void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
@@ -500,28 +565,37 @@ void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
//qDebug() << "Frame Mouse Release Event";
QFrame::mouseReleaseEvent(ev);
if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){
+ //WinWidget->raiseWindow();//need to ensure the native window is always on top of this frame but under the menu
otherM->popup(ev->globalPos());
return;
}
- if(activeState!=Normal){ WinWidget->resume(); }
- if(activeState!=Normal && activeState!=Move){WinWidget->resume(); }
- activeState = Normal;
- QApplication::restoreOverrideCursor();
- setMouseCursor( getStateAtPoint(ev->pos()) );
+ if(activeState!=Normal){
+ if(WinWidget->isPaused()){ WinWidget->resume(); }
+ activeState = Normal;
+ QApplication::restoreOverrideCursor();
+ setMouseCursor( getStateAtPoint(ev->pos()) );
+ }
if(QFrame::mouseGrabber() == this){ this->releaseMouse(); }
+ activate();
+ //QTimer::singleShot(0, WinWidget, SLOT(raiseWindow()) );
}
-void RootSubWindow::leaveEvent(QEvent *ev){
+/*void RootSubWindow::enterEvent(QEvent *ev){
+ QFrame::enterEvent(ev);
+ WinWidget->raiseWindow();
+}*/
+/*void RootSubWindow::leaveEvent(QEvent *ev){
QFrame::leaveEvent(ev);
if(activeState == Normal){
setMouseCursor(Normal);
}
-}
+ if(!QRect(QPoint(0,0),this->size()).contains( this->mapFromGlobal(QCursor::pos())) ){ WinWidget->lowerWindow(); }
+}*/
void RootSubWindow::moveEvent(QMoveEvent *ev){
//qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry();
QFrame::moveEvent(ev);
- if(!closing && anim->state()!=QAbstractAnimation::Running){
+ if(!closing && !WinWidget->isPaused()){
moveTimer->start();
}
}
diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/obsolete/RootSubWindow.h
index 0af77009..598298e2 100644
--- a/src-qt5/core/libLumina/RootSubWindow.h
+++ b/src-qt5/core/libLumina/obsolete/RootSubWindow.h
@@ -55,16 +55,22 @@ private:
QPropertyAnimation *anim;
QVariant animResetProp;
QTimer *moveTimer;
- QRect lastGeom; //frame coordinates
+ QRect lastGeom, lastMaxGeom; //frame coordinates
void initWindowFrame();
void enableFrame(bool);
+ void enableFrame(QList<NativeWindow::Type> types);
void LoadProperties( QList< NativeWindow::Property> list);
static QStringList validAnimations(NativeWindow::Property);
public slots:
+ void ensureVisible(){ WIN->setProperty(NativeWindow::Visible, true); }
+ void giveMouseFocus(){ WinWidget->raiseWindow(); }
+ void removeMouseFocus(){ WinWidget->lowerWindow(); }
+ void giveKeyboardFocus(){ WIN->requestProperty(NativeWindow::Active, true, true); }
+
void clientClosed();
void LoadAllProperties();
@@ -91,11 +97,13 @@ protected:
void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
- void leaveEvent(QEvent *ev);
-
+ //void leaveEvent(QEvent *ev);
+ //void enterEvent(QEvent *ev);
void moveEvent(QMoveEvent *ev);
-
+signals:
+ void windowMoved(RootSubWindow*);
+ void windowAnimFinished();
};
#endif
diff --git a/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp b/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp
new file mode 100644
index 00000000..24ea639b
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp
@@ -0,0 +1,95 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RootWindow.h"
+
+//Primary/private function
+void RootWindow::arrangeWindows(RootSubWindow *primary, QString type, bool primaryonly){
+ if(type.isEmpty()){ type = "center"; }
+ if(primary==0){
+ //Get the currently active window and treat that as the primary
+ for(int i=0; i<WINDOWS.length(); i++){
+ if(WINDOWS[i]->nativeWindow()->property(NativeWindow::Active).toBool()){ primary = WINDOWS[i]; }
+ }
+ if(primary==0 && !WINDOWS.isEmpty()){ primary = WINDOWS[0]; } //just use the first one in the list
+ }
+ //Now get the current screen that the mouse cursor is over (and valid area)
+ QScreen *screen = screenUnderMouse();
+ QRect desktopArea = screen->availableGeometry();
+ //qDebug() << "Arrange Windows:" << primary->geometry() << type << primaryonly << desktopArea;
+ //Now start filtering out all the windows that need to be ignored
+ int wkspace = primary->nativeWindow()->property(NativeWindow::Workspace).toInt();
+ QList<RootSubWindow*> winlist = WINDOWS;
+ for(int i=0; i<winlist.length(); i++){
+ if(winlist[i]->nativeWindow()->property(NativeWindow::Workspace).toInt()!=wkspace
+ || !winlist[i]->nativeWindow()->property(NativeWindow::Visible).toBool()
+ || desktopArea.intersected(winlist[i]->geometry()).isNull() ){
+ //window is outside of the desired area or invisible - ignore it
+ winlist.removeAt(i);
+ i--;
+ }
+ }
+ if(!winlist.contains(primary)){ winlist << primary; } //could be doing this on a window right before it is shown
+ else if(primaryonly){ winlist.removeAll(primary); winlist << primary; } //move primary window to last
+ //QRegion used;
+ for(int i=0; i<winlist.length(); i++){
+ if(primaryonly && winlist[i]!=primary){ continue; } //skip this window
+ //Now loop over the windows and arrange them as needed
+ QRect geom = winlist[i]->geometry();
+ //verify that the window is contained by the desktop area
+ if(geom.width()>desktopArea.width()){ geom.setWidth(desktopArea.width()); }
+ if(geom.height()>desktopArea.height()){ geom.setHeight(desktopArea.height()); }
+ //Now apply the proper placement routine
+ if(type=="center"){
+ QPoint ct = desktopArea.center();
+ winlist[i]->setGeometry( ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height());
+ }else if(type=="snap"){
+
+ }else if(type=="single_max"){
+ winlist[i]->setGeometry( desktopArea.x(), desktopArea.y(), desktopArea.width(), desktopArea.height());
+ }else if(type=="under-mouse"){
+ QPoint ct = QCursor::pos();
+ geom = QRect(ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height() );
+ //Now verify that the top of the window is still contained within the desktop area
+ if(geom.y() < desktopArea.y() ){ geom.moveTop(desktopArea.y()); }
+ winlist[i]->setGeometry(geom);
+
+ }
+ //qDebug() << " - New Geometry:" << winlist[i]->geometry();
+ } //end loop over winlist
+}
+
+// ================
+// Public slots for starting the arrangement routine(s) above
+// ================
+void RootWindow::ArrangeWindows(WId primary, QString type){
+ RootSubWindow* win = windowForId(primary);
+ if(type.isEmpty()){ type = "center"; } //grab the default arrangement format
+ arrangeWindows(win, type);
+}
+
+void RootWindow::TileWindows(WId primary, QString type){
+ RootSubWindow* win = windowForId(primary);
+ if(type.isEmpty()){ type = "single_max"; } //grab the default arrangement format for tiling
+ arrangeWindows(win, type);
+}
+
+void RootWindow::CheckWindowPosition(WId id, bool newwindow){
+ //used after a "drop" to validate/snap/re-arrange window(s) as needed
+ // if "newwindow" is true, then this is the first-placement routine for a window before it initially appears
+ RootSubWindow* win = windowForId(id);
+ if(win==0){ return; } //invalid window
+ QRect geom = win->nativeWindow()->geometry();
+ bool changed = false;
+ //Make sure it is on the screen (quick check)
+ if(geom.x() < 0){ changed = true; geom.moveLeft(0); }
+ if(geom.y() < 0){ changed = true; geom.moveTop(0); }
+ if(geom.width() < 20){ changed = true; geom.setWidth(100); }
+ if(geom.height() < 20){ changed = true; geom.setHeight(100); }
+ if(changed){ win->setGeometry(geom); }
+ //Now run it through the window arrangement routine
+ arrangeWindows(win, newwindow ?"center" : "snap", true);
+}
diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/obsolete/RootWindow.cpp
index 48c37c86..705297be 100644
--- a/src-qt5/core/libLumina/RootWindow.cpp
+++ b/src-qt5/core/libLumina/obsolete/RootWindow.cpp
@@ -10,12 +10,14 @@
#include <QScreen>
#include <QDebug>
-#define DEBUG 1
+#define DEBUG 0
// === PUBLIC ===
RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){
qRegisterMetaType<WId>("WId");
autoResizeTimer = 0;
+ lastActiveMouse = 0;
+ mouseFocusTimer = 0;
this->setMouseTracking(true);
}
@@ -33,6 +35,12 @@ void RootWindow::start(){
connect(QApplication::desktop(), SIGNAL(resized(int)), autoResizeTimer, SLOT(start()) );
connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), autoResizeTimer, SLOT(start()) );
}
+ if(mouseFocusTimer==0){
+ mouseFocusTimer = new QTimer(this);
+ mouseFocusTimer->setInterval(100);
+ connect(mouseFocusTimer, SIGNAL(timeout()), this, SLOT(checkMouseFocus()) );
+
+ }
this->show();
ResizeRoot();
emit RegisterVirtualRoot(this->winId());
@@ -108,6 +116,16 @@ RootSubWindow* RootWindow::windowForId(WId id){
return tmp;
}
+QScreen* RootWindow::screenUnderMouse(){
+ QPoint mpos = QCursor::pos();
+ QList<QScreen*> scrns = QApplication::screens();
+ for(int i=0; i<scrns.length(); i++){
+ if(scrns[i]->geometry().contains(mpos)){ return scrns[i]; }
+ }
+ //Could not find an exact match - just return the first one
+ return scrns.first();
+}
+
// === PUBLIC SLOTS ===
void RootWindow::ResizeRoot(){
if(DEBUG){ qDebug() << "Resize Root..."; }
@@ -182,6 +200,32 @@ void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QStrin
}
+void RootWindow::checkMouseFocus(){
+ QPoint cpos = QCursor::pos();
+ if(lastCursorPos != cpos){ emit MouseMoved(); }
+ lastCursorPos = cpos;
+ QWidget *child = this->childAt(QCursor::pos());
+ while(child!=0 && child->whatsThis()!="RootSubWindow"){
+ child = child->parentWidget();
+ if(child==this){ child = 0;} //end of the line
+ }
+
+ if(child==lastActiveMouse){ return; } //nothing new to do
+ //Make sure the child is actually a RootSubWindow
+ if(lastActiveMouse!=0){ lastActiveMouse->removeMouseFocus(); lastActiveMouse = 0; }
+ if(child!=0){
+ lastActiveMouse = static_cast<RootSubWindow*>(child);
+
+ if(DesktopSettings::instance()->value(DesktopSettings::WM, "focusFollowsMouse", true).toBool()){
+ lastActiveMouse->giveKeyboardFocus();
+ if(DesktopSettings::instance()->value(DesktopSettings::WM, "raiseOnFocus", false).toBool()){
+ lastActiveMouse->raise();
+ }
+ }
+ lastActiveMouse->giveMouseFocus(); //always give mouse focus on mouseover
+ }
+}
+
void RootWindow::NewWindow(NativeWindow *win){
RootSubWindow *subwin = 0;
//qDebug() << "Got New Window:" << win->property(NativeWindow::Title);
@@ -190,19 +234,29 @@ void RootWindow::NewWindow(NativeWindow *win){
}
if(subwin==0){
subwin = new RootSubWindow(this, win);
+ subwin->setWhatsThis("RootSubWindow");
connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) );
+ connect(subwin, SIGNAL(windowAnimFinished()), this, SLOT(checkMouseFocus()) );
WINDOWS << subwin;
}
+ //QApplication::processEvents();
CheckWindowPosition(win->id(), true); //first-time run
- //win->setProperty(NativeWindow::Visible, true);
+ //QTimer::singleShot(300, subwin, SLOT(ensureVisible()));
+ win->setProperty(NativeWindow::Visible, true);
//win->requestProperty( NativeWindow::Active, true);
- win->requestProperties(QList<NativeWindow::Property>() << NativeWindow::Visible << NativeWindow::Active, QList<QVariant>() << true << true);
+ //win->requestProperties(QList<NativeWindow::Property>() << NativeWindow::Visible << NativeWindow::Active, QList<QVariant>() << true << true, true);
+ if(!mouseFocusTimer->isActive()){ mouseFocusTimer->start(); }
}
void RootWindow::CloseWindow(WId win){
for(int i=0; i<WINDOWS.length(); i++){
- if(WINDOWS[i]->id() == win){ WINDOWS.takeAt(i)->clientClosed(); break; }
+ if(WINDOWS[i]->id() == win){
+ if(lastActiveMouse==WINDOWS[i]){ lastActiveMouse = 0; } //no longer valid
+ WINDOWS.takeAt(i)->clientClosed();
+ break;
+ }
}
+ if(WINDOWS.isEmpty()){ mouseFocusTimer->stop(); } //no windows to look for
}
// === PRIVATE SLOTS ===
@@ -210,11 +264,11 @@ void RootWindow::CloseWindow(WId win){
// === PROTECTED ===
void RootWindow::paintEvent(QPaintEvent *ev){
//qDebug() << "RootWindow: PaintEvent:" << ev->rect(); //<< QDateTime::currentDateTime()->toString(QDateTime::ShortDate);
- QWidget::paintEvent(ev);
+ //QWidget::paintEvent(ev);
bool found = false;
QPainter painter(this);
QRect geom = ev->rect();
- geom.adjust(-10,-10,10,10); //give it a few more pixels in each direction to repaint (noticing some issues in Qt 5.7.1)
+ geom.adjust(-100,-100,100,100); //give it a few more pixels in each direction to repaint (noticing some issues in Qt 5.7.1)
for(int i=0; i<WALLPAPERS.length(); i++){
if(WALLPAPERS[i].area.intersects(geom) ){
found = true;
diff --git a/src-qt5/core/libLumina/RootWindow.h b/src-qt5/core/libLumina/obsolete/RootWindow.h
index 9b1334dc..c5cd44a0 100644
--- a/src-qt5/core/libLumina/RootWindow.h
+++ b/src-qt5/core/libLumina/obsolete/RootWindow.h
@@ -18,6 +18,8 @@
#include <QTimer>
#include <QApplication>
#include <QPaintEvent>
+#include <QScreen>
+#include <QDebug>
#include "RootSubWindow.h"
@@ -43,7 +45,9 @@ private:
ScaleType scale;
QPixmap wallpaper; //Note: This pixmap will always be the same size as "area"
};
- QTimer *autoResizeTimer;
+ QTimer *autoResizeTimer, *mouseFocusTimer;
+ RootSubWindow *lastActiveMouse;
+ QPoint lastCursorPos;
QList<screeninfo> WALLPAPERS;
void updateScreenPixmap(screeninfo *info); //used for recalculating the wallpaper pixmap based on file/area/scale as needed
@@ -51,12 +55,16 @@ private:
//Window Management
QList<RootSubWindow*> WINDOWS;
RootSubWindow* windowForId(WId id);
- void arrangeWindows(RootSubWindow *primary = 0, QString type = "");
+ void arrangeWindows(RootSubWindow *primary = 0, QString type = "", bool primaryonly = false);
+
+ QScreen* screenUnderMouse();
+
public slots:
void ResizeRoot();
void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file);
//Note: for "SingleColor" scaling the "file" variable should be "rgb(R,G,B)" or "#hexcode"
+ void checkMouseFocus();
void NewWindow(NativeWindow*);
void CloseWindow(WId); //automatically connected for any new native window
@@ -76,6 +84,8 @@ signals:
void RootResized(QRect);
void NewScreens(QStringList); // [screen_id_1, screen_id_2, etc..]
void RemovedScreens(QStringList); // [screen_id_1, screen_id_2, etc..]
+ void WorkspaceChanged(int);
+ void MouseMoved();
};
diff --git a/src-qt5/core/libLumina/RootWindow.pri b/src-qt5/core/libLumina/obsolete/RootWindow.pri
index 9426b6b4..9426b6b4 100644
--- a/src-qt5/core/libLumina/RootWindow.pri
+++ b/src-qt5/core/libLumina/obsolete/RootWindow.pri
bgstack15