[Interest] QWindow::setTransientParent()

Rutledge Shawn Shawn.Rutledge at theqtcompany.com
Fri Nov 7 09:13:23 CET 2014


On 7 Nov 2014, at 02:05, John Weeks <john at wavemetrics.com> wrote:

> Can anyone tell me about  QWindow::setTransientParent()? When building with Qt 5 I keep seeing warnings:
> 
> void QWindow::setTransientParent(QWindow *) QWidgetWindow(0x118c39a10, name = "QWidgetClassWindow") must be a top level window.
> 
> One situation where I see it is on Macintosh:
> 
> Our application can make a 3D graph window that uses OpenGL calls to draw. The OpenGL context is implemented via a QGLWidget. The  QGLWidget is contained in a QWidget that is itself contained in a QWidget that is (usually) a top-level window.
> 
> I see the warning when calling new QMenu(QGLWidget *). Here's a (truncated) stack trace (GizmoWD is our class, of course):
> 
> 0	QWindow::setTransientParent(QWindow*)	qwindow.cpp	1131	0x10969ac1a	
> 1	QWidgetPrivate::setParent_sys(QWidget*, QFlags<Qt::WindowType>)	qwidget.cpp	10516	0x10898b528	
> 2	QWidget::setParent(QWidget*, QFlags<Qt::WindowType>)	qwidget.cpp	10375	0x108971b07	
> 3	QWidgetPrivate::init(QWidget*, QFlags<Qt::WindowType>)	qwidget.cpp	1179	0x10896fe3c	
> 4	QWidget	qwidget.cpp	1026	0x1089701a9	
> 5	QMenu	qmenu.cpp	1333	0x108b3468f	
> 6	QMenu	qmenu.cpp	1336	0x108b3460d	
> 7	GizmoWD::init(char const*, int)	GizmoWD.cpp	90	0x100cb58f9	
> 8	doNewGizmo(GizmoWD**, char const*, char*, wDataClass*, wdChildInfo::hostRectType, WMRect*, int, int, int)	GizmoBuiltInOps.cpp	279	0x100c81f7a	
> 
> In tracing into this, I see that QGLWidget requires a WinID. The QWindow * being passed to setTransientParent() is the QGLWidget. The QWindow whose setTransientParent() method was called is the QMenu.
> 
> I haven't seen any obvious problems that I can trace to this, but maybe I'm missing something.
> 
> 
> I also see it on Windows in some other situations.
> 
> 
> My apologies for a somewhat vague and abstruse question. I'm trying to understand the warning, but I don't have an obvious place to start. Thanks for any light you can shed!

I can reproduce it with qtbase/examples/opengl/legacy/hellogl like this:

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
    if (event->button() == Qt::RightButton) {
        QMenu m(this);
        m.addAction("test item");
        m.exec(event->globalPos());
    }
}

and the warning is in 

void QWindow::setTransientParent(QWindow *parent)
{
    Q_D(QWindow);
    if (parent && !parent->isTopLevel()) {
        qWarning() << Q_FUNC_INFO << parent << "must be a top level window.";
        return;
    }

which is harmless, right?  Have you actually seen any behavior problems?  But we shouldn’t emit needless warnings either.  So I wrote up https://bugreports.qt-project.org/browse/QTBUG-42464

QGLWidget is obsolete, because it has the disadvantage of requiring its own platform window for the GL content to render into, which has caused various problems over the years.  QOpenGLWidget (new in Qt 5.4) simplifies some things: Qt uses FBO tricks to composite the OpenGL content and the other widgets into a single window.  So you should probably try to switch from QGLWidget to QOpenGLWidget.

setTransientParent just provides a hint that one window is a dependent of another, so that e.g. a dialog is to be shown centered over the main window.  For a context menu’s popup window, maybe that should not be necessary at all, actually, because it has to set its position to be right next to the cursor: we can’t depend on the window manager to position it.




More information about the Interest mailing list