aboutsummaryrefslogtreecommitdiff
path: root/libLumina
diff options
context:
space:
mode:
Diffstat (limited to 'libLumina')
-rw-r--r--libLumina/LuminaOS.h1
-rw-r--r--libLumina/LuminaSingleApplication.cpp107
-rw-r--r--libLumina/LuminaSingleApplication.h54
-rw-r--r--libLumina/LuminaThemes.cpp2
-rw-r--r--libLumina/LuminaUtils.cpp4
-rw-r--r--libLumina/LuminaUtils.h1
-rw-r--r--libLumina/LuminaX11.cpp208
-rw-r--r--libLumina/LuminaX11.h35
-rw-r--r--libLumina/LuminaXDG.cpp19
-rw-r--r--libLumina/LuminaXDG.h2
-rw-r--r--libLumina/libLumina.pro12
-rwxr-xr-x[-rw-r--r--]libLumina/make-linux-distro.sh0
12 files changed, 430 insertions, 15 deletions
diff --git a/libLumina/LuminaOS.h b/libLumina/LuminaOS.h
index 90f68691..7bf0e923 100644
--- a/libLumina/LuminaOS.h
+++ b/libLumina/LuminaOS.h
@@ -16,6 +16,7 @@
#include <QStringList>
#include <QProcess>
#include <QDir>
+#include <QObject>
#include "LuminaUtils.h"
diff --git a/libLumina/LuminaSingleApplication.cpp b/libLumina/LuminaSingleApplication.cpp
new file mode 100644
index 00000000..ce983035
--- /dev/null
+++ b/libLumina/LuminaSingleApplication.cpp
@@ -0,0 +1,107 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2014, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LuminaSingleApplication.h"
+#include <QDir>
+#include <QFile>
+#include <QLocalSocket>
+#include <QDebug>
+
+#include <unistd.h> //for getlogin()
+
+LSingleApplication::LSingleApplication(int &argc, char **argv) : QApplication(argc, argv){
+ //Initialize a couple convenience internal variables
+ cfile = QDir::tempPath()+"/.LSingleApp-%1-%2";
+ QString username = QString(getlogin());
+ QString appname = this->applicationName();
+ //Obscure the user/app in the filename (TO DO)
+ //qDebug() << username << appname;
+ //bool junk;
+ //qDebug() << QString::number( username.toInt(&junk,16) );
+ cfile = cfile.arg( username, appname );
+ lockfile = new QLockFile(cfile+"-lock");
+ lockfile->setStaleLockTime(0); //long-lived processes
+ for(int i=1; i<argc; i++){ inputlist << QString(argv[i]); }
+ isActive = false;
+ lserver = 0;
+ PerformLockChecks();
+}
+
+LSingleApplication::~LSingleApplication(){
+ if(lserver != 0 && lockfile->isLocked() ){
+ //currently locked instance: remove the lock now
+ lserver->close();
+ QLocalServer::removeServer(cfile);
+ lockfile->unlock();
+ }
+}
+
+bool LSingleApplication::isPrimaryProcess(){
+ return isActive;
+}
+
+void LSingleApplication::PerformLockChecks(){
+ bool primary = lockfile->tryLock();
+ //qDebug() << "Try Lock: " << primary;
+ if(!primary){
+ //Pre-existing lock - check it for validity
+ QString appname, hostname;
+ qint64 pid;
+ lockfile->getLockInfo(&pid, &hostname, &appname); //PID already exists if it gets this far, ignore hostname
+ //qDebug() << " - Lock Info:" << pid << hostname << appname;
+ if( appname!=this->applicationName() || !QFile::exists(cfile) ){
+ //Some other process has the same PID or the server does not exist - stale lock
+ //qDebug() << " - Stale Lock";
+ lockfile->removeStaleLockFile();
+ //Now re-try to create the lock
+ primary = lockfile->tryLock();
+ //qDebug() << " - Try Lock Again:" << primary;
+ }
+ }
+ if(primary){
+ //Create the server socket
+ //qDebug() << "Create Local Server";
+ if(QFile::exists(cfile)){ QLocalServer::removeServer(cfile); } //stale socket/server file
+ lserver = new QLocalServer(this);
+ connect(lserver, SIGNAL(newConnection()), this, SLOT(newInputsAvailable()) );
+ if( lserver->listen(cfile) ){
+ lserver->setSocketOptions(QLocalServer::UserAccessOption);
+ //qDebug() << " - Success";
+ isActive = true;
+ }else{
+ //qDebug() << " - Failure:" << lserver->errorString();
+ lockfile->unlock();
+ }
+
+ }else{
+ //forward the current inputs to the locked process for processing and exit
+ //qDebug() << "Forward inputs to locking process:" << inputlist;
+ QLocalSocket socket(this);
+ socket.connectToServer(cfile);
+ socket.waitForConnected();
+ if(!socket.isValid()){ exit(1); } //error - could not forward info
+ socket.write( inputlist.join("::::").toLocal8Bit() );
+ socket.waitForDisconnected(500); //max out at 1/2 second (only hits this if no inputs)
+ }
+
+}
+
+//New messages detected
+void LSingleApplication::newInputsAvailable(){
+ while(lserver->hasPendingConnections()){
+ QLocalSocket *sock = lserver->nextPendingConnection();
+ QByteArray bytes;
+ sock->waitForReadyRead();
+ while(sock->bytesAvailable() > 0){ //if(sock->waitForReadyRead()){
+ //qDebug() << "Info Available";
+ bytes.append( sock->readAll() );
+ }
+ sock->disconnectFromServer();
+ QStringList inputs = QString::fromLocal8Bit(bytes).split("::::");
+ //qDebug() << " - New Inputs Detected:" << inputs;
+ emit InputsAvailable(inputs);
+ }
+} \ No newline at end of file
diff --git a/libLumina/LuminaSingleApplication.h b/libLumina/LuminaSingleApplication.h
new file mode 100644
index 00000000..f61a90c0
--- /dev/null
+++ b/libLumina/LuminaSingleApplication.h
@@ -0,0 +1,54 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2014, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This is the general class for a single-instance application
+//===========================================
+//EXAMPLE USAGE in main.cpp:
+//
+// LSingleApplication app(argc, argv);
+// if( !app.isPrimaryProcess() ){
+// return 0;
+// }
+// QMainWindow w; //or whatever the main window class is
+// connect(app, SIGNAL(InputsAvailable(QStringList)), w, SLOT(<some slot>)); //for interactive apps - optional
+// app.exec();
+//===========================================
+#ifndef _LUMINA_LIBRARY_SINGLE_APPLICATION_H
+#define _LUMINA_LIBRARY_SINGLE_APPLICATION_H
+
+#include <QApplication>
+#include <QString>
+#include <QStringList>
+#include <QLocalServer>
+#include <QLockFile>
+
+
+class LSingleApplication : public QApplication{
+ Q_OBJECT
+public:
+ LSingleApplication(int &argc, char **argv);
+ ~LSingleApplication();
+
+ bool isPrimaryProcess();
+
+private:
+ bool isActive;
+ QLockFile *lockfile;
+ QLocalServer *lserver;
+ QString cfile;
+ QStringList inputlist;
+
+ void PerformLockChecks();
+
+private slots:
+ void newInputsAvailable(); //internally used to detect a message from an alternate instance
+
+signals:
+ void InputsAvailable(QStringList);
+
+};
+
+#endif
diff --git a/libLumina/LuminaThemes.cpp b/libLumina/LuminaThemes.cpp
index feacc81d..fd740e20 100644
--- a/libLumina/LuminaThemes.cpp
+++ b/libLumina/LuminaThemes.cpp
@@ -11,7 +11,7 @@
#include <QIcon>
#include <QFont>
#include <QDebug>
-
+#include <QObject>
QStringList LTHEME::availableSystemThemes(){
//returns: [name::::path] for each item
diff --git a/libLumina/LuminaUtils.cpp b/libLumina/LuminaUtils.cpp
index 830cfc97..ed08857f 100644
--- a/libLumina/LuminaUtils.cpp
+++ b/libLumina/LuminaUtils.cpp
@@ -5,6 +5,10 @@
// See the LICENSE file for full details
//===========================================
#include "LuminaUtils.h"
+#include <QString>
+#include <QFile>
+#include <QStringList>
+#include <QObject>
int LUtils::runCmd(QString cmd, QStringList args){
QProcess *proc = new QProcess;
diff --git a/libLumina/LuminaUtils.h b/libLumina/LuminaUtils.h
index 44bec991..3a75fc3b 100644
--- a/libLumina/LuminaUtils.h
+++ b/libLumina/LuminaUtils.h
@@ -16,6 +16,7 @@
#include <QStringList>
#include <QFile>
#include <QFileInfo>
+#include <QObject>
class LUtils{
public:
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp
index 68d54c6d..699d7b99 100644
--- a/libLumina/LuminaX11.cpp
+++ b/libLumina/LuminaX11.cpp
@@ -6,6 +6,12 @@
//===========================================
#include "LuminaX11.h"
+#include <QString>
+#include <QByteArray>
+#include <QFile>
+#include <QObject>
+#include <QImage>
+
//X includes (these need to be last due to Qt compile issues)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -13,6 +19,27 @@
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h>
+//XCB Library includes
+#include <xcb/xcb.h>
+#include <xcb/xcb_atom.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_ewmh.h>
+#include <xcb/xcb_icccm.h>
+
+//xcb_ewmh_connection_t ewmh_handle;
+
+//===== Get EWMH connection handle =====
+/*xcb_ewmh_connection_t* LX11::EWMH_C(){
+ static bool firstrun = true;
+ if(firstrun){
+ qDebug() << "Init EWMH structure";
+ xcb_ewmh_init_atoms(QX11Info::connection(), &ewmh_handle);
+ firstrun = false;
+ }
+ qDebug() << "Return EWMH structure pointer:" << &ewmh_handle;
+ return &ewmh_handle;
+}*/
+
//===== WindowList() ========
QList<WId> LX11::WindowList(){
QList<WId> output;
@@ -26,7 +53,7 @@ QList<WId> LX11::WindowList(){
QString name = LX11::WindowClass(output[i]);
if(output[i] == 0){ remove=true; }
else if( desk >= 0 && LX11::WindowDesktop(output[i]) != desk){ remove = true; }
- else if( name=="Lumina-DE" ){ remove = true; }
+ else if( name=="Lumina Desktop Environment" ){ remove = true; }
else if(name.startsWith("Lumina-")){
//qDebug() << "Lumina Window:" << name << LX11::WindowName(output[i]);
if(LX11::WindowName(output[i]).toLower()==name.toLower() ){ remove=true; }
@@ -52,6 +79,17 @@ QList<WId> LX11::WindowList(){
// ===== GetClientList() =====
QList<WId> LX11::GetClientList(){
QList<WId> output;
+ //XCB Library
+ /*qDebug() << "Get Client list cookie";
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list_unchecked( LX11::EWMH_C(), 0);
+ xcb_ewmh_get_windows_reply_t winlist;
+ qDebug() << "Get client list";
+ if( xcb_ewmh_get_client_list_reply( LX11::EWMH_C(), cookie, &winlist, NULL) ){
+ qDebug() << " - Loop over items";
+ for(unsigned int i=0; i<winlist.windows_len; i++){ output << winlist.windows[i]; }
+ }*/
+
+ //XLib
Atom a = XInternAtom(QX11Info::display(), "_NET_CLIENT_LIST", true);
Atom realType;
int format;
@@ -90,7 +128,7 @@ QList<WId> LX11::GetClientStackingList(){
}
// ===== findChildren() =====
-QList<WId> LX11::findChildren(Window parent, int levels){
+QList<WId> LX11::findChildren(WId parent, int levels){
Window rootR, parentR;
Window *childrenR;
unsigned int num;
@@ -129,6 +167,9 @@ WId LX11::ActiveWindow(){
// ===== SetNumberOfDesktops() =====
void LX11::SetNumberOfDesktops(int number){
+ //XCB Library
+
+ //XLib
Display *display = QX11Info::display();
Window rootWindow = QX11Info::appRootWindow();
@@ -253,8 +294,13 @@ void LX11::IconifyWindow(WId win){
// ===== RestoreWindow() =====
void LX11::RestoreWindow(WId win){
- Display *disp = QX11Info::display();
- XMapRaised(disp, win); //make it visible again and raise it to the top
+ //XCB Library
+ uint32_t val = XCB_STACK_MODE_ABOVE;
+ xcb_configure_window(QX11Info::connection(), win, XCB_CONFIG_WINDOW_STACK_MODE, &val); //raise it
+ xcb_map_window(QX11Info::connection(), win); //map it
+ //XLib
+ //Display *disp = QX11Info::display();
+ //XMapRaised(disp, win); //make it visible again and raise it to the top
}
// ===== ActivateWindow() =====
@@ -315,12 +361,16 @@ void LX11::ReservePanelLocation(WId win, int xstart, int ystart, int width, int
// ===== SetAsSticky() =====
void LX11::SetAsSticky(WId win){
//make this window "stick" to all virtual desktops
+
+ //XCB Library
+ // xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_APPEND, win, _NET_WM_STATE, XCB_ATOM, 32, 1, _NET_WM_STATE_STICKY);
+
+ //XLib
Display *disp = QX11Info::display();
Atom stick = XInternAtom(disp, "_NET_WM_STATE_STICKY",false);
Atom state = XInternAtom(disp, "_NET_WM_STATE", false);
- XChangeProperty(disp, win, state, XA_ATOM, 32, PropModeAppend, (unsigned char*) &stick, 1);
-
+ XChangeProperty(disp, win, state, XA_ATOM, 32, PropModeAppend, (unsigned char*) &stick, 1L);
}
// ===== SetAsPanel() =====
@@ -549,7 +599,12 @@ int LX11::WindowDesktop(WId win){
// ===== GetWindowState() =====
LX11::WINDOWSTATE LX11::GetWindowState(WId win){
+ LX11::WINDOWSTATE state = LX11::VISIBLE;
+
+ //XCB Library (TO DO)
+
+ //XLib
Display *disp = QX11Info::display();
Atom SA = XInternAtom(disp, "_NET_WM_STATE", true);
Atom ATTENTION = XInternAtom(disp, "_NET_WM_STATE_DEMANDS_ATTENTION", false);
@@ -564,8 +619,7 @@ LX11::WINDOWSTATE LX11::GetWindowState(WId win){
int status = XGetWindowProperty( disp, win, SA, 0, ~(0L), false, AnyPropertyType,
&type, &format, &num, &bytes, (unsigned char**) &data);
-
- LX11::WINDOWSTATE state = LX11::VISIBLE;
+
if(status >= Success && data){
for(unsigned int i=0; i<num; i++){
if(data[i] == SKIPP || data[i]==SKIPT){
@@ -671,7 +725,7 @@ WId LX11::startSystemTray(int screen){
//Get the appropriate atom for this screen
QString str = QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(screen));
qDebug() << "Default Screen Atom Name:" << str;
- Atom _NET_SYSTEM_TRAY_S = XInternAtom(disp,str.toAscii(),false);
+ Atom _NET_SYSTEM_TRAY_S = XInternAtom(disp,str.toLatin1(),false);
//Make sure that there is no other system tray running
if(XGetSelectionOwner(disp, _NET_SYSTEM_TRAY_S) != None){
qWarning() << "An alternate system tray is currently in use";
@@ -783,3 +837,139 @@ QString LX11::getNetWMProp(WId win, QString prop){
}
return property;
}
+
+//===============================
+//===============================
+// XCB LIBRARY FUNCTIONS
+//===============================
+//===============================
+LXCB::LXCB(){
+ 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";
+ }else{
+ qDebug() << "Number of XCB screens:" << EWMH.nb_screens;
+ }
+}
+LXCB::~LXCB(){
+ xcb_ewmh_connection_wipe(&EWMH);
+}
+
+// === WindowList() ===
+QList<WId> LXCB::WindowList(bool rawlist){
+ QList<WId> output;
+ qDebug() << "Get Client list cookie";
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list_unchecked( &EWMH, 0);
+ xcb_ewmh_get_windows_reply_t winlist;
+ qDebug() << "Get client list";
+ 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++){
+ //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];
+ }
+ }
+ }
+ return output;
+}
+
+// === CurrentWorkspace() ===
+unsigned int LXCB::CurrentWorkspace(){
+ qDebug() << "Get Current Workspace";
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop_unchecked(&EWMH, 0);
+ uint32_t wkspace = 0;
+ xcb_ewmh_get_current_desktop_reply(&EWMH, cookie, &wkspace, NULL);
+ qDebug() << " - done:" << wkspace;
+ return wkspace;
+}
+
+// === WindowClass() ===
+QString LXCB::WindowClass(WId win){
+ QString out;
+ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win);
+ xcb_icccm_get_wm_class_reply_t value;
+ if( 1== xcb_icccm_get_wm_class_reply( QX11Info::connection(), cookie, &value, NULL) ){
+ out = QString(value.class_name);
+ }
+ xcb_icccm_get_wm_class_reply_wipe(&value);
+ return out;
+}
+
+// === WindowWorkspace() ===
+unsigned int LXCB::WindowWorkspace(WId win){
+ qDebug() << "Get Window Workspace";
+ uint32_t wkspace = 0;
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&EWMH, win);
+ xcb_ewmh_get_wm_desktop_reply(&EWMH, cookie, &wkspace, NULL);
+ qDebug() << " - done: " << wkspace;
+ return wkspace;
+}
+
+// === WindowState() ===
+LXCB::WINDOWSTATE LXCB::WindowState(WId win){
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state_unchecked(&EWMH, win);
+ xcb_ewmh_get_atoms_reply_t states;
+ WINDOWSTATE cstate = IGNORE;
+ //First Check for special states (ATTENTION in particular);
+ if( 1 == xcb_ewmh_get_wm_state_reply(&EWMH, cookie, &states, NULL) ){
+ for(unsigned int i=0; i<states.atoms_len; i++){
+ if(states.atoms[i] == EWMH._NET_WM_STATE_DEMANDS_ATTENTION){ cstate = ATTENTION; break; } //nothing more urgent - stop here
+ else if(states.atoms[i] == EWMH._NET_WM_STATE_HIDDEN){ cstate = INVISIBLE; }
+ }
+ }
+ //Now check for ICCCM Urgency hint (not sure if this is still valid with EWMH instead)
+ /*if(cstate == IGNORE){
+ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints_unchecked(QX11Info::connection(), win);
+ xcb_icccm_wm_hints_t hints;
+ if( 1== xcb_icccm_get_wm_hints_reply(QX11Info::connection(), cookie, &hints, NULL) ){
+ if(xcb_icccm_wm_hints_get_urgency(hints) ){ cstate = ATTENTION; };
+ }
+ }*/
+ //Now check for standard visible/invisible attribute (current mapping state)
+ if(cstate == IGNORE){
+ xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), win);
+ xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL);
+ if(attr!=0){
+ if(attr->map_state==XCB_MAP_STATE_VIEWABLE){ cstate = VISIBLE; }
+ else{ cstate = INVISIBLE; }
+ free(attr);
+ }
+ }
+ return cstate;
+}
+
+// === SetAsSticky() ===
+void LXCB::SetAsSticky(WId win){
+ xcb_change_property( QX11Info::connection(), XCB_PROP_MODE_APPEND, win, EWMH._NET_WM_STATE, XCB_ATOM_ATOM, 32, 1, &(EWMH._NET_WM_STATE_STICKY) );
+ xcb_flush(QX11Info::connection()); //apply it right away
+}
+
+// === SetScreenWorkArea() ===
+/*void LXCB::SetScreenWorkArea(unsigned int screen, QRect rect){
+ //This is only useful because Fluxbox does not set the _NET_WORKAREA root atom
+ // This needs to be better incorporated into the new window manager later
+
+ //First get the current workarea array (for all monitors/screens)
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_workarea_unchecked(&EWMH, 0);
+ xcb_ewmh_get_workarea_reply_t work;
+ if(0==xcb_ewmh_get_workarea_reply(&EWMH, cookie, &work, NULL)){ return; } //Error: Could not retrieve current work areas
+ //Save what we need only from the reply
+ unsigned int desks = work.workarea_len;
+ if(desks <= screen){ return; } //invalid screen to modify
+ qDebug() << "Number of desktops/screens:" << desks;
+ xcb_ewmh_geometry_t *dareas = work.workarea;
+ //Adjust the work area for the input monitor/screen
+ dareas[screen].x = rect.x();
+ dareas[screen].y = rect.y();
+ dareas[screen].width = rect.width();
+ dareas[screen].height = rect.height();
+ //Now save the array again
+ xcb_ewmh_set_workarea(&EWMH, 0, desks, dareas); //_NET_WORKAREA
+ //Make sure to clear that reply
+ xcb_ewmh_get_workarea_reply_wipe(&work);
+}*/ \ No newline at end of file
diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h
index e7cded49..ac232de1 100644
--- a/libLumina/LuminaX11.h
+++ b/libLumina/LuminaX11.h
@@ -20,6 +20,7 @@
#include <QX11Info>
#include <QDebug>
#include <QPainter>
+#include <QObject>
// Addition includes for compilations (cause issues with X11 libs later)
#include <QDir>
#include <QEvent>
@@ -33,6 +34,8 @@
//#include <X11/Xatom.h>
//#include <X11/extensions/Xrender.h>
+#include <xcb/xcb_ewmh.h>
+
//SYSTEM TRAY STANDARD DEFINITIONS
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
@@ -46,6 +49,9 @@ class LX11{
public:
enum WINDOWSTATE {VISIBLE, INVISIBLE, ACTIVE, ATTENTION, IGNORE};
+ //Internal Use Functions
+ //static xcb_ewmh_connection_t* EWMH_C(); //Get the XCB_ewmh handle;
+
//General Info Functions
static QList<WId> WindowList(); //List all current windows
static QList<WId> GetClientList(); // _NET_WM_CLIENT list
@@ -102,4 +108,33 @@ public:
static QString getNetWMProp(WId win, QString prop); //Returns a _NET_WM_* string value
};
+//XCB Library replacement for LX11 (Qt5 uses XCB instead of XLib)
+class LXCB{
+
+private:
+ xcb_ewmh_connection_t EWMH;
+
+public:
+ enum WINDOWSTATE {VISIBLE, INVISIBLE, ACTIVE, ATTENTION, IGNORE};
+
+ LXCB();
+ ~LXCB();
+
+ //== Main Interface functions ==
+ // General Information
+ QList<WId> WindowList(bool rawlist = false); //list all non-Lumina windows (rawlist -> all workspaces)
+ unsigned int CurrentWorkspace();
+
+ //Session Modification
+
+
+ //Window Information
+ QString WindowClass(WId);
+ unsigned int WindowWorkspace(WId);
+ WINDOWSTATE WindowState(WId win); //Visible state of window
+
+ //Window Modification
+ void SetAsSticky(WId);
+};
+
#endif \ No newline at end of file
diff --git a/libLumina/LuminaXDG.cpp b/libLumina/LuminaXDG.cpp
index 057954dd..84a6f665 100644
--- a/libLumina/LuminaXDG.cpp
+++ b/libLumina/LuminaXDG.cpp
@@ -6,6 +6,8 @@
//===========================================
#include "LuminaXDG.h"
#include "LuminaOS.h"
+#include <QObject>
+#include <QMediaPlayer>
static QStringList mimeglobs;
static qint64 mimechecktime;
@@ -44,7 +46,7 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){
QString var = line.section("=",0,0).simplified();
QString loc = var.section("[",1,1).section("]",0,0).simplified(); // localization
var = var.section("[",0,0).simplified(); //remove the localization
- QString val = line.section("=",1,1).simplified();
+ QString val = line.section("=",1,50).simplified();
//-------------------
if(var=="Name"){
if(DF.name.isEmpty() && loc.isEmpty()){ DF.name = val; }
@@ -558,6 +560,21 @@ void LXDG::setDefaultAppForMime(QString mime, QString app){
return;
}
+QStringList LXDG::findAVFileExtensions(){
+ //output format: QDir name filter for valid A/V file extensions
+ QStringList globs = LXDG::loadMimeFileGlobs2();
+ QStringList av = globs.filter(":audio/");
+ av << globs.filter(":video/");
+ for(int i=0; i<av.length(); i++){
+ //Just use all audio/video mimetypes (for now)
+ av[i] = av[i].section(":",2,2);
+ //Qt5 Auto detection (broken - QMediaPlayer seg faults with Qt 5.3 - 11/24/14)
+ /*if( QMultimedia::NotSupported != QMediaPlayer::hasSupport(av[i].section(":",1,1)) ){ av[i] = av[i].section(":",2,2); }
+ else{ av.removeAt(i); i--; }*/
+ }
+ return av;
+}
+
QStringList LXDG::loadMimeFileGlobs2(){
//output format: <weight>:<mime type>:<file extension (*.something)>
if(mimeglobs.isEmpty() || (mimechecktime < (QDateTime::currentMSecsSinceEpoch()-30000)) ){
diff --git a/libLumina/LuminaXDG.h b/libLumina/LuminaXDG.h
index ec994820..ad09d490 100644
--- a/libLumina/LuminaXDG.h
+++ b/libLumina/LuminaXDG.h
@@ -93,6 +93,8 @@ public:
static QString findDefaultAppForMime(QString mime);
//Set the default application for a mime-type
static void setDefaultAppForMime(QString mime, QString app);
+ //List all the registered audio/video file extensions
+ static QStringList findAVFileExtensions();
//Load all the "globs2" mime database files
static QStringList loadMimeFileGlobs2();
};
diff --git a/libLumina/libLumina.pro b/libLumina/libLumina.pro
index d37c2c0d..5b9cfe6c 100644
--- a/libLumina/libLumina.pro
+++ b/libLumina/libLumina.pro
@@ -1,5 +1,6 @@
-QT += core
+QT += core network
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras multimedia
TARGET=LuminaUtils
@@ -24,12 +25,14 @@ HEADERS += LuminaXDG.h \
LuminaUtils.h \
LuminaX11.h \
LuminaThemes.h \
- LuminaOS.h
+ LuminaOS.h \
+ LuminaSingleApplication.h
SOURCES += LuminaXDG.cpp \
LuminaUtils.cpp \
LuminaX11.cpp \
LuminaThemes.cpp \
+ LuminaSingleApplication.cpp \
LuminaOS-FreeBSD.cpp \
LuminaOS-DragonFly.cpp \
LuminaOS-OpenBSD.cpp \
@@ -39,14 +42,15 @@ SOURCES += LuminaXDG.cpp \
INCLUDEPATH += $$PREFIX/include
-LIBS += -lX11 -lXrender -lXcomposite
+LIBS += -lX11 -lXrender -lXcomposite -lxcb -lxcb-ewmh -lxcb-icccm
include.path=$$PREFIX/include/
include.files=LuminaXDG.h \
LuminaUtils.h \
LuminaX11.h \
LuminaThemes.h \
- LuminaOS.h
+ LuminaOS.h \
+ LuminaSingleApplication.h
colors.path=$$PREFIX/share/Lumina-DE/colors/
colors.files=colors/Lumina-Red.qss.colors \
diff --git a/libLumina/make-linux-distro.sh b/libLumina/make-linux-distro.sh
index 552894d5..552894d5 100644..100755
--- a/libLumina/make-linux-distro.sh
+++ b/libLumina/make-linux-distro.sh
bgstack15