aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/obsolete
diff options
context:
space:
mode:
authorWeblate <noreply@weblate.org>2017-11-04 19:28:17 +0000
committerWeblate <noreply@weblate.org>2017-11-04 19:28:17 +0000
commit7787f617656751ee7e0a58c813d0bfd5757c5c97 (patch)
tree48aa053bbd4fda9c64f89a061a2f442c860ab13d /src-qt5/core/libLumina/obsolete
parentTranslated using Weblate (Lithuanian) (diff)
parentMerge pull request #497 from a-stjohn/patch-1 (diff)
downloadlumina-7787f617656751ee7e0a58c813d0bfd5757c5c97.tar.gz
lumina-7787f617656751ee7e0a58c813d0bfd5757c5c97.tar.bz2
lumina-7787f617656751ee7e0a58c813d0bfd5757c5c97.zip
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src-qt5/core/libLumina/obsolete')
-rw-r--r--src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp116
-rw-r--r--src-qt5/core/libLumina/obsolete/RootSubWindow.cpp601
-rw-r--r--src-qt5/core/libLumina/obsolete/RootSubWindow.h109
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp95
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow.cpp283
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow.h92
-rw-r--r--src-qt5/core/libLumina/obsolete/RootWindow.pri17
7 files changed, 1313 insertions, 0 deletions
diff --git a/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp b/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp
new file mode 100644
index 00000000..efab20fe
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp
@@ -0,0 +1,116 @@
+//===========================================
+// Lumina Desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RootSubWindow.h"
+#include <QDebug>
+
+QStringList RootSubWindow::validAnimations(NativeWindow::Property prop){
+ QStringList valid;
+ if(prop == NativeWindow::Visible){
+ valid << "zoom" << "wipe-center-vertical" << "wipe-center-horizontal" << "shade-top" << "shade-right" << "shade-left" << "shade-bottom";
+ }else if(prop == NativeWindow::Size){
+ //Note: this is used for pretty much all geometry changes to the window where it is visible both before/after animation
+ valid << "direct";
+ }
+ return valid;
+}
+
+void RootSubWindow::loadAnimation(QString name, NativeWindow::Property prop, QVariant nval){
+ if(anim->state()==QAbstractAnimation::Running){ return; } //already running
+ animResetProp.clear();
+ //Special case - random animation each time
+ if(name=="random"){
+ QStringList valid = validAnimations(prop);
+ if(!valid.isEmpty()){ name = valid.at(qrand()%valid.length()); }
+ }
+ //Now setup the animation
+ if(prop == NativeWindow::Visible){
+ //NOTE: Assigns values for "invisible->visible" animation: will reverse it afterwards as needed
+ anim->setPropertyName("geometry");
+ QRect geom = this->geometry();
+ if(name == "zoom"){
+ //Zoom to/from the center point
+ anim->setStartValue( QRect(geom.center(), QSize(0,0)) );
+ anim->setEndValue(geom);
+ }else if(name == "wipe-center-vertical"){
+ anim->setStartValue( QRect( geom.center().x(), geom.y(), 0, geom.height()) );
+ anim->setEndValue( geom );
+ }else if(name == "wipe-center-horizontal"){
+ anim->setStartValue( QRect( geom.x(), geom.center().y(), geom.width(), 0) );
+ anim->setEndValue( geom );
+ }else if(name == "shade-top"){
+ anim->setStartValue( QRect( geom.x(), geom.y(), geom.width(), 0) );
+ anim->setEndValue( geom );
+ }else if(name == "shade-bottom"){
+ anim->setStartValue( QRect( geom.x(), geom.y()+geom.height(), geom.width(), 0) );
+ anim->setEndValue( geom );
+ }else if(name == "shade-left"){
+ anim->setStartValue( QRect( geom.x(), geom.y(), 0, geom.height()) );
+ anim->setEndValue( geom );
+ }else if(name == "shade-right"){
+ anim->setStartValue( QRect( geom.x()+geom.width(), geom.y(), 0, geom.height()) );
+ anim->setEndValue( geom );
+ }else{
+ //Invalid/None animation
+ if(nval.toBool()){ this->show(); }
+ else{ this->hide(); }
+ return;
+ }
+ if(nval.toBool()){
+ this->setGeometry( anim->startValue().toRect() ); //ensure the window is the initial geom before it becomes visible
+ //QTimer::singleShot( anim->duration()+5, this, SLOT(activate()) );
+ }else{
+ QVariant tmp = anim->startValue();
+ anim->setStartValue(anim->endValue());
+ anim->setEndValue(tmp);
+ animResetProp = anim->startValue();
+ QTimer::singleShot(anim->duration(), this, SLOT(hide()) );
+ }
+ WinWidget->pause();
+ anim->start();
+ this->show();
+ } //end of Visibility animation
+ else if(prop == NativeWindow::Size){
+ //This is pretty much all geometry animations where the window is visible->visible
+ anim->setPropertyName("geometry");
+ anim->setStartValue(this->geometry());
+ anim->setEndValue(nval.toRect());
+ /*if(name==""){
+ // TO-DO modify the path from beginning->end somehow
+ }*/
+ // Now start the animation
+ WinWidget->pause();
+ anim->start();
+ this->show();
+ }
+}
+
+void RootSubWindow::animFinished(){
+ if(closing){ this->close(); return;}
+ else if(anim->propertyName()=="geometry"){
+ if(!animResetProp.isNull()){
+ /*qDebug() << "Animation Finished, Reset Geometry:" << animResetProp.toRect();
+ qDebug() << " - Starting Value:" << anim->startValue().toRect();
+ qDebug() << " - Ending Value:" << anim->endValue().toRect();*/
+ this->setGeometry( animResetProp.toRect() );
+ //Also ensure that the proper geometry is saved to the window structure
+ QRect curg = this->geometry();
+ QRect wing = WIN->geometry();
+ //qDebug() << " - After Animation Reset:" << curg << wing;
+ if(curg!=wing){
+ QRect clientg = clientGlobalGeom();
+ //qDebug() << "Sub Window geometry:" << clientg;
+ WIN->setProperties(QList< NativeWindow::Property>() << NativeWindow::Size << NativeWindow::GlobalPos,
+ QList<QVariant>() << clientg.size() << clientg.topLeft() );
+ }
+ }
+ WinWidget->resyncWindow(); //also let the window know about the current geometry
+ }
+ animResetProp = QVariant(); //clear the variable
+ //QTimer::singleShot(10, WinWidget, SLOT(resume()) );
+ WinWidget->resume();
+ emit windowAnimFinished();
+}
diff --git a/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp b/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp
new file mode 100644
index 00000000..5040f2f9
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp
@@ -0,0 +1,601 @@
+//===========================================
+// Lumina Desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RootSubWindow.h"
+#include <QDebug>
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QTimer>
+#include <QScreen>
+
+#define WIN_BORDER 5
+
+#include <LIconCache.h>
+#include <DesktopSettings.h>
+
+// === PUBLIC ===
+RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){
+ this->setAttribute(Qt::WA_DeleteOnClose);
+ this->setMouseTracking(true);
+ //Create the QWindow and QWidget containers for the window
+ WIN = win;
+ closing = false;
+ initWindowFrame();
+ //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(){
+ return WIN->id();
+}
+
+NativeWindow* RootSubWindow::nativeWindow(){
+ return WIN;
+}
+
+// === PRIVATE ===
+RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset){
+ //Note: pt should be in widget-relative coordinates, not global
+ if(!WinWidget->geometry().contains(pt) && !titleBar->geometry().contains(pt)){
+ //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() < 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()*4.0/5.0)){
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner
+ return ResizeTopRight;
+ }else{
+ if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter)
+ return ResizeTop;
+ }
+ }else if(pt.y() > (this->height()-WIN_BORDER) ){
+ //One of the bottom options
+ if(pt.x() < this->width()/5){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner
+ return ResizeBottomLeft;
+ }else if(pt.x() > (this->width()*4.0/5.0)){
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner
+ return ResizeBottomRight;
+ }else{
+ if(setoffset){ offset.setX(0); offset.setY(pt.y()-this->height()); } //difference from bottom edge (X does not matter)
+ 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(pt.y()-this->height()); } //difference from bottom-left corner
+ return ResizeBottomLeft;
+ }else{
+ if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter)
+ return ResizeLeft;
+ }
+ }else if(pt.x() > (this->width()-WIN_BORDER) ){
+ //Right side options
+ if(pt.y() < this->height()/5){
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner
+ return ResizeTopRight;
+ }else if(pt.y() > (this->height()*4.0/5.0)){
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner
+ return ResizeBottomRight;
+ }else{
+ if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(0); } //difference from right edge (Y does not matter)
+ return ResizeRight;
+ }
+ }else{
+ return Normal;
+ }
+ }
+ //if it gets this far just return normal
+ return Normal;
+}
+
+void RootSubWindow::setMouseCursor(ModState state, bool override){
+ if(currentCursor==state && !override){ return; } //nothing to change
+ Qt::CursorShape shape;
+ switch(state){
+ case Normal:
+ shape = Qt::ArrowCursor;
+ break;
+ case Move:
+ shape = Qt::SizeAllCursor;
+ break;
+ case ResizeTop:
+ shape = Qt::SizeVerCursor;
+ break;
+ case ResizeTopRight:
+ shape = Qt::SizeBDiagCursor;
+ break;
+ case ResizeRight:
+ shape = Qt::SizeHorCursor;
+ break;
+ case ResizeBottomRight:
+ shape = Qt::SizeFDiagCursor;
+ break;
+ case ResizeBottom:
+ shape = Qt::SizeVerCursor;
+ break;
+ case ResizeBottomLeft:
+ shape = Qt::SizeBDiagCursor;
+ break;
+ case ResizeLeft:
+ shape = Qt::SizeHorCursor;
+ break;
+ case ResizeTopLeft:
+ shape = Qt::SizeFDiagCursor;
+ break;
+ }
+ if(override){
+ QApplication::setOverrideCursor(QCursor(shape));
+ }else{
+ currentCursor = state;
+ this->setCursor(shape);
+ }
+}
+
+void RootSubWindow::initWindowFrame(){
+ //qDebug() << "Create RootSubWindow Frame";
+ this->setContentsMargins(0,0,0,0);
+ mainLayout = new QVBoxLayout(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
+ titleBarL->addWidget(otherB);
+ titleBarL->addWidget(titleLabel);
+ titleBarL->addWidget(minB);
+ titleBarL->addWidget(maxB);
+ titleBarL->addWidget(closeB);
+ WinWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ mainLayout->addWidget(titleBar);
+ mainLayout->addWidget(WinWidget);
+ mainLayout->setAlignment(titleBar, Qt::AlignTop);
+ //Setup the cursors for the buttons
+ closeB->setCursor(Qt::ArrowCursor);
+ minB->setCursor(Qt::ArrowCursor);
+ maxB->setCursor(Qt::ArrowCursor);
+ otherB->setCursor(Qt::ArrowCursor);
+ titleLabel->setCursor(Qt::ArrowCursor);
+ WinWidget->setCursor(Qt::ArrowCursor);
+ //Now all the stylesheet options
+ this->setObjectName("WindowFrame");
+ closeB->setObjectName("Button_Close");
+ minB->setObjectName("Button_Minimize");
+ maxB->setObjectName("Button_Maximize");
+ otherM->setObjectName("Menu_Actions");
+ titleLabel->setObjectName("Label_Title");
+ 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->setSpacing(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::enableFrame(QList<NativeWindow::Type> types){
+ static QList<NativeWindow::Type> noframe;
+ if(noframe.isEmpty()){ noframe << NativeWindow::T_DESKTOP << NativeWindow::T_DOCK << NativeWindow::T_TOOLBAR << NativeWindow::T_MENU << NativeWindow::T_SPLASH << NativeWindow::T_DROPDOWN_MENU << NativeWindow::T_POPUP_MENU << NativeWindow::T_TOOLTIP << NativeWindow::T_NOTIFICATION << NativeWindow::T_COMBO << NativeWindow::T_DND; }
+ for(int i=0; i<types.length(); i++){
+ if(noframe.contains(types[i])){ enableFrame(false); return; }
+ }
+ enableFrame(true);
+ //Now make buttons visible as appropriate for the type
+ //NativeWindow::T_UTILITY, NativeWindow::T_DIALOG, , NativeWindow::T_NORMAL
+}
+void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){
+ QList<QVariant> vals;
+ //Always ensure that visibility changes are evaluated last
+ 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);
+}
+
+QRect RootSubWindow::clientGlobalGeom(){
+ QRect tot = this->geometry();
+ QList<int> frame = WIN->property(NativeWindow::FrameExtents).value< QList<int> >();
+ //Now adjust this to take out the frame
+ tot.adjust(frame[0], frame[2], -frame[1], -frame[3]);
+ return tot;
+}
+
+// === PUBLIC SLOTS ===
+void RootSubWindow::clientClosed(){
+ //qDebug() << "Client Closed";
+ closing = true;
+ 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->toggleVisibility();
+}
+
+void RootSubWindow::toggleMaximize(){
+ //Get the current screen that this window is on
+ QList<QScreen*> screens = QApplication::screens();
+ QRect rect;
+ int primaryscreen = 0; //fallback value
+ for(int i=0; i<screens.length(); i++){
+ QRect intersect = screens[i]->geometry().intersected(this->geometry());
+ if( (intersect.width()-rect.width() + intersect.height()-rect.height()) > 0){
+ rect = intersect;
+ primaryscreen = i;
+ }
+ }
+ //Now that we have the screen dimensions, lets check/change the window
+ rect = screens[primaryscreen]->availableGeometry();
+ QList< NativeWindow::State > states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State> >();
+ if(rect == this->geometry() || states.contains(NativeWindow::S_MAX_VERT) || states.contains(NativeWindow::S_MAX_HORZ)){
+ //Already maximized - try to restore it to the previous size/location
+ if(!lastMaxGeom.isNull()){
+ rect = lastMaxGeom;
+ }else{
+ // no last geometry - started out maximized?
+ // make it half the screen size and centered on the screen
+ QPoint center = rect.center();
+ rect.setWidth( rect.width()/2 );
+ rect.setHeight( rect.height()/2 );
+ rect.moveTopLeft( center - QPoint(rect.width()/2, rect.height()/2) );
+ }
+ lastMaxGeom = QRect(); //clear this saved geom
+ }else{
+ //Not maximized yet - go ahead and make it so
+ lastMaxGeom = this->geometry(); //save this for later;
+ }
+ //qDebug() << "Toggle Maximize:" << this->geometry() << rect;
+ QString anim_type = DesktopSettings::instance()->value(DesktopSettings::Animation, "window/move", "random").toString();
+ loadAnimation(anim_type, NativeWindow::Size, rect);
+}
+
+void RootSubWindow::triggerClose(){
+ WIN->requestClose();
+}
+
+void RootSubWindow::toggleSticky(){
+ QList< NativeWindow::State> states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State > >();
+ if(states.contains(NativeWindow::S_STICKY)){
+ states.removeAll(NativeWindow::S_STICKY);
+ }else{
+ states << NativeWindow::S_STICKY;
+ }
+ WIN->requestProperty(NativeWindow::States, QVariant::fromValue<QList <NativeWindow::State> >(states) );
+}
+
+void RootSubWindow::activate(){
+ //WinWidget->raiseWindow();
+ WIN->requestProperty(NativeWindow::Active, true, true);
+}
+
+//Mouse Interactivity
+void RootSubWindow::startMoving(){
+ //If the cursor is not over this window, move it to the center of the titlebar
+ QPoint curpt = QCursor::pos(); //global coords
+ if(!this->geometry().contains(curpt)){
+ curpt = this->mapToGlobal(titleBar->geometry().center());
+ QCursor::setPos(curpt);
+ }
+ //Calculate the offset
+ activeState = Move;
+ offset = this->mapFromGlobal(curpt);
+ setMouseCursor(activeState, true); //this one is an override cursor
+ WinWidget->pause();
+ this->grabMouse();
+}
+
+void RootSubWindow::startResizing(){
+ activeState = getStateAtPoint( this->mapFromGlobal(QCursor::pos()), true); //also have it set the offset variable
+ setMouseCursor(activeState, true); //this one is an override cursor
+ WinWidget->pause();
+ this->grabMouse();
+}
+
+// === PRIVATE SLOTS ===
+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()){ 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(!WinWidget->isPaused() && (this->isVisible()!=vals[i].toBool()) && activeState==Normal ){
+ //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry();
+ if(vals[i].toBool()){ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/appear", "random").toString(), NativeWindow::Visible, vals[i]); }
+ else{ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/disappear", "random").toString(), NativeWindow::Visible, vals[i]); }
+ }
+ break;
+ case NativeWindow::Title:
+ titleLabel->setText(vals[i].toString());
+ break;
+ case NativeWindow::Icon:
+ //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:
+ if(vals[i].toPoint()!=QPoint(0,0)){
+ WinWidget->resyncWindow();
+ }
+ break;
+ case NativeWindow::Size:
+ //qDebug() << " - SIZE CHANGE";
+ if(WIN->property(NativeWindow::FrameExtents).isNull() && (i<props.indexOf(NativeWindow::FrameExtents)) ){
+ //Frame not loaded yet - push this back until after the frame is set
+ props << props.takeAt(i);
+ vals << vals.takeAt(i);
+ i--;
+ }else if(!WinWidget->isPaused() && activeState==Normal){
+ if(WIN->property(NativeWindow::Size).toSize() != WinWidget->size()){
+ //qDebug() << "Got Direct Geometry Change:" << WIN->geometry();
+ this->setGeometry( QRect(this->geometry().topLeft(), WIN->geometry().size()) );
+ WinWidget->resyncWindow();
+ }
+ }
+ break;
+ case NativeWindow::MinSize:
+ if(vals[i].toSize().isValid()){
+ //Just larger than titlebar, with enough space for 8 characters in the titlebar (+4 buttons)
+ //qDebug() << "Got invalid Min Size: Set a reasonable default minimum";
+ WinWidget->setMinimumSize( QSize( this->fontMetrics().height()*4 + this->fontMetrics().width("O")*10, this->fontMetrics().height()*10) );
+ WIN->setProperty(NativeWindow::MinSize, WinWidget->minimumSize());
+ }else{
+ WinWidget->setMinimumSize(vals[i].toSize());
+ }
+ if(WIN->property(NativeWindow::Size).toSize().width() < WinWidget->minimumSize().width() \
+ || WIN->property(NativeWindow::Size).toSize().height() < WinWidget->minimumSize().height() ){
+ WIN->setProperty(NativeWindow::Size, WinWidget->minimumSize(), true); //force this
+ //WinWidget->resize(WinWidget->minimumSize());
+ }
+ break;
+ case NativeWindow::MaxSize:
+ WinWidget->setMaximumSize(vals[i].toSize());
+ break;
+ case NativeWindow::Active:
+ if(vals[i].toBool()){ activate(); } //WinWidget->raiseWindow(); }
+ break;
+ /*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:
+ //qDebug() << "Got Window Types:" << vals[i].value< QList<NativeWindow::Type> >();
+ enableFrame(vals[i].value< QList<NativeWindow::Type> >() );
+ break;
+ default:
+ qDebug() << "Window Property Unused:" << props[i] << vals[i];
+ }
+ }
+}
+
+// === PROTECTED ===
+void RootSubWindow::mousePressEvent(QMouseEvent *ev){
+ activate();
+ this->raise();
+ QFrame::mousePressEvent(ev);
+ //qDebug() << "Frame Mouse Press Event";
+ if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse
+ offset.setX(0); offset.setY(0);
+ if(ev->button()==Qt::LeftButton){
+ if(this->childAt(ev->pos())!=0){
+ //Clicked on the titlebar
+ startMoving();
+ }else{
+ //Clicked on the frame somewhere
+ startResizing();
+ }
+ }
+
+}
+
+void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
+ QFrame::mouseMoveEvent(ev);
+ if(activeState == Normal){
+ setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
+ }else{
+ //Currently in a modification state
+ QRect geom = this->geometry();
+ QSize minsize(WinWidget->minimumSize().width() + (2*WIN_BORDER), WinWidget->minimumSize().height()+(2*WIN_BORDER)+titleBar->geometry().size().height());
+ switch(activeState){
+ case Move:
+ geom.moveTopLeft(ev->globalPos()-offset); //will not change size
+ break;
+ case ResizeTop:
+ geom.setTop(ev->globalPos().y()-offset.y());
+ if(geom.size().height() < minsize.height()){
+ geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height
+ }
+ break;
+ case ResizeTopRight:
+ geom.setTopRight(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setRight(geom.x() + minsize.width()); //reset back to min width
+ }
+ break;
+ case ResizeRight:
+ geom.setRight(ev->globalPos().x()-offset.x());
+ if(geom.size().width() < minsize.width()){
+ geom.setRight(geom.x() + minsize.width()); //reset back to min width
+ }
+ break;
+ case ResizeBottomRight:
+ geom.setBottomRight(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setBottom(geom.y() + minsize.height()); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setRight(geom.x() + minsize.width()); //reset back to min width
+ }
+ break;
+ case ResizeBottom:
+ geom.setBottom(ev->globalPos().y()-offset.y());
+ if(geom.size().height() < minsize.height()){
+ geom.setBottom(geom.y() + minsize.height()); //reset back to min height
+ }
+ break;
+ case ResizeBottomLeft:
+ geom.setBottomLeft(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setBottom(geom.y() + minsize.height()); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width
+ }
+ break;
+ case ResizeLeft:
+ geom.setLeft(ev->globalPos().x()-offset.x());
+ if(geom.size().width() < minsize.width()){
+ geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width
+ }
+ break;
+ case ResizeTopLeft:
+ geom.setTopLeft(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width
+ }
+ break;
+ default:
+ break;
+ }
+ //if( (geom.width()%2==0 && geom.height()%2==0) || activeState==Move){
+ //qDebug() << " Change Window:" << this->geometry() << geom;
+ if(activeState==Move){ this->setGeometry(geom); }
+ else{
+ //qDebug() << " Change Window Dimensions:" << this->geometry() << geom;
+ //qDebug() << " - Mouse Pos:" << ev->globalPos() << ev->pos() << "Offset" << offset;
+ this->setGeometry(geom);
+ }
+ //}
+ }
+}
+
+void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
+ //Check for a right-click event
+ //qDebug() << "Frame Mouse Release Event";
+ QFrame::mouseReleaseEvent(ev);
+ if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){
+ //WinWidget->raiseWindow();//need to ensure the native window is always on top of this frame but under the menu
+ otherM->popup(ev->globalPos());
+ return;
+ }
+ if(activeState!=Normal){
+ if(WinWidget->isPaused()){ WinWidget->resume(); }
+ activeState = Normal;
+ QApplication::restoreOverrideCursor();
+ setMouseCursor( getStateAtPoint(ev->pos()) );
+ }
+ if(QFrame::mouseGrabber() == this){ this->releaseMouse(); }
+ activate();
+ //QTimer::singleShot(0, WinWidget, SLOT(raiseWindow()) );
+}
+
+/*void RootSubWindow::enterEvent(QEvent *ev){
+ QFrame::enterEvent(ev);
+ WinWidget->raiseWindow();
+}*/
+/*void RootSubWindow::leaveEvent(QEvent *ev){
+ QFrame::leaveEvent(ev);
+ if(activeState == Normal){
+ setMouseCursor(Normal);
+ }
+ if(!QRect(QPoint(0,0),this->size()).contains( this->mapFromGlobal(QCursor::pos())) ){ WinWidget->lowerWindow(); }
+}*/
+
+void RootSubWindow::moveEvent(QMoveEvent *ev){
+ //qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry();
+ QFrame::moveEvent(ev);
+ if(!closing && !WinWidget->isPaused()){
+ moveTimer->start();
+ }
+}
diff --git a/src-qt5/core/libLumina/obsolete/RootSubWindow.h b/src-qt5/core/libLumina/obsolete/RootSubWindow.h
new file mode 100644
index 00000000..598298e2
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootSubWindow.h
@@ -0,0 +1,109 @@
+//===========================================
+// Lumina Desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class embeds a native window
+// within the RootWindow area
+//===========================================
+#ifndef _LUMINA_ROOT_WINDOW_SUB_WINDOW_H
+#define _LUMINA_ROOT_WINDOW_SUB_WINDOW_H
+
+#include <QWindow>
+#include <QWidget>
+#include <QCloseEvent>
+#include <QFrame>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QToolButton>
+#include <QMenu>
+#include <QPropertyAnimation>
+#include <NativeWindow.h>
+#include <NativeEmbedWidget.h>
+
+class RootSubWindow : public QFrame{
+ Q_OBJECT
+public:
+ RootSubWindow(QWidget *root, NativeWindow *win);
+ ~RootSubWindow();
+
+ WId id();
+ NativeWindow* nativeWindow();
+
+private:
+ //Window status
+ enum ModState{Normal, Move, ResizeTop, ResizeTopRight, ResizeRight, ResizeBottomRight, ResizeBottom, ResizeBottomLeft, ResizeLeft, ResizeTopLeft};
+ ModState activeState;
+ ModState currentCursor;
+ QPoint offset; //needed for movement calculations (offset from mouse click to movement point)
+ //Functions for getting/setting state
+ ModState getStateAtPoint(QPoint pt, bool setoffset = false); //generally used for mouse location detection
+ void setMouseCursor(ModState, bool override = false); //Update the mouse cursor based on state
+
+ //Native window embed objects
+ NativeWindow *WIN;
+ NativeEmbedWidget *WinWidget;
+ bool closing;
+ //Title bar objects
+ 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, lastMaxGeom; //frame coordinates
+
+ void initWindowFrame();
+ void enableFrame(bool);
+ void enableFrame(QList<NativeWindow::Type> types);
+
+ void LoadProperties( QList< NativeWindow::Property> list);
+
+ static QStringList validAnimations(NativeWindow::Property);
+
+public slots:
+ void ensureVisible(){ WIN->setProperty(NativeWindow::Visible, true); }
+ void giveMouseFocus(){ WinWidget->raiseWindow(); }
+ void removeMouseFocus(){ WinWidget->lowerWindow(); }
+ void giveKeyboardFocus(){ WIN->requestProperty(NativeWindow::Active, true, true); }
+
+ void clientClosed();
+ void LoadAllProperties();
+
+ QRect clientGlobalGeom();
+
+ //Button Actions - public so they can be tied to key shortcuts and stuff as well
+ void toggleMinimize();
+ void toggleMaximize();
+ void triggerClose();
+ void toggleSticky();
+ void activate();
+
+ //Mouse Interactivity
+ void startMoving();
+ void startResizing();
+
+private slots:
+ void propertiesChanged(QList<NativeWindow::Property>, QList<QVariant>);
+
+ void loadAnimation(QString name, NativeWindow::Property, QVariant nval); //new val
+ void animFinished();
+
+protected:
+ void mousePressEvent(QMouseEvent*);
+ void mouseMoveEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent*);
+ //void leaveEvent(QEvent *ev);
+ //void enterEvent(QEvent *ev);
+ void moveEvent(QMoveEvent *ev);
+
+signals:
+ void windowMoved(RootSubWindow*);
+ void windowAnimFinished();
+};
+
+#endif
diff --git a/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp b/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp
new file mode 100644
index 00000000..24ea639b
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp
@@ -0,0 +1,95 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RootWindow.h"
+
+//Primary/private function
+void RootWindow::arrangeWindows(RootSubWindow *primary, QString type, bool primaryonly){
+ if(type.isEmpty()){ type = "center"; }
+ if(primary==0){
+ //Get the currently active window and treat that as the primary
+ for(int i=0; i<WINDOWS.length(); i++){
+ if(WINDOWS[i]->nativeWindow()->property(NativeWindow::Active).toBool()){ primary = WINDOWS[i]; }
+ }
+ if(primary==0 && !WINDOWS.isEmpty()){ primary = WINDOWS[0]; } //just use the first one in the list
+ }
+ //Now get the current screen that the mouse cursor is over (and valid area)
+ QScreen *screen = screenUnderMouse();
+ QRect desktopArea = screen->availableGeometry();
+ //qDebug() << "Arrange Windows:" << primary->geometry() << type << primaryonly << desktopArea;
+ //Now start filtering out all the windows that need to be ignored
+ int wkspace = primary->nativeWindow()->property(NativeWindow::Workspace).toInt();
+ QList<RootSubWindow*> winlist = WINDOWS;
+ for(int i=0; i<winlist.length(); i++){
+ if(winlist[i]->nativeWindow()->property(NativeWindow::Workspace).toInt()!=wkspace
+ || !winlist[i]->nativeWindow()->property(NativeWindow::Visible).toBool()
+ || desktopArea.intersected(winlist[i]->geometry()).isNull() ){
+ //window is outside of the desired area or invisible - ignore it
+ winlist.removeAt(i);
+ i--;
+ }
+ }
+ if(!winlist.contains(primary)){ winlist << primary; } //could be doing this on a window right before it is shown
+ else if(primaryonly){ winlist.removeAll(primary); winlist << primary; } //move primary window to last
+ //QRegion used;
+ for(int i=0; i<winlist.length(); i++){
+ if(primaryonly && winlist[i]!=primary){ continue; } //skip this window
+ //Now loop over the windows and arrange them as needed
+ QRect geom = winlist[i]->geometry();
+ //verify that the window is contained by the desktop area
+ if(geom.width()>desktopArea.width()){ geom.setWidth(desktopArea.width()); }
+ if(geom.height()>desktopArea.height()){ geom.setHeight(desktopArea.height()); }
+ //Now apply the proper placement routine
+ if(type=="center"){
+ QPoint ct = desktopArea.center();
+ winlist[i]->setGeometry( ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height());
+ }else if(type=="snap"){
+
+ }else if(type=="single_max"){
+ winlist[i]->setGeometry( desktopArea.x(), desktopArea.y(), desktopArea.width(), desktopArea.height());
+ }else if(type=="under-mouse"){
+ QPoint ct = QCursor::pos();
+ geom = QRect(ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height() );
+ //Now verify that the top of the window is still contained within the desktop area
+ if(geom.y() < desktopArea.y() ){ geom.moveTop(desktopArea.y()); }
+ winlist[i]->setGeometry(geom);
+
+ }
+ //qDebug() << " - New Geometry:" << winlist[i]->geometry();
+ } //end loop over winlist
+}
+
+// ================
+// Public slots for starting the arrangement routine(s) above
+// ================
+void RootWindow::ArrangeWindows(WId primary, QString type){
+ RootSubWindow* win = windowForId(primary);
+ if(type.isEmpty()){ type = "center"; } //grab the default arrangement format
+ arrangeWindows(win, type);
+}
+
+void RootWindow::TileWindows(WId primary, QString type){
+ RootSubWindow* win = windowForId(primary);
+ if(type.isEmpty()){ type = "single_max"; } //grab the default arrangement format for tiling
+ arrangeWindows(win, type);
+}
+
+void RootWindow::CheckWindowPosition(WId id, bool newwindow){
+ //used after a "drop" to validate/snap/re-arrange window(s) as needed
+ // if "newwindow" is true, then this is the first-placement routine for a window before it initially appears
+ RootSubWindow* win = windowForId(id);
+ if(win==0){ return; } //invalid window
+ QRect geom = win->nativeWindow()->geometry();
+ bool changed = false;
+ //Make sure it is on the screen (quick check)
+ if(geom.x() < 0){ changed = true; geom.moveLeft(0); }
+ if(geom.y() < 0){ changed = true; geom.moveTop(0); }
+ if(geom.width() < 20){ changed = true; geom.setWidth(100); }
+ if(geom.height() < 20){ changed = true; geom.setHeight(100); }
+ if(changed){ win->setGeometry(geom); }
+ //Now run it through the window arrangement routine
+ arrangeWindows(win, newwindow ?"center" : "snap", true);
+}
diff --git a/src-qt5/core/libLumina/obsolete/RootWindow.cpp b/src-qt5/core/libLumina/obsolete/RootWindow.cpp
new file mode 100644
index 00000000..705297be
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootWindow.cpp
@@ -0,0 +1,283 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RootWindow.h"
+
+#include <QDesktopWidget>
+#include <QScreen>
+#include <QDebug>
+
+#define DEBUG 0
+
+// === PUBLIC ===
+RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){
+ qRegisterMetaType<WId>("WId");
+ autoResizeTimer = 0;
+ lastActiveMouse = 0;
+ mouseFocusTimer = 0;
+ this->setMouseTracking(true);
+}
+
+RootWindow::~RootWindow(){
+
+}
+
+void RootWindow::start(){
+
+ if(autoResizeTimer==0){
+ autoResizeTimer = new QTimer(this);
+ autoResizeTimer->setInterval(100); //1/10 second (collect all nearly-simultaneous signals and compress into a single update)
+ autoResizeTimer->setSingleShot(true);
+ connect(autoResizeTimer, SIGNAL(timeout()), this, SLOT(ResizeRoot()) );
+ connect(QApplication::desktop(), SIGNAL(resized(int)), autoResizeTimer, SLOT(start()) );
+ connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), autoResizeTimer, SLOT(start()) );
+ }
+ if(mouseFocusTimer==0){
+ mouseFocusTimer = new QTimer(this);
+ mouseFocusTimer->setInterval(100);
+ connect(mouseFocusTimer, SIGNAL(timeout()), this, SLOT(checkMouseFocus()) );
+
+ }
+ this->show();
+ ResizeRoot();
+ emit RegisterVirtualRoot(this->winId());
+}
+
+// === PRIVATE ===
+void RootWindow::updateScreenPixmap(screeninfo *info){
+ QPixmap pix(info->area.size());
+ if(info->scale == RootWindow::SolidColor){
+ QColor color;
+ if(info->file.startsWith("rgb(")){
+ QStringList colors = info->file.section(")",0,0).section("(",1,1).split(",");
+ color = QColor(colors[0].toInt(), colors[1].toInt(), colors[2].toInt());
+ }else{
+ color = QColor(info->file);
+ }
+ pix.fill(color);
+ }else{
+ 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;
+ 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()){
+ raw = raw.scaled(info->area.size(), armode);
+ }
+ }
+ //Now calculate offset and draw width/height
+ QRect drawRect(0,0, raw.width(), raw.height());
+ 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 );
+ }else if(info->scale == RootWindow::Center ){
+ 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());
+ }else if(info->scale == RootWindow::BottomLeft ){
+ drawRect.moveTo( 0 , info->area.height() - raw.height() );
+ }else if(info->scale == RootWindow::BottomRight ){
+ drawRect.moveTo( (info->area.width() - raw.width()), (info->area.height() - raw.height()) );
+ }else if(info->scale == RootWindow::BottomCenter ){
+ drawRect.moveTo( (info->area.width() - raw.width())/2, info->area.height() - raw.height() );
+ }else if(info->scale == RootWindow::TopLeft ){
+ drawRect.moveTo( 0, 0 );
+ }else if(info->scale == RootWindow::TopRight ){
+ drawRect.moveTo( (info->area.width() - raw.width()), 0);
+ }else if(info->scale == RootWindow::TopCenter ){
+ drawRect.moveTo( (info->area.width() - raw.width())/2, 0);
+ }else if(info->scale == RootWindow::CenterLeft ){
+ drawRect.moveTo( 0, (info->area.height() - raw.height())/2 );
+ }else if(info->scale == RootWindow::CenterRight ){
+ drawRect.moveTo( (info->area.width() - raw.width()), (info->area.height() - raw.height())/2 );
+ }
+
+ QPainter P(&pix);
+ P.setBrush(raw);
+ P.setBrushOrigin( drawRect.x(), drawRect.y() );
+ P.drawRect( drawRect );
+} //end SolidColor Check
+
+ info->wallpaper = pix;
+}
+
+RootSubWindow* RootWindow::windowForId(WId id){
+ RootSubWindow *tmp = 0;
+ for(int i=0; i<WINDOWS.length() && tmp==0; i++){
+ if(WINDOWS[i]->id() == id){ tmp = WINDOWS[i]; }
+ }
+ return tmp;
+}
+
+QScreen* RootWindow::screenUnderMouse(){
+ QPoint mpos = QCursor::pos();
+ QList<QScreen*> scrns = QApplication::screens();
+ for(int i=0; i<scrns.length(); i++){
+ if(scrns[i]->geometry().contains(mpos)){ return scrns[i]; }
+ }
+ //Could not find an exact match - just return the first one
+ return scrns.first();
+}
+
+// === PUBLIC SLOTS ===
+void RootWindow::ResizeRoot(){
+ if(DEBUG){ qDebug() << "Resize Root..."; }
+ QList<QScreen*> scrns = QApplication::screens();
+ //Update all the screen locations and ID's in the WALLPAPERS list
+ QRect fullscreen;
+ QStringList valid;
+ //Update the size of the rootWindow itself
+ for(int i=0; i<scrns.length(); i++){
+ if(DEBUG){ qDebug() << " - Found Screen:" << scrns[i]->name() << scrns[i]->geometry(); }
+ fullscreen = fullscreen.united(scrns[i]->geometry());
+ valid << scrns[i]->name();
+ for(int j=0; j<WALLPAPERS.length(); j++){
+ if(WALLPAPERS[j].id == scrns[i]->name()){
+ QSize oldsize = WALLPAPERS[j].area.size();
+ WALLPAPERS[j].area = scrns[i]->geometry();
+ if(oldsize != WALLPAPERS[j].area.size()){ updateScreenPixmap(&WALLPAPERS[j]); }
+ break;
+ }
+ }
+ }
+ //Now clean up any invalid screen info in the WALLPAPERS List
+ QStringList invalid;
+ for(int i=0; i<WALLPAPERS.length(); i++){
+ if(valid.contains(WALLPAPERS[i].id)){
+ valid.removeAll(WALLPAPERS[i].id); //Already handled - remove it from the list
+ }else{
+ invalid << WALLPAPERS[i].id;
+ WALLPAPERS.takeAt(i);
+ i--;
+ }
+ }
+ //Trigger a repaint and send out any signals
+ if(DEBUG){ qDebug() << " - FullScreen Geometry:" << fullscreen; }
+ this->setGeometry(fullscreen);
+ this->update();
+ emit RootResized(fullscreen);
+ if(!valid.isEmpty()){ emit NewScreens(valid); }
+ if(!invalid.isEmpty()){ emit RemovedScreens(invalid); }
+ if(DEBUG){ qDebug() << " - Geom after change:" << this->geometry(); }
+}
+
+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){
+ WALLPAPERS[i].scale = scale;
+ WALLPAPERS[i].file = file;
+ updateScreenPixmap(&WALLPAPERS[i]);
+ //qDebug() << " --- Updated Wallpaper:" << WALLPAPERS[i].id << WALLPAPERS[i].file << WALLPAPERS[i].area;
+ found = true;
+ }
+ }
+ if(!found){
+ ResizeRoot();
+ //Need to create a new screeninfo structure
+ QList<QScreen*> scrns = QApplication::screens();
+ for(int i=0; i<scrns.length(); i++){
+ if(scrns[i]->name()==id){
+ screeninfo info;
+ info.id = id;
+ info.file = file;
+ info.scale = scale;
+ info.area = scrns[i]->geometry();
+ updateScreenPixmap(&info);
+ //qDebug() << " --- Loaded Wallpaper:" << info.id << info.file << info.area;
+ WALLPAPERS << info;
+ break;
+ }
+ }
+ } //end check for a new id
+
+}
+
+void RootWindow::checkMouseFocus(){
+ QPoint cpos = QCursor::pos();
+ if(lastCursorPos != cpos){ emit MouseMoved(); }
+ lastCursorPos = cpos;
+ QWidget *child = this->childAt(QCursor::pos());
+ while(child!=0 && child->whatsThis()!="RootSubWindow"){
+ child = child->parentWidget();
+ if(child==this){ child = 0;} //end of the line
+ }
+
+ if(child==lastActiveMouse){ return; } //nothing new to do
+ //Make sure the child is actually a RootSubWindow
+ if(lastActiveMouse!=0){ lastActiveMouse->removeMouseFocus(); lastActiveMouse = 0; }
+ if(child!=0){
+ lastActiveMouse = static_cast<RootSubWindow*>(child);
+
+ if(DesktopSettings::instance()->value(DesktopSettings::WM, "focusFollowsMouse", true).toBool()){
+ lastActiveMouse->giveKeyboardFocus();
+ if(DesktopSettings::instance()->value(DesktopSettings::WM, "raiseOnFocus", false).toBool()){
+ lastActiveMouse->raise();
+ }
+ }
+ lastActiveMouse->giveMouseFocus(); //always give mouse focus on mouseover
+ }
+}
+
+void RootWindow::NewWindow(NativeWindow *win){
+ RootSubWindow *subwin = 0;
+ //qDebug() << "Got New Window:" << win->property(NativeWindow::Title);
+ for(int i=0; i<WINDOWS.length() && subwin==0; i++){
+ if(WINDOWS[i]->id() == win->id()){ subwin = WINDOWS[i]; }
+ }
+ if(subwin==0){
+ subwin = new RootSubWindow(this, win);
+ subwin->setWhatsThis("RootSubWindow");
+ connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) );
+ connect(subwin, SIGNAL(windowAnimFinished()), this, SLOT(checkMouseFocus()) );
+ WINDOWS << subwin;
+ }
+ //QApplication::processEvents();
+ CheckWindowPosition(win->id(), true); //first-time run
+ //QTimer::singleShot(300, subwin, SLOT(ensureVisible()));
+ win->setProperty(NativeWindow::Visible, true);
+ //win->requestProperty( NativeWindow::Active, true);
+ //win->requestProperties(QList<NativeWindow::Property>() << NativeWindow::Visible << NativeWindow::Active, QList<QVariant>() << true << true, true);
+ if(!mouseFocusTimer->isActive()){ mouseFocusTimer->start(); }
+}
+
+void RootWindow::CloseWindow(WId win){
+ for(int i=0; i<WINDOWS.length(); i++){
+ if(WINDOWS[i]->id() == win){
+ if(lastActiveMouse==WINDOWS[i]){ lastActiveMouse = 0; } //no longer valid
+ WINDOWS.takeAt(i)->clientClosed();
+ break;
+ }
+ }
+ if(WINDOWS.isEmpty()){ mouseFocusTimer->stop(); } //no windows to look for
+}
+
+// === PRIVATE SLOTS ===
+
+// === PROTECTED ===
+void RootWindow::paintEvent(QPaintEvent *ev){
+ //qDebug() << "RootWindow: PaintEvent:" << ev->rect(); //<< QDateTime::currentDateTime()->toString(QDateTime::ShortDate);
+ //QWidget::paintEvent(ev);
+ bool found = false;
+ QPainter painter(this);
+ QRect geom = ev->rect();
+ geom.adjust(-100,-100,100,100); //give it a few more pixels in each direction to repaint (noticing some issues in Qt 5.7.1)
+ for(int i=0; i<WALLPAPERS.length(); i++){
+ if(WALLPAPERS[i].area.intersects(geom) ){
+ found = true;
+ QRect intersect = WALLPAPERS[i].area.intersected(geom);
+ painter.drawPixmap( intersect, WALLPAPERS[i].wallpaper, intersect.translated(-WALLPAPERS[i].area.x(), -WALLPAPERS[i].area.y()) );
+ }
+ }
+ painter.end();
+ /*if(!found){
+ QWidget::paintEvent(ev);
+ }*/
+}
diff --git a/src-qt5/core/libLumina/obsolete/RootWindow.h b/src-qt5/core/libLumina/obsolete/RootWindow.h
new file mode 100644
index 00000000..c5cd44a0
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootWindow.h
@@ -0,0 +1,92 @@
+//===========================================
+// Lumina Desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This class creates and manages a virtual "root" window
+// for all monitors at all times.
+//===========================================
+#ifndef _LUMINA_ROOT_WINDOW_H
+#define _LUMINA_ROOT_WINDOW_H
+
+#include <QWidget>
+#include <QRect>
+#include <QString>
+#include <QPixmap>
+#include <QPainter>
+#include <QTimer>
+#include <QApplication>
+#include <QPaintEvent>
+#include <QScreen>
+#include <QDebug>
+
+#include "RootSubWindow.h"
+
+#include <NativeWindow.h>
+#include <DesktopSettings.h>
+
+class RootWindow : public QWidget{
+ Q_OBJECT
+public:
+ enum ScaleType{ SolidColor, Stretch, Full, Fit, Center, Tile, BottomLeft, BottomRight, BottomCenter, \
+ TopLeft, TopRight, TopCenter, CenterLeft, CenterRight};
+
+ RootWindow();
+ ~RootWindow();
+
+ void start();
+
+private:
+ struct screeninfo{
+ QString id;
+ QRect area;
+ QString file;
+ ScaleType scale;
+ QPixmap wallpaper; //Note: This pixmap will always be the same size as "area"
+ };
+ QTimer *autoResizeTimer, *mouseFocusTimer;
+ RootSubWindow *lastActiveMouse;
+ QPoint lastCursorPos;
+
+ QList<screeninfo> WALLPAPERS;
+ void updateScreenPixmap(screeninfo *info); //used for recalculating the wallpaper pixmap based on file/area/scale as needed
+
+ //Window Management
+ QList<RootSubWindow*> WINDOWS;
+ RootSubWindow* windowForId(WId id);
+ void arrangeWindows(RootSubWindow *primary = 0, QString type = "", bool primaryonly = false);
+
+ QScreen* screenUnderMouse();
+
+
+public slots:
+ void ResizeRoot();
+ void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file);
+ //Note: for "SingleColor" scaling the "file" variable should be "rgb(R,G,B)" or "#hexcode"
+ void checkMouseFocus();
+
+ void NewWindow(NativeWindow*);
+ void CloseWindow(WId); //automatically connected for any new native window
+
+ //Window arrangement functions - defined in "RootWindow-mgmt.cpp"
+ void ArrangeWindows(WId primary = 0, QString type = "");
+ void TileWindows(WId primary = 0, QString type = "");
+ void CheckWindowPosition(WId, bool newwindow = false); //used after a "drop" to validate/snap/re-arrange window(s) as needed
+
+private slots:
+
+protected:
+ void paintEvent(QPaintEvent *ev);
+
+signals:
+ void RegisterVirtualRoot(WId);
+ void RootResized(QRect);
+ void NewScreens(QStringList); // [screen_id_1, screen_id_2, etc..]
+ void RemovedScreens(QStringList); // [screen_id_1, screen_id_2, etc..]
+ void WorkspaceChanged(int);
+ void MouseMoved();
+
+};
+
+#endif
diff --git a/src-qt5/core/libLumina/obsolete/RootWindow.pri b/src-qt5/core/libLumina/obsolete/RootWindow.pri
new file mode 100644
index 00000000..9426b6b4
--- /dev/null
+++ b/src-qt5/core/libLumina/obsolete/RootWindow.pri
@@ -0,0 +1,17 @@
+
+# Files
+SOURCES *= $${PWD}/RootWindow.cpp \
+ $${PWD}/RootWindow-mgmt.cpp \
+ $${PWD}/RootSubWindow.cpp \
+ $${PWD}/RootSubWindow-animations.cpp
+
+HEADERS *= $${PWD}/RootWindow.h \
+ $${PWD}/RootSubWindow.h
+
+INCLUDEPATH *= ${PWD}
+
+# include other library dependencies
+include(LUtils.pri)
+include(NativeWindow.pri)
+include(LIconCache.pri)
+include(DesktopSettings.pri)
bgstack15