aboutsummaryrefslogtreecommitdiff
path: root/src-qt5
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2018-01-11 09:22:40 -0500
committerKen Moore <ken@ixsystems.com>2018-01-11 09:22:40 -0500
commitbbabaada12e6d7e355c396961fe180e8e5b2b911 (patch)
treea7b2fb758ed94ba8e8f31666685bcb2c03477599 /src-qt5
parentGet the window compositing/painting routine finished up with a seamless image... (diff)
downloadlumina-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')
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp15
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp56
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h13
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml36
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp10
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);
bgstack15