summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEven Oscar Andersen <even.oscar.andersen@qt.io>2024-02-26 12:46:35 +0800
committerEven Oscar Andersen <even.oscar.andersen@qt.io>2024-03-21 17:50:00 +0100
commit0737fca6b2f4b29b7e4eda221147187cf72f96f3 (patch)
tree5ac870f68631e07020006003dc2147c902c62114
parentedb8bac39b9e7c16925aa0762bbf7feaf6f552ab (diff)
wasm: Qt::WA_ShowWithoutActivating was not respected
The Qt::WA_ShowWithoutActivating flag was not respected Added test in the part of the code that calls requestActivateWindow Added selenium focus test Fixes: QTBUG-122776 Change-Id: I1a248ed4352f86376d615a4cb7022e7ea095d4e7 Reviewed-by: Piotr WierciƄski <piotr.wiercinski@qt.io>
-rw-r--r--src/plugins/platforms/wasm/qwasmwindowtreenode.cpp8
-rw-r--r--tests/auto/wasm/selenium/CMakeLists.txt1
-rw-r--r--tests/auto/wasm/selenium/qwasmwindow.py85
-rw-r--r--tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp138
4 files changed, 224 insertions, 8 deletions
diff --git a/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp b/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp
index e16410dcde..ea8d8dbcfa 100644
--- a/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp
@@ -39,8 +39,12 @@ void QWasmWindowTreeNode::onSubtreeChanged(QWasmWindowTreeNodeChangeType changeT
QWasmWindowTreeNode *parent, QWasmWindow *child)
{
if (changeType == QWasmWindowTreeNodeChangeType::NodeInsertion && parent == this
- && m_childStack.topWindow()) {
- m_childStack.topWindow()->requestActivateWindow();
+ && m_childStack.topWindow()
+ && m_childStack.topWindow()->window()) {
+
+ const QVariant showWithoutActivating = m_childStack.topWindow()->window()->property("_q_showWithoutActivating");
+ if (!showWithoutActivating.isValid() || !showWithoutActivating.toBool())
+ m_childStack.topWindow()->requestActivateWindow();
}
if (parentNode())
diff --git a/tests/auto/wasm/selenium/CMakeLists.txt b/tests/auto/wasm/selenium/CMakeLists.txt
index a4963be579..b544c2a0d6 100644
--- a/tests/auto/wasm/selenium/CMakeLists.txt
+++ b/tests/auto/wasm/selenium/CMakeLists.txt
@@ -12,6 +12,7 @@ qt_internal_add_test(tst_qwasmwindow_harness
LIBRARIES
Qt::Core
Qt::Gui
+ Qt::Widgets
)
if(CMAKE_HOST_WIN32)
diff --git a/tests/auto/wasm/selenium/qwasmwindow.py b/tests/auto/wasm/selenium/qwasmwindow.py
index 39147b7a0f..1932feb4bb 100644
--- a/tests/auto/wasm/selenium/qwasmwindow.py
+++ b/tests/auto/wasm/selenium/qwasmwindow.py
@@ -27,9 +27,45 @@ class WidgetTestCase(unittest.TestCase):
self.addTypeEqualityFunc(Color, assert_colors_equal)
self.addTypeEqualityFunc(Rect, assert_rects_equal)
+ def test_hasFocus_returnsFalse_whenSetNoFocusShowWasCalled(self):
+ screen = Screen(self._driver, ScreenPosition.FIXED,
+ x=0, y=0, width=600, height=1200)
+
+ w0 = Widget(self._driver, "w0")
+ w0.show()
+ self.assertEqual(w0.hasFocus(), True)
+
+ w1 = Widget(self._driver, "w1")
+ w1.setNoFocusShow()
+ w1.show()
+ self.assertEqual(w0.hasFocus(), True)
+ self.assertEqual(w1.hasFocus(), False)
+
+ w2 = Widget(self._driver, "w2")
+ w2.show()
+ self.assertEqual(w0.hasFocus(), False)
+ self.assertEqual(w1.hasFocus(), False)
+ self.assertEqual(w2.hasFocus(), True)
+
+ w3 = Widget(self._driver, "w3")
+ w3.setNoFocusShow()
+ w3.show()
+ self.assertEqual(w0.hasFocus(), False)
+ self.assertEqual(w1.hasFocus(), False)
+ self.assertEqual(w2.hasFocus(), True)
+ self.assertEqual(w3.hasFocus(), False)
+ w3.activate();
+ self.assertEqual(w0.hasFocus(), False)
+ self.assertEqual(w1.hasFocus(), False)
+ self.assertEqual(w2.hasFocus(), False)
+ self.assertEqual(w3.hasFocus(), True)
+
+ clearWidgets(self._driver)
+
def test_window_resizing(self):
screen = Screen(self._driver, ScreenPosition.FIXED,
x=0, y=0, width=600, height=600)
+
window = Window(parent=screen, rect=Rect(x=100, y=100, width=200, height=200))
self.assertEqual(window.rect, Rect(x=100, y=100, width=200, height=200))
@@ -527,6 +563,48 @@ class Screen:
shadow_container = self.element.find_element(By.CSS_SELECTOR, f'#qt-shadow-container')
return shadow_container.shadow_root.find_element(method, query)
+def clearWidgets(driver):
+ driver.execute_script(
+ f'''
+ instance.clearWidgets();
+ '''
+ )
+
+class Widget:
+ def __init__(self, driver, name):
+ self.name=name
+ self.driver=driver
+
+ self.driver.execute_script(
+ f'''
+ instance.createWidget('{self.name}');
+ '''
+ )
+
+ def setNoFocusShow(self):
+ self.driver.execute_script(
+ f'''
+ instance.setWidgetNoFocusShow('{self.name}');
+ '''
+ )
+
+ def show(self):
+ self.driver.execute_script(
+ f'''
+ instance.showWidget('{self.name}');
+ '''
+ )
+ def hasFocus(self):
+ focus = call_instance_function_arg(self.driver, 'hasWidgetFocus', self.name)
+ return focus
+
+ def activate(self):
+ self.driver.execute_script(
+ f'''
+ instance.activateWidget('{self.name}');
+ '''
+ )
+
class Window:
def __init__(self, parent=None, rect=None, title=None, element=None, visible=True):
@@ -815,6 +893,13 @@ def call_instance_function(driver, name):
instance.{name}();
return eval(result);''')
+def call_instance_function_arg(driver, name, arg):
+ return driver.execute_script(
+ f'''let result;
+ window.{name}Callback = data => result = data;
+ instance.{name}('{arg}');
+ return eval(result);''')
+
def wait_for_animation_frame(driver):
driver.execute_script(
'''
diff --git a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp
index f69cb9775f..a54173e058 100644
--- a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp
+++ b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QEvent>
+#include <QtWidgets/qwidget.h>
#include <QtGui/qevent.h>
#include <QtCore/qobject.h>
@@ -11,6 +12,10 @@
#include <QtGui/qscreen.h>
#include <QtGui/qwindow.h>
#include <QtGui/qguiapplication.h>
+#include <QtWidgets/qlineedit.h>
+#include <QApplication>
+#include <QDialog>
+#include <QSysInfo>
#include <emscripten.h>
#include <emscripten/bind.h>
@@ -20,6 +25,12 @@
#include <sstream>
#include <vector>
+class TestWidget : public QDialog
+{
+ Q_OBJECT
+};
+
+
class TestWindow : public QRasterWindow
{
Q_OBJECT
@@ -76,6 +87,71 @@ TestWindow *findWindowByTitle(const std::string &title)
});
return window_it == windows.end() ? nullptr : static_cast<TestWindow *>(*window_it);
}
+
+class WidgetStorage
+{
+private:
+ ~WidgetStorage()
+ {
+ }
+public:
+ static WidgetStorage *getInstance()
+ {
+ if (!s_instance)
+ {
+ s_instance = new WidgetStorage();
+ }
+ return s_instance;
+ }
+ static void clearInstance()
+ {
+ delete s_instance;
+ s_instance = nullptr;
+ }
+
+ TestWidget *findWidget(const std::string &name)
+ {
+ auto it = m_widgets.find(name);
+ if (it != m_widgets.end())
+ return it->second.get();
+ return nullptr;
+ }
+
+ QLineEdit *findEdit(const std::string &name)
+ {
+ auto it = m_lineEdits.find(name);
+ if (it != m_lineEdits.end())
+ return it->second;
+ return nullptr;
+ }
+
+ void make(const std::string &name)
+ {
+ auto widget = std::make_shared<TestWidget>();
+ auto *lineEdit = new QLineEdit(widget.get());
+
+ 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_lineEdits[name] = lineEdit;
+ }
+
+private:
+ using TestWidgetPtr = std::shared_ptr<TestWidget>;
+
+ static WidgetStorage * s_instance;
+ std::map<std::string, TestWidgetPtr> m_widgets;
+ std::map<std::string, QLineEdit *> m_lineEdits;
+ int m_widgetY = 0;
+};
+
+WidgetStorage *WidgetStorage::s_instance = nullptr;
+
} // namespace
using namespace emscripten;
@@ -161,8 +237,50 @@ void screenInformation()
emscripten::val(toJSArray(screensAsJsObjects)));
}
-void createWindow(int x, int y, int w, int h, std::string parentType, std::string parentId,
- std::string title)
+void createWidget(const std::string &name)
+{
+ WidgetStorage::getInstance()->make(name);
+}
+
+void setWidgetNoFocusShow(const std::string &name)
+{
+ auto w = WidgetStorage::getInstance()->findWidget(name);
+ if (w)
+ w->setAttribute(Qt::WA_ShowWithoutActivating);
+}
+
+void showWidget(const std::string &name)
+{
+ auto w = WidgetStorage::getInstance()->findWidget(name);
+ if (w)
+ w->show();
+}
+
+void hasWidgetFocus(const std::string &name)
+{
+ bool focus = false;
+ auto le = WidgetStorage::getInstance()->findEdit(name);
+ if (le)
+ focus = le->hasFocus();
+
+ emscripten::val::global("window").call<void>("hasWidgetFocusCallback",
+ emscripten::val(focus));
+}
+
+void activateWidget(const std::string &name)
+{
+ auto w = WidgetStorage::getInstance()->findWidget(name);
+ if (w)
+ w->activateWindow();
+}
+
+void clearWidgets()
+{
+ WidgetStorage::clearInstance();
+}
+
+void createWindow(int x, int y, int w, int h, const std::string &parentType, const std::string &parentId,
+ const std::string &title)
{
QScreen *parentScreen = nullptr;
QWindow *parentWindow = nullptr;
@@ -202,7 +320,7 @@ void createWindow(int x, int y, int w, int h, std::string parentType, std::strin
window->setParent(parentWindow);
}
-void setWindowBackgroundColor(std::string title, int r, int g, int b)
+void setWindowBackgroundColor(const std::string &title, int r, int g, int b)
{
auto *window = findWindowByTitle(title);
if (!window) {
@@ -225,7 +343,7 @@ void setWindowVisible(int windowId, bool visible) {
(*window_it)->setVisible(visible);
}
-void setWindowParent(std::string windowTitle, std::string parentTitle)
+void setWindowParent(const std::string &windowTitle, const std::string &parentTitle)
{
QWindow *window = findWindowByTitle(windowTitle);
if (!window) {
@@ -242,7 +360,7 @@ void setWindowParent(std::string windowTitle, std::string parentTitle)
window->setParent(parent);
}
-bool closeWindow(std::string title)
+bool closeWindow(const std::string &title)
{
QWindow *window = findWindowByTitle(title);
return window ? window->close() : false;
@@ -252,16 +370,24 @@ EMSCRIPTEN_BINDINGS(qwasmwindow)
{
emscripten::function("screenInformation", &screenInformation);
emscripten::function("windowInformation", &windowInformation);
+
emscripten::function("createWindow", &createWindow);
emscripten::function("setWindowVisible", &setWindowVisible);
emscripten::function("setWindowParent", &setWindowParent);
emscripten::function("closeWindow", &closeWindow);
emscripten::function("setWindowBackgroundColor", &setWindowBackgroundColor);
+
+ emscripten::function("createWidget", &createWidget);
+ emscripten::function("setWidgetNoFocusShow", &setWidgetNoFocusShow);
+ emscripten::function("showWidget", &showWidget);
+ emscripten::function("activateWidget", &activateWidget);
+ emscripten::function("hasWidgetFocus", &hasWidgetFocus);
+ emscripten::function("clearWidgets", &clearWidgets);
}
int main(int argc, char **argv)
{
- QGuiApplication app(argc, argv);
+ QApplication app(argc, argv);
app.exec();
return 0;