diff options
author | Weblate <noreply@weblate.org> | 2017-11-04 19:28:17 +0000 |
---|---|---|
committer | Weblate <noreply@weblate.org> | 2017-11-04 19:28:17 +0000 |
commit | 7787f617656751ee7e0a58c813d0bfd5757c5c97 (patch) | |
tree | 48aa053bbd4fda9c64f89a061a2f442c860ab13d /src-qt5/core/libLumina/obsolete | |
parent | Translated using Weblate (Lithuanian) (diff) | |
parent | Merge pull request #497 from a-stjohn/patch-1 (diff) | |
download | lumina-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.cpp | 116 | ||||
-rw-r--r-- | src-qt5/core/libLumina/obsolete/RootSubWindow.cpp | 601 | ||||
-rw-r--r-- | src-qt5/core/libLumina/obsolete/RootSubWindow.h | 109 | ||||
-rw-r--r-- | src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp | 95 | ||||
-rw-r--r-- | src-qt5/core/libLumina/obsolete/RootWindow.cpp | 283 | ||||
-rw-r--r-- | src-qt5/core/libLumina/obsolete/RootWindow.h | 92 | ||||
-rw-r--r-- | src-qt5/core/libLumina/obsolete/RootWindow.pri | 17 |
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) |