get pointer to QMainWindow from child QProcess

Viewed 99

I have an parent "Application A" which starts a QProcess "Application B".

From "Application B" I would like to have a local representation of "Application A"'s MainWindow. From a comment in another post I learned that I could achieve this by: exchanging the window id by some means and then use QWidget::createWindowContainer(id) to create a wrapper widget

QWindow *QWindow::fromWinId(WId id)

So I'm sharing "Application A"'s MainWindow id via shared memory:

void MainWindow::manageSharedMemory()
{
    ...
    WId thisAppWinId = this->winId();
    ...
    // load thisAppWinId into the shared memory
}

In "Application B" I then access thisAppWinId as follow:

void MainWindow::get_parent_window()
{
    QBuffer buffer;
    QDataStream in(&buffer);
    WId parentAppWinId;
    sharedMemory.lock();
    buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
    buffer.open(QBuffer::ReadOnly);
    in >> parentAppWinId;
    qDebug() <<"Parent WId " << parentAppWinId; // here I can read the same WId as defined in Application A
    sharedMemory.unlock();
    sharedMemory.detach();
    QObject* parent = QWindow::fromWinId(parentAppWinId);
}

but the application crashes.

I tried to pass "Application B"'s MainWindow as an argument of QWindow::fromWinId(this->winId()); for debugging purposes: the application doesn't crash, but "Application B"'s MainWindow size changes...

Why is this happening? Is this the cause of the crash in the first case?

How can I avoid crashing when using QWindow::fromWinId(parentAppWinId);?

p.s. the ultimate goal would be to be able to instantiate QObjects (such as QDockWidget) from Application B as children of Application A's MainWindow

UPDATE!!

it is working on Linux! The application doesn't crash but I cannot dock a QDockWidget into Application A's MainWindow when I use

QWidget* parentRepresentation = QWidget::createWindowContainer(QWindow::fromWinId(parentAppWinId));

nor I can

QWidget* parentRepresentation = QWidget::find(parentAppWinId)

because it returns a nullptr

I have updated the minimale reproducible example.

Thank you very very much


FOR MINIMAL REPRODUCIBLE EXAMPLE

this example does not use a shared memory, but shares the window Id as an argument of the QProcess. The crash occurs in the same context.

APPLICATION A

//mainwindow.h
#include <QtWidgets>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    void startAppB();
private:
    QProcess* m_child;

};
// mainwindow.cpp
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    m_child = new QProcess(this);
    setWindowTitle("Application A");
    startAppB();
}

void MainWindow::startAppB()
{
    QString rel_path = QCoreApplication::applicationDirPath() + "/../../../../child/child.app/Contents/MacOS/";
    QString app = rel_path + "child";
    QStringList args;
    WId myId = this->winId();
    qDebug() << myId;
    args << QString::number(myId);
    m_child->start(app, args, QIODevice::ReadWrite);
}

APPLICATION B

// main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#include <QtWidgets>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    argv[1] is the WId id of the MainWindow's parent process
    WId parentId = std::strtoul(argv[1], NULL, 0);
    MainWindow w(nullptr, parentId);
    w.show();
    return a.exec();
}
// mainwindow.h
#include <QtWidgets>
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr, WId parentId = 0);
    WId parentId;
};
// mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent, WId parentId)
    : QMainWindow(parent)
{
    setWindowTitle("Application B");
    this->parentId = parentId;
    qInfo() << "The parentId is: "<< parentId;

    WId parentAppWinId = this->parentId;
    QWidget* parentRepresentation = QWidget::createWindowContainer(QWindow::fromWinId(parentAppWinId));
    qDebug() << parentRepresentation; // QWindowContainer(0xhex)

    QDockWidget* dock = new QDockWidget(parentRepresentation);
    dock->setFloating(true);
    dock->show(); // it appears but I can't even drag it
}

0 Answers
Related