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
}