Warning when closing an undocked qwidget
-
Hello,
I've recently migrated code from qt 5.7 to qt 5.15 and when I close an undocked dock widget, I get this warning :QMainWindowLayout::tabPosition called with out-of-bounds value '0'
If I close it programmaticaly by calling DockWidget->close(), there si no warning.
If I dock and undock it before closing it, there is no warning either.What does this error mean?
I have stepped in qt source, and when I close the widget by clicking on the X, the dockwidget close event call d->endDrag(true);
But it does not call that function when I close it programmatically or when the widget is docked. -
Hi,
Can you provide a minimal compilable example that shows that behaviour ?
-
The code is complex, and a single example doesnt show the issue. Thats why I hoped someone could explain what the error message means, so I would know where to search the issue.
Gonna keep debugging on my side and update here if I fond something usefull
-
Install Qt debug libs, set a breakpoint on the warning message and show us the backtrace.
-
Call stack is
Qt5Widgetsd.dll!QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) Line 1588 C++
Qt5Widgetsd.dll!QDockWidgetPrivate::endDrag(bool abort) Line 870 C++
Qt5Widgetsd.dll!QDockWidget::closeEvent(QCloseEvent * event) Line 1469 C++And in each fonction (check //This line comment)
QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const { const auto dockPos = toDockPos(area); if (dockPos < QInternal::DockCount) return tabPositions[dockPos]; qWarning("QMainWindowLayout::tabPosition called with out-of-bounds value '%d'", int(area)); //This line return QTabWidget::North; }
void QDockWidgetPrivate::endDrag(bool abort) { Q_Q(QDockWidget); Q_ASSERT(state != nullptr); q->releaseMouse(); if (state->dragging) { const QMainWindow *mainWindow = mainwindow_from_dock(q); Q_ASSERT(mainWindow != nullptr); QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow); if (abort || !mwLayout->plug(state->widgetItem)) { if (hasFeature(this, QDockWidget::DockWidgetFloatable)) { // This QDockWidget will now stay in the floating state. if (state->ownWidgetItem) { delete state->widgetItem; state->widgetItem = nullptr; } mwLayout->restore(); QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); if (!dwLayout->nativeWindowDeco()) { // get rid of the X11BypassWindowManager window flag and activate the resizer Qt::WindowFlags flags = q->windowFlags(); flags &= ~Qt::X11BypassWindowManagerHint; q->setWindowFlags(flags); setResizerActive(q->isFloating()); q->show(); } else { setResizerActive(false); } if (q->isFloating()) { // Might not be floating when dragging a QDockWidgetGroupWindow undockedGeometry = q->geometry(); #if QT_CONFIG(tabwidget) tabPosition = mwLayout->tabPosition(mainWindow->dockWidgetArea(q)); //This line #endif } q->activateWindow(); } else { // The tab was not plugged back in the QMainWindow but the QDockWidget cannot // stay floating, revert to the previous state. mwLayout->revert(state->widgetItem); } } } delete state; state = nullptr; }
void QDockWidget::closeEvent(QCloseEvent *event) { Q_D(QDockWidget); if (d->state) d->endDrag(true); //This line QWidget::closeEvent(event); }
And if I close the widget programatically, we dont go in d->enDrag(true) from closeEvent
-
So you somehow get into QDockWidgetPrivate::initDrag(). Is it possible to set a breakpoint there to see why it is entered?
-
When closing the widget with the mouse (top right button)
Call stack is
Qt5Widgetsd.dll!QDockWidgetPrivate::initDrag(const QPoint & pos, bool nca) Line 778 C++
Qt5Widgetsd.dll!QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent * event) Line 1043 C++
Qt5Widgetsd.dll!QDockWidget::event(QEvent * event) Line 1586 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3630 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3580 C++
Qt5Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1063 C++
Qt5Cored.dll!QCoreApplication::forwardEvent(QObject * receiver, QEvent * event, QEvent * originatingEvent) Line 1079 C++
Qt5Widgetsd.dll!QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent * e) Line 505 C++
Qt5Widgetsd.dll!QWidgetWindow::event(QEvent * event) Line 308 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3630 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 2970 C++
Qt5Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1063 C++
Qt5Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 1471 C++
Qt5Guid.dll!QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent * e) Line 2278 C++
Qt5Guid.dll!QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e) Line 2003 C++
Qt5Guid.dll!QWindowSystemInterface::sendWindowSystemEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 1181 C++And for the last function:
void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event) { Q_Q(QDockWidget); int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, nullptr, q); QWidget *tl = q->topLevelWidget(); QRect geo = tl->geometry(); QRect titleRect = tl->frameGeometry(); { titleRect.setLeft(geo.left()); titleRect.setRight(geo.right()); titleRect.setBottom(geo.top() - 1); titleRect.adjust(0, fw, 0, 0); } switch (event->type()) { case QEvent::NonClientAreaMouseButtonPress: if (!titleRect.contains(event->globalPos())) break; if (state != nullptr) break; if (qobject_cast<QMainWindow*>(parent) == 0 && qobject_cast<QDockWidgetGroupWindow*>(parent) == 0) break; if (isAnimating()) break; initDrag(event->pos(), true); //This line if (state == nullptr) break; state->ctrlDrag = (event->modifiers() & Qt::ControlModifier) || (!hasFeature(this, QDockWidget::DockWidgetMovable) && q->isFloating()); startDrag(); break; case QEvent::NonClientAreaMouseMove: if (state == nullptr || !state->dragging) break; #ifndef Q_OS_MAC if (state->nca) { endDrag(); } #endif break; case QEvent::NonClientAreaMouseButtonRelease: #ifdef Q_OS_MAC if (state) endDrag(); #endif break; case QEvent::NonClientAreaMouseButtonDblClick: _q_toggleTopLevel(); break; default: break; } }
-
This is strange, I don't see anything within QDockWidget sources. But there were mouse handling changes in 5.12 - can you maybe check with 5.11.x and 5.12.x to see if this may be the culprit?
-
Just run basic tests with version 5.11.3 and 5.12.0.
Looks like I dont have the issue with any of them -
Can you check latest 5.12.x?
-
I have managed to reproduce it with a really basic example:
#include <QApplication> #include <QMainWindow> #include <QLabel> #include <QDockWidget> int main(int argc, char* argv[]) { QApplication lApp(argc, argv); QMainWindow a; a.setCentralWidget(new QLabel("Main")); a.show(); auto lWindow = new QDockWidget(&a); lWindow->setFloating(true); lWindow->show(); return lApp.exec(); }
and the cmake file im using:
cmake_minimum_required(VERSION 3.16.0) set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON" FORCE) project(test) #Qt libs and macro SET(CMAKE_PREFIX_PATH "C:/Qt/5.15.1/msvc2019_64") set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt5 COMPONENTS Widgets Gui REQUIRED) set(Src ${CMAKE_CURRENT_LIST_DIR}/main.cpp ) add_executable(Test ${Src}) target_link_libraries(Test PRIVATE Qt5::Widgets Qt5::Gui)
-
Ran more test with this simple example, the issue is actually there with qt 5.11.3 ,5.12.0 and 5.12.9.
Edit:
I confirm the issue is not here with 5.7.1Should I test with more versions?
Raise a bug?Do you know if there is a workaround?
-
So you can also reproduce it with 5.11? Then it's not the change I thought.
It would be nice when you find some time to investigate with which version the issue came in. -
This post is deleted!
-
The issue is there in 5.9.
Cant test between 5.7.1 and 5.9, versions are not available for download
-
Thx for the information. I would suggest you to create a bug reports with all your findings. Sadly I can't compile such an old version on my system anymore so I can't hep figuring out which exact commit creates this issue.
-
Bug report created: https://bugreports.qt.io/browse/QTBUG-88157
(Cant figure out how to properly format the code in the report) -
Thx, I reformatted the code, the CMakeLists.txt is not needed.