diff --git a/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp b/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp index ea8d8dbcfab..f11adf9b78c 100644 --- a/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp +++ b/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp @@ -42,9 +42,13 @@ void QWasmWindowTreeNode::onSubtreeChanged(QWasmWindowTreeNodeChangeType changeT && m_childStack.topWindow() && m_childStack.topWindow()->window()) { + const auto flags = m_childStack.topWindow()->window()->flags(); + const bool notToolOrPopup = ((flags & Qt::ToolTip) != Qt::ToolTip) && ((flags & Qt::Popup) != Qt::Popup); const QVariant showWithoutActivating = m_childStack.topWindow()->window()->property("_q_showWithoutActivating"); - if (!showWithoutActivating.isValid() || !showWithoutActivating.toBool()) - m_childStack.topWindow()->requestActivateWindow(); + if (!showWithoutActivating.isValid() || !showWithoutActivating.toBool()) { + if (notToolOrPopup) + m_childStack.topWindow()->requestActivateWindow(); + } } if (parentNode()) diff --git a/tests/auto/wasm/selenium/qwasmwindow.py b/tests/auto/wasm/selenium/qwasmwindow.py index 260e9d2d24a..d02272c432b 100644 --- a/tests/auto/wasm/selenium/qwasmwindow.py +++ b/tests/auto/wasm/selenium/qwasmwindow.py @@ -34,6 +34,13 @@ class WidgetTestCase(unittest.TestCase): w0 = Widget(self._driver, "w0") w0.show() + w0.showToolTip() + + # + # Wait for tooltip to disappear + # + time.sleep(60) + #time.sleep(3600) self.assertEqual(w0.hasFocus(), True) w1 = Widget(self._driver, "w1") @@ -63,6 +70,35 @@ class WidgetTestCase(unittest.TestCase): clearWidgets(self._driver) + #Looks weird, no asserts, the test is that + #the test itself finishes + def test_showContextMenu_doesNotDeadlock(self): + screen = Screen(self._driver, ScreenPosition.FIXED, + x=0, y=0, width=600, height=1200) + + w0 = Widget(self._driver, "w0") + w0.show() + w0.showToolTip() + + w1 = Widget(self._driver, "w1") + w1.setNoFocusShow() + w1.show() + w1.showToolTip() + + w2 = Widget(self._driver, "w2") + w2.show() + w2.showToolTip() + + w3 = Widget(self._driver, "w3") + w3.setNoFocusShow() + w3.show() + w3.showToolTip() + + w3.activate(); + w3.showToolTip(); + + clearWidgets(self._driver) + def test_window_resizing(self): screen = Screen(self._driver, ScreenPosition.FIXED, x=0, y=0, width=600, height=600) @@ -641,6 +677,19 @@ class Widget: ''' ) + def showContextMenu(self): + self.driver.execute_script( + f''' + instance.showContextMenuWidget('{self.name}'); + ''' + ) + + def showToolTip(self): + self.driver.execute_script( + f''' + instance.showToolTipWidget('{self.name}'); + ''' + ) class Window: def __init__(self, parent=None, rect=None, title=None, element=None, visible=True, opengl=0): diff --git a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp index 365fc74a34e..5a8246935c3 100644 --- a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp +++ b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp @@ -16,6 +16,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -46,6 +52,25 @@ class TestWidget : public QDialog Q_OBJECT }; +// We override to be able to test that the contextMenu +// calls popup and not exec. Calling exec locks the +// test. +class TestSpinBox : public QSpinBox +{ + Q_OBJECT + +public: + TestSpinBox(QWidget *parent = nullptr) : QSpinBox(parent) { } + + void ShowContextMenu() + { + QContextMenuEvent event(QContextMenuEvent::Reason::Mouse, QPoint(0, geometry().bottom()), + mapToGlobal(QPoint(0, geometry().bottom())), Qt::NoModifier); + + contextMenuEvent(&event); + } +}; + class TestWindow : public QRasterWindow, public TestWindowBase { Q_OBJECT @@ -378,10 +403,10 @@ public: return nullptr; } - QLineEdit *findEdit(const std::string &name) + TestSpinBox *findSpinBox(const std::string &name) { - auto it = m_lineEdits.find(name); - if (it != m_lineEdits.end()) + auto it = m_spinBoxes.find(name); + if (it != m_spinBoxes.end()) return it->second; return nullptr; } @@ -389,17 +414,45 @@ public: void make(const std::string &name) { auto widget = std::make_shared(); - auto *lineEdit = new QLineEdit(widget.get()); + + widget->setWindowTitle("Dialog"); + auto spinBox = new TestSpinBox(widget.get()); + spinBox->setToolTip(QString(u"A ToolTip")); widget->setMinimumSize(200, 200); widget->setMaximumSize(200, 200); widget->setGeometry(0, m_widgetY, 200, 200); m_widgetY += 200; - lineEdit->setText("Hello world"); + m_widgets[name] = widget; + m_spinBoxes[name] = spinBox; + } + void showContextMenu(const std::string &name) + { + TestSpinBox *spinBox = findSpinBox(name); + if (spinBox) + spinBox->ShowContextMenu(); + } + void showToolTip(const std::string &name) + { + TestSpinBox *spinBox = findSpinBox(name); + if (spinBox) + QToolTip::showText(spinBox->mapToGlobal(QPoint(0, 0)), spinBox->toolTip()); + } + void makeNative(const std::string &name) + { + auto widget = std::make_shared(); + widget->setWindowTitle("Dialog"); + auto spinBox = new TestSpinBox(widget.get()); + spinBox->setToolTip(QString(u"A ToolTip")); + + widget->setMinimumSize(200, 200); + widget->setMaximumSize(200, 200); + widget->setGeometry(0, m_widgetY, 200, 200); + m_widgetY += 200; m_widgets[name] = widget; - m_lineEdits[name] = lineEdit; + m_spinBoxes[name] = spinBox; } private: @@ -407,7 +460,7 @@ private: static WidgetStorage * s_instance; std::map m_widgets; - std::map m_lineEdits; + std::map m_spinBoxes; int m_widgetY = 0; }; @@ -503,6 +556,21 @@ void createWidget(const std::string &name) WidgetStorage::getInstance()->make(name); } +void createNativeWidget(const std::string &name) +{ + WidgetStorage::getInstance()->makeNative(name); +} + +void showContextMenuWidget(const std::string &name) +{ + WidgetStorage::getInstance()->showContextMenu(name); +} + +void showToolTipWidget(const std::string &name) +{ + WidgetStorage::getInstance()->showToolTip(name); +} + void setWidgetNoFocusShow(const std::string &name) { auto w = WidgetStorage::getInstance()->findWidget(name); @@ -520,9 +588,9 @@ void showWidget(const std::string &name) void hasWidgetFocus(const std::string &name) { bool focus = false; - auto le = WidgetStorage::getInstance()->findEdit(name); - if (le) - focus = le->hasFocus(); + auto spinBox = WidgetStorage::getInstance()->findSpinBox(name); + if (spinBox) + focus = spinBox->hasFocus(); emscripten::val::global("window").call("hasWidgetFocusCallback", emscripten::val(focus)); @@ -678,6 +746,9 @@ EMSCRIPTEN_BINDINGS(qwasmwindow) emscripten::function("getOpenGLColorAt_0_0", &getOpenGLColorAt_0_0); emscripten::function("createWidget", &createWidget); + emscripten::function("createNativeWidget", &createNativeWidget); + emscripten::function("showContextMenuWidget", &showContextMenuWidget); + emscripten::function("showToolTipWidget", &showToolTipWidget); emscripten::function("setWidgetNoFocusShow", &setWidgetNoFocusShow); emscripten::function("showWidget", &showWidget); emscripten::function("activateWidget", &activateWidget);