aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/RootSubWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina/RootSubWindow.cpp')
-rw-r--r--src-qt5/core/libLumina/RootSubWindow.cpp265
1 files changed, 211 insertions, 54 deletions
diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp
index 41c04ee1..9ef6464e 100644
--- a/src-qt5/core/libLumina/RootSubWindow.cpp
+++ b/src-qt5/core/libLumina/RootSubWindow.cpp
@@ -8,9 +8,12 @@
#include <QDebug>
#include <QApplication>
#include <QVBoxLayout>
-#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QTimer>
+
+#define WIN_BORDER 5
-#define WIN_BORDER 3
+#include <LIconCache.h>
// === PUBLIC ===
RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){
@@ -19,15 +22,18 @@ RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){
//Create the QWindow and QWidget containers for the window
WIN = win;
closing = false;
- WinWidget = QWidget::createWindowContainer( WIN->window(), this);
initWindowFrame();
- LoadProperties( NativeWindow::allProperties() );
//Hookup the signals/slots
connect(WIN, SIGNAL(PropertiesChanged(QList<NativeWindow::Property>, QList<QVariant>)), this, SLOT(propertiesChanged(QList<NativeWindow::Property>, QList<QVariant>)));
+ WinWidget->embedWindow(WIN);
+ //qDebug() << "[NEW WINDOW]" << WIN->id() << WinWidget->winId() << this->winId();
+ activeState = RootSubWindow::Normal;
+ LoadAllProperties();
}
RootSubWindow::~RootSubWindow(){
-
+ //qDebug() << "Visible Window Destroyed";
+ WIN->deleteLater();
}
WId RootSubWindow::id(){
@@ -41,41 +47,57 @@ RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset
//above the frame itself - need to figure out which quadrant it is in (8-directions)
if(pt.y() < WIN_BORDER){
//One of the top options
- if(pt.x() < WIN_BORDER){
+ if(pt.x() < this->width()/5){
if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
return ResizeTopLeft;
- }else if(pt.x() > (this->width()-WIN_BORDER)){
+ }else if(pt.x() > (this->width()*4.0/5.0)){
if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(pt.y()); } //difference from top-right corner
return ResizeTopRight;
- }else{
+ }else{
if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter)
- return ResizeTop;
- }
+ return ResizeTop;
+ }
}else if(pt.y() > (this->height()-WIN_BORDER) ){
//One of the bottom options
- if(pt.x() < WIN_BORDER){
+ if(pt.x() < this->width()/5){
if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
return ResizeBottomLeft;
- }else if(pt.x() > (this->width()-WIN_BORDER)){
+ }else if(pt.x() > (this->width()*4.0/5.0)){
if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-right corner
return ResizeBottomRight;
- }else{
+ }else{
if(setoffset){ offset.setX(0); offset.setY(this->height() - pt.y()); } //difference from bottom edge (X does not matter)
- return ResizeBottom;
- }
- }else{
- //One of the side options
- if(pt.x() < WIN_BORDER){
+ return ResizeBottom;
+ }
+ }else if(pt.x() < WIN_BORDER){
+ //Left side options
+ if(pt.y() < this->height()/5){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
+ return ResizeTopLeft;
+ }else if(pt.y() > (this->height()*4.0/5.0)){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
+ return ResizeBottomLeft;
+ }else{
if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter)
return ResizeLeft;
- }else if(pt.x() > (this->width()-WIN_BORDER) ){
+ }
+ }else if(pt.x() > (this->width()-WIN_BORDER) ){
+ //Right side options
+ if(pt.y() < this->height()/5){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(pt.y()); } //difference from top-right corner
+ return ResizeTopRight;
+ }else if(pt.y() > (this->height()*4.0/5.0)){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-right corner
+ return ResizeBottomRight;
+ }else{
if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(0); } //difference from right edge (Y does not matter)
return ResizeRight;
- }else{
- return Normal;
}
+ }else{
+ return Normal;
}
}
+ //if it gets this far just return normal
return Normal;
}
@@ -112,7 +134,7 @@ void RootSubWindow::setMouseCursor(ModState state, bool override){
break;
case ResizeTopLeft:
shape = Qt::SizeFDiagCursor;
- break;
+ break;
}
if(override){
QApplication::setOverrideCursor(QCursor(shape));
@@ -123,31 +145,48 @@ void RootSubWindow::setMouseCursor(ModState state, bool override){
}
void RootSubWindow::initWindowFrame(){
+ //qDebug() << "Create RootSubWindow Frame";
+ this->setContentsMargins(0,0,0,0);
mainLayout = new QVBoxLayout(this);
- titleBar = new QHBoxLayout(this);
+ mainLayout->setContentsMargins(0,0,0,0);
+ titleBar = new QWidget(this);
+ titleBar->setContentsMargins(0,0,0,0);
+ titleBarL = new QHBoxLayout(titleBar);
+ titleBarL->setContentsMargins(0,0,0,0);
closeB = new QToolButton(this);
maxB = new QToolButton(this);
minB = new QToolButton(this);
otherB = new QToolButton(this);
+ anim = new QPropertyAnimation(this);
+ anim->setTargetObject(this);
+ anim->setDuration(200); //1/5 second (appx)
+ connect(anim, SIGNAL(finished()), this, SLOT(animFinished()) );
titleLabel = new QLabel(this);
titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
otherM = new QMenu(this); //menu of other actions
otherB->setMenu(otherM);
otherB->setPopupMode(QToolButton::InstantPopup);
otherB->setAutoRaise(true);
+ WinWidget = new NativeEmbedWidget(this);
connect(closeB, SIGNAL(clicked()), this, SLOT(triggerClose()) );
connect(maxB, SIGNAL(clicked()), this, SLOT(toggleMaximize()) );
connect(minB, SIGNAL(clicked()), this, SLOT(toggleMinimize()) );
//Now assemble the frame layout based on the current settings
- this->setLayout(mainLayout);
- titleBar->addWidget(otherB);
- titleBar->addWidget(titleLabel);
- titleBar->addWidget(minB);
- titleBar->addWidget(maxB);
- titleBar->addWidget(closeB);
+ titleBarL->addWidget(otherB);
+ titleBarL->addWidget(titleLabel);
+ titleBarL->addWidget(minB);
+ titleBarL->addWidget(maxB);
+ titleBarL->addWidget(closeB);
WinWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- mainLayout->addLayout(titleBar);
+ titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ mainLayout->addWidget(titleBar);
mainLayout->addWidget(WinWidget);
+ //Setup the cursors for the buttons
+ closeB->setCursor(Qt::ArrowCursor);
+ minB->setCursor(Qt::ArrowCursor);
+ maxB->setCursor(Qt::ArrowCursor);
+ otherM->setCursor(Qt::ArrowCursor);
+ titleLabel->setCursor(Qt::ArrowCursor);
//Now all the stylesheet options
this->setObjectName("WindowFrame");
closeB->setObjectName("Button_Close");
@@ -155,36 +194,82 @@ void RootSubWindow::initWindowFrame(){
maxB->setObjectName("Button_Maximize");
otherM->setObjectName("Menu_Actions");
titleLabel->setObjectName("Label_Title");
- this->setStyleSheet("QWidget#WindowFrame{background-color: darkblue;} QWidget#Label_Title{background-color: transparent; color: white; }");
+ this->setStyleSheet("QFrame#WindowFrame{background-color: rgba(0,0,0,125)} QWidget#Label_Title{background-color: transparent; color: white; } QToolButton{background-color: transparent; border: 1px solid transparent; border-radius: 3px; } QToolButton::hover{background-color: rgba(255,255,255,150); } QToolButton::pressed{ background-color: white; } QToolButton::menu-arrow{ image: none; }");
//And adjust the margins
- mainLayout->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER);
mainLayout->setSpacing(0);
- titleBar->setSpacing(1);
- titleBar->setContentsMargins(0,0,0,0);
+ titleBarL->setSpacing(1);
+ this->setFrameStyle(QFrame::NoFrame);
+ this->setLineWidth(0);
+ this->setMidLineWidth(0);
+ this->setFrameRect(QRect(0,0,0,0));
+
+ //Setup the timer object to syncronize info
+ moveTimer = new QTimer(this);
+ moveTimer->setSingleShot(true);
+ moveTimer->setInterval(100); //1/10 second
+ connect(moveTimer, SIGNAL(timeout()), WinWidget, SLOT(resyncWindow()) );
+
+ //Now load the icons for the button
+ LIconCache::instance()->loadIcon(closeB, "window-close");
+ LIconCache::instance()->loadIcon(maxB, "window-maximize");
+ LIconCache::instance()->loadIcon(minB, "window-minimize");
+ LIconCache::instance()->loadIcon(otherB, "list");
+}
+
+void RootSubWindow::enableFrame(bool on){
+ //Make the individual frame elements visible as needed
+ if(on){ this->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER); }//default border
+ else{ this->setContentsMargins(0, 0, 0, 0); }
+ titleBar->setVisible(on);
+ //And now calculate/save the frame extents
+ QList<int> extents; extents << 0 << 0 << 0 << 0; //left, right, top, bottom
+ if(on){
+ extents[0] = WIN_BORDER;
+ extents[1] = WIN_BORDER;
+ extents[2] = WIN_BORDER + titleBar->height();
+ extents[3] = WIN_BORDER;
+ }
+ //qDebug() << "SET FRAME EXTENTS:" << extents;
+ WIN->requestProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList<int> >(extents) ); //save on raw window itself
+ WIN->setProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList<int> >(extents) ); //save to structure now
}
void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){
QList<QVariant> vals;
+ //Always ensure that visibility changes are evaluated last
+ bool addvisible = false;
for(int i=0; i<list.length(); i++){
+ if(list[i] == NativeWindow::Visible){ list.removeAt(i); i--; addvisible = true; continue; }
vals << WIN->property(list[i]);
}
+ //if(addvisible){ list << NativeWindow::Visible; vals << WIN->property(NativeWindow::Visible); }
propertiesChanged(list, vals);
}
// === PUBLIC SLOTS ===
void RootSubWindow::clientClosed(){
- qDebug() << "Client Closed";
+ //qDebug() << "Client Closed";
closing = true;
- this->close();
+ if(anim->state()!=QAbstractAnimation::Running){ this->close(); }
+}
+
+void RootSubWindow::LoadAllProperties(){
+ QList< NativeWindow::Property> list;
+ list << NativeWindow::WinTypes << NativeWindow::WinActions << NativeWindow::States
+ << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Title << NativeWindow::ShortTitle
+ << NativeWindow::Icon << NativeWindow::Size << NativeWindow::GlobalPos << NativeWindow::Visible << NativeWindow::Active;
+ LoadProperties(list);
+ WIN->requestProperty(NativeWindow::Visible, true);
}
//Button Actions - public so they can be tied to key shortcuts and stuff as well
void RootSubWindow::toggleMinimize(){
-
+ WIN->setProperty(NativeWindow::Visible, false);
+ QTimer::singleShot(2000, this, SLOT(toggleMaximize()) );
}
void RootSubWindow::toggleMaximize(){
-
+ WIN->setProperty(NativeWindow::Visible, true);
}
void RootSubWindow::triggerClose(){
@@ -219,26 +304,62 @@ void RootSubWindow::startResizing(){
}
-
-
// === PRIVATE SLOTS ===
void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList<QVariant> vals){
for(int i=0; i<props.length() && i<vals.length(); i++){
- if(vals[i].isNull()){ return; } //not the same as a default/empty value - the property has just not been set yet
- //qDebug() << "Set Window Property:" << props[i] << vals[i];
+ if(vals[i].isNull()){ continue; } //not the same as a default/empty value - the property has just not been set yet
+ //qDebug() << "RootSubWindow: Property Changed:" << props[i] << vals[i];
switch(props[i]){
case NativeWindow::Visible:
- if(vals[i].toBool()){ this->show(); }
- else{ this->hide(); }
+ //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry();
+ if(vals[i].toBool()){
+ if(lastGeom.isNull()){ animResetProp = this->geometry(); }
+ else{ animResetProp = lastGeom; }
+ anim->setPropertyName("geometry");
+ anim->setStartValue( QRect(animResetProp.toRect().center(), QSize(0,0)) );
+ anim->setEndValue(animResetProp);
+ this->setGeometry( anim->startValue().toRect() ); //ensure the window is the initial geom before it becomes visible
+ anim->start();
+ this->show();
+ }else{
+ animResetProp = this->geometry(); //hide event - should already be the right geom
+ lastGeom = this->geometry();
+ anim->setPropertyName("geometry");
+ anim->setStartValue(this->geometry());
+ anim->setEndValue( QRect(this->geometry().center(), QSize(0,0) ) );
+ anim->start();
+ QTimer::singleShot(anim->duration(), this, SLOT(hide()) );
+ }
break;
case NativeWindow::Title:
titleLabel->setText(vals[i].toString());
break;
case NativeWindow::Icon:
- otherB->setIcon(vals[i].value< QIcon>());
+ //qDebug() << "Got Icon Change:" << vals[i];
+ if(vals[i].value<QIcon>().isNull() ){ LIconCache::instance()->loadIcon(otherB, "list"); }
+ else{ otherB->setIcon(vals[i].value<QIcon>()); }
+ break;
+ case NativeWindow::GlobalPos:
+ //qDebug() << "Got Global Pos:" << this->pos() << WinWidget->mapToGlobal(QPoint(0,0)) << WIN->geometry().topLeft() << vals[i].toPoint();
+ if(activeState == RootSubWindow::Normal){
+ this->move( WIN->geometry().topLeft() );
+ }
break;
case NativeWindow::Size:
- WinWidget->resize(vals[i].toSize());
+ //qDebug() << " - SIZE CHANGE";
+ if(WIN->property(NativeWindow::FrameExtents).isNull() && (i<props.indexOf(NativeWindow::FrameExtents)) ){
+ //Frame not loaded yet - push this back until after the frame is set
+ props << props.takeAt(i);
+ vals << vals.takeAt(i);
+ i--;
+ }else if(anim->state() != QPropertyAnimation::Running ){
+ if(vals[i].toSize() != WinWidget->size() && activeState==Normal){
+ //qDebug() << "Got Widget Size Change:" << vals[i].toSize() << WinWidget->size();
+ WinWidget->resize(vals[i].toSize());
+ this->resize( WIN->geometry().size() );
+ //qDebug() << " - Size after change:" << WinWidget->size() << this->size() << WIN->geometry();
+ }
+ }
break;
case NativeWindow::MinSize:
WinWidget->setMinimumSize(vals[i].toSize());
@@ -247,19 +368,44 @@ void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList
WinWidget->setMaximumSize(vals[i].toSize());
break;
case NativeWindow::Active:
- if(vals[i].toBool()){ WinWidget->setFocus(); }
+ //if(vals[i].toBool()){ WinWidget->setFocus(); }
break;
- /*case NativeWindow::WindowFlags:
- this->setWindowFlags( val.value< Qt::WindowFlags >() );
+ /*case NativeWindow::FrameExtents:
+ qDebug() << " - FRAME CHANGE";
+ if(vals[i].isNull()){
+ vals[i] = QVariant::fromValue<QList<int> >( QList<int>() << WinWidget->geometry().x() << this->width()-WinWidget->geometry().x()-WinWidget->geometry().width() << WinWidget->y() << this->height() - WinWidget->y() - WinWidget->geometry().height() );
+ WIN->setProperty(NativeWindow::FrameExtents, vals[i]);
+ }
+ qDebug() << "Setting Frame Extents:" << vals[i].value<QList<int> >();
+ mainLayout->setContentsMargins( vals[i].value< QList<int> >().at(0),vals[i].value< QList<int> >().at(2) - titleLabel->height(),vals[i].value< QList<int> >().at(1),vals[i].value< QList<int> >().at(3));
break;*/
+ case NativeWindow::WinTypes:
+ enableFrame(vals[i].value< QList<NativeWindow::Type> >().contains(NativeWindow::T_NORMAL) );
+ break;
default:
qDebug() << "Window Property Unused:" << props[i] << vals[i];
}
}
}
+void RootSubWindow::animFinished(){
+ if(closing){ this->close(); return;}
+ else if(anim->propertyName()=="geometry"){
+ if(!animResetProp.isNull()){
+ /*qDebug() << "Animation Finished, Reset Geometry:" << animResetProp;
+ qDebug() << " - Starting Value:" << anim->startValue();
+ qDebug() << " - Ending Value:" << anim->endValue();
+ qDebug() << " - Current Value:" << this->geometry();*/
+ this->setGeometry( animResetProp.toRect() );
+ }
+ }
+ animResetProp = QVariant(); //clear the variable
+}
+
// === PROTECTED ===
void RootSubWindow::mousePressEvent(QMouseEvent *ev){
+ activate();
+ this->raise();
//qDebug() << "Frame Mouse Press Event";
offset.setX(0); offset.setY(0);
if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse
@@ -274,11 +420,11 @@ void RootSubWindow::mousePressEvent(QMouseEvent *ev){
activeState = getStateAtPoint(ev->pos(), true); //also have it set the offset variable
}
setMouseCursor(activeState, true); //this one is an override cursor
-
+ QFrame::mousePressEvent(ev);
}
void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
- ev->accept();
+ activate(); //make sure this window is "Active"
if(activeState == Normal){
setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
}else{
@@ -352,15 +498,15 @@ void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
default:
break;
}
-
this->setGeometry(geom);
}
+ QFrame::mouseMoveEvent(ev);
}
void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
//Check for a right-click event
//qDebug() << "Frame Mouse Release Event";
- ev->accept();
+ QFrame::mouseReleaseEvent(ev);
if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){
otherM->popup(ev->globalPos());
return;
@@ -368,7 +514,7 @@ void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
activeState = Normal;
QApplication::restoreOverrideCursor();
setMouseCursor( getStateAtPoint(ev->pos()) );
- if(QWidget::mouseGrabber() == this){ this->releaseMouse(); }
+ if(QFrame::mouseGrabber() == this){ this->releaseMouse(); }
}
void RootSubWindow::leaveEvent(QEvent *ev){
@@ -377,3 +523,14 @@ void RootSubWindow::leaveEvent(QEvent *ev){
setMouseCursor(Normal);
}
}
+
+void RootSubWindow::moveEvent(QMoveEvent *ev){
+ //qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry();
+ QFrame::moveEvent(ev);
+ if(!closing && anim->state()!=QAbstractAnimation::Running){
+ moveTimer->start();
+ //WinWidget->resyncWindow();
+ //WIN->requestProperty(NativeWindow::GlobalPos, ev->pos() );
+ }
+
+}
bgstack15