From 2261b6f7bad6efaca196b430857e199441fdf14e Mon Sep 17 00:00:00 2001 From: Alexander Tuxen <tuxen@silpion.de> Date: Thu, 22 Sep 2022 22:19:16 +0200 Subject: [PATCH] first working PoC of PID based window switching approach. getScreen function is implemented, window management functions need to be adjusted. --- .../compositor-messages.cpp | 22 +++- multiscreen-compositor/compositor-messages.h | 6 +- multiscreen-compositor/main.cpp | 15 +++ multiscreen-compositor/message-server.cpp | 11 +- multiscreen-compositor/message-server.h | 2 + .../message-serverconnection.cpp | 4 +- .../message-serverconnection.h | 2 +- multiscreen-compositor/qml/main.qml | 100 ++++++++++++++---- 8 files changed, 138 insertions(+), 24 deletions(-) diff --git a/multiscreen-compositor/compositor-messages.cpp b/multiscreen-compositor/compositor-messages.cpp index e3bf734..07a9adc 100644 --- a/multiscreen-compositor/compositor-messages.cpp +++ b/multiscreen-compositor/compositor-messages.cpp @@ -1,4 +1,5 @@ #include "compositor-messages.h" +#include <message-serverconnection.h> #include <QDebug> CompositorMessages::CompositorMessages(QObject *parent) @@ -7,17 +8,36 @@ CompositorMessages::CompositorMessages(QObject *parent) } void CompositorMessages::messageReceived(QString message, quint32 windowId, quint32 screenId){ - qDebug() << "New message" << message; + qDebug() << "CompositorMessage::messageReceived New message" << message; if(message == "moveWindowToScreen"){ emit moveWindowToScreen(windowId, screenId); }else if(message == "hideWindow"){ emit hideWindow(windowId); + emit sendStatus(0); }else if(message == "showWindow"){ emit showWindow(windowId); + emit sendStatus(0); + }else + if(message == "logWindows"){ + emit logWindows(); + emit sendStatus(0); + }else + if(message == "getScreen"){ + emit getScreen(windowId); + }else + if(message == "setActiveScreen"){ + emit setActiveScreen(screenId); + emit sendStatus(screenId); }else{ qWarning() << "Unknown message received: " << message; } } + +void CompositorMessages::screenInfoReceived(int screenId){ + qDebug() << "CompositorMessage::screenInfoReceived " << screenId; + + emit sendStatus(screenId); +} diff --git a/multiscreen-compositor/compositor-messages.h b/multiscreen-compositor/compositor-messages.h index f09a39a..288eb78 100644 --- a/multiscreen-compositor/compositor-messages.h +++ b/multiscreen-compositor/compositor-messages.h @@ -11,11 +11,15 @@ public: public slots: void messageReceived(QString, quint32 value0, quint32 value2); + void screenInfoReceived(int screenId); signals: void moveWindowToScreen(qint32 windowid, qint32 screenid); void hideWindow(qint32); void showWindow(qint32); - + void logWindows(void); + void getScreen(qint32); + void sendStatus(int); + void setActiveScreen(quint32); }; #endif // COMPOSITORCOMMANDS_H diff --git a/multiscreen-compositor/main.cpp b/multiscreen-compositor/main.cpp index 17738a2..26fd0cb 100644 --- a/multiscreen-compositor/main.cpp +++ b/multiscreen-compositor/main.cpp @@ -64,6 +64,7 @@ int main(int argc, char *argv[]) { + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QGuiApplication app(argc, argv); QCommandLineParser parser; @@ -90,10 +91,24 @@ int main(int argc, char *argv[]) QObject::connect(&server, SIGNAL(newMessage(QString,quint32,quint32)), &commands, SLOT(messageReceived(QString,quint32,quint32))); + QObject::connect(&commands, SIGNAL(sendStatus(int)), + &server, SLOT(returnStatus(int))); + + QQmlApplicationEngine appEngine; appEngine.rootContext()->setContextProperty("config", config); appEngine.rootContext()->setContextProperty("commands", &commands); appEngine.load(QUrl("qrc:///qml/main.qml")); + /* + QQmlEngine engine; + QQmlComponent component(&engine, QUrl("qrc:///qml/main.qml"), nullptr); + QObject *object = component.create(); + + QObject *object = appEngine.rootObjects().constFirst()->findChild<QObject *>("screenSignal"); + QObject::connect(object, SIGNAL(sendStatus(int)), + &commands, SLOT(screenInfoReceived(int))); + */ + return app.exec(); } diff --git a/multiscreen-compositor/message-server.cpp b/multiscreen-compositor/message-server.cpp index 9b4a85a..532be30 100644 --- a/multiscreen-compositor/message-server.cpp +++ b/multiscreen-compositor/message-server.cpp @@ -18,6 +18,7 @@ bool MessageServer::listen() { server = new QLocalServer(this); while(true) { + // FIXME: This isn't working correctly. When the compositor is stopped, the socket isn't deleted and this logic can't handle that. if (server->listen(socketName)) { break; } @@ -51,6 +52,8 @@ void MessageServer::handleConnection() MessageServerConnection *c = new MessageServerConnection(server->nextPendingConnection(), this); connect(c, &MessageServerConnection::disconnected, this, &MessageServer::connectionGone); connect(c, &MessageServerConnection::newMessage, this, &MessageServer::messageReceived); + //connect(c, &MessageServerConnection::newMessage, this, &MessageServer::messageReceived); + connect(this, &MessageServer::sendStatus, c, &MessageServerConnection::sendStatus); connections.append(c); } @@ -62,6 +65,12 @@ void MessageServer::connectionGone(MessageServerConnection* c){ void MessageServer::messageReceived(QString m, quint32 value0, quint32 value1) { - qDebug() << "Got message" << m << value0 << value1; + qDebug() << "MessageServer::messageReceived Got message" << m << value0 << value1; emit newMessage(m , value0, value1); } + +void MessageServer::returnStatus(int status) +{ + qDebug() <<"returning Status " << status; + emit sendStatus(status); +} diff --git a/multiscreen-compositor/message-server.h b/multiscreen-compositor/message-server.h index f85d0db..46e97e0 100644 --- a/multiscreen-compositor/message-server.h +++ b/multiscreen-compositor/message-server.h @@ -17,11 +17,13 @@ public slots: signals: void newMessage(QString, quint32 value0, quint32 value2); + void sendStatus(int); private slots: void handleConnection(void); void connectionGone(MessageServerConnection *c); void messageReceived(QString, quint32, quint32); + void returnStatus(int); private: static const QString socketName; diff --git a/multiscreen-compositor/message-serverconnection.cpp b/multiscreen-compositor/message-serverconnection.cpp index 7b10b29..d853fad 100644 --- a/multiscreen-compositor/message-serverconnection.cpp +++ b/multiscreen-compositor/message-serverconnection.cpp @@ -20,7 +20,7 @@ void MessageServerConnection::readData(void){ QString message; quint32 value0; quint32 value1; - qDebug() << "Client send data: " << socket->bytesAvailable(); + qDebug() << "Client sent data: " << socket->bytesAvailable(); while(socket->bytesAvailable() > 0){ // Use transaction to make sure to receive a complete message @@ -39,7 +39,7 @@ void MessageServerConnection::readData(void){ emit newMessage(message , value0, value1); // Reply status to client - sendStatus(0); + //sendStatus(0); if(socket->bytesAvailable() > 0){ qDebug() << "Still bytes available: " << socket->bytesAvailable(); diff --git a/multiscreen-compositor/message-serverconnection.h b/multiscreen-compositor/message-serverconnection.h index 15981ab..909303c 100644 --- a/multiscreen-compositor/message-serverconnection.h +++ b/multiscreen-compositor/message-serverconnection.h @@ -10,6 +10,7 @@ class MessageServerConnection : public QObject Q_OBJECT public: explicit MessageServerConnection( QLocalSocket *socket, QObject *parent = nullptr); + void sendStatus(int status); signals: void disconnected(MessageServerConnection*); @@ -23,7 +24,6 @@ private: QLocalSocket *socket; QDataStream socketReadData; - void sendStatus(int status); }; #endif // SERVERCONNECTION_H diff --git a/multiscreen-compositor/qml/main.qml b/multiscreen-compositor/qml/main.qml index b3cd503..822ad06 100644 --- a/multiscreen-compositor/qml/main.qml +++ b/multiscreen-compositor/qml/main.qml @@ -55,10 +55,12 @@ import QtQuick.Window 2.3 as Window import QtWayland.Compositor 1.3 import QtQml.Models 2.1 +//import WindowAssignment 1.0 + WaylandCompositor { id: comp - property int current_screen: 0 + property int active_screen: 0 property var activeSurfaces: [] Instantiator { @@ -121,24 +123,26 @@ WaylandCompositor { } onSurfaceRequested: { - console.log("Surface requested", client, id, version); + console.log("Surface requested: client", client, "id", id, "version", version, "pid", client.processId); } function createShellSurfaceItem(shellSurface, output) { + console.log("createShellSurfaceItem: Creating surface", shellSurface, "on output", output); var item = chromeComponent.createObject(output.surfaceArea, { "shellSurface": shellSurface, }); } function handleShellSurfaceCreated(shellSurface) { - if (current_screen+1 > screens.count-1) - current_screen = 0; - else - current_screen++; - createShellSurfaceItem(shellSurface, screens.objectAt(current_screen)); + console.log("handleShellSurfaceCreated: Adding surface to applist", shellSurface, "on screen", active_screen, + "pid", shellSurface.surface.client.processId); + createShellSurfaceItem(shellSurface, screens.objectAt(active_screen)); + var surfaceOnScreen = ({ 'surface': shellSurface, 'screen': active_screen }); + activeSurfaces.push(surfaceOnScreen); } function createIviSurfaceItem(iviSurface, output) { + console.log("createIviSurfaceItem: surface", iviSurface, "output", output); var item = iviChromeComponent.createObject(output.surfaceArea, { "shellSurface": iviSurface, }); @@ -153,6 +157,7 @@ WaylandCompositor { // We select the screen by evaluating the iviId of the app, // if more than one screen is present. // If the unique ivi id is greater or equal 2000 we select screen 2 + console.log("handleIviSurfaceCreated: surface", iviSurface, "id", iviSurface.iviId); var item; if (screens.count > 1) { if (iviSurface.iviId > 1999) @@ -164,8 +169,8 @@ WaylandCompositor { } console.log("Add to applist: ", item, "id", iviSurface.iviId); - activeSurfaces.push(item); - //console.log("AppId here: ", shellSurface.toplevel.appId) + var surfaceOnScreen = ({ 'surface': item, 'screen': active_screen }); + activeSurfaces.push(surfaceOnScreen); } // ============================================= @@ -176,13 +181,37 @@ WaylandCompositor { console.log("appList length: ", activeSurfaces.length); for (var i=0; i < activeSurfaces.length; i++) { var item = activeSurfaces[i]; - var id = item.shellSurface.iviId; - console.log("Surface", i, id, item.shellSurface, item.shellSurface.surface) - if( item.shellSurface.surface === surface){ - console.log("Remove surface from list") - activeSurfaces = Array.from(activeSurfaces).filter(e => e !== item) - } + if (item.surface){ + var id; + + if (item.surface.shellSurface){ + id = item.surface.shellSurface.iviId; + console.log("Testing IVI surface", i, id, item.surface) + if( item.surface.shellSurface.surface === surface){ + console.log("Removing IVI surface from list", surface) + activeSurfaces = Array.from(activeSurfaces).filter(e => e !== item) + console.log("Removed surface from Applist:", surface); + } + } + else if ((item.surface.surface) && (item.surface.surface.client.processId)){ + id = item.surface.surface.client.processId; + console.log("Testing XDG surface", i, item.surface) + if( item.surface.surface === surface){ + console.log("Removing XDG surface from list", surface) + activeSurfaces = Array.from(activeSurfaces).filter(e => e !== item) + } + } + else + { + console.log("ERROR! applist index", i, "object has vanished!"); + console.log("Removing lost surface from applist!") + activeSurfaces = Array.from(activeSurfaces).filter((e, idx) => idx !== i) + } + + }else{ + console.log("surface not defined!", item.surface); + } } } @@ -193,9 +222,13 @@ WaylandCompositor { console.log("Lookung for surface with id", id); for (var i=0; i < activeSurfaces.length; i++) { var item = activeSurfaces[i]; - if( id === item.shellSurface.iviId){ - console.log("Surface", i, id, item.shellSurface, item.shellSurface.surface) - return item; + if( id === item.surface.shellSurface.iviId){ + console.log("found IVI Shell Surface", i, id, item.surface.shellSurface, item.surface.shellSurface.surface) + return item.surface; + } + else if( id === item.surface.surface.client.processId){ + console.log("found XDG Shell Surface", i, id, item.surface.shellSurface, item.surface.shellSurface.surface) + return item.surface; } } console.log("Failed to find surface by id", id) @@ -240,5 +273,36 @@ WaylandCompositor { console.log("Received a showWindow Signal", windowid) windowVisibility(windowid, true) } + function onLogWindows(){ + console.log("Active surfaces:") + for (var i=0; i < activeSurfaces.length; i++) { + var item = activeSurfaces[i]; + console.log("- Surface", i, ": ", item.surface, "on", item.screen) + } + } + function onGetScreen(windowid){ + console.log("Received a getScreen Signal for window ID: ", windowid) + var screenId = -1; + for (var i=0; i < activeSurfaces.length; i++) { + var item = activeSurfaces[i]; + if (item.surface) { + if( windowid === item.surface.surface.client.processId){ + console.log("Surface", i, item.surface, "pid", item.surface.surface.client.processId, "on screen", item.screen) + screenId = item.screen; + } + } + + } + commands.screenInfoReceived(screenId) + } + + function onSetActiveScreen(screenId) + { + if (screenId <= screens.count) + { + console.log("setting active screen", screenId); + active_screen = screenId; + } + } } } -- GitLab