diff options
7 files changed, 115 insertions, 28 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp index b94a241d..edde5ed7 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp @@ -8,6 +8,10 @@ #include "global-objects.h" +#ifdef USE_WIDGETS +#include "src-widgets/NativeWindow.h" +#endif + // === PUBLIC === DesktopManager::DesktopManager(){ @@ -124,6 +128,7 @@ void DesktopManager::NewWindowAvailable(NativeWindowObject* win){ //connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(syncWindowList()) ); #ifdef USE_WIDGETS qDebug() << "Got New Widget Window:" << win->name(); + NativeWindow *tmp = new NativeWindow(win); #endif syncWindowList(); } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp index e2cac852..c9dd97f8 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp @@ -26,6 +26,7 @@ NativeWindowObject::NativeWindowObject(WId id) : QObject(){ geomTimer->setSingleShot(true); geomTimer->setInterval(50); //1/20 second connect(geomTimer, SIGNAL(timeout()), this, SLOT(sendNewGeom()) ); + qRegisterMetaType<WId>("WId"); } NativeWindowObject::~NativeWindowObject(){ @@ -281,6 +282,33 @@ void NativeWindowObject::toggleVisibility(){ setProperty(NativeWindowObject::Visible, !property(NativeWindowObject::Visible).toBool() ); } +void NativeWindowObject::toggleMaximize(){ + //Find the screen containing this window (center of window) + QRect curgeom = frameGeometry(); + QPoint ctr = curgeom.center(); + QList<QScreen*> scrns = QApplication::screens(); + QRect max; + for(int i=0; i<scrns.length(); i++){ + if(scrns[i]->geometry().contains(ctr)){ + max = scrns[i]->availableGeometry(); + break; + } + } + //Now compare the current geometry to the screen geometry + if(curgeom!=max){ + setGeometryNow(max); //will set newgeom to max + newgeom = curgeom; //now reset newgeom + }else{ + //Already maximized, look at the old geometry and figure out how to restore it + if(newgeom.isNull()){ + //no old info available - center the window at half maximum size + newgeom = QRect(max.x()-max.width()/2, max.y()-max.height()/2, max.width()/2, max.height()/2); + } + setGeometryNow(newgeom); + } + emit geomChanged(); +} + void NativeWindowObject::requestClose(){ emit RequestClose(winid); } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h index 87df1f10..ed52c956 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h @@ -120,6 +120,7 @@ public: public slots: Q_INVOKABLE void toggleVisibility(); + Q_INVOKABLE void toggleMaximize(); Q_INVOKABLE void requestClose(); //ask the app to close the window (may/not depending on activity) Q_INVOKABLE void requestKill(); //ask the WM to kill the app associated with this window (harsh - only use if not responding) Q_INVOKABLE void requestPing(); //ask the app if it is still active (a WindowNotResponding signal will get sent out if there is no reply); diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp index 3bde9ab8..44b2d715 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp @@ -12,14 +12,15 @@ NativeWindow::NativeWindow( NativeWindowObject *obj ) : QFrame(0, Qt::Window | Q createFrame(); WIN->addFrameWinID(this->winId()); //Setup all the property connections - connect(WIN, SIGNAL(winImageChanged()), this, SLOT(syncWinImage()): - connect(WIN, SIGNAL(nameChanged()), this, SLOT(syncName()): - connect(WIN, SIGNAL(titleChanged()), this, SLOT(syncTitle()): - connect(WIN, SIGNAL(iconChanged()), this, SLOT(syncIcon()): - connect(WIN, SIGNAL(stickyChanged()), this, SLOT(syncSticky()): - connect(WIN, SIGNAL(visibilityChanged()), this, SLOT(syncVisibility()): - connect(WIN, SIGNAL(winTypeChanged()), this, SLOT(syncWinType()): - connect(WIN, SIGNAL(geomChanged()), this, SLOT(syncGeom()): + connect(WIN, SIGNAL(winImageChanged()), this, SLOT(syncWinImage()) ); + connect(WIN, SIGNAL(nameChanged()), this, SLOT(syncName()) ); + connect(WIN, SIGNAL(titleChanged()), this, SLOT(syncTitle()) ); + connect(WIN, SIGNAL(iconChanged()), this, SLOT(syncIcon()) ); + connect(WIN, SIGNAL(stickyChanged()), this, SLOT(syncSticky()) ); + connect(WIN, SIGNAL(visibilityChanged()), this, SLOT(syncVisibility()) ); + connect(WIN, SIGNAL(winTypeChanged()), this, SLOT(syncWinType()) ); + connect(WIN, SIGNAL(geomChanged()), this, SLOT(syncGeom()) ); + connect(WIN, SIGNAL(WindowClosed(WId)), this, SLOT(deleteLater()) ); //Now Perform the initial property loads syncWinImage(); syncName(); @@ -29,10 +30,17 @@ NativeWindow::NativeWindow( NativeWindowObject *obj ) : QFrame(0, Qt::Window | Q syncVisibility(); syncWinType(); syncGeom(); + //Setup all the button connections + connect(minB, SIGNAL(clicked()), WIN, SLOT(toggleVisibility()) ); + connect(maxB, SIGNAL(clicked()), WIN, SLOT(toggleMaximize()) ); + connect(closeB, SIGNAL(clicked()), WIN, SLOT(requestClose()) ); + + } NativeWindow::~NativeWindow(){ - + vlayout->deleteLater(); + toolbarL->deleteLater(); } // === PRIVATE === @@ -40,17 +48,26 @@ void NativeWindow::createFrame(){ //Initialize the widgets closeB = new QToolButton(this); closeB->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + closeB->setAutoRaise(true); minB = new QToolButton(this); minB->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + minB->setAutoRaise(true); maxB = new QToolButton(this); maxB->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + maxB->setAutoRaise(true); otherB = new QToolButton(this); otherB->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - toolbarL = new QHBoxLayout(this); - vlayout = new QVBoxLayout(this); - vlayout.align + otherB->setAutoRaise(true); + vlayout = new QVBoxLayout(); + vlayout->setSpacing(0); + toolbarL = new QHBoxLayout(); + toolbarL->setSpacing(0); + + //vlayout.align titleLabel = new QLabel(this); titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + //contentW = new QWidget(this); + //contentW->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); //Now put the widgets in the right places toolbarL->addWidget(otherB); toolbarL->addWidget(titleLabel); @@ -60,8 +77,14 @@ void NativeWindow::createFrame(){ vlayout->addLayout(toolbarL); vlayout->addStretch(); this->setLayout(vlayout); + // Load the icons for the buttons + loadIcons(); +} - // +void NativeWindow::loadIcons(){ + closeB->setIcon( QIcon::fromTheme("window-close") ); + minB->setIcon( QIcon::fromTheme("window-minimize") ); + maxB->setIcon( QIcon::fromTheme("window-maximize") ); } // === PRIVATE SLOTS === @@ -77,6 +100,7 @@ void NativeWindow::syncName(){ void NativeWindow::syncTitle(){ titleLabel->setText(WIN->title()); + titleLabel->setToolTip(WIN->title()); } void NativeWindow::syncIcon(){ @@ -89,18 +113,33 @@ void NativeWindow::syncSticky(){ } void NativeWindow::syncVisibility(){ + qDebug() << "Sync Visibility:" << WIN->isVisible(); this->setVisible(WIN->isVisible()); } void NativeWindow::syncWinType(){ + qDebug() << "Sync Win Type"; closeB->setVisible(WIN->showCloseButton()); maxB->setVisible(WIN->showMaxButton()); minB->setVisible(WIN->showMinButton()); titleLabel->setVisible(WIN->showTitlebar()); otherB->setVisible(WIN->showGenericButton()); - + //toolbarL->setVisible(WIN->showTitlebar()); + + //Update all the margins for the frame + QList<int> frame = WIN->property(NativeWindowObject::FrameExtents).value<QList<int> >(); + /*QList<int> : [Left, Right, Top, Bottom] in pixels */ + vlayout->setContentsMargins( frame[0], frame[1], 0, frame[3]); + int topM = frame[2] - titleLabel->fontMetrics().height(); //figure out how much extra we have to work with + if(topM<0){ topM = 0; } + int botM = topM/2.0; + toolbarL->setContentsMargins( 0, 0, topM-botM, botM); + //QPoint containerCorner(frame[0], topM-botM); + //WIN->emit RequestReparent(WIN->id(), this->winId(), containerCorner); } void NativeWindow::syncGeom(){ - + qDebug() << "Sync Geometry:" << WIN->name(); + qDebug() << " Frame:" << WIN->frameGeometry() << "Win:" << WIN->imageGeometry(); + this->setGeometry( WIN->frameGeometry() ); } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h index 794cfad2..1d87ed71 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h @@ -8,6 +8,7 @@ #define _LUMINA_DESKTOP_NATIVE_WINDOW_WIDGET_H #include <global-includes.h> +#include <NativeWindowObject.h> class NativeWindow : public QFrame{ Q_OBJECT @@ -20,6 +21,8 @@ private: NativeWindowObject *WIN; // Interface items void createFrame(); + void loadIcons(); + QToolButton *closeB, *minB, *maxB, *otherB; QHBoxLayout *toolbarL; QVBoxLayout *vlayout; diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri index 7994bb93..f1e200fd 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri @@ -2,7 +2,9 @@ INCLUDEPATH *= $${PWD} SOURCES *= $${PWD}/RootDesktop.cpp \ - $${PWD}/ContextMenu.cpp + $${PWD}/ContextMenu.cpp \ + $${PWD}/NativeWindow.cpp HEADERS *= $${PWD}/RootDesktop.h \ - $${PWD}/ContextMenu.h + $${PWD}/ContextMenu.h \ + $${PWD}/NativeWindow.h diff --git a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp index da004061..65fa98a7 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp @@ -581,13 +581,17 @@ void NativeWindowSystem::ChangeWindowProperties(NativeWindowObject* win, QList< //Only one window can be "Active" at a time - so only do anything if this window wants to be active if(vals[props.indexOf(NativeWindowObject::Active)].toBool() ){ //Lower the currently active window (invisible window) to the bottom of the stack - xcb_window_t cactive; + /*xcb_window_t cactive; if( 1 == xcb_ewmh_get_active_window_reply( &obj->EWMH, xcb_ewmh_get_active_window_unchecked(&obj->EWMH, QX11Info::appScreen()), &cactive, NULL) ){ uint32_t val = XCB_STACK_MODE_BELOW; xcb_configure_window(QX11Info::connection(), cactive, XCB_CONFIG_WINDOW_STACK_MODE, &val); - } + }*/ + + /*uint32_t val = XCB_STACK_MODE_ABOVE; + if(win->frameId()!=0){ xcb_configure_window(QX11Info::connection(), win->frameId(), XCB_CONFIG_WINDOW_STACK_MODE, &val); } + xcb_configure_window(QX11Info::connection(), win->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val);*/ xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win->id() ); //Also send the active window a message to take input focus @@ -982,7 +986,8 @@ void NativeWindowSystem::CheckDamageID(WId win){ void NativeWindowSystem::raiseWindow(NativeWindowObject *win){ qDebug() << "Raise Window:" << win->name() << win->id(); //Note: Always ensure the desktop canvas is right under the main window that is raised - xcb_circulate_window(QX11Info::connection(), XCB_CIRCULATE_RAISE_LOWEST, Lumina::ROOTWIN->viewID()); + //xcb_circulate_window(QX11Info::connection(), XCB_CIRCULATE_RAISE_LOWEST, Lumina::ROOTWIN->viewID()); + if(win->frameId()!=0){ xcb_circulate_window(QX11Info::connection(), XCB_CIRCULATE_RAISE_LOWEST ,win->frameId()); } xcb_circulate_window(QX11Info::connection(), XCB_CIRCULATE_RAISE_LOWEST ,win->id()); } @@ -990,6 +995,7 @@ void NativeWindowSystem::raiseWindow(NativeWindowObject *win){ void NativeWindowSystem::lowerWindow(NativeWindowObject *win){ qDebug() << "Lower Window:" << win->name() << win->id(); xcb_circulate_window(QX11Info::connection(), XCB_CIRCULATE_LOWER_HIGHEST ,win->id()); + if(win->frameId()!=0){ xcb_circulate_window(QX11Info::connection(), XCB_CIRCULATE_LOWER_HIGHEST ,win->frameId()); } } // === PRIVATE SLOTS === @@ -1029,11 +1035,14 @@ void NativeWindowSystem::RequestPing(WId win){ void NativeWindowSystem::RequestReparent(WId win, WId container, QPoint relorigin){ NativeWindowObject *WIN = findWindow(win); + qDebug() << "Got reparent request:" << win; if(WIN==0){ return; } //could not find corresponding window structure -//Reparent the window into the container - xcb_reparent_window(QX11Info::connection(), win, container, relorigin.x(), relorigin.y()); - //xcb_map_window(QX11Info::connection(), win); + qDebug() << "Reparent Window into container:" << WIN->name(); + //Reparent the window into the container + xcb_reparent_window(QX11Info::connection(), win, container, relorigin.x(), relorigin.y()); + xcb_map_window(QX11Info::connection(), win); + return; //Now send the embed event to the app //qDebug() << " - send _XEMBED event"; xcb_client_message_event_t event; @@ -1051,20 +1060,20 @@ void NativeWindowSystem::RequestReparent(WId win, WId container, QPoint relorigi //Now setup any redirects and return //this->SelectInput(win, true); //Notify of structure changes - registerClientEvents(win); + //registerClientEvents(win); //xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); //Now map the window (will be a transparent child of the container) - xcb_map_window(QX11Info::connection(), win); - xcb_map_window(QX11Info::connection(), container); + //xcb_map_window(QX11Info::connection(), win); + //xcb_map_window(QX11Info::connection(), container); //Now create/register the damage handler // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore) // -- Retested 6/29/17 (no change) Ken Moore //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer //xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself). - Damage dmgID = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles); - WIN->addDamageID( (uint) dmgID); //save this for later + //Damage dmgID = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles); + //WIN->addDamageID( (uint) dmgID); //save this for later //qDebug() << " - Done"; //return ( (uint) dmgID ); } |