Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.15.1, 6.1.0 Beta 1
-
None
-
macOS 10.15, Qt 5.15 & 6.1, single monitor
Description
In Qt 5.15 and earlier, there was a QMacNativeWidget class to embed a QWidget inside a native window, which is specially useful when creating plugins using Qt inside other non-Qt apps.
Since Qt 6.0 the QMacNativeWidget class was removed ( QTBUG-83254 ), and fully replaced by QWindow::fromWinId, which allows creating a QWindow from a native window handle.
From there, you can assign your main app QWidget to it like this:
windowHandle()->setParent(nativeWindow); move(0,0);
And this works pretty well on both macOS and Windows... Except for one issue on macOS: popup menus appear at the wrong position (see attached screenshots at the end of this post).
The only instance where the popup menus are correctly positioned is when the globalPos is directly accessible, for instance when invoking a contextual menu.
Here's a recap of when popup menu position works/doesn't work:
Qt 5.15, macOS, QMacNativeWidget: OK
Qt 5.15, macOS, QWindow::fromWinId: NOT OK
Qt 6.1, macOS, QWindow::fromWinId: NOT OK
Qt 6.1, Windows, QWindow::fromWinId: OK
Here's the minimal code to repro the issue, corresponding to the attached screenshots:
//project.pro
QT = core gui widgets
SOURCES += main.mm
//main.mm #import <Cocoa/Cocoa.h> #include <QApplication> #include <QtWidgets> int main(int argc, char *argv[]) { ////////////////// //NATIVE HOST VIEW ////////////////// //Create a NSWindow [NSApplication sharedApplication]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; id applicationName = [[NSProcessInfo processInfo] processName]; id window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 256, 256) styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO]; [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; [window setTitle: applicationName]; [window makeKeyAndOrderFront:nil]; [NSApp activateIgnoringOtherApps:YES]; //Create a NSView NSRect frameRect = NSMakeRect(0, 0 , 256, 256); NSView* view = [[NSView alloc] initWithFrame:frameRect]; [view setHidden:NO]; [view setNeedsDisplay:YES]; [window setContentView:view]; //////////////////// //EMBEDDED QT WIDGET //////////////////// //Create a Qt app and a QWindow from the NSView handle QApplication* a=new QApplication(argc, argv); QWindow* qwindow=QWindow::fromWinId((WId)view); QWidget* widget=new QWidget(); //Add a contextual menu to the main widget (right click to show) widget->setContextMenuPolicy(Qt::ActionsContextMenu); widget->addAction(new QAction("Context Action 1")); widget->addAction(new QAction("Context Action 2")); widget->addAction(new QAction("Context Action 3")); //Add actions to the tool button (long click the tool button to show) QToolButton* toolButton=new QToolButton(); QMenu* menu=new QMenu(); menu->addAction(new QAction("Toolbutton Action 1")); menu->addAction(new QAction("Toolbutton Action 2")); menu->addAction(new QAction("Toolbutton Action 3")); toolButton->setMenu(menu); //Add items to the combo box (click the combo box to show) QComboBox* comboBox=new QComboBox(); comboBox->addItem("Combo Item 1"); comboBox->addItem("Combo Item 2"); comboBox->addItem("Combo Item 3"); //Set the layout of the main widget QVBoxLayout* layout=new QVBoxLayout(); layout->addWidget(toolButton); layout->addWidget(comboBox); widget->setLayout(layout); //Show the main widget, and assign it to the QWindow widget->show(); widget->move(0,0); widget->windowHandle()->setParent(qwindow); a->exec(); [NSApp run]; return 0; }
Also attached as a zip file to this issue.