Search code examples
qtdrop-down-menuqt5touch-eventqtwebengine

Touch freeze in QtWebEngine after opening a DropDown menu


I stumbled across a QtWebEngine problem while using a touch display. I can browse through all websites via my touch display, but when I click on a DropDown menu (for example on https://www.ebay.com/ clicking on "All categories" next to the search field), touch is not working anymore (or 1/30 touch clicks works). I can still close it via mouse/keyboard. After closing the DropDown menu, touch is working again.

I created a small example browser:

BrowserWidget::BrowserWidget(QWidget *parent)
    : QWidget(parent), ui(new Ui::BrowserWidget),
      m_webView(new QWebEngineView(this)), m_page(new QWebEnginePage(this)) {
  ui->setupUi(this);
  ui->verticalLayout->addWidget(m_webView);

  m_page->setUrl(QUrl(QStringLiteral("https://www.ebay.com/")));
  m_webView->setPage(m_page);

  m_webView->setAttribute(Qt::WA_AcceptTouchEvents);
  m_webView->installEventFilter(this);
}

bool BrowserWidget::eventFilter(QObject *watched, QEvent *e) {
  qDebug() << "event: " << e->type();

  if (e->type() == QEvent::ChildAdded) {
    QChildEvent *ce = static_cast<QChildEvent *>(e);
    if (ce && ce->child()) {
      ce->child()->installEventFilter(this);
    }
  }

  return false;
}

I installed my event filter to the widgets in the QEvent::ChildAdded for a better debugging (so I can observe more events).

This behaviour is always reproducable and I don't know if I did something wrong, because I can operate the browser via touch. I also added the Qt::WA_AcceptTouchEvents to the child widgets, but it didn't make any difference.

I hope somebody of you can help me out, thank you!


Solution

  • Found out that it is a Qt-bug https://bugreports.qt.io/browse/QTBUG-79254

    I created a workaround for this problem, maybe somebody needs this in the future:

    bool WebEngineView::event(QEvent *e)
    {
      // Workaround for QTBUG-79254: DropDown-menus are not accepting any touchevents
      if (e->type() == QEvent::ChildAdded) {
        QChildEvent *ce = static_cast<QChildEvent *>(e);
    
        if (ce && ce->child() && ce->child()->isWidgetType()) {
          QWidget *child = static_cast<QWidget *>(ce->child());
    
          if (child->windowFlags() & Qt::Popup) {
            Qt::WindowFlags flags = child->windowFlags();
            flags = flags & (~Qt::Popup) | Qt::Dialog;
            child->setWindowFlags(flags);
          }
        }
      }
    
      return QWebEngineView::event(e);
    }