QWaylandCompositor question
-
Hi,
I'm trying to convert the Pure QML Wayland compositor example into C++.
main.cpp
#include "compositor.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts,true); QGuiApplication app(argc,argv); Compositor *compositor=new Compositor; return app.exec(); }
compositor.h
#ifndef COMPOSITOR_H #define COMPOSITOR_H #include <QWaylandCompositor> #include <QWaylandOutput> #include <QWaylandXdgShell> #include <QQuickView> #include "chrome.h" class Compositor:public QWaylandCompositor { Q_OBJECT public: Compositor(); private: QWaylandOutput *m_output=nullptr; QWaylandXdgShell *m_xdgShell=nullptr; private slots: void createdChangedSlot(); void toplevelCreatedSlot(QWaylandXdgToplevel *toplevel,QWaylandXdgSurface *xdgSurface); }; #endif
compositor.cpp
#include "compositor.h" Compositor::Compositor() { setSocketName("testcomp"); setUseHardwareIntegrationExtension(true); connect(this,SIGNAL(createdChanged()),this,SLOT(createdChangedSlot())); m_xdgShell=new QWaylandXdgShell(this); connect(m_xdgShell,SIGNAL(toplevelCreated(QWaylandXdgToplevel*,QWaylandXdgSurface*)),SLOT(toplevelCreatedSlot(QWaylandXdgToplevel*,QWaylandXdgSurface*))); Chrome::rootWindow=new QQuickView(QUrl("qrc:/testcomp/Root.qml")); create(); } void Compositor::createdChangedSlot() { if(isCreated()){ m_output=new QWaylandOutput(this,Chrome::rootWindow); m_output->setSizeFollowsWindow(true); } } void Compositor::toplevelCreatedSlot(QWaylandXdgToplevel *toplevel,QWaylandXdgSurface *surface) { Chrome::list.append(new Chrome(toplevel,surface)); }
chrome.h
#ifndef CHROME_H #define CHROME_H #include <QWaylandQuickShellSurfaceItem> #include <QWaylandXdgToplevel> class Chrome:public QWaylandQuickShellSurfaceItem { Q_OBJECT public: explicit Chrome(QWaylandXdgToplevel *toplevel,QWaylandShellSurface *surface); ~Chrome(); static QList<Chrome*> list; static QQuickView *rootWindow; private: QWaylandXdgToplevel *m_toplevel; }; #endif
chrome.cpp
#include "chrome.h" Chrome::Chrome(QWaylandXdgToplevel *toplevel,QWaylandShellSurface *surface) { m_toplevel=toplevel; setParentItem(rootWindow->contentItem()); setShellSurface(surface); } QList<Chrome*> Chrome::list; QQuickView *Chrome::rootWindow;
Root.qml
import QtQuick Rectangle{ anchors.fill:parent color:'black' }
Running this code gets me a semi-working compositor, which allows me to open other Qt-based apps in it (by setting WAYLAND_DISPLAY=testcomp). I can maximize/unmaximize them and close them using the titlebar buttons, but the apps themselves do not respond to any mouse clicks. (Interestingly, right-button clicks appear to work, and popup menus appear). Apps with animated content (like projectM-pulseaudio) show up but do not 'animate', while they work fine in the QML example.
I run the compositor nested in another (for now).
I am guessing I need to do something with the QWaylandXdgTopLevel object, but I don't know what, and I can't figure it out from the QML example either.
I would really appreciate it if somebody could help me out.
-
Hi,
I'm trying to convert the Pure QML Wayland compositor example into C++.
main.cpp
#include "compositor.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts,true); QGuiApplication app(argc,argv); Compositor *compositor=new Compositor; return app.exec(); }
compositor.h
#ifndef COMPOSITOR_H #define COMPOSITOR_H #include <QWaylandCompositor> #include <QWaylandOutput> #include <QWaylandXdgShell> #include <QQuickView> #include "chrome.h" class Compositor:public QWaylandCompositor { Q_OBJECT public: Compositor(); private: QWaylandOutput *m_output=nullptr; QWaylandXdgShell *m_xdgShell=nullptr; private slots: void createdChangedSlot(); void toplevelCreatedSlot(QWaylandXdgToplevel *toplevel,QWaylandXdgSurface *xdgSurface); }; #endif
compositor.cpp
#include "compositor.h" Compositor::Compositor() { setSocketName("testcomp"); setUseHardwareIntegrationExtension(true); connect(this,SIGNAL(createdChanged()),this,SLOT(createdChangedSlot())); m_xdgShell=new QWaylandXdgShell(this); connect(m_xdgShell,SIGNAL(toplevelCreated(QWaylandXdgToplevel*,QWaylandXdgSurface*)),SLOT(toplevelCreatedSlot(QWaylandXdgToplevel*,QWaylandXdgSurface*))); Chrome::rootWindow=new QQuickView(QUrl("qrc:/testcomp/Root.qml")); create(); } void Compositor::createdChangedSlot() { if(isCreated()){ m_output=new QWaylandOutput(this,Chrome::rootWindow); m_output->setSizeFollowsWindow(true); } } void Compositor::toplevelCreatedSlot(QWaylandXdgToplevel *toplevel,QWaylandXdgSurface *surface) { Chrome::list.append(new Chrome(toplevel,surface)); }
chrome.h
#ifndef CHROME_H #define CHROME_H #include <QWaylandQuickShellSurfaceItem> #include <QWaylandXdgToplevel> class Chrome:public QWaylandQuickShellSurfaceItem { Q_OBJECT public: explicit Chrome(QWaylandXdgToplevel *toplevel,QWaylandShellSurface *surface); ~Chrome(); static QList<Chrome*> list; static QQuickView *rootWindow; private: QWaylandXdgToplevel *m_toplevel; }; #endif
chrome.cpp
#include "chrome.h" Chrome::Chrome(QWaylandXdgToplevel *toplevel,QWaylandShellSurface *surface) { m_toplevel=toplevel; setParentItem(rootWindow->contentItem()); setShellSurface(surface); } QList<Chrome*> Chrome::list; QQuickView *Chrome::rootWindow;
Root.qml
import QtQuick Rectangle{ anchors.fill:parent color:'black' }
Running this code gets me a semi-working compositor, which allows me to open other Qt-based apps in it (by setting WAYLAND_DISPLAY=testcomp). I can maximize/unmaximize them and close them using the titlebar buttons, but the apps themselves do not respond to any mouse clicks. (Interestingly, right-button clicks appear to work, and popup menus appear). Apps with animated content (like projectM-pulseaudio) show up but do not 'animate', while they work fine in the QML example.
I run the compositor nested in another (for now).
I am guessing I need to do something with the QWaylandXdgTopLevel object, but I don't know what, and I can't figure it out from the QML example either.
I would really appreciate it if somebody could help me out.
I condensed the QML example down to the following:
import QtQuick import QtWayland.Compositor import QtWayland.Compositor.XdgShell Item{ WaylandCompositor{ id:waylandCompositor WaylandOutput{ id:output compositor:waylandCompositor property ListModel shellSurfaces:ListModel{} function handleShellSurface(shellSurface){shellSurfaces.append({shellSurface:shellSurface});} sizeFollowsWindow:true window:Window{ width:1024 height:760 visible:true Repeater{ model:output.shellSurfaces ShellSurfaceItem{ shellSurface:modelData onSurfaceDestroyed:output.shellSurfaces.remove(index) } } } } XdgShell{ onToplevelCreated:{ console.log(xdgSurface) output.handleShellSurface(xdgSurface) } } } }
I really wish the Qt devs didn't obscure the inner working of the compositor behind their QML like this. It looks very simple on the surface but the use of the Repeater here does things that I am unable to replicate in C++.
So what is the proper way to display a QWaylandXdgSurface on a QWaylandOutput?
Could somebody please help? I've been stuck on this for days and I am unable to make any meaningful progress. The documentation is hugely confusing as well.
-
Hi,
This module is likely part of the set that are less used by people on this forum. You might want to check on the interest mailing list. You'll find there Qt's developers/maintainers.
-
Hi,
This module is likely part of the set that are less used by people on this forum. You might want to check on the interest mailing list. You'll find there Qt's developers/maintainers.