aboutsummaryrefslogtreecommitdiff
path: root/lumina-wm-INCOMPLETE
diff options
context:
space:
mode:
Diffstat (limited to 'lumina-wm-INCOMPLETE')
-rw-r--r--lumina-wm-INCOMPLETE/GlobalDefines.h3
-rw-r--r--lumina-wm-INCOMPLETE/LWindow.cpp151
-rw-r--r--lumina-wm-INCOMPLETE/LWindow.h55
-rw-r--r--lumina-wm-INCOMPLETE/LWindowManager.cpp155
-rw-r--r--lumina-wm-INCOMPLETE/LWindowManager.h40
-rw-r--r--lumina-wm-INCOMPLETE/LXcbEventFilter.cpp169
-rw-r--r--lumina-wm-INCOMPLETE/LXcbEventFilter.h46
-rw-r--r--lumina-wm-INCOMPLETE/WMSession.cpp14
-rw-r--r--lumina-wm-INCOMPLETE/WMSession.h6
-rw-r--r--lumina-wm-INCOMPLETE/lumina-wm.pro6
-rw-r--r--lumina-wm-INCOMPLETE/main.cpp2
11 files changed, 486 insertions, 161 deletions
diff --git a/lumina-wm-INCOMPLETE/GlobalDefines.h b/lumina-wm-INCOMPLETE/GlobalDefines.h
index b6e6587d..68cf927d 100644
--- a/lumina-wm-INCOMPLETE/GlobalDefines.h
+++ b/lumina-wm-INCOMPLETE/GlobalDefines.h
@@ -42,6 +42,7 @@
#include <QHostInfo>
#include <QDesktopWidget>
#include <QStyleOption>
+#include <QThread>
// libLumina includes
#include <LuminaX11.h>
@@ -62,7 +63,7 @@
//Global flags/structures
namespace LWM{
//Flags/enumerations
- enum WindowAction{MoveResize, Show, Hide, TryClose, Closed};
+ enum WindowAction{MoveResize, Show, Hide, TryClose, Closed, WA_NONE};
//Data structures
extern LXCB *SYSTEM;
diff --git a/lumina-wm-INCOMPLETE/LWindow.cpp b/lumina-wm-INCOMPLETE/LWindow.cpp
index 9d9f9fcd..ad34c4dd 100644
--- a/lumina-wm-INCOMPLETE/LWindow.cpp
+++ b/lumina-wm-INCOMPLETE/LWindow.cpp
@@ -6,45 +6,36 @@
//===========================================
#include "LWindow.h"
-LWindow::LWindow(WId client) : QFrame(){
- activeState = LWindow::Normal;
+LWindowFrame::LWindowFrame(WId client, QWidget *parent) : QFrame(parent, Qt::X11BypassWindowManagerHint){
+ activeState = LWindowFrame::Normal;
CID = client;
- qDebug() << "New Window:" << CID << "Frame:" << this->winId();
+ lastAction = LWM::WA_NONE;
+ Closing = false;
+ //qDebug() << "New Window:" << CID << "Frame:" << this->winId();
this->setMouseTracking(true); //need this to determine mouse location when not clicked
this->setObjectName("LWindowFrame");
- this->setStyleSheet("LWindow#LWindowFrame{ border: 2px solid white; border-radius:3px; } QWidget#TitleBar{background: grey; } QLabel{ color: black; }");
- //this->setAttribute(Qt::WA_TranslucentBackground, true);
- //this->setAttribute(Qt::WA_StyledBackground, true);
- this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); //Qt::X11BypassWindowManagerHint); //ensure that this frame does not get a frame itself
+ this->setStyleSheet("LWindowFrame#LWindowFrame{ border: 2px solid white; border-radius:3px; } QWidget#TitleBar{background: grey; } QLabel{ color: black; }");
InitWindow(); //initially create all the child widgets
+ //LWM::SYSTEM->setupEventsForFrame(this->winId());
updateAppearance(); //this loads the appearance based on window/theme settings
- QApplication::processEvents();
+ //QApplication::processEvents();
//Now set the frame size on this window
SyncSize();
- SyncText();
- //LWM::SYSTEM->RestoreWindow(CID);
+ SyncText();
this->show();
}
-LWindow::~LWindow(){
-
+LWindowFrame::~LWindowFrame(){
}
// =================
-// PUBLIC
-// =================
-//Return the ID of the managed window for the current graphics system (X11/Wayland/other)
-WId LWindow::clientID(){ return CID; }
-
-bool LWindow::hasFrame(){ return this->isEnabled(); }
-
-// =================
// PRIVATE
// =================
-void LWindow::InitWindow(){
+void LWindowFrame::InitWindow(){
anim = new QPropertyAnimation(this); //For simple window animations
anim->setTargetObject(this);
anim->setDuration(ANIMTIME); //In milliseconds
+ connect(anim, SIGNAL(finished()), this, SLOT(finishedAnimation()) );
titleBar = new QLabel(this); //This is the "container" for all the title buttons/widgets
titleBar->setObjectName("TitleBar");
titleBar->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
@@ -91,15 +82,20 @@ void LWindow::InitWindow(){
VL->setAlignment(titleBar, Qt::AlignTop);
VL->setContentsMargins(0,0,0,0);
VL->setSpacing(0);
+ //Have the window take the same initial size of the client window
+ this->setGeometry( LWM::SYSTEM->WM_Window_Geom(CID) );
+ qDebug() << "First Geom:" << this->geometry();
+ if(this->width() < 100 && this->height() < 100){ this->resize(100,100); }
+
//Now embed the native window into the frame
WIN = QWindow::fromWinId(CID);
+ WinWidget = QWidget::createWindowContainer( WIN, this);
//WINBACK = new QBackingStore(WIN); //create a data backup for the widget
- this->layout()->addWidget( QWidget::createWindowContainer( WIN, this) );
- //this->layout()-> //set the container as expanding
- VL->setStretch(1,1);
+ //this->layout()->addWidget( WinWidget );
+ //VL->setStretch(1,1);
}
-LWindow::ModState LWindow::getStateAtPoint(QPoint pt, bool setoffset){
+LWindowFrame::ModState LWindowFrame::getStateAtPoint(QPoint pt, bool setoffset){
//Note: pt should be in widget-relative coordinates, not global
if(!this->layout()->geometry().contains(pt)){
//above the frame itself - need to figure out which quadrant it is in (8-directions)
@@ -141,7 +137,7 @@ LWindow::ModState LWindow::getStateAtPoint(QPoint pt, bool setoffset){
return Normal;
}
-void LWindow::setMouseCursor(ModState state, bool override){
+void LWindowFrame::setMouseCursor(ModState state, bool override){
Qt::CursorShape shape;
switch(state){
case Normal:
@@ -185,40 +181,48 @@ void LWindow::setMouseCursor(ModState state, bool override){
// ==========================
// WINDOW INTERACTIONS
//==========================
-void LWindow::SyncSize(){
+void LWindowFrame::SyncSize(bool fromwin){
//sync the window/frame geometries (generally only done before embedding the client window)
int frame = this->frameWidth();
int TH = titleBar->height();
- //SYSTEM->SetFrameValues(CID, frame, frame, frame, frame);
//Now load the information about the window and adjust the frame to match
- lastGeom = LWM::SYSTEM->WindowGeometry(CID,false);
+ if(fromwin){ lastGeom = LWM::SYSTEM->WM_Window_Geom(CID); }
+ else{ lastGeom = this->geometry(); }
qDebug() << "Initial Size:" << lastGeom << frame << TH;
//Add in the frame size
lastGeom.moveTop(lastGeom.y()-frame-TH);
lastGeom.setHeight(lastGeom.height()+(2*frame)+TH);
lastGeom.moveLeft(lastGeom.x()-frame);
lastGeom.setWidth( lastGeom.width()+(2*frame));
+ QList<unsigned int> margins;
+ margins << frame << frame << frame+TH << frame; //L/R/Top/Bottom
qDebug() << " - With Frame:" << lastGeom;
//Now adjust for a out-of-bounds location
if(lastGeom.x() < 0){ lastGeom.moveLeft(0); }
if(lastGeom.y() < 0){ lastGeom.moveTop(0); }
qDebug() << " - Adjusted:" << lastGeom;
this->setGeometry(lastGeom);
+ LWM::SYSTEM->WM_Set_Frame_Extents(CID, margins);
}
-void LWindow::SyncText(){
+void LWindowFrame::SyncText(){
QString txt = WIN->title();
if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowName(CID); }
if(txt.isEmpty()){ txt = LWM::SYSTEM->OldWindowName(CID); }
if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowVisibleName(CID); }
if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowIconName(CID); }
if(txt.isEmpty()){ txt = LWM::SYSTEM->WindowVisibleIconName(CID); }
+ if(txt.isEmpty()){ txt = LWM::SYSTEM->WM_ICCCM_GetClass(CID); }
title->setText(txt);
}
// SIMPLE ANIMATIONS
-void LWindow::showAnimation(LWM::WindowAction act){
- bool useanimation = true; //placeholder for the actual setting check
+void LWindowFrame::showAnimation(LWM::WindowAction act){
+ bool useanimation = (act!=lastAction);
+ if(anim->state()==QAbstractAnimation::Running){
+ qDebug() << "New Animation Event:" << act;
+ return;
+ }
//Setup the animation routine
if(act==LWM::Show){
if(useanimation){
@@ -232,10 +236,13 @@ void LWindow::showAnimation(LWM::WindowAction act){
//anim->setStartValue( 0.0 );
//anim->setEndValue( 1.0 );
}else{
+ if(this->layout()->count() <2){ this->layout()->addWidget(WinWidget); }
+ this->raise();
this->show(); //just show it right away
}
}else if(act==LWM::Hide){
+ if(this->layout()->count() >1){ this->layout()->removeWidget(WinWidget); }
if(useanimation){
//Collapse in on center point
lastGeom = this->geometry();
@@ -248,8 +255,7 @@ void LWindow::showAnimation(LWM::WindowAction act){
}else if(act==LWM::Closed){
//Need to clean up the container widget first to prevent XCB errors
//qDebug() << "Window Closed:" << WIN->winId() << CID;
- //WIN->destroy(); //clean up any data
- if(this->layout()->count()>1){ delete this->layout()->takeAt(1); }
+ if(this->layout()->count() >1){ this->layout()->removeWidget(WinWidget); }
if(useanimation){
//Collapse in on center line
lastGeom = this->geometry();
@@ -257,21 +263,42 @@ void LWindow::showAnimation(LWM::WindowAction act){
anim->setStartValue( QRect(this->geometry()) );
anim->setEndValue( QRect(this->geometry().x(), this->geometry().center().y(), this->width(), 0 ) );
}else{
- this->close(); //just hide it right away
+ CloseAll(); //just hide it right away
}
}
if(useanimation){
+ if(this->layout()->count() >1){ this->layout()->removeWidget(WinWidget); }
this->show();
+ //if(WIN!=0){ LWM::SYSTEM->WM_HideWindow(CID); }
+ qDebug() << " - Starting Animation:" << act;
+ lastAction = act;
anim->start();
- //Also set any final values
- if(act==LWM::Hide){ QTimer::singleShot(ANIMTIME, this, SLOT(hide()) ); }
- if(act==LWM::Closed){ QTimer::singleShot(ANIMTIME, this, SLOT(close()) ); }
};
}
+
+void LWindowFrame::finishedAnimation(){
+ //Also set any final values
+ qDebug() << " - Finished Animation:" << lastAction;
+ switch(lastAction){
+ case LWM::Show:
+ if(WIN!=0 && !Closing){ LWM::SYSTEM->WM_ShowWindow(CID); }
+ if(this->layout()->count()<2){ this->layout()->addWidget(WinWidget); }
+ break;
+ case LWM::Closed:
+ case LWM::Hide:
+ this->hide();
+ default:
+ break;
+ }
+ if(Closing){
+ emit Finished();
+ }
+}
+
// =================
// PUBLIC SLOTS
// =================
-void LWindow::updateAppearance(){
+void LWindowFrame::updateAppearance(){
//Reload any button icons and such
minB->setIcon(LXDG::findIcon("window-suppressed",""));
maxB->setIcon(LXDG::findIcon("view-fullscreen",""));
@@ -279,37 +306,44 @@ void LWindow::updateAppearance(){
otherB->setIcon(LXDG::findIcon("configure",""));
}
-void LWindow::windowChanged(LWM::WindowAction act){
+void LWindowFrame::windowChanged(LWM::WindowAction act){
//A window property was changed - update accordingly
switch(act){
+ case LWM::Closed:
+ /*if(anim->state()==QAbstractAnimation::Running){
+ anim->pause();
+ //delete WinWidget;
+ WIN = 0;
+ anim->resume();
+ }*/
+ Closing = true;
case LWM::Hide:
case LWM::Show:
- case LWM::Closed:
showAnimation(act);
break;
case LWM::MoveResize:
//Re-adjust to the new position/size of the window
-
+ SyncSize(true);
break;
+ default:
+ break; //do nothing
}
}
// =================
// PRIVATE SLOTS
// =================
-void LWindow::closeClicked(){
- qDebug() << "Closing Window";
+void LWindowFrame::closeClicked(){
+ qDebug() << "Closing Window" << LWM::SYSTEM->WM_ICCCM_GetClass(CID);
//First try the close event to let the client app do cleanup/etc
- WIN->hide();
LWM::SYSTEM->WM_CloseWindow(CID);
- showAnimation(LWM::Closed); //temporary testing line - should be run after destroy event automatically later
}
-void LWindow::minClicked(){
+void LWindowFrame::minClicked(){
qDebug() << "Minimize Window";
this->showMinimized();
}
-void LWindow::maxClicked(){
+void LWindowFrame::maxClicked(){
if(normalGeom.isNull()){
qDebug() << "Maximize Window";
normalGeom = this->geometry(); //save for later
@@ -322,17 +356,23 @@ void LWindow::maxClicked(){
}
}
-void LWindow::otherClicked(QAction* act){
+void LWindowFrame::otherClicked(QAction* act){
QString action = act->whatsThis();
}
+void LWindowFrame::CloseAll(){
+ qDebug() << " - Closing Frame";
+ this->hide();
+ emit Finished();
+}
// =====================
// PROTECTED
// =====================
-void LWindow::mousePressEvent(QMouseEvent *ev){
- qDebug() << "Mouse Press Event";
+void LWindowFrame::mousePressEvent(QMouseEvent *ev){
+ qDebug() << "Frame Mouse Press Event";
offset.setX(0); offset.setY(0);
if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse
+ this->activateWindow();
if(this->childAt(ev->pos())!=0){
//Check for any non-left-click event and skip it
if(ev->button()!=Qt::LeftButton){ return; }
@@ -346,7 +386,7 @@ void LWindow::mousePressEvent(QMouseEvent *ev){
}
-void LWindow::mouseMoveEvent(QMouseEvent *ev){
+void LWindowFrame::mouseMoveEvent(QMouseEvent *ev){
ev->accept();
if(activeState == Normal){
setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
@@ -381,14 +421,17 @@ void LWindow::mouseMoveEvent(QMouseEvent *ev){
break;
case ResizeTopLeft:
geom.setTopLeft(ev->globalPos()-offset);
- break;
+ break;
+ default:
+ break;
}
this->setGeometry(geom);
}
}
-void LWindow::mouseReleaseEvent(QMouseEvent *ev){
+void LWindowFrame::mouseReleaseEvent(QMouseEvent *ev){
//Check for a right-click event
+ qDebug() << "Frame Mouse Release Event";
ev->accept();
if( (activeState==Normal) && (this->childAt(ev->pos())==titleBar) && (ev->button()==Qt::RightButton) ){
otherM->popup(ev->globalPos());
diff --git a/lumina-wm-INCOMPLETE/LWindow.h b/lumina-wm-INCOMPLETE/LWindow.h
index 61345736..10b0dd84 100644
--- a/lumina-wm-INCOMPLETE/LWindow.h
+++ b/lumina-wm-INCOMPLETE/LWindow.h
@@ -9,14 +9,11 @@
#include "GlobalDefines.h"
-class LWindow : public QFrame{
+class LWindowFrame : public QFrame{
Q_OBJECT
public:
- LWindow(WId client); //MUST have a valid client window
- ~LWindow();
-
- WId clientID();
- bool hasFrame();
+ LWindowFrame(WId client, QWidget *parent = 0); //MUST have a valid client window
+ ~LWindowFrame();
private:
void InitWindow(); //Initialize all the internal widgets
@@ -32,8 +29,11 @@ private:
//General Properties/Modifications
WId CID; //Client ID
QWindow *WIN; //Embedded window container
+ QWidget *WinWidget;
+ bool Closing;
+ LWM::WindowAction lastAction;
//QBackingStore *WINBACK;
- void SyncSize(); //sync the window/frame geometries
+ void SyncSize(bool fromwin = false); //sync the window/frame geometries
void SyncText();
//Window Frame Widgets/Items
@@ -45,7 +45,8 @@ private:
//Animations
QPropertyAnimation *anim; //used for appear/disappear animations
QRect lastGeom; //used for appear/disappear animations
- void showAnimation(LWM::WindowAction);
+ void showAnimation(LWM::WindowAction); //sets lastAction
+
public slots:
//These slots are generally used for the outside event watcher to prod for changes
@@ -53,19 +54,55 @@ public slots:
void windowChanged(LWM::WindowAction);
private slots:
+ void finishedAnimation(); //uses lastAction
void closeClicked();
void minClicked();
void maxClicked();
void otherClicked(QAction*);
+ void CloseAll();
+
protected:
void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
signals:
+ void Finished(); //This means the window is completely finished (with animations and such) and should be removed from any lists
+
+};
+class LWindow : public QObject{
+ Q_OBJECT
+signals:
+ void Finished(WId client); //ready to be removed
+private:
+ WId CID;
+ LWindowFrame *FID;
+private slots:
+ void frameclosed(){
+ qDebug() << " - Window got frame closed signal";
+ FID->close();
+ delete FID;
+ emit Finished(CID);
+ }
+public:
+ LWindow(WId client){
+ FID= 0;
+ CID = client;
+ QList<LXCB::WINDOWTYPE> list = LWM::SYSTEM->WM_Get_Window_Type(CID);
+ if(list.isEmpty() || (list.first()==LXCB::T_DIALOG || list.first()==LXCB::T_NORMAL) ){
+ FID = new LWindowFrame(CID);
+ connect(FID, SIGNAL(Finished()), this, SLOT(frameclosed()) );
+ }
+ }
+ ~LWindow(){
+ if(FID!=0){delete FID;}
+ }
+
+ WId clientID(){ return CID; }
+ bool hasFrame(){ return FID!=0; }
+ LWindowFrame* frame(){ return FID; }
};
-
#endif \ No newline at end of file
diff --git a/lumina-wm-INCOMPLETE/LWindowManager.cpp b/lumina-wm-INCOMPLETE/LWindowManager.cpp
new file mode 100644
index 00000000..87519ff6
--- /dev/null
+++ b/lumina-wm-INCOMPLETE/LWindowManager.cpp
@@ -0,0 +1,155 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LWindowManager.h"
+
+#define DEBUG 1
+
+LWindowManager::LWindowManager(){
+
+}
+
+LWindowManager::~LWindowManager(){
+
+}
+
+bool LWindowManager::start(){
+ //Should probably do a quick loop over any existing windows with the root as parent (just in case)
+ QList<WId> initial = LWM::SYSTEM->WM_RootWindows();
+ for(int i=0; i<initial.length(); i++){
+ NewWindow(initial[i], false); //These ones did not explicitly request to be mapped
+ }
+ RestackWindows();
+ return true;
+}
+
+void LWindowManager::stop(){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->hasFrame()){
+ LWM::SYSTEM->UnembedWindow(WINS[i]->clientID());
+ WINS[i]->frame()->close();
+ }
+ }
+}
+//===============
+// PUBLIC SLOTS
+//===============
+void LWindowManager::NewWindow(WId win, bool requested){
+ //Verify that this window can/should be managed first
+ //if(DEBUG){ qDebug() << "New Window:" << LWM::SYSTEM->WM_ICCCM_GetClass(win); }
+ QString wclass = LWM::SYSTEM->WM_ICCCM_GetClass(win);
+ if( wclass.contains("lumina-wm",Qt::CaseInsensitive) ){ return; } //just in case: prevent recursion
+ else{
+ bool ok = (wclass.isEmpty() ? false : LWM::SYSTEM->WM_ManageWindow(win, requested) );
+ if(!ok){
+ //See if this window is just a transient pointing to some other window
+ WId tran = LWM::SYSTEM->WM_ICCCM_GetTransientFor(win);
+ if(tran!=win && tran!=0){
+ win = tran;
+ ok = LWM::SYSTEM->WM_ManageWindow(win);
+ }
+ }
+ if(!ok){ return; }
+ }
+ if(DEBUG){ qDebug() << "New Managed Window:" << LWM::SYSTEM->WM_ICCCM_GetClass(win); }
+ LWindow *lwin = new LWindow(win);
+ connect(lwin, SIGNAL(Finished(WId)), this, SLOT(FinishedWindow(WId)) );
+ WINS << lwin;
+ if(lwin->hasFrame()){
+ lwin->frame()->windowChanged(LWM::Show); //Make sure to show it right away
+ }else{
+ LWM::SYSTEM->WM_ShowWindow(win); //just map the window right now
+ }
+}
+
+void LWindowManager::ClosedWindow(WId win){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->clientID()==win){
+ qDebug() << " - Closed Window";
+ if(WINS[i]->hasFrame()){ WINS[i]->frame()->windowChanged(LWM::Closed); }
+ else{
+ FinishedWindow(win);
+ }
+ break;
+ }
+ }
+}
+
+void LWindowManager::ModifyWindow(WId win, LWM::WindowAction act){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->clientID()==win){
+ if(WINS[i]->hasFrame()){ WINS[i]->frame()->windowChanged(act); }
+ return;
+ }
+ }
+ //If it gets this far - it is an unmanaged window
+ if(act==LWM::Show){
+ NewWindow(win);
+ }
+ RestackWindows();
+}
+
+void LWindowManager::RestackWindows(){
+ Stack_Desktop.clear(); Stack_Below.clear(); Stack_Normal.clear(); Stack_Above.clear(); Stack_Fullscreen.clear();
+ QList<WId> currwins;
+ int cwork = LWM::SYSTEM->WM_Get_Current_Desktop();
+ int winwork = -1;
+ QList<LXCB::WINDOWSTATE> states;
+ QList<LXCB::WINDOWTYPE> types;
+ for(int i=0; i<WINS.length(); i++){
+ //Only show windows on the current desktop
+ winwork = LWM::SYSTEM->WM_Get_Desktop(WINS[i]->clientID());
+ states = LWM::SYSTEM->WM_Get_Window_States(WINS[i]->clientID());
+ types = LWM::SYSTEM->WM_Get_Window_Type(WINS[i]->clientID());
+ WId id = WINS[i]->clientID();
+ if(WINS[i]->hasFrame()){ id = WINS[i]->frame()->winId(); }
+ if(winwork<0 || winwork == cwork || states.contains(LXCB::S_STICKY) ){
+ //Now check the state/type and put it in the proper stack
+ currwins << WINS[i]->clientID(); //add this to the overall "age" list
+ //Now add it to the proper stack
+ if(types.contains(LXCB::T_DESKTOP)){ Stack_Desktop << id; }
+ else if(states.contains(LXCB::S_BELOW)){ Stack_Below << id; }
+ else if(types.contains(LXCB::T_DOCK) || states.contains(LXCB::S_ABOVE) ){ Stack_Above << id; }
+ else if(states.contains(LXCB::S_FULLSCREEN)){ Stack_Fullscreen << id; }
+ else{ Stack_Normal << id; }
+ }
+ }
+ //Now set the root properties for these lists
+ LWM::SYSTEM->WM_Set_Client_List(currwins, false); //age-ordered version
+ LWM::SYSTEM->WM_Set_Client_List(QList<WId>() << Stack_Desktop << Stack_Below << Stack_Normal << Stack_Above << Stack_Fullscreen, true); //stacking order version
+ //Now re-paint (in order) the windows
+ RepaintWindows();
+}
+
+void LWindowManager::RepaintWindows(){
+ //Go through all the current windows (in stacking order) and re-paint them
+ for(int i=0; i<Stack_Desktop.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Desktop[i]);
+ }
+ for(int i=0; i<Stack_Below.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Below[i]);
+ }
+ for(int i=0; i<Stack_Normal.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Normal[i]);
+ }
+ for(int i=0; i<Stack_Above.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Above[i]);
+ }
+ for(int i=0; i<Stack_Fullscreen.length(); i++){
+ LWM::SYSTEM->WM_ShowWindow(Stack_Fullscreen[i]);
+ }
+}
+
+//=================
+// PRIVATE SLOTS
+//=================
+void LWindowManager::FinishedWindow(WId win){
+ for(int i=0; i<WINS.length(); i++){
+ if(WINS[i]->clientID() == win){ qDebug() << " - Finished Window"; delete WINS.takeAt(i); break; }
+ }
+ //Now update the list of clients
+ RestackWindows();
+}
diff --git a/lumina-wm-INCOMPLETE/LWindowManager.h b/lumina-wm-INCOMPLETE/LWindowManager.h
new file mode 100644
index 00000000..203efa1b
--- /dev/null
+++ b/lumina-wm-INCOMPLETE/LWindowManager.h
@@ -0,0 +1,40 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_WINDOW_MANAGER_MAIN_CLASS_H
+#define _LUMINA_DESKTOP_WINDOW_MANAGER_MAIN_CLASS_H
+
+#include "GlobalDefines.h"
+#include "LWindow.h"
+
+class LWindowManager : public QObject{
+ Q_OBJECT
+public:
+ LWindowManager();
+ ~LWindowManager();
+
+ bool start();
+ void stop();
+
+private:
+ QList<LWindow*> WINS;
+ QList<WId> Stack_Desktop, Stack_Below, Stack_Normal, Stack_Above, Stack_Fullscreen;
+public slots:
+ void NewWindow(WId win, bool requested = true);
+ void ClosedWindow(WId win);
+ void ModifyWindow(WId win, LWM::WindowAction act);
+
+ void RestackWindows();
+ void RepaintWindows();
+
+private slots:
+ void FinishedWindow(WId win); //This is used for LWindow connections/animations
+
+signals:
+ void NewFullScreenWindows(QList<WId>);
+};
+
+#endif
diff --git a/lumina-wm-INCOMPLETE/LXcbEventFilter.cpp b/lumina-wm-INCOMPLETE/LXcbEventFilter.cpp
index ba825b90..6d6cef55 100644
--- a/lumina-wm-INCOMPLETE/LXcbEventFilter.cpp
+++ b/lumina-wm-INCOMPLETE/LXcbEventFilter.cpp
@@ -30,20 +30,23 @@ EventFilter::EventFilter() : QObject(){
EF = new XCBEventFilter(this);
L_XCB::root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
L_XCB::root = L_XCB::root_screen->root;
+ SSLocked = false;
+ WMFlag = 0;
}
void EventFilter::start(){
if(DEBUG){ qDebug() << " - Install event filter..."; }
QCoreApplication::instance()->installNativeEventFilter(EF);
if(DEBUG){ qDebug() << " - Run request check..."; }
- xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), L_XCB::root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK} ) );
- if(status){
+ if(!LWM::SYSTEM->setupEventsForRoot()){
qCritical() << "[ERROR] Unable to setup WM event retrieval. Is another WM running?";
exit(1);
}
- //xcb_screensaver_select_input(QX11Info::connection(),QX11Info::appRootWindow() , masks);
- xcb_flush(QX11Info::connection());
-
+ if(DEBUG){ qDebug() << " - Create WM ID Window"; }
+ WMFlag = LWM::SYSTEM->WM_CreateWindow();
+ LWM::SYSTEM->setupEventsForRoot(WMFlag);
+ LWM::SYSTEM->WM_Set_Supporting_WM(WMFlag);
+ QCoreApplication::instance()->flush();
}
//Constructor for the XCB event filter
@@ -64,96 +67,138 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag
//Now parse the event and emit signals as necessary
switch( ev->response_type & ~0x80){
//==============================
+// INTERACTIVITY EVENTS
+//==============================
case XCB_KEY_PRESS:
- qDebug() << "Key Press Event";
+ //This is a keyboard key press
+ //qDebug() << "Key Press Event";
obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_key_press_event_t *) ev)->root ); //use the main "root" window - not the child widget
break;
case XCB_KEY_RELEASE:
- qDebug() << "Key Release Event";
+ //This is a keyboard key release
+ //qDebug() << "Key Release Event";
obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_key_release_event_t *) ev)->root ); //use the main "root" window - not the child widget
break;
case XCB_BUTTON_PRESS:
- qDebug() << "Button Press Event";
+ //This is a mouse button press
+ //qDebug() << "Button Press Event";
obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_button_press_event_t *) ev)->root ); //use the main "root" window - not the child widget
+ if(!stopevent){
+ //Activate the window right now if needed
+ if(LWM::SYSTEM->WM_Get_Active_Window()!=((xcb_button_press_event_t *) ev)->root){
+ LWM::SYSTEM->WM_Set_Active_Window( ((xcb_button_press_event_t *) ev)->root);
+ }
+ }
break;
case XCB_BUTTON_RELEASE:
- qDebug() << "Button Release Event";
- obj->emit NewInputEvent();
+ //This is a mouse button release
+ //qDebug() << "Button Release Event";
+ //xcb_button_release_event_t *tmp = (xcb_button_release_event_t *)ev;
+ stopevent = BlockInputEvent( ((xcb_button_release_event_t *) ev)->root ); //use the main "root" window - not the child widget
break;
case XCB_MOTION_NOTIFY:
- qDebug() << "Motion Notify Event";
+ //This is a mouse movement event
+ //qDebug() << "Motion Notify Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_motion_notify_event_t *) ev)->root ); //use the main "root" window - not the child widget);
+ break;
+ case XCB_ENTER_NOTIFY:
+ //This is a mouse movement event when mouse goes over a new window
+ //qDebug() << "Enter Notify Event";
+ obj->emit NewInputEvent();
+ stopevent = BlockInputEvent( ((xcb_enter_notify_event_t *) ev)->root );
+ break;
+ case XCB_LEAVE_NOTIFY:
+ //This is a mouse movement event when mouse goes leaves a window
+ //qDebug() << "Leave Notify Event";
obj->emit NewInputEvent();
+ stopevent = BlockInputEvent();
break;
//==============================
- case XCB_PROPERTY_NOTIFY:
- qDebug() << "Property Notify Event:";
- //qDebug() << " - Root Window:" << QX11Info::appRootWindow();
+ case XCB_EXPOSE:
+ //qDebug() << "Expose Notify Event:";
//qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
- //System-specific proprty change
- if( SysNotifyAtoms.contains( ((xcb_property_notify_event_t*)ev)->atom ) ){
- //Update the status/list of all running windows
- //session->WindowPropertyEvent();
-
- //window-specific property change
- }else if( WinNotifyAtoms.contains( ((xcb_property_notify_event_t*)ev)->atom ) ){
- //Ping only that window
- //session->WindowPropertyEvent( ((xcb_property_notify_event_t*)ev)->window );
- //session->WindowPropertyEvent();
- }
+ break;
+//==============================
+ case XCB_MAP_NOTIFY:
+ break; //This is just a notification that a window was mapped - nothing needs to change here
+ case XCB_MAP_REQUEST:
+ qDebug() << "Window Map Request Event";
+ obj->emit ModifyWindow( ((xcb_map_request_event_t *) ev)->window, LWM::Show);
break;
//==============================
- case XCB_CLIENT_MESSAGE:
- qDebug() << "Client Message Event";
- //qDebug() << " - Root Window:" << QX11Info::appRootWindow();
- //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
- //if( TrayDmgFlag!=0 && ((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]){
- //session->SysTrayDockRequest( ((xcb_client_message_event_t*)ev)->data.data32[2] );
- //}
- //Ignore the System Tray messages at the moment (let the WM handle it)
-
- //window-specific property changes
- /*}else if( ((xcb_client_message_event_t*)ev)->type == session->XCB->EWMH._NET_WM_STATE ){
- if( session->XCB->WindowIsMaximized( ((xcb_client_message_event_t*)ev)->window ) ){
- //Quick fix for maximized windows (since Fluxbox is not doing the STRUT detection properly)
- session->adjustWindowGeom( ((xcb_client_message_event_t*)ev)->window );
- }
- session->WindowPropertyEvent( ((xcb_client_message_event_t*)ev)->window );*/
- //}else if( WinNotifyAtoms.contains( ((xcb_client_message_event_t*)ev)->type ) ){
- //Ping only that window
- //session->WindowPropertyEvent( ((xcb_client_message_event_t*)ev)->window );
- //session->WindowPropertyEvent();
- //}
+ case XCB_CREATE_NOTIFY:
+ qDebug() << "Window Create Event";
break;
+//==============================
+ case XCB_UNMAP_NOTIFY:
+ qDebug() << "Window Unmap Event";
+ obj->emit ModifyWindow( ((xcb_unmap_notify_event_t *)ev)->window, LWM::Hide);
+ break;
//==============================
case XCB_DESTROY_NOTIFY:
qDebug() << "Window Closed Event";
- //session->WindowClosedEvent( ( (xcb_destroy_notify_event_t*)ev )->window );
+ obj->emit WindowClosed( ((xcb_destroy_notify_event_t *) ev)->window );
+ break;
+//==============================
+ case XCB_FOCUS_IN:
+ //qDebug() << "Focus In Event:";
+ break;
+//==============================
+ case XCB_FOCUS_OUT:
+ //qDebug() << "Focus Out Event:";
+ break;
+//==============================
+ case XCB_PROPERTY_NOTIFY:
+ //qDebug() << "Property Notify Event:";
+ //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
+ break;
+//==============================
+ case XCB_CLIENT_MESSAGE:
+ //qDebug() << "Client Message Event";
+ //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
break;
//==============================
case XCB_CONFIGURE_NOTIFY:
- qDebug() << "Configure Notify Event";
- //session->WindowConfigureEvent( ((xcb_configure_notify_event_t*)ev)->window );
+ //qDebug() << "Configure Notify Event";
+ break;
+//==============================
+ case XCB_CONFIGURE_REQUEST:
+ //qDebug() << "Configure Request Event";
break;
//==============================
case XCB_SELECTION_CLEAR:
- qDebug() << "Selection Clear Event";
- //session->WindowSelectionClearEvent( ((xcb_selection_clear_event_t*)ev)->owner );
+ //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(TrayDmgFlag!=0){
- //if( (ev->response_type & ~0x80)==TrayDmgFlag){
- //session->WindowDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable );
- //}
- //}
- //else{
- qDebug() << "Default Event:" << (ev->response_type & ~0x80);
- //}
+ qDebug() << "Default Event:" << (ev->response_type & ~0x80);
//==============================
}
}
- //qDebug() << " - finished event";
return stopevent;
}
+
+bool XCBEventFilter::BlockInputEvent(WId win){
+ //Checks the current state of the WM and sets the stop flag as needed
+ // - Always let the screensaver know about the event first (need to reset timers and such)
+ obj->emit NewInputEvent();
+ // - Check the state of the screensaver
+
+ if(obj->SSLocked){ qDebug() << "SS Locked"; return true; }
+ // - Check the state of any fullscreen apps
+ else if( win!=0 && !obj->FS_WINS.isEmpty()){
+ if(!obj->FS_WINS.contains(win) ){
+ //If this event is for an app underneath a fullscreen window - stop it
+ if(obj->FS_WINS.length() == QApplication::desktop()->screenCount()){ qDebug() << "Screens Covered"; return true; } //all screens covered right now
+ }
+ }
+ return false;
+}
diff --git a/lumina-wm-INCOMPLETE/LXcbEventFilter.h b/lumina-wm-INCOMPLETE/LXcbEventFilter.h
index 86e77939..28bab024 100644
--- a/lumina-wm-INCOMPLETE/LXcbEventFilter.h
+++ b/lumina-wm-INCOMPLETE/LXcbEventFilter.h
@@ -46,46 +46,33 @@ XCB_CLIENT_MESSAGE
//#define SYSTEM_TRAY_BEGIN_MESSAGE 1
//#define SYSTEM_TRAY_CANCEL_MESSAGE 2
-
-// ---------------------------------------------
-// Lifted these mask definitions from the i3 window manager (BSD Licensed as well) 5/14/15 - Ken Moore
-#define CHILD_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_FOCUS_CHANGE)
-
-/** The XCB_CW_EVENT_MASK for its frame */
-#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | /* ...mouse is pressed/released */ \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | /* ...mouse is moved */ \
- XCB_EVENT_MASK_EXPOSURE | /* ...our window needs to be redrawn */ \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | /* ...the frame gets destroyed */ \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | /* ...the application tries to resize itself */ \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | /* ...subwindows get notifies */ \
- XCB_EVENT_MASK_ENTER_WINDOW) /* ...user moves cursor inside our window */
-
-#define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | /* when the user adds a screen (e.g. video \
- projector), the root window gets a \
- ConfigureNotify */ \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_ENTER_WINDOW)
-// ---------------------------------------------
-
class EventFilter : public QObject{
Q_OBJECT
private:
QAbstractNativeEventFilter* EF;
+ WId WMFlag; //used to flag a running WM process
+
public:
EventFilter();
~EventFilter(){}
void start();
+ //Public variables for the event filter to use/check
+ QList<WId> FS_WINS; //Full-screen windows (1 per monitor) - used for hiding non-app events as needed
+ bool SSLocked;
+
+public slots:
+ void StartedSS(){ SSLocked = true; }
+ void StoppedSS(){ SSLocked = false; }
+ void FullScreenChanged(QList<WId> fslist){ FS_WINS = fslist; }
+
signals:
void NewInputEvent();
+ void NewManagedWindow(WId);
+ void WindowClosed(WId);
+ void ModifyWindow(WId win, LWM::WindowAction);
};
class XCBEventFilter : public QAbstractNativeEventFilter{
@@ -97,7 +84,6 @@ public:
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE;
private:
- //LXCB *XCB;
EventFilter *obj;
QList<xcb_atom_t> WinNotifyAtoms, SysNotifyAtoms;
@@ -123,7 +109,9 @@ private:
}
- //Event handling functions (return true if event accepted/blocked)
+ bool BlockInputEvent(WId win = 0); //Checks the current state of the WM and sets the stop flag as needed
+
+ //Longer Event handling functions
//bool ParseKeyPressEvent();
//bool ParseKeyReleaseEvent();
//bool ParseButtonPressEvent();
diff --git a/lumina-wm-INCOMPLETE/WMSession.cpp b/lumina-wm-INCOMPLETE/WMSession.cpp
index bed31ed9..4a7c6e02 100644
--- a/lumina-wm-INCOMPLETE/WMSession.cpp
+++ b/lumina-wm-INCOMPLETE/WMSession.cpp
@@ -15,9 +15,18 @@ WMSession::WMSession(){
EFILTER = new EventFilter();
if(DEBUG){ qDebug() << "Creating Screen Saver..."; }
SS = new LScreenSaver();
-
+ if(DEBUG){ qDebug() << "Creating Window Manager..."; }
+ WM = new LWindowManager();
+ EVThread = new QThread();
+ EFILTER->moveToThread(EVThread);
//Setup connections
connect(EFILTER, SIGNAL(NewInputEvent()), SS, SLOT(newInputEvent()) );
+ connect(EFILTER, SIGNAL(NewManagedWindow(WId)), WM, SLOT(NewWindow(WId)) );
+ connect(EFILTER, SIGNAL(WindowClosed(WId)), WM, SLOT(ClosedWindow(WId)) );
+ connect(EFILTER, SIGNAL(ModifyWindow(WId, LWM::WindowAction)), WM, SLOT(ModifyWindow(WId,LWM::WindowAction)) );
+ connect(SS, SIGNAL(StartingScreenSaver()), EFILTER, SLOT(StartedSS()) );
+ connect(SS, SIGNAL(ClosingScreenSaver()), EFILTER, SLOT(StoppedSS()) );
+ connect(WM, SIGNAL(NewFullScreenWindows(QList<WId>)), EFILTER, SLOT(FullScreenChanged(QList<WId>)) );
}
WMSession::~WMSession(){
@@ -29,7 +38,10 @@ void WMSession::start(bool SSONLY){
SS->start();
if(SSONLY){ return; }
//Now start pulling/filtering events
+ if(DEBUG){ qDebug() << "Starting Window Manager..."; }
+ WM->start();
if(DEBUG){ qDebug() << "Starting Event Filter..."; }
+ EVThread->start();
EFILTER->start();
if(DEBUG){ qDebug() << "Done Starting WM session..."; }
}
diff --git a/lumina-wm-INCOMPLETE/WMSession.h b/lumina-wm-INCOMPLETE/WMSession.h
index 575a61e7..5b511326 100644
--- a/lumina-wm-INCOMPLETE/WMSession.h
+++ b/lumina-wm-INCOMPLETE/WMSession.h
@@ -11,6 +11,7 @@
#include "LScreenSaver.h"
#include "LXcbEventFilter.h"
+#include "LWindowManager.h"
class WMSession : public QObject{
Q_OBJECT
@@ -25,9 +26,10 @@ private:
EventFilter *EFILTER;
//ScreenSaver
LScreenSaver *SS;
-
//Window Manager
-
+ LWindowManager *WM;
+
+ QThread *EVThread; //X Event thread
public slots:
void reloadIcons();
diff --git a/lumina-wm-INCOMPLETE/lumina-wm.pro b/lumina-wm-INCOMPLETE/lumina-wm.pro
index 7e2c0c82..aba210fe 100644
--- a/lumina-wm-INCOMPLETE/lumina-wm.pro
+++ b/lumina-wm-INCOMPLETE/lumina-wm.pro
@@ -31,7 +31,8 @@ SOURCES += main.cpp \
SSBaseWidget.cpp \
LLockScreen.cpp \
LXcbEventFilter.cpp \
- LWindow.cpp
+ LWindow.cpp \
+ LWindowManager.cpp
HEADERS += GlobalDefines.h \
@@ -40,7 +41,8 @@ HEADERS += GlobalDefines.h \
SSBaseWidget.h \
LLockScreen.h \
LXcbEventFilter.h \
- LWindow.h
+ LWindow.h \
+ LWindowManager.h
FORMS += LLockScreen.ui
diff --git a/lumina-wm-INCOMPLETE/main.cpp b/lumina-wm-INCOMPLETE/main.cpp
index 9ac227c8..50251fa5 100644
--- a/lumina-wm-INCOMPLETE/main.cpp
+++ b/lumina-wm-INCOMPLETE/main.cpp
@@ -42,7 +42,7 @@ int main(int argc, char ** argv)
qDebug() << " - Loading window frame...";
LWindow win(dlg.winId()); //have it wrap around the dialog
qDebug() << " - Show frame...";
- win.windowChanged(LWM::Show);
+ win.frame()->windowChanged(LWM::Show);
qDebug() << " - Start event loop...";
a.setQuitOnLastWindowClosed(true);
return a.exec();
bgstack15