diff options
author | Ken Moore <ken@ixsystems.com> | 2018-01-11 09:22:40 -0500 |
---|---|---|
committer | Ken Moore <ken@ixsystems.com> | 2018-01-11 09:22:40 -0500 |
commit | bbabaada12e6d7e355c396961fe180e8e5b2b911 (patch) | |
tree | a7b2fb758ed94ba8e8f31666685bcb2c03477599 /src-qt5 | |
parent | Get the window compositing/painting routine finished up with a seamless image... (diff) | |
download | lumina-bbabaada12e6d7e355c396961fe180e8e5b2b911.tar.gz lumina-bbabaada12e6d7e355c396961fe180e8e5b2b911.tar.bz2 lumina-bbabaada12e6d7e355c396961fe180e8e5b2b911.zip |
Get a lot more of the Native Window embed routine up and running. Actually usable now.
Diffstat (limited to 'src-qt5')
5 files changed, 88 insertions, 42 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp index 0899337c..3f595245 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp @@ -27,14 +27,25 @@ QImage QMLImageProvider::requestImage(const QString &id, QSize *size, const QSiz QImage img(requestedSize,QImage::Format_RGB32); if(win==0){ img.fill("black"); } //invalid window ID (should never happen) else if(id.startsWith("image:")){ img = Lumina::NWS->GetWindowImage(win); } + else if(id.startsWith("icon:")){ + QIcon ico = win->property(NativeWindowObject::Icon).value<QIcon>(); + QList<QSize> sizes = ico.availableSizes(); + QSize sz(0,0); + //Just grab the largest size currently available + for(int i=0; i<sizes.length(); i++){ + if(sz.width()<sizes[i].width() && sz.height()<sizes[i].height()){ sz = sizes[i]; } + } + qDebug() << "Icon Sizes:" <<sizes; + img = ico.pixmap(sz).toImage(); + } //else if(id.startsWith("icon:")){ img = Lumina::NWS->GetWindowIcon(win); } - qDebug() << "Got Window Image:" << img.size(); + //qDebug() << "Got Window Image:" << img.size(); if(img.size().isNull()){ if(requestedSize.isValid()){ img = QImage(requestedSize,QImage::Format_RGB32); } else{ img = QImage(QSize(64,64), QImage::Format_RGB32); } img.fill("black"); } - qDebug() << "Final Window Image:" << img.size(); + //qDebug() << "Final Window Image:" << img.size(); if(size!=0){ size->setHeight(img.height()); size->setWidth( img.width() ); 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 8ea00cc1..61a82e5c 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 @@ -22,6 +22,10 @@ NativeWindowObject::NativeWindowObject(WId id) : QObject(){ winid = id; frameid = 0; dmgID = dmg = 0; + geomTimer = new QTimer(this); + geomTimer->setSingleShot(true); + geomTimer->setInterval(50); //1/20 second + connect(geomTimer, SIGNAL(timeout()), this, SLOT(sendNewGeom()) ); } NativeWindowObject::~NativeWindowObject(){ @@ -62,17 +66,9 @@ void NativeWindowObject::setProperty(NativeWindowObject::Property prop, QVariant if(prop == NativeWindowObject::RelatedWindows){ relatedTo = val.value< QList<WId> >(); } else if(prop == NativeWindowObject::None || (!force && hash.value(prop)==val)){ return; } else if(prop == NativeWindowObject::WinImage){ - //special case - QImage is passed in, but QString is passed out (needed for QML) - QByteArray ba; - QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - val.value<QImage>().save(&buffer, "PNG"); - QString img("data:image/png;base64,"); - img.append(QString::fromLatin1(ba.toBase64().data())); - qDebug() << "Image Data Header:" << img.section(",",0,0); - hash.insert(prop, img); //save the string instead - } - else{ hash.insert(prop, val); } + //special case - This should never be actually set in the property hash + // it is loaded dynamically by the QMLImageProvider instead (prevent flickering/caching image) + } else{ hash.insert(prop, val); } emitSinglePropChanged(prop); emit PropertiesChanged(QList<NativeWindowObject::Property>() << prop, QList<QVariant>() << val); } @@ -83,15 +79,8 @@ void NativeWindowObject::setProperties(QList<NativeWindowObject::Property> props if(props[i] == NativeWindowObject::None || (!force && (hash.value(props[i]) == vals[i])) ){ props.removeAt(i); vals.removeAt(i); i--; continue; //Invalid property or identical value }else if(props[i] == NativeWindowObject::WinImage){ - //special case - QImage is passed in, but QString is passed out (needed for QML) - QByteArray ba; - QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - vals[i].value<QImage>().save(&buffer, "PNG"); - QString img("data:image/png;base64,"); - img.append(QString::fromLatin1(ba.toBase64().data())); - qDebug() << "Image Data Header:" << img.section(",",0,0); - hash.insert(props[i], img); //save the string instead + //special case - This should never be actually set in the property hash + // it is loaded dynamically by the QMLImageProvider instead (prevent flickering/caching image) }else{ hash.insert(props[i], vals[i]); } @@ -164,8 +153,11 @@ QString NativeWindowObject::shortTitle(){ return tmp; } -QIcon NativeWindowObject::icon(){ - return this->property(NativeWindowObject::Name).value<QIcon>(); +QString NativeWindowObject::icon(){ + if(icodmg==0){ icodmg=1; } + else{ icodmg = 0; } + qDebug() << "Window Icon:" << icodmg << this->property(NativeWindowObject::Icon).value<QIcon>().availableSizes(); + return "image://native_window/icon:"+QString::number(winid)+":"+QString::number(icodmg); } //QML Button states @@ -260,6 +252,18 @@ QRect NativeWindowObject::imageGeometry(){ return geom; } +void NativeWindowObject::updateGeometry(int x, int y, int width, int height){ + // Full frame+window geometry - go ahead and pull it apart and only update the interior window geom + QList<int> fgeom = this->property(NativeWindowObject::FrameExtents).value<QList<int> >(); + if(fgeom.isEmpty()){ fgeom << 0<<0<<0<<0; } //just in case (left/right/top/bottom) + QPoint pos(x+fgeom[0], y+fgeom[2]); + QSize sz(width-fgeom[0]-fgeom[1], height-fgeom[2]-fgeom[3]); + newgeom = QRect(pos, sz); + //qDebug() << "Update Geometry:" << fgeom << QRect(x,y,width,height) << pos << sz; + //requestProperties(QList<NativeWindowObject::Property>() << NativeWindowObject::GlobalPos << NativeWindowObject::Size, QList<QVariant>() << pos << sz); + if(!geomTimer->isActive()){ geomTimer->start(); } +} + // ==== PUBLIC SLOTS === void NativeWindowObject::toggleVisibility(){ setProperty(NativeWindowObject::Visible, !property(NativeWindowObject::Visible).toBool() ); @@ -284,7 +288,9 @@ void NativeWindowObject::emitSinglePropChanged(NativeWindowObject::Property prop case NativeWindowObject::Name: emit nameChanged(); break; case NativeWindowObject::Title: - emit titleChanged(); break; + emit titleChanged(); + if(this->property(NativeWindowObject::ShortTitle).toString().isEmpty()){ emit shortTitleChanged(); } + break; case NativeWindowObject::ShortTitle: emit shortTitleChanged(); break; case NativeWindowObject::Icon: @@ -300,3 +306,7 @@ void NativeWindowObject::emitSinglePropChanged(NativeWindowObject::Property prop break; //do nothing otherwise } } + +void NativeWindowObject::sendNewGeom(){ +requestProperties(QList<NativeWindowObject::Property>() << NativeWindowObject::GlobalPos << NativeWindowObject::Size, QList<QVariant>() << newgeom.topLeft() << newgeom.size()); +} 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 0030d27c..332fe896 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 @@ -21,7 +21,7 @@ class NativeWindowObject : public QObject{ Q_PROPERTY( QString name READ name NOTIFY nameChanged) Q_PROPERTY( QString title READ title NOTIFY titleChanged) Q_PROPERTY( QString shortTitle READ shortTitle NOTIFY shortTitleChanged) - Q_PROPERTY( QIcon icon READ icon NOTIFY iconChanged) + Q_PROPERTY( QString icon READ icon NOTIFY iconChanged) Q_PROPERTY( bool sticky READ isSticky NOTIFY stickyChanged) //Button/Titlebar visibility Q_PROPERTY( bool showCloseButton READ showCloseButton NOTIFY winTypeChanged) @@ -98,7 +98,7 @@ public: Q_INVOKABLE QString name(); Q_INVOKABLE QString title(); Q_INVOKABLE QString shortTitle(); - Q_INVOKABLE QIcon icon(); + Q_INVOKABLE QString icon(); //QML Button states Q_INVOKABLE bool showCloseButton(); Q_INVOKABLE bool showMaxButton(); @@ -113,6 +113,7 @@ public: //QML Geometry reporting Q_INVOKABLE QRect frameGeometry(); Q_INVOKABLE QRect imageGeometry(); + Q_INVOKABLE void updateGeometry(int x, int y, int width, int height); //For QML to change the current window position public slots: Q_INVOKABLE void toggleVisibility(); @@ -125,10 +126,16 @@ private: //QWindow *WIN; WId winid, frameid; QList<WId> relatedTo; - unsigned int dmgID, dmg; + unsigned int dmgID, dmg, icodmg; + //Collation/Delay for window resize events + QTimer *geomTimer; + QRect newgeom; void emitSinglePropChanged(NativeWindowObject::Property); +private slots: + void sendNewGeom(); + signals: //General Notifications void PropertiesChanged(QList<NativeWindowObject::Property>, QList<QVariant>); diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml index 74c3f025..2150e37c 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml @@ -15,13 +15,21 @@ Rectangle { id: windowFrame border.width: 5 - //border.color: palette.window - color: palette.window + border.color: palette.highlight + radius: 5 + color: "transparent" //palette.window x: object.frameGeometry.x y: object.frameGeometry.y width: object.frameGeometry.width height: object.frameGeometry.height + onXChanged: { + windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height) + } + onYChanged: { + windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height) + } + MouseArea { id: resizeArea anchors.fill: parent @@ -31,6 +39,7 @@ Rectangle { property int positionY: -1 onPressed: { + //NOTE: This is only triggered for resize events var globalP = windowFrame.mapToItem(rootCanvas, mouse.x, mouse.y) positionX = globalP.x positionY = globalP.y @@ -60,9 +69,11 @@ Rectangle { onReleased: { positionX = -1 positionY = -1 + //windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height) } - onPositionChanged: { + onPositionChanged: { + //NOTE: This is only triggered for resize events if(positionX != -1 && positionY != -1) { var globalP = windowFrame.mapToItem(rootCanvas, mouse.x, mouse.y) /*console.log("Global P: ", globalP); @@ -109,13 +120,14 @@ Rectangle { positionY = globalP.y positionX = globalP.x } + windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height) } } Rectangle { id: titleBar - border.width: 2 - color: palette.window + border.width: 0 + color: palette.window height: 25 anchors.top: windowFrame.top anchors.right: windowFrame.right @@ -133,9 +145,10 @@ Rectangle { //released: { function(); } } - Button { + ToolButton { id: otherButton anchors.left: parent.left + height: parent.height iconSource: windowFrame.object.icon } @@ -150,20 +163,25 @@ Rectangle { RowLayout { spacing: 0 anchors.right: parent.right - Button { + height: parent.height + + ToolButton { id: minButton + Layout.fillHeight: true iconName: "window-minimize" onClicked: { windowFrame.object.toggleVisibility() } } - Button { + ToolButton { id: maxButton + Layout.fillHeight: true iconName: "window-maximize" //onClicked: { windowFrame.object.toggleMaximize() } } - Button { + ToolButton { id: closeButton + Layout.fillHeight: true iconName: "document-close" onClicked: { windowFrame.object.requestClose() } } 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 15c79099..bd6d0179 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp @@ -523,7 +523,7 @@ void NativeWindowSystem::ChangeWindowProperties(NativeWindowObject* win, QList< } if(props.contains(NativeWindowObject::Size) || props.contains(NativeWindowObject::GlobalPos) ){ - /*xcb_configure_window_value_list_t valList; + xcb_configure_window_value_list_t valList; //valList.x = 0; //Note that this is the relative position - should always be 0,0 relative to the embed widget //valList.y = 0; QSize sz = win->property(NativeWindowObject::Size).toSize(); @@ -543,7 +543,7 @@ void NativeWindowSystem::ChangeWindowProperties(NativeWindowObject* win, QList< uint16_t mask = 0; mask = mask | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; //qDebug() << "Configure window Geometry:" << sz; - xcb_configure_window_aux(QX11Info::connection(), win->id(), mask, &valList);*/ + xcb_configure_window_aux(QX11Info::connection(), win->id(), mask, &valList); } if(props.contains(NativeWindowObject::Name)){ @@ -630,7 +630,7 @@ void NativeWindowSystem::SetupNewWindow(NativeWindowObject *win){ QImage NativeWindowSystem::GetWindowImage(NativeWindowObject* win){ QImage img; - qDebug() << "Update Window Image:" << win->name(); + //qDebug() << "Update Window Image:" << win->name(); QRect geom(QPoint(0,0), win->property(NativeWindowObject::Size).toSize()); if(DISABLE_COMPOSITING){ QList<QScreen*> screens = static_cast<QApplication*>( QApplication::instance() )->screens(); @@ -641,12 +641,12 @@ QImage NativeWindowSystem::GetWindowImage(NativeWindowObject* win){ //Pull the XCB pixmap out of the compositing layer xcb_pixmap_t pix = xcb_generate_id(QX11Info::connection()); xcb_composite_name_window_pixmap(QX11Info::connection(), win->id(), pix); - if(pix==0){ qDebug() << "Got blank pixmap!"; return QImage(); } + if(pix==0){ return QImage(); } //Convert this pixmap into a QImage //xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, 0, 0, this->width(), this->height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP); xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, geom.x(), geom.y(), geom.width(), geom.height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP); - if(ximg == 0){ qDebug() << "Got blank image!"; return QImage(); } + if(ximg == 0){ return QImage(); } QImage tmp(ximg->data, ximg->width, ximg->height, ximg->stride, QImage::Format_ARGB32_Premultiplied); img = tmp.copy(); //detach this image from the XCB data structures before we clean them up, otherwise the QImage will try to clean it up a second time on window close and crash xcb_image_destroy(ximg); |