Qt5 and OSG port issue: Shaking motion when moving a osgQt widget on Linux
-
Hello,
While porting to Qt5, I've run into a problem on Linux with moving an osgQt widget. The
mouse move events are incorrect and the widget shakes while moving. This issue did not occur with QT4.I am using osg version 3.4.0-01 and Qt version 5.4.2.
This problem is reproducible with a simple update to the example from the osg distribution , osg/examples/osgviewerQt/osgviewerQt.cpp
In the updated source, the ViewerWidget is added as a child to a QMdiSubwindow. There are two QMdiSubWindows displayed: the first window is the osg cow, the second window is a QLabel containing text. When the osg cow is displayed, both windows shake when moved. When the cow window is closed, the text window moves without shaking.
This problem does not occur on Windows.
I am interested in any help figuring out this problem and also any help to understand the QT xcb changes and how they may conflict with osg/openGL's use of xlib.
Thank you.
The source code is:
// The ViewerWidget is from osg/examples/osgViewerQt // Modified to display the cow only class ViewerWidget : public QWidget, public osgViewer::CompositeViewer { public: ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded) : QWidget(parent, f) { setThreadingModel(threadingModel); // disable the default setting of viewer.done() by pressing Escape. setKeyEventSetsDone(0); QWidget* widget1 = addViewWidget(createGraphicsWindow(0, 0, 300, 300), osgDB::readNodeFile("cow.osgt")); widget1->setMinimumSize(300, 300); QVBoxLayout *pLayout = new QVBoxLayout(); pLayout->setContentsMargins(1, 1, 1, 1); pLayout->addWidget(widget1); setLayout(pLayout); connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) ); _timer.start( 10 ); } QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene ) { osgViewer::View* view = new osgViewer::View; addView( view ); osg::Camera* camera = view->getCamera(); camera->setGraphicsContext( gw ); const osg::GraphicsContext::Traits* traits = gw->getTraits(); camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f ); view->setSceneData( scene ); view->addEventHandler( new osgViewer::StatsHandler ); view->setCameraManipulator( new osgGA::MultiTouchTrackballManipulator ); //gw->setTouchEventsEnabled( true ); return gw->getGLWidget(); } osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false ) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->windowName = name; traits->windowDecoration = windowDecoration; traits->x = x; traits->y = y; traits->width = w; traits->height = h; traits->doubleBuffer = true; traits->alpha = ds->getMinimumNumAlphaBits(); traits->stencil = ds->getMinimumNumStencilBits(); traits->sampleBuffers = ds->getMultiSamples(); traits->samples = ds->getNumMultiSamples(); return new osgQt::GraphicsWindowQt(traits.get()); } virtual void paintEvent( QPaintEvent* event ) { frame(); } protected: QTimer _timer; }; QMdiSubWindow *CreateCowView() { // Create widget for the osg 3d cow QMdiSubWindow *pSubWindow = new QMdiSubWindow(); QWidget *pOsgWidget = new QWidget(); QVBoxLayout *pOsgLayout = new QVBoxLayout(); pOsgLayout->setContentsMargins(1, 1, 1, 1); pOsgWidget->setLayout(pOsgLayout); // Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different thread" when the viewer is run multi-threaded, this is regression from Qt4 ViewerWidget* viewWidget = new ViewerWidget(0, Qt::Widget, osgViewer::ViewerBase::SingleThreaded); pOsgLayout->addWidget(viewWidget); pSubWindow->setWidget(pOsgWidget); return pSubWindow; } QMdiSubWindow *CreateTextView() { // Create widget for a text label QMdiSubWindow *pSubWindow = new QMdiSubWindow(); QWidget *pLabelWidget = new QWidget(); pLabelWidget->setMinimumSize(150, 150); QVBoxLayout *pLabelLayout = new QVBoxLayout(); pLabelLayout->setContentsMargins(1, 1, 1, 1); pLabelWidget->setLayout(pLabelLayout); QLabel *pLabel = new QLabel("Hello World!\n\nReproduce the issue by:\n1. Move both windows. Observe the shaking behavior of both windows\n2. Close the cow window.\n3. Move this window again. Observe that the shaking is gone"); pLabel->setAlignment(Qt::AlignCenter); pLabelLayout->addWidget(pLabel); pSubWindow->setWidget(pLabelWidget); return pSubWindow; } int main( int argc, char** argv ) { // To reproduce the problem: // Execute the testOsgviewerQt program // Observe that there are two windows. an osg view with a cow displayed, and a text view // Move both windows. // Observe that the move operations shake the windows // Close the osg window // Move the text window // Observe that the text window moves without shaking osg::ArgumentParser arguments(&argc, argv); QApplication app(argc, argv); QMainWindow window; window.setWindowTitle(QString::fromUtf8("Test Shake on Move")); QMdiArea area; area.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); //Add subWindow to Main QMdiWindow here // One window has an osg cow (code is from examples/osgviewerQt) // One window has a Qt text label area.addSubWindow(CreateCowView()); area.addSubWindow(CreateTextView()); window.setCentralWidget(&area); window.show(); return app.exec(); }