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.cpp32
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.h2
-rw-r--r--src-qt5/core/libLumina/LDesktopUtils.cpp110
-rw-r--r--src-qt5/core/libLumina/LIconCache.h2
-rw-r--r--src-qt5/core/libLumina/LuminaX11.cpp23
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.h24
-rw-r--r--src-qt5/core/libLumina/NativeEmbedWidget.cpp208
-rw-r--r--src-qt5/core/libLumina/NativeEmbedWidget.h55
-rw-r--r--src-qt5/core/libLumina/NativeEventFilter.cpp272
-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.cpp65
-rw-r--r--src-qt5/core/libLumina/NativeWindow.h58
-rw-r--r--src-qt5/core/libLumina/NativeWindow.pri11
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.cpp515
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.h63
-rw-r--r--src-qt5/core/libLumina/RootSubWindow.cpp265
-rw-r--r--src-qt5/core/libLumina/RootSubWindow.h20
-rw-r--r--src-qt5/core/libLumina/RootWindow.cpp24
-rw-r--r--src-qt5/core/libLumina/RootWindow.h6
-rw-r--r--src-qt5/core/libLumina/RootWindow.pri3
21 files changed, 2023 insertions, 333 deletions
diff --git a/src-qt5/core/libLumina/DesktopSettings.cpp b/src-qt5/core/libLumina/DesktopSettings.cpp
index 30bd5bc2..47dc29de 100644
--- a/src-qt5/core/libLumina/DesktopSettings.cpp
+++ b/src-qt5/core/libLumina/DesktopSettings.cpp
@@ -9,7 +9,7 @@
#include <QDir>
#include <QDebug>
-#include <unistd.h>
+#include <unistd.h>
#include <pwd.h>
#include <grp.h>
@@ -25,6 +25,16 @@ DesktopSettings::~DesktopSettings(){
if(!files.isEmpty()){ stop(); }
}
+DesktopSettings* DesktopSettings::instance(){
+ static DesktopSettings *set = 0;
+ if(set==0){
+ //First-time init
+ set = new DesktopSettings();
+ set->start();
+ }
+ return set;
+}
+
//Start/stop routines
void DesktopSettings::start(){
files.clear(); settings.clear(); //clear the internal hashes (just in case)
@@ -35,7 +45,7 @@ void DesktopSettings::start(){
}
parseSystemSettings(); //set the runmode appropriately
locateFiles(); //
-
+
}
void DesktopSettings::stop(){
@@ -111,7 +121,7 @@ void DesktopSettings::parseSystemSettings(){
//Now determine the runmode for this user
struct passwd *pw = getpwuid(getuid());
- if(pw!=0){
+ if(pw!=0){
QString cuser = QString(pw->pw_name);
free(pw); //done with this structure
if( settings[path]->value("fulluser_users", QStringList()).toStringList().contains(cuser) ){ runmode = DesktopSettings::UserFull; }
@@ -123,10 +133,10 @@ void DesktopSettings::parseSystemSettings(){
gid_t grpList[100];
int grpSize = 100;
if( getgrouplist(cuser.toLocal8Bit(), getgid(), grpList, &grpSize) > 0 ){
- QStringList groups;
- for(int i=0; i<grpSize; i++){
+ QStringList groups;
+ for(int i=0; i<grpSize; i++){
struct group *g = getgrgid(grpList[i]);
- if(g!=0){
+ if(g!=0){
groups << QString(g->gr_name);
free(g);
}
@@ -136,18 +146,18 @@ void DesktopSettings::parseSystemSettings(){
if( (fromfile+groups).removeDuplicates() > 0 ){ runmode = DesktopSettings::UserFull; }
else{
fromfile = settings[path]->value("fullsystem_groups", QStringList()).toStringList();
- fromfile.removeDuplicates();
+ fromfile.removeDuplicates();
if((fromfile+groups).removeDuplicates() > 0 ){ runmode = DesktopSettings::SystemFull; }
else{
fromfile = settings[path]->value("staticinterface_groups", QStringList()).toStringList();
- fromfile.removeDuplicates();
+ fromfile.removeDuplicates();
if((fromfile+groups).removeDuplicates() > 0 ){ runmode = DesktopSettings::SystemInterface; }
}
}
- } //end group list read
+ } //end group list read
}
}else{
- runmode = DesktopSettings::SystemFull; //could not read user name - assume system files only
+ runmode = DesktopSettings::SystemFull; //could not read user name - assume system files only
}
break; //found this file - go ahead and stop now (no hierarchy for this special file)
@@ -246,7 +256,7 @@ void DesktopSettings::fileChanged(QString file){
QList< DesktopSettings::File > types = files.keys();
for(int i=0; i<types.length(); i++){
if(files[types[i]].contains(file)){
- emit FileModified(types[i]);
+ emit FileModified(types[i]);
break;
}
}
diff --git a/src-qt5/core/libLumina/DesktopSettings.h b/src-qt5/core/libLumina/DesktopSettings.h
index 57eede9d..57a85791 100644
--- a/src-qt5/core/libLumina/DesktopSettings.h
+++ b/src-qt5/core/libLumina/DesktopSettings.h
@@ -30,6 +30,8 @@ public:
DesktopSettings(QObject *parent = 0);
~DesktopSettings();
+ static DesktopSettings* instance();
+
//Start/stop routines
void start();
void stop();
diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp
index d76c68e9..4454d29b 100644
--- a/src-qt5/core/libLumina/LDesktopUtils.cpp
+++ b/src-qt5/core/libLumina/LDesktopUtils.cpp
@@ -15,12 +15,12 @@
static QStringList fav;
-QString LDesktopUtils::LuminaDesktopVersion(){
- QString ver = "1.2.2";
+QString LDesktopUtils::LuminaDesktopVersion(){
+ QString ver = "1.3.1";
#ifdef GIT_VERSION
ver.append( QString(" (Git Revision: %1)").arg(GIT_VERSION) );
#endif
- return ver;
+ return ver;
}
QString LDesktopUtils::LuminaDesktopBuildDate(){
@@ -88,7 +88,7 @@ QStringList LDesktopUtils::listFavorites(){
fav.removeDuplicates();
lastRead = cur;
}
-
+
return fav;
}
@@ -138,7 +138,7 @@ void LDesktopUtils::removeFavorite(QString path){
void LDesktopUtils::upgradeFavorites(int){ //fromoldversionnumber
//NOTE: Version number syntax: <major>*1000000 + <minor>*1000 + <revision>
// Example: 1.2.3 -> 1002003
-}
+}
void LDesktopUtils::LoadSystemDefaults(bool skipOS){
//Will create the Lumina configuration files based on the current system template (if any)
@@ -156,15 +156,15 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QDesktopWidget *desk =QApplication::desktop();
QRect screenGeom;
for(int i=0; i<desk->screenCount(); i++){
- if(desk->screenGeometry(i).x()==0){
- screen = QString::number(i);
- screenGeom = desk->screenGeometry(i);
- break;
+ if(desk->screenGeometry(i).x()==0){
+ screen = QString::number(i);
+ screenGeom = desk->screenGeometry(i);
+ break;
}
}
//Now setup the default "desktopsettings.conf" and "sessionsettings.conf" files
QStringList deskset, sesset;//, lopenset;
-
+
// -- SESSION SETTINGS --
QStringList tmp = sysDefaults.filter("session_");
if(tmp.isEmpty()){ tmp = sysDefaults.filter("session."); }//for backwards compat
@@ -177,36 +177,36 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
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
-
+ if(var.contains(".")){ var.replace(".","_"); }
+ //Now parse the variable and put the value in the proper file
+
if(var.contains("_default_")){ val = LUtils::AppToAbsolute(val); } //got an application/binary
//Special handling for values which need to exist first
- if(var.endsWith("_ifexists") ){
+ if(var.endsWith("_ifexists") ){
var = var.remove("_ifexists"); //remove this flag from the variable
//Check if the value exists (absolute path only)
if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist
}
-
+
//Parse/save the value
QString sset; //temporary strings
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"){
LXDG::setDefaultAppForMime("application/terminal", val);
- //sset = "default-terminal="+val;
- }else if(var=="session_default_filemanager"){
+ //sset = "default-terminal="+val;
+ }else if(var=="session_default_filemanager"){
LXDG::setDefaultAppForMime("inode/directory", val);
//sset = "default-filemanager="+val;
- //loset = "directory="+val;
- }else if(var=="session_default_webbrowser"){
- //loset = "webbrowser="+val;
+ //loset = "directory="+val;
+ }else if(var=="session_default_webbrowser"){
+ //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"){
LXDG::setDefaultAppForMime("application/email",val);
- //loset = "email="+val;
+ //loset = "email="+val;
}
//Put the line into the file (overwriting any previous assignment as necessary)
/*if(!loset.isEmpty()){
@@ -218,7 +218,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
if(!sset.isEmpty()){
int index = sesset.indexOf(QRegExp(sset.section("=",0,0)+"=*", Qt::CaseSensitive, QRegExp::Wildcard));
if(index<0){ sesset << sset; } //new line
- else{ sesset[index] = sset; } //overwrite the other line
+ else{ sesset[index] = sset; } //overwrite the other line
}
}
//if(!lopenset.isEmpty()){ lopenset.prepend("[default]"); } //the session options exist within this set
@@ -232,11 +232,11 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
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
+ 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") ){
+ if(var.endsWith("_ifexists") ){
var = var.remove("_ifexists"); //remove this flag from the variable
//Check if the value exists (absolute path only)
if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist
@@ -259,8 +259,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
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
+ if(var.contains(".")){ var.replace(".","_"); }
+ //Now parse the variable and put the value in the proper file
if(var=="desktop_visiblepanels"){ deskset << "panels="+val; }
else if(var=="desktop_backgroundfiles"){ deskset << "background\\filelist="+val; }
else if(var=="desktop_backgroundrotateminutes"){ deskset << "background\\minutesToChange="+val; }
@@ -282,8 +282,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
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
+ if(var.contains(".")){ var.replace(".","_"); }
+ //Now parse the variable and put the value in the proper file
if(var==(panvar+"_pixelsize")){
//qDebug() << "Panel Size:" << val;
if(val.contains("%")){
@@ -293,7 +293,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
else if(last=="w"){ val = QString::number( qRound(screenGeom.width()*val.toDouble())/100 ); }//adjust value to a percentage of the width of the screen
}
//qDebug() << " -- Adjusted:" << val;
- deskset << "height="+val;
+ deskset << "height="+val;
}
else if(var==(panvar+"_autohide")){ deskset << "hidepanel="+istrue; }
else if(var==(panvar+"_location")){ deskset << "location="+val.toLower(); }
@@ -314,8 +314,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QString val = tmp[i].section("=",1,1).section("#",0,0).toLower().simplified();
if(val.isEmpty()){ continue; }
//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
+ if(var.contains(".")){ var.replace(".","_"); }
+ //Now parse the variable and put the value in the proper file
if(var=="menu_plugins"){ deskset << "itemlist="+val; }
}
if(!tmp.isEmpty()){ deskset << ""; } //space between sections
@@ -328,7 +328,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QString var = tmp[i].section("=",0,0).toLower().simplified();
QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
//Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while
- if(var.contains(".")){ var.replace(".","_"); }
+ if(var.contains(".")){ var.replace(".","_"); }
//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
@@ -346,19 +346,19 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QString var = tmp[i].section("=",0,0).toLower().simplified();
QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
//Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while
- if(var.contains(".")){ var.replace(".","_"); }
+ if(var.contains(".")){ var.replace(".","_"); }
//Now parse the variable and put the value in the proper file
val = LUtils::AppToAbsolute(val); //turn any relative files into absolute
if(var=="quicklaunch_add_ifexists" && QFile::exists(val)){ quickL << val; }
else if(var=="quicklaunch_add"){ quickL << val; }
}
- if(!quickL.isEmpty()){
+ if(!quickL.isEmpty()){
if(sesset.isEmpty()){ sesset << "[General]"; } //everything is in this section
- sesset << "QuicklaunchApps="+quickL.join(", ");
+ sesset << "QuicklaunchApps="+quickL.join(", ");
}
//Now do any theme settings
- QStringList themesettings = LTHEME::currentSettings();
+ QStringList themesettings = LTHEME::currentSettings();
//List: [theme path, colorspath, iconsname, font, fontsize]
//qDebug() << "Current Theme Color:" << themesettings[1];
tmp = sysDefaults.filter("theme_");
@@ -370,19 +370,19 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
if(val.isEmpty()){ continue; }
//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
+ 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_colorfile"){ themesettings[1] = val; }
else if(var=="theme_iconset"){ themesettings[2] = val; }
else if(var=="theme_font"){ themesettings[3] = val; }
- else if(var=="theme_fontsize"){
+ else if(var=="theme_fontsize"){
if(val.endsWith("%")){ val = QString::number( (screenGeom.height()*val.section("%",0,0).toDouble())/100 )+"px"; }
- themesettings[4] = val;
+ themesettings[4] = val;
}
}
//qDebug() << " - Now Color:" << themesettings[1] << setTheme;
-
+
//Now double check that the custom theme/color files exist and reset it will the full path as necessary
if(setTheme){
QStringList systhemes = LTHEME::availableSystemThemes();
@@ -414,15 +414,15 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
//Ensure that the settings directory exists
QString setdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop";
- if(!QFile::exists(setdir)){
- QDir dir;
- dir.mkpath(setdir);
+ 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]); }
LUtils::writeFile(setdir+"/sessionsettings.conf", sesset, true);
LUtils::writeFile(setdir+"/desktopsettings.conf", deskset, true);
-
+
//Now run any extra config scripts or utilities as needed
tmp = sysDefaults.filter("usersetup_run");
if(tmp.isEmpty()){ tmp = sysDefaults.filter("usersetup.run"); }
@@ -431,25 +431,25 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){
QString var = tmp[i].section("=",0,0).toLower().simplified();
QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
//Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while
- if(var.contains(".")){ var.replace(".","_"); }
+ if(var.contains(".")){ var.replace(".","_"); }
//Now parse the variable and put the value in the proper file
if(var=="usersetup_run"){
qDebug() << "Running user setup command:" << val;
QProcess::execute(val);
}
}
-
+
}
bool LDesktopUtils::checkUserFiles(QString lastversion){
- //internal version conversion examples:
+ //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());
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
-
+
QString confdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/";
//Check for the desktop settings file
QString dset = confdir+"desktopsettings.conf";
@@ -461,7 +461,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion){
}
//Convert the favorites framework as necessary (change occured with 0.8.4)
if(newversion || newrelease){
- LDesktopUtils::upgradeFavorites(oldversion);
+ LDesktopUtils::upgradeFavorites(oldversion);
}
//Convert from the old desktop numbering system to the new one (change occured with 1.0.1)
if(oldversion<=1000001){
@@ -488,7 +488,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion){
}
LUtils::writeFile(dset, DS, true);
}
-
+
//Check the fluxbox configuration files
dset = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/";
if(!QFile::exists(dset+"fluxbox-init")){
@@ -517,7 +517,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion){
int LDesktopUtils::VersionStringToNumber(QString version){
version = version.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;
+ maj = mid = min = 0;
bool ok = true;
maj = version.section(".",0,0).toInt(&ok);
if(ok){ mid = version.section(".",1,1).toInt(&ok); }else{ maj = 0; }
diff --git a/src-qt5/core/libLumina/LIconCache.h b/src-qt5/core/libLumina/LIconCache.h
index 0344e0f3..f58a5510 100644
--- a/src-qt5/core/libLumina/LIconCache.h
+++ b/src-qt5/core/libLumina/LIconCache.h
@@ -69,7 +69,7 @@ private:
private slots:
void IconLoaded(QString id, QDateTime sync, QByteArray *data);
-
+
signals:
void InternalIconLoaded(QString, QDateTime, QByteArray*); //INTERNAL SIGNAL - DO NOT USE in other classes/objects
void IconAvailable(QString); //way for classes to listen/reload icons as they change
diff --git a/src-qt5/core/libLumina/LuminaX11.cpp b/src-qt5/core/libLumina/LuminaX11.cpp
index ab6cd880..dd98d12c 100644
--- a/src-qt5/core/libLumina/LuminaX11.cpp
+++ b/src-qt5/core/libLumina/LuminaX11.cpp
@@ -75,9 +75,6 @@ void LXCB::createWMAtoms(){
i--;
}
}
-
-
-
}
// === WindowList() ===
@@ -91,13 +88,13 @@ QList<WId> LXCB::WindowList(bool rawlist){
if( 1 == xcb_ewmh_get_client_list_reply( &EWMH, cookie, &winlist, NULL) ){
//qDebug() << " - Loop over items";
unsigned int wkspace = CurrentWorkspace();
- for(unsigned int i=0; i<winlist.windows_len; i++){
+ for(unsigned int i=0; i<winlist.windows_len; i++){
//Filter out the Lumina Desktop windows
if(WindowClass(winlist.windows[i]) == "Lumina Desktop Environment"){ continue; }
//Also filter out windows not on the active workspace
else if( (WindowWorkspace(winlist.windows[i])!=wkspace) && !rawlist ){ continue; }
else{
- output << winlist.windows[i];
+ output << winlist.windows[i];
}
}
}
@@ -182,7 +179,7 @@ void LXCB::SetCurrentWorkspace(int number){
event.data.data32[4] = 0;
xcb_send_event(QX11Info::connection(), 0, QX11Info::appRootWindow(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
-
+
//EWMH function (does not seem to be recognized by Fluxbox)
xcb_ewmh_request_change_showing_desktop(&EWMH, QX11Info::appScreen(), number);
}
@@ -193,7 +190,7 @@ QString LXCB::WindowClass(WId win){
QString out;
if(win==0){ return ""; }
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win);
- if(cookie.sequence == 0){ return out; }
+ if(cookie.sequence == 0){ return out; }
xcb_icccm_get_wm_class_reply_t value;
if( 1== xcb_icccm_get_wm_class_reply( QX11Info::connection(), cookie, &value, NULL) ){
out = QString::fromUtf8(value.class_name);
@@ -210,7 +207,7 @@ unsigned int LXCB::WindowWorkspace(WId win){
uint32_t wkspace = 0;
xcb_get_property_cookie_t scookie = xcb_ewmh_get_wm_state_unchecked(&EWMH, win);
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&EWMH, win);
- if(cookie.sequence == 0){ return wkspace; }
+ if(cookie.sequence == 0){ return wkspace; }
xcb_ewmh_get_wm_desktop_reply(&EWMH, cookie, &wkspace, NULL);
xcb_ewmh_get_atoms_reply_t reply;
if(1==xcb_ewmh_get_wm_state_reply(&EWMH,scookie, &reply, NULL)){
@@ -220,7 +217,7 @@ unsigned int LXCB::WindowWorkspace(WId win){
}
}
//qDebug() << " - done: " << wkspace;
- return wkspace;
+ return wkspace;
}
// === WindowGeometry() ===
@@ -500,7 +497,7 @@ QIcon LXCB::WindowIcon(WId win){
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;
+ ((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
@@ -1514,7 +1511,7 @@ void LXCB::WM_Set_Client_List(QList<WId> list, bool stacking){
xcb_ewmh_set_client_list_stacking(&EWMH, QX11Info::appScreen(), list.length(), array);
}else{
xcb_ewmh_set_client_list(&EWMH, QX11Info::appScreen(), list.length(), array);
- }
+ }
}
@@ -1528,7 +1525,7 @@ unsigned int LXCB::WM_Get_Number_Desktops(){
}
void LXCB::WM_SetNumber_Desktops(unsigned int number){
- //NOTE: number should be at least 1
+ //NOTE: number should be at least 1
xcb_ewmh_set_number_of_desktops(&EWMH, QX11Info::appScreen(), number);
}
@@ -1555,7 +1552,7 @@ QList<QPoint> LXCB::WM_Get_Desktop_Viewport(){
out << QPoint( reply.desktop_viewport[i].x, reply.desktop_viewport[i].y );
}
xcb_ewmh_get_desktop_viewport_reply_wipe(&reply); //clean up the reply structure first
- }
+ }
return out;
}
diff --git a/src-qt5/core/libLumina/LuminaXDG.h b/src-qt5/core/libLumina/LuminaXDG.h
index d159ef43..cc250c7e 100644
--- a/src-qt5/core/libLumina/LuminaXDG.h
+++ b/src-qt5/core/libLumina/LuminaXDG.h
@@ -12,8 +12,6 @@
// *.desktop Exec Compliance Updated: 9/9/2014
// Mime Application Version Compliance: 1.0.1 (11/14/14) (Skips random *.desktop parsing: ~80% compliant)
//===========================================
-
-
#ifndef _LUMINA_LIBRARY_XDG_H
#define _LUMINA_LIBRARY_XDG_H
@@ -83,7 +81,7 @@ public:
bool saveDesktopFile(bool merge = true); //This will use the "filePath" variable for where to save the file
- bool setAutoStarted(bool autostart = true);
+ bool setAutoStarted(bool autostart = true);
};
// ========================
@@ -127,29 +125,29 @@ private:
XDGDesktop *desk;
void loadExtraInfo();
-
+
public:
//Couple overloaded contructors
LFileInfo();
LFileInfo(QString filepath);
LFileInfo(QFileInfo info);
- ~LFileInfo(){
- desk->deleteLater();
+ ~LFileInfo(){
+ desk->deleteLater();
}
-
+
//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 isAVFile(); //Is an audio/video file
@@ -165,7 +163,7 @@ public:
//static XDGDesktop* loadDesktopFile(QString filepath, bool&ok, QObject *parent = 0);
//static bool saveDesktopFile(XDGDesktop *dFile, bool merge = true);
//Check a *.desktop file for validity (showAll skips the DE-exclusivity checks)
- //static bool checkValidity(XDGDesktop *dFile, bool showAll = true);
+ //static bool checkValidity(XDGDesktop *dFile, bool showAll = true);
//Check for a valid executable
static bool checkExec(QString exec);
//Get a list of all the directories where *.desktop files exist
@@ -210,7 +208,7 @@ public:
static QStringList findAVFileExtensions();
//Load all the "globs2" mime database files
static QStringList loadMimeFileGlobs2();
-
+
//Find all the autostart *.desktop files
static QList<XDGDesktop*> findAutoStartFiles(bool includeInvalid = false);
//static bool setAutoStarted(bool autostart, XDGDesktop *app);
diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.cpp b/src-qt5/core/libLumina/NativeEmbedWidget.cpp
new file mode 100644
index 00000000..80c843e0
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeEmbedWidget.cpp
@@ -0,0 +1,208 @@
+//===========================================
+// 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 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; }
+ 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());
+}
+
+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){ 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){ 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
+ 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
+ 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());
+ 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
+// ==============
+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);
+
+ xcb_flush(QX11Info::connection());
+}
+
+void NativeEmbedWidget::repaintWindow(){
+ this->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){
+ //QWidget::paintEvent(ev); //ensure all the Qt-compositing is done first
+ if(this->size()!=winSize){ return; } //do not paint here - waiting to re-sync the sizes
+ if(WIN==0){ QWidget::paintEvent(ev); return; }
+ //Need to paint the image from the window onto the widget as an overlay
+ QRect geom = QRect(0,0,this->width(), this->height()); //always paint the whole window
+ //qDebug() << "Get Paint image:" << ev->rect() << geom;
+ //geom = ev->rect(); //atomic updates
+ //geom.adjust(-1,-1,1,1); //add an additional pixel in each direction to be painted
+ //geom = geom.intersected(QRect(0,0,this->width(), this->height())); //ensure intersection with actual window
+ QImage img = windowImage(geom);
+ if(!img.isNull()){
+ if(img.size() != geom.size()){ return; }
+ QPainter P(this);
+ P.drawImage( geom , img, QRect(geom.topLeft(), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping
+ //qDebug() << "Painted Rect:" << ev->rect() << this->geometry();
+ //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 most of the time.
+ }
+ //qDebug() << "Done Painting";
+}
diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.h b/src-qt5/core/libLumina/NativeEmbedWidget.h
new file mode 100644
index 00000000..78c11dfc
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeEmbedWidget.h
@@ -0,0 +1,55 @@
+//===========================================
+// 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;
+
+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:
+ 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
new file mode 100644
index 00000000..d6c2da50
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeEventFilter.cpp
@@ -0,0 +1,272 @@
+//===========================================
+// 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;
+ }
+}
+
+
+//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
+ }
+ 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
new file mode 100644
index 00000000..2b184f99
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeEventFilter.h
@@ -0,0 +1,70 @@
+//===========================================
+// 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
new file mode 100644
index 00000000..06056be7
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeKeyToQt.cpp
@@ -0,0 +1,528 @@
+
+#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
index 97131b52..94d39cb7 100644
--- a/src-qt5/core/libLumina/NativeWindow.cpp
+++ b/src-qt5/core/libLumina/NativeWindow.cpp
@@ -6,59 +6,96 @@
//===========================================
#include "NativeWindow.h"
+#include <QDebug>
+
// === PUBLIC ===
NativeWindow::NativeWindow(WId id) : QObject(){
winid = id;
- WIN = QWindow::fromWinId(winid);
+ frameid = 0;
+ dmgID = 0;
}
NativeWindow::~NativeWindow(){
hash.clear();
- //WIN->deleteLater(); //This class only deals with Native windows which were created outside the app - they need to be cleaned up outside the app too
+}
+
+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;
}
-QWindow* NativeWindow::window(){
- return WIN;
+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){
- if(prop == NativeWindow::None || hash.value(prop)==val){ return; }
- hash.insert(prop, val);
+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){
+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 propertu
- if(props[i] == NativeWindow::None || (hash.value(props[i]) == vals[i]) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value
+ 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){
- if(prop == NativeWindow::None || hash.value(prop)==val ){ return; }
+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){
+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 || hash.value(props[i])==vals[i] ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value
+ 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)
+ QRect geom( hash.value(NativeWindow::GlobalPos).toPoint(), hash.value(NativeWindow::Size).toSize() );
+ //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);
diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h
index fbdf9e1b..47359b7d 100644
--- a/src-qt5/core/libLumina/NativeWindow.h
+++ b/src-qt5/core/libLumina/NativeWindow.h
@@ -5,8 +5,8 @@
// 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,
+// 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
//===========================================
@@ -29,10 +29,10 @@ public:
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, /*null*/
- MinSize, /*QSize*/
- MaxSize, /*QSize*/
- Size, /*QSize*/
+ None=0, /*null*/
+ MinSize, /*QSize*/
+ MaxSize, /*QSize*/
+ Size, /*QSize*/
GlobalPos, /*QPoint*/
Title, /*QString*/
ShortTitle, /*QString*/
@@ -41,31 +41,41 @@ public:
Workspace, /*int*/
States, /*QList<NativeWindow::State> : Current state of the window */
WinTypes, /*QList<NativeWindow::Type> : Current type of window (typically does not change)*/
- WinActions, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/
- FrameExtents, /*QList<int> : [Left, Right, Top, Bottom] in pixels */
+ WinActions, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/
+ FrameExtents, /*QList<int> : [Left, Right, Top, Bottom] in pixels */
+ RelatedWindows, /* QList<WId> - better to use the "isRelatedTo(WId)" function instead of reading this directly*/
Active, /*bool*/
Visible /*bool*/
};
static QList<NativeWindow::Property> allProperties(){
- //Return all the available properties (excluding "None")
+ //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 << Active << Visible;
+ << States << WinTypes << WinActions << RelatedWindows << Active << Visible;
return props;
};
NativeWindow(WId id);
~NativeWindow();
+ void addFrameWinID(WId);
+ void addDamageID(unsigned int);
+ bool isRelatedTo(WId);
+
WId id();
- QWindow* window();
+ WId frameId();
+ unsigned int damageId();
+
+ //QWindow* window();
QVariant property(NativeWindow::Property);
- void setProperty(NativeWindow::Property, QVariant);
- void setProperties(QList<NativeWindow::Property>, QList<QVariant>);
- void requestProperty(NativeWindow::Property, QVariant);
- void requestProperties(QList<NativeWindow::Property>, QList<QVariant>);
+ 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)
@@ -74,8 +84,10 @@ public slots:
private:
QHash <NativeWindow::Property, QVariant> hash;
- QWindow *WIN;
- WId winid;
+ //QWindow *WIN;
+ WId winid, frameid;
+ QList<WId> relatedTo;
+ unsigned int dmgID;
signals:
//General Notifications
@@ -83,15 +95,23 @@ signals:
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 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
index a5715287..c2ac0137 100644
--- a/src-qt5/core/libLumina/NativeWindow.pri
+++ b/src-qt5/core/libLumina/NativeWindow.pri
@@ -1,12 +1,17 @@
# Files
QT *= x11extras
-LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lXdamage
+LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lxcb-keysyms -lXdamage
SOURCES *= $${PWD}/NativeWindow.cpp \
- $${PWD}/NativeWindowSystem.cpp
+ $${PWD}/NativeWindowSystem.cpp \
+ $${PWD}/NativeKeyToQt.cpp \
+ $${PWD}/NativeEventFilter.cpp \
+ $${PWD}/NativeEmbedWidget.cpp
HEADERS *= $${PWD}/NativeWindow.h \
- $${PWD}/NativeWindowSystem.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
index 36a0b7f0..e0f3fe91 100644
--- a/src-qt5/core/libLumina/NativeWindowSystem.cpp
+++ b/src-qt5/core/libLumina/NativeWindowSystem.cpp
@@ -14,6 +14,10 @@
#include <QDebug>
#include <QApplication>
#include <QScreen>
+#include <QFont>
+#include <QFontMetrics>
+#include <QKeySequence>
+
//XCB Library includes
#include <xcb/xcb.h>
@@ -48,6 +52,22 @@
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:
@@ -58,15 +78,21 @@ public:
//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"
- << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION"
+ 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);
+ 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
@@ -81,9 +107,19 @@ public:
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));
+ 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
@@ -97,7 +133,7 @@ public:
//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));
+ 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;
}
@@ -144,18 +180,18 @@ public:
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);
+ 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[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;
@@ -175,6 +211,7 @@ public:
NativeWindowSystem::NativeWindowSystem() : QObject(){
obj = 0;
pingTimer = 0;
+ screenLocked = false;
}
NativeWindowSystem::~NativeWindowSystem(){
@@ -200,7 +237,12 @@ bool NativeWindowSystem::start(){
if( !obj->init_ATOMS() ){ return false; }
} //Done with private object init
bool ok = obj->register_wm();
- if(ok){ ok = obj->start_system_tray(); }
+ if(ok){
+ setRoot_supportedActions();
+ ok = obj->start_system_tray();
+ }else{
+ qWarning() << "Could not register the WM";
+ }
return ok;
}
@@ -208,37 +250,30 @@ void NativeWindowSystem::stop(){
}
-//Small simplification functions
-Qt::Key NativeWindowSystem::KeycodeToQt(int keycode){
- 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;
+// === 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() || id==NWindows[i]->frameId() ){ 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;
}
-// === PRIVATE ===
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)){
@@ -255,7 +290,7 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native
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){
+ 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);
@@ -271,7 +306,7 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native
xcb_icccm_get_text_property_reply_wipe(&reply);
}
}
- win->setProperty(NativeWindow::Name, name);
+ win->setProperty(NativeWindow::Title, name);
} //end TITLE property
if(props.contains(NativeWindow::ShortTitle)){
@@ -288,7 +323,7 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native
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){
+ 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);
@@ -337,7 +372,7 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native
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;
+ ((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
@@ -350,7 +385,7 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native
win->setProperty(NativeWindow::Icon, icon);
} //end ICON property
- if(props.contains(NativeWindow::MinSize) || props.contains(NativeWindow::MaxSize)
+ 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());
@@ -401,41 +436,244 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native
}*/
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 only used by the desktop system itself or the NativeWindowEventFilter
-void NativeWindowSystem::RegisterVirtualRoot(WId){
+//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) != 0){ return; } //already managed
+ 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);
- //Register for events from this 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)
-
- uint32_t value_list[1] = {NORMAL_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);
+ //Register for events from this window
+ registerClientEvents(win->id());
NWindows << win;
UpdateWindowProperties(win, NativeWindow::allProperties());
+ qDebug() << "New Window [& associated ID's]:" << win->id() << 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);
}
@@ -457,7 +695,7 @@ void NativeWindowSystem::NewTrayWindowDetected(WId id){
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
@@ -468,30 +706,66 @@ void NativeWindowSystem::NewTrayWindowDetected(WId id){
}
void NativeWindowSystem::WindowCloseDetected(WId id){
- NativeWindow *win = findWindow(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);
- win->deleteLater();
+ qDebug() << "Visible Window Closed!!!";
+ //win->deleteLater();
}else{
win = findTrayWindow(id);
if(win!=0){
TWindows.removeAll(win);
win->emit WindowClosed(id);
- win->deleteLater();
+ win->deleteLater();
}
}
+ //qDebug() << " - Now:" << NWindows.length();
}
void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop){
- //NOTE: This is triggered by the NativeWindowEventFilter - not by changes to the NativeWindow objects themselves
- NativeWindow *win = findWindow(id);
+ //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);
@@ -499,56 +773,40 @@ void NativeWindowSystem::GotPong(WId id){
if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); }
}
-/*void NativeWindowSystem::NewKeyPress(int keycode, WId win){
+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();
- //Convert the native button code into a Qt keycode
- //Qt::Key key = keycode; //TODO
- //emit KeyReleaseDetected( key, win);
+ 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();
- //Convert the native button code into a Qt mouse button code
- Qt::MouseButton button;
- switch(buttoncode){
- case 1:
- button = Qt::LeftButton ; break;
- case 2:
- button = Qt::MiddleButton ; break;
- case 3:
- button = Qt::RightButton ; break;
- case 4:
- button = Qt::LeftButton ; break;
- default:
- return; //Unhandled button
- }
- emit MousePressDetected(button, win);
+ if(screenLocked){ return; }
+ emit MousePressDetected(win, MouseToQt(buttoncode));
}
void NativeWindowSystem::NewMouseRelease(int buttoncode, WId win){
emit NewInputEvent();
- //Convert the native button code into a Qt mouse button code
- Qt::MouseButton button;
- switch(buttoncode){
- case 1:
- button = Qt::LeftButton ; break;
- case 2:
- button = Qt::MiddleButton ; break;
- case 3:
- button = Qt::RightButton ; break;
- case 4:
- button = Qt::LeftButton ; break;
- default:
- return; //Unhandled button
- }
- emit MouseReleaseDetected(button, win);
-}*/
+ 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);
@@ -557,15 +815,6 @@ void NativeWindowSystem::CheckDamageID(WId win){
// === PRIVATE SLOTS ===
//These are the slots which are built-in and automatically connected when a new NativeWindow is created
-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
-
-}
void NativeWindowSystem::RequestClose(WId win){
//Send the window a WM_DELETE_WINDOW message
@@ -598,3 +847,53 @@ void NativeWindowSystem::RequestPing(WId win){
}
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
index 59e54ca4..97208c2f 100644
--- a/src-qt5/core/libLumina/NativeWindowSystem.h
+++ b/src-qt5/core/libLumina/NativeWindowSystem.h
@@ -14,6 +14,7 @@
#include "NativeWindow.h"
#include <QDateTime>
#include <QTimer>
+#include <QDebug>
class NativeWindowSystem : public QObject{
Q_OBJECT
@@ -22,21 +23,11 @@ private:
QList<NativeWindow*> TWindows;
//Simplifications to find an already-created window object
- NativeWindow* findWindow(WId id){
- for(int i=0; i<NWindows.length(); i++){
- if(id==NWindows[i]->id()){ return NWindows[i]; }
- }
- return 0;
- }
+ NativeWindow* findWindow(WId id, bool checkRelated = true);
- NativeWindow* findTrayWindow(WId id){
- for(int i=0; i<TWindows.length(); i++){
- if(id==TWindows[i]->id()){ return TWindows[i]; }
- }
- return 0;
- }
+ NativeWindow* findTrayWindow(WId id);
- //Now define a simple private_objects class so that each implementation
+ //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;
@@ -58,12 +49,16 @@ private:
}
}
- // Since some properties may be easier to update in bulk
+ // 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 Property{ None, CurrentWorkspace, Workspaces, VirtualRoots, WorkAreas };
enum MouseButton{NoButton, LeftButton, RightButton, MidButton, BackButton, ForwardButton, TaskButton, WheelUp, WheelDown, WheelLeft, WheelRight};
NativeWindowSystem();
@@ -84,11 +79,25 @@ public:
public slots:
//These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter
- //RootWindow interactions
+ //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);
- //void RegisterWorkspaces(QStringList); //Names of workspaces, in ascending order
- //void RegisterKnownInteractions();
//NativeWindowEventFilter interactions
@@ -96,29 +105,33 @@ public slots:
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 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 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 RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>);
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(Qt::Key, WId); //only emitted if lockstate = false
- void KeyReleaseDetected(Qt::Key, WId); //only emitted if lockstate = false
- void MousePressDetected(Qt::MouseButton, WId); //only emitted if lockstate = false
- void MouseReleaseDetected(Qt::MouseButton, WId); //only emitted if lockstate = false
+ 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
};
diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp
index 41c04ee1..9ef6464e 100644
--- a/src-qt5/core/libLumina/RootSubWindow.cpp
+++ b/src-qt5/core/libLumina/RootSubWindow.cpp
@@ -8,9 +8,12 @@
#include <QDebug>
#include <QApplication>
#include <QVBoxLayout>
-#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QTimer>
+
+#define WIN_BORDER 5
-#define WIN_BORDER 3
+#include <LIconCache.h>
// === PUBLIC ===
RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){
@@ -19,15 +22,18 @@ RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){
//Create the QWindow and QWidget containers for the window
WIN = win;
closing = false;
- WinWidget = QWidget::createWindowContainer( WIN->window(), this);
initWindowFrame();
- LoadProperties( NativeWindow::allProperties() );
//Hookup the signals/slots
connect(WIN, SIGNAL(PropertiesChanged(QList<NativeWindow::Property>, QList<QVariant>)), this, SLOT(propertiesChanged(QList<NativeWindow::Property>, QList<QVariant>)));
+ WinWidget->embedWindow(WIN);
+ //qDebug() << "[NEW WINDOW]" << WIN->id() << WinWidget->winId() << this->winId();
+ activeState = RootSubWindow::Normal;
+ LoadAllProperties();
}
RootSubWindow::~RootSubWindow(){
-
+ //qDebug() << "Visible Window Destroyed";
+ WIN->deleteLater();
}
WId RootSubWindow::id(){
@@ -41,41 +47,57 @@ RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset
//above the frame itself - need to figure out which quadrant it is in (8-directions)
if(pt.y() < WIN_BORDER){
//One of the top options
- if(pt.x() < WIN_BORDER){
+ if(pt.x() < this->width()/5){
if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
return ResizeTopLeft;
- }else if(pt.x() > (this->width()-WIN_BORDER)){
+ }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
return ResizeTopRight;
- }else{
+ }else{
if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter)
- return ResizeTop;
- }
+ return ResizeTop;
+ }
}else if(pt.y() > (this->height()-WIN_BORDER) ){
//One of the bottom options
- if(pt.x() < WIN_BORDER){
+ if(pt.x() < this->width()/5){
if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
return ResizeBottomLeft;
- }else if(pt.x() > (this->width()-WIN_BORDER)){
+ }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
return ResizeBottomRight;
- }else{
+ }else{
if(setoffset){ offset.setX(0); offset.setY(this->height() - pt.y()); } //difference from bottom edge (X does not matter)
- return ResizeBottom;
- }
- }else{
- //One of the side options
- if(pt.x() < WIN_BORDER){
+ return ResizeBottom;
+ }
+ }else if(pt.x() < WIN_BORDER){
+ //Left side options
+ if(pt.y() < this->height()/5){
+ 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
+ return ResizeBottomLeft;
+ }else{
if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter)
return ResizeLeft;
- }else if(pt.x() > (this->width()-WIN_BORDER) ){
+ }
+ }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
+ 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
+ return ResizeBottomRight;
+ }else{
if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(0); } //difference from right edge (Y does not matter)
return ResizeRight;
- }else{
- return Normal;
}
+ }else{
+ return Normal;
}
}
+ //if it gets this far just return normal
return Normal;
}
@@ -112,7 +134,7 @@ void RootSubWindow::setMouseCursor(ModState state, bool override){
break;
case ResizeTopLeft:
shape = Qt::SizeFDiagCursor;
- break;
+ break;
}
if(override){
QApplication::setOverrideCursor(QCursor(shape));
@@ -123,31 +145,48 @@ void RootSubWindow::setMouseCursor(ModState state, bool override){
}
void RootSubWindow::initWindowFrame(){
+ //qDebug() << "Create RootSubWindow Frame";
+ this->setContentsMargins(0,0,0,0);
mainLayout = new QVBoxLayout(this);
- titleBar = new QHBoxLayout(this);
+ mainLayout->setContentsMargins(0,0,0,0);
+ titleBar = new QWidget(this);
+ titleBar->setContentsMargins(0,0,0,0);
+ titleBarL = new QHBoxLayout(titleBar);
+ titleBarL->setContentsMargins(0,0,0,0);
closeB = new QToolButton(this);
maxB = new QToolButton(this);
minB = new QToolButton(this);
otherB = new QToolButton(this);
+ anim = new QPropertyAnimation(this);
+ anim->setTargetObject(this);
+ anim->setDuration(200); //1/5 second (appx)
+ connect(anim, SIGNAL(finished()), this, SLOT(animFinished()) );
titleLabel = new QLabel(this);
titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
otherM = new QMenu(this); //menu of other actions
otherB->setMenu(otherM);
otherB->setPopupMode(QToolButton::InstantPopup);
otherB->setAutoRaise(true);
+ WinWidget = new NativeEmbedWidget(this);
connect(closeB, SIGNAL(clicked()), this, SLOT(triggerClose()) );
connect(maxB, SIGNAL(clicked()), this, SLOT(toggleMaximize()) );
connect(minB, SIGNAL(clicked()), this, SLOT(toggleMinimize()) );
//Now assemble the frame layout based on the current settings
- this->setLayout(mainLayout);
- titleBar->addWidget(otherB);
- titleBar->addWidget(titleLabel);
- titleBar->addWidget(minB);
- titleBar->addWidget(maxB);
- titleBar->addWidget(closeB);
+ titleBarL->addWidget(otherB);
+ titleBarL->addWidget(titleLabel);
+ titleBarL->addWidget(minB);
+ titleBarL->addWidget(maxB);
+ titleBarL->addWidget(closeB);
WinWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- mainLayout->addLayout(titleBar);
+ titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ mainLayout->addWidget(titleBar);
mainLayout->addWidget(WinWidget);
+ //Setup the cursors for the buttons
+ closeB->setCursor(Qt::ArrowCursor);
+ minB->setCursor(Qt::ArrowCursor);
+ maxB->setCursor(Qt::ArrowCursor);
+ otherM->setCursor(Qt::ArrowCursor);
+ titleLabel->setCursor(Qt::ArrowCursor);
//Now all the stylesheet options
this->setObjectName("WindowFrame");
closeB->setObjectName("Button_Close");
@@ -155,36 +194,82 @@ void RootSubWindow::initWindowFrame(){
maxB->setObjectName("Button_Maximize");
otherM->setObjectName("Menu_Actions");
titleLabel->setObjectName("Label_Title");
- this->setStyleSheet("QWidget#WindowFrame{background-color: darkblue;} QWidget#Label_Title{background-color: transparent; color: white; }");
+ this->setStyleSheet("QFrame#WindowFrame{background-color: rgba(0,0,0,125)} QWidget#Label_Title{background-color: transparent; color: white; } QToolButton{background-color: transparent; border: 1px solid transparent; border-radius: 3px; } QToolButton::hover{background-color: rgba(255,255,255,150); } QToolButton::pressed{ background-color: white; } QToolButton::menu-arrow{ image: none; }");
//And adjust the margins
- mainLayout->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER);
mainLayout->setSpacing(0);
- titleBar->setSpacing(1);
- titleBar->setContentsMargins(0,0,0,0);
+ titleBarL->setSpacing(1);
+ this->setFrameStyle(QFrame::NoFrame);
+ this->setLineWidth(0);
+ this->setMidLineWidth(0);
+ this->setFrameRect(QRect(0,0,0,0));
+
+ //Setup the timer object to syncronize info
+ moveTimer = new QTimer(this);
+ moveTimer->setSingleShot(true);
+ moveTimer->setInterval(100); //1/10 second
+ connect(moveTimer, SIGNAL(timeout()), WinWidget, SLOT(resyncWindow()) );
+
+ //Now load the icons for the button
+ LIconCache::instance()->loadIcon(closeB, "window-close");
+ LIconCache::instance()->loadIcon(maxB, "window-maximize");
+ LIconCache::instance()->loadIcon(minB, "window-minimize");
+ LIconCache::instance()->loadIcon(otherB, "list");
+}
+
+void RootSubWindow::enableFrame(bool on){
+ //Make the individual frame elements visible as needed
+ if(on){ this->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER); }//default border
+ else{ this->setContentsMargins(0, 0, 0, 0); }
+ titleBar->setVisible(on);
+ //And now calculate/save the frame extents
+ QList<int> extents; extents << 0 << 0 << 0 << 0; //left, right, top, bottom
+ if(on){
+ extents[0] = WIN_BORDER;
+ extents[1] = WIN_BORDER;
+ extents[2] = WIN_BORDER + titleBar->height();
+ extents[3] = WIN_BORDER;
+ }
+ //qDebug() << "SET FRAME EXTENTS:" << extents;
+ WIN->requestProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList<int> >(extents) ); //save on raw window itself
+ WIN->setProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList<int> >(extents) ); //save to structure now
}
void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){
QList<QVariant> vals;
+ //Always ensure that visibility changes are evaluated last
+ bool addvisible = false;
for(int i=0; i<list.length(); i++){
+ if(list[i] == NativeWindow::Visible){ list.removeAt(i); i--; addvisible = true; continue; }
vals << WIN->property(list[i]);
}
+ //if(addvisible){ list << NativeWindow::Visible; vals << WIN->property(NativeWindow::Visible); }
propertiesChanged(list, vals);
}
// === PUBLIC SLOTS ===
void RootSubWindow::clientClosed(){
- qDebug() << "Client Closed";
+ //qDebug() << "Client Closed";
closing = true;
- this->close();
+ if(anim->state()!=QAbstractAnimation::Running){ this->close(); }
+}
+
+void RootSubWindow::LoadAllProperties(){
+ QList< NativeWindow::Property> list;
+ list << NativeWindow::WinTypes << NativeWindow::WinActions << NativeWindow::States
+ << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Title << NativeWindow::ShortTitle
+ << NativeWindow::Icon << NativeWindow::Size << NativeWindow::GlobalPos << NativeWindow::Visible << NativeWindow::Active;
+ LoadProperties(list);
+ WIN->requestProperty(NativeWindow::Visible, true);
}
//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()) );
}
void RootSubWindow::toggleMaximize(){
-
+ WIN->setProperty(NativeWindow::Visible, true);
}
void RootSubWindow::triggerClose(){
@@ -219,26 +304,62 @@ void RootSubWindow::startResizing(){
}
-
-
// === PRIVATE SLOTS ===
void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList<QVariant> vals){
for(int i=0; i<props.length() && i<vals.length(); i++){
- if(vals[i].isNull()){ return; } //not the same as a default/empty value - the property has just not been set yet
- //qDebug() << "Set Window Property:" << props[i] << vals[i];
+ if(vals[i].isNull()){ continue; } //not the same as a default/empty value - the property has just not been set yet
+ //qDebug() << "RootSubWindow: Property Changed:" << props[i] << vals[i];
switch(props[i]){
case NativeWindow::Visible:
- if(vals[i].toBool()){ this->show(); }
- else{ this->hide(); }
+ //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry();
+ if(vals[i].toBool()){
+ if(lastGeom.isNull()){ animResetProp = this->geometry(); }
+ else{ animResetProp = lastGeom; }
+ anim->setPropertyName("geometry");
+ anim->setStartValue( QRect(animResetProp.toRect().center(), QSize(0,0)) );
+ anim->setEndValue(animResetProp);
+ this->setGeometry( anim->startValue().toRect() ); //ensure the window is the initial geom before it becomes visible
+ anim->start();
+ this->show();
+ }else{
+ animResetProp = this->geometry(); //hide event - should already be the right geom
+ lastGeom = this->geometry();
+ anim->setPropertyName("geometry");
+ anim->setStartValue(this->geometry());
+ anim->setEndValue( QRect(this->geometry().center(), QSize(0,0) ) );
+ anim->start();
+ QTimer::singleShot(anim->duration(), this, SLOT(hide()) );
+ }
break;
case NativeWindow::Title:
titleLabel->setText(vals[i].toString());
break;
case NativeWindow::Icon:
- otherB->setIcon(vals[i].value< QIcon>());
+ //qDebug() << "Got Icon Change:" << vals[i];
+ if(vals[i].value<QIcon>().isNull() ){ LIconCache::instance()->loadIcon(otherB, "list"); }
+ else{ otherB->setIcon(vals[i].value<QIcon>()); }
+ break;
+ case NativeWindow::GlobalPos:
+ //qDebug() << "Got Global Pos:" << this->pos() << WinWidget->mapToGlobal(QPoint(0,0)) << WIN->geometry().topLeft() << vals[i].toPoint();
+ if(activeState == RootSubWindow::Normal){
+ this->move( WIN->geometry().topLeft() );
+ }
break;
case NativeWindow::Size:
- WinWidget->resize(vals[i].toSize());
+ //qDebug() << " - SIZE CHANGE";
+ if(WIN->property(NativeWindow::FrameExtents).isNull() && (i<props.indexOf(NativeWindow::FrameExtents)) ){
+ //Frame not loaded yet - push this back until after the frame is set
+ props << props.takeAt(i);
+ vals << vals.takeAt(i);
+ i--;
+ }else if(anim->state() != QPropertyAnimation::Running ){
+ if(vals[i].toSize() != WinWidget->size() && activeState==Normal){
+ //qDebug() << "Got Widget Size Change:" << vals[i].toSize() << WinWidget->size();
+ WinWidget->resize(vals[i].toSize());
+ this->resize( WIN->geometry().size() );
+ //qDebug() << " - Size after change:" << WinWidget->size() << this->size() << WIN->geometry();
+ }
+ }
break;
case NativeWindow::MinSize:
WinWidget->setMinimumSize(vals[i].toSize());
@@ -247,19 +368,44 @@ 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()){ WinWidget->setFocus(); }
break;
- /*case NativeWindow::WindowFlags:
- this->setWindowFlags( val.value< Qt::WindowFlags >() );
+ /*case NativeWindow::FrameExtents:
+ qDebug() << " - FRAME CHANGE";
+ if(vals[i].isNull()){
+ vals[i] = QVariant::fromValue<QList<int> >( QList<int>() << WinWidget->geometry().x() << this->width()-WinWidget->geometry().x()-WinWidget->geometry().width() << WinWidget->y() << this->height() - WinWidget->y() - WinWidget->geometry().height() );
+ WIN->setProperty(NativeWindow::FrameExtents, vals[i]);
+ }
+ qDebug() << "Setting Frame Extents:" << vals[i].value<QList<int> >();
+ 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) );
+ break;
default:
qDebug() << "Window Property Unused:" << props[i] << vals[i];
}
}
}
+void RootSubWindow::animFinished(){
+ if(closing){ this->close(); return;}
+ else if(anim->propertyName()=="geometry"){
+ if(!animResetProp.isNull()){
+ /*qDebug() << "Animation Finished, Reset Geometry:" << animResetProp;
+ qDebug() << " - Starting Value:" << anim->startValue();
+ qDebug() << " - Ending Value:" << anim->endValue();
+ qDebug() << " - Current Value:" << this->geometry();*/
+ this->setGeometry( animResetProp.toRect() );
+ }
+ }
+ animResetProp = QVariant(); //clear the variable
+}
+
// === PROTECTED ===
void RootSubWindow::mousePressEvent(QMouseEvent *ev){
+ activate();
+ this->raise();
//qDebug() << "Frame Mouse Press Event";
offset.setX(0); offset.setY(0);
if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse
@@ -274,11 +420,11 @@ void RootSubWindow::mousePressEvent(QMouseEvent *ev){
activeState = getStateAtPoint(ev->pos(), true); //also have it set the offset variable
}
setMouseCursor(activeState, true); //this one is an override cursor
-
+ QFrame::mousePressEvent(ev);
}
void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
- ev->accept();
+ activate(); //make sure this window is "Active"
if(activeState == Normal){
setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
}else{
@@ -352,15 +498,15 @@ void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
default:
break;
}
-
this->setGeometry(geom);
}
+ QFrame::mouseMoveEvent(ev);
}
void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
//Check for a right-click event
//qDebug() << "Frame Mouse Release Event";
- ev->accept();
+ QFrame::mouseReleaseEvent(ev);
if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){
otherM->popup(ev->globalPos());
return;
@@ -368,7 +514,7 @@ void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
activeState = Normal;
QApplication::restoreOverrideCursor();
setMouseCursor( getStateAtPoint(ev->pos()) );
- if(QWidget::mouseGrabber() == this){ this->releaseMouse(); }
+ if(QFrame::mouseGrabber() == this){ this->releaseMouse(); }
}
void RootSubWindow::leaveEvent(QEvent *ev){
@@ -377,3 +523,14 @@ void RootSubWindow::leaveEvent(QEvent *ev){
setMouseCursor(Normal);
}
}
+
+void RootSubWindow::moveEvent(QMoveEvent *ev){
+ //qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry();
+ QFrame::moveEvent(ev);
+ if(!closing && anim->state()!=QAbstractAnimation::Running){
+ moveTimer->start();
+ //WinWidget->resyncWindow();
+ //WIN->requestProperty(NativeWindow::GlobalPos, ev->pos() );
+ }
+
+}
diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h
index 779f783b..de6aba89 100644
--- a/src-qt5/core/libLumina/RootSubWindow.h
+++ b/src-qt5/core/libLumina/RootSubWindow.h
@@ -18,8 +18,9 @@
#include <QLabel>
#include <QToolButton>
#include <QMenu>
+#include <QPropertyAnimation>
#include <NativeWindow.h>
-
+#include <NativeEmbedWidget.h>
class RootSubWindow : public QFrame{
Q_OBJECT
@@ -40,19 +41,28 @@ private:
void setMouseCursor(ModState, bool override = false); //Update the mouse cursor based on state
//Native window embed objects
NativeWindow *WIN;
- QWidget *WinWidget;
+ NativeEmbedWidget *WinWidget;
bool closing;
//Title bar objects
- QBoxLayout *titleBar, *mainLayout;
+ QBoxLayout *titleBarL, *mainLayout;
QToolButton *closeB, *maxB, *minB, *otherB;
QLabel *titleLabel;
QMenu *otherM; //menu of other actions
+ QWidget *titleBar;
+ //Other random objects (animations,etc)
+ QPropertyAnimation *anim;
+ QVariant animResetProp;
+ QTimer *moveTimer;
+ QRect lastGeom; //frame coordinates
+
void initWindowFrame();
+ void enableFrame(bool);
void LoadProperties( QList< NativeWindow::Property> list);
public slots:
void clientClosed();
+ void LoadAllProperties();
//Button Actions - public so they can be tied to key shortcuts and stuff as well
void toggleMinimize();
@@ -67,6 +77,7 @@ public slots:
private slots:
void propertiesChanged(QList<NativeWindow::Property>, QList<QVariant>);
+ void animFinished();
protected:
void mousePressEvent(QMouseEvent*);
@@ -74,6 +85,9 @@ protected:
void mouseReleaseEvent(QMouseEvent*);
void leaveEvent(QEvent *ev);
+ void moveEvent(QMoveEvent *ev);
+
+
};
#endif
diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/RootWindow.cpp
index b1f740d3..31faaf50 100644
--- a/src-qt5/core/libLumina/RootWindow.cpp
+++ b/src-qt5/core/libLumina/RootWindow.cpp
@@ -14,6 +14,7 @@
RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){
qRegisterMetaType<WId>("WId");
autoResizeTimer = 0;
+ this->setMouseTracking(true);
}
RootWindow::~RootWindow(){
@@ -51,7 +52,7 @@ void RootWindow::updateScreenPixmap(screeninfo *info){
QPixmap raw(info->file); //load the image from file
//Now apply the proper aspect ratio as needed
if(info->scale == RootWindow::Stretch || info->scale == RootWindow::Full || info->scale == RootWindow::Fit){
- Qt::AspectRatioMode armode = Qt::KeepAspectRatio;
+ Qt::AspectRatioMode armode = Qt::KeepAspectRatio;
if(info->scale == RootWindow::Stretch ){ armode = Qt::IgnoreAspectRatio; }
else if(info->scale == RootWindow::Full ){ armode = Qt::KeepAspectRatioByExpanding; }
if(raw.height()!=info->area.height() && raw.width() !=info->area.width()){
@@ -60,16 +61,16 @@ void RootWindow::updateScreenPixmap(screeninfo *info){
}
//Now calculate offset and draw width/height
QRect drawRect(0,0, raw.width(), raw.height());
- if(info->scale == RootWindow::Full ){
+ if(info->scale == RootWindow::Full ){
drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 );
}else if(info->scale == RootWindow::Fit ){
- drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 );
+ drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 );
}else if(info->scale == RootWindow::Center ){
- drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 );
+ drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 );
}else if(info->scale == RootWindow::Tile ){
//Draw the entire area - no offset
drawRect.setHeight(info->area.height());
- drawRect.setWidth(info->area.width());
+ drawRect.setWidth(info->area.width());
}else if(info->scale == RootWindow::BottomLeft ){
drawRect.moveTo( 0 , info->area.height() - raw.height() );
}else if(info->scale == RootWindow::BottomRight ){
@@ -130,7 +131,7 @@ void RootWindow::ResizeRoot(){
//Trigger a repaint and send out any signals
this->setGeometry(fullscreen);
this->update();
- emit RootResized();
+ emit RootResized(fullscreen);
if(!valid.isEmpty()){ emit NewScreens(valid); }
if(!invalid.isEmpty()){ emit RemovedScreens(invalid); }
}
@@ -138,7 +139,7 @@ void RootWindow::ResizeRoot(){
void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file){
bool found = false;
for(int i=0; i<WALLPAPERS.length() && !found; i++){
- if(WALLPAPERS[i].id == id){
+ if(WALLPAPERS[i].id == id){
WALLPAPERS[i].scale = scale;
WALLPAPERS[i].file = file;
updateScreenPixmap(&WALLPAPERS[i]);
@@ -168,20 +169,23 @@ void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QStrin
void RootWindow::NewWindow(NativeWindow *win){
RootSubWindow *subwin = 0;
+ qDebug() << "Got New Window:" << win->property(NativeWindow::Title);
for(int i=0; i<WINDOWS.length() && subwin==0; i++){
- if(WINDOWS[i]->id() == win->id()){ subwin = WINDOWS[i]; }
+ if(WINDOWS[i]->id() == win->id()){ subwin = WINDOWS[i]; }
}
if(subwin==0){
subwin = new RootSubWindow(this, win);
connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) );
WINDOWS << subwin;
}
- //subwin->show();
+ //win->setProperty(NativeWindow::Visible, true);
+ //win->requestProperty( NativeWindow::Active, true);
+ win->requestProperties(QList<NativeWindow::Property>() << NativeWindow::Visible << NativeWindow::Active, QList<QVariant>() << true << true);
}
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){ qDebug() << "Remove Window From Root List"; WINDOWS.takeAt(i)->clientClosed(); break; }
}
}
diff --git a/src-qt5/core/libLumina/RootWindow.h b/src-qt5/core/libLumina/RootWindow.h
index 0ae248b5..a7792752 100644
--- a/src-qt5/core/libLumina/RootWindow.h
+++ b/src-qt5/core/libLumina/RootWindow.h
@@ -31,7 +31,7 @@ public:
RootWindow();
~RootWindow();
-
+
void start();
private:
@@ -49,7 +49,7 @@ private:
//Window Management
QList<RootSubWindow*> WINDOWS;
-
+
public slots:
void ResizeRoot();
void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file);
@@ -65,7 +65,7 @@ protected:
signals:
void RegisterVirtualRoot(WId);
- void RootResized();
+ void RootResized(QRect);
void NewScreens(QStringList); // [screen_id_1, screen_id_2, etc..]
void RemovedScreens(QStringList); // [screen_id_1, screen_id_2, etc..]
diff --git a/src-qt5/core/libLumina/RootWindow.pri b/src-qt5/core/libLumina/RootWindow.pri
index 35e0e770..e4d5f00b 100644
--- a/src-qt5/core/libLumina/RootWindow.pri
+++ b/src-qt5/core/libLumina/RootWindow.pri
@@ -10,4 +10,5 @@ INCLUDEPATH *= ${PWD}
# include other library dependencies
include(LUtils.pri)
-include(NativeWindow.pri);
+include(NativeWindow.pri)
+include(LIconCache.pri)
bgstack15