diff options
author | Even Oscar Andersen <[email protected]> | 2024-10-29 09:00:08 +0100 |
---|---|---|
committer | Even Oscar Andersen <[email protected]> | 2024-11-26 16:25:11 +0100 |
commit | ef8bf4c2cf3d86a869ff8a555d4e390168864144 (patch) | |
tree | 99020819212b9c2ec2056c5cddbfbea8aa9b2c82 | |
parent | 6085b9399053cd6665dc1a7b636c078992aaffe0 (diff) |
wasm: Fix focus handling
We had input handling enabled as a precondition for setting focus.
This is wrong, we need to have the focus for toggle buttons
and other non-input things as well.
(Also toggle buttons act on spacebar).
Also selects a new active window if the window
that is active (i.e a dialog) is deleted.
Also shift + tab did not always work, fixed
to emit Key_Backtab
Fixes: QTBUG-130371
Pick-to: 6.8
Change-Id: I3b36a3e200ba9d4b0791865e75235ddfb72bcaa5
Reviewed-by: Morten Johan Sørvig <[email protected]>
-rw-r--r-- | src/plugins/platforms/wasm/qwasmevent.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasminputcontext.cpp | 10 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindowtreenode.cpp | 39 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindowtreenode.h | 8 | ||||
-rw-r--r-- | tests/auto/wasm/selenium/qwasmwindow.py | 19 | ||||
-rw-r--r-- | tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp | 16 |
7 files changed, 91 insertions, 5 deletions
diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp index 5ff6f4f12cc..0278ad4af55 100644 --- a/src/plugins/platforms/wasm/qwasmevent.cpp +++ b/src/plugins/platforms/wasm/qwasmevent.cpp @@ -62,6 +62,8 @@ Qt::Key webKeyToQtKey(const std::string &code, const std::string &key, bool isDe return Qt::Key_unknown; } } else if (auto mapping = QWasmKeyTranslator::mapWebKeyTextToQtKey(key.c_str())) { + if (modifiers.testFlag(Qt::ShiftModifier) && (*mapping == Qt::Key::Key_Tab)) + *mapping = Qt::Key::Key_Backtab; return *mapping; } diff --git a/src/plugins/platforms/wasm/qwasminputcontext.cpp b/src/plugins/platforms/wasm/qwasminputcontext.cpp index df4b95b7b4b..5ce24588973 100644 --- a/src/plugins/platforms/wasm/qwasminputcontext.cpp +++ b/src/plugins/platforms/wasm/qwasminputcontext.cpp @@ -352,16 +352,16 @@ void QWasmInputContext::setFocusObject(QObject *object) if (m_focusObject && !m_preeditString.isEmpty()) commitPreeditAndClear(); - if (inputMethodAccepted()) { + if (object) { m_inputElement.call<void>("focus"); - m_usingTextInput = true; - + m_usingTextInput = inputMethodAccepted(); m_focusObject = object; - } else { + } else if (m_focusObject) { m_inputElement.call<void>("blur"); m_usingTextInput = false; - m_focusObject = nullptr; + } else { + m_usingTextInput = false; } QPlatformInputContext::setFocusObject(object); } diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index b77f2e616c6..3b1e3dff5f4 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -127,6 +127,8 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport, QWasmWindow::~QWasmWindow() { + shutdown(); + emscripten::val::module_property("specialHTMLTargets").delete_(canvasSelector()); m_window.call<void>("removeChild", m_canvas); m_context2d = emscripten::val::undefined(); diff --git a/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp b/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp index f11adf9b78c..08eb7e327b1 100644 --- a/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp +++ b/src/plugins/platforms/wasm/qwasmwindowtreenode.cpp @@ -4,6 +4,9 @@ #include "qwasmwindowtreenode.h" #include "qwasmwindow.h" +#include "qwasmscreen.h" + +uint64_t QWasmWindowTreeNode::s_nextActiveIndex = 0; QWasmWindowTreeNode::QWasmWindowTreeNode() : m_childStack(std::bind(&QWasmWindowTreeNode::onTopWindowChanged, this)) @@ -12,6 +15,39 @@ QWasmWindowTreeNode::QWasmWindowTreeNode() QWasmWindowTreeNode::~QWasmWindowTreeNode() = default; +void QWasmWindowTreeNode::shutdown() +{ + QWasmWindow *window = asWasmWindow(); + if (!window || + !window->window() || + (QGuiApplication::focusWindow() && // Don't act if we have a focus window different from this + QGuiApplication::focusWindow() != window->window())) + return; + + // Make a list of all windows sorted on active index. + // Skip windows with active index 0 as they have + // never been active. + std::map<uint64_t, QWasmWindow *> allWindows; + for (const auto &w : window->platformScreen()->allWindows()) { + if (w->getActiveIndex() > 0) + allWindows.insert({w->getActiveIndex(), w}); + } + + // window is not in all windows + if (window->getActiveIndex() > 0) + allWindows.insert({window->getActiveIndex(), window}); + + if (allWindows.size() >= 2) { + const auto lastIt = std::prev(allWindows.end()); + const auto prevIt = std::prev(lastIt); + const auto lastW = lastIt->second; + const auto prevW = prevIt->second; + + if (lastW == window) // Only act if window is last to be active + prevW->requestActivateWindow(); + } +} + void QWasmWindowTreeNode::onParentChanged(QWasmWindowTreeNode *previousParent, QWasmWindowTreeNode *currentParent, QWasmWindowStack::PositionPreference positionPreference) @@ -73,6 +109,9 @@ void QWasmWindowTreeNode::setAsActiveNode() { if (parentNode()) parentNode()->setActiveChildNode(asWasmWindow()); + + // At the end, this is a recursive function + m_activeIndex = ++s_nextActiveIndex; } void QWasmWindowTreeNode::bringToTop() diff --git a/src/plugins/platforms/wasm/qwasmwindowtreenode.h b/src/plugins/platforms/wasm/qwasmwindowtreenode.h index 344fdb43cbd..170d777f02a 100644 --- a/src/plugins/platforms/wasm/qwasmwindowtreenode.h +++ b/src/plugins/platforms/wasm/qwasmwindowtreenode.h @@ -38,14 +38,22 @@ protected: void setAsActiveNode(); void bringToTop(); void sendToBottom(); + void shutdown(); const QWasmWindowStack &childStack() const { return m_childStack; } QWasmWindow *activeChild() const { return m_activeChild; } + uint64_t getActiveIndex() const { + return m_activeIndex; + } + private: void onTopWindowChanged(); void setActiveChildNode(QWasmWindow *activeChild); + uint64_t m_activeIndex = 0; + static uint64_t s_nextActiveIndex; + QWasmWindowStack m_childStack; QWasmWindow *m_activeChild = nullptr; }; diff --git a/tests/auto/wasm/selenium/qwasmwindow.py b/tests/auto/wasm/selenium/qwasmwindow.py index bf05aed9db4..fcda0359c4c 100644 --- a/tests/auto/wasm/selenium/qwasmwindow.py +++ b/tests/auto/wasm/selenium/qwasmwindow.py @@ -91,6 +91,18 @@ class WidgetTestCase(unittest.TestCase): self.assertEqual(w2.hasFocus(), False) self.assertEqual(w3.hasFocus(), True) + w3.close(); + self.assertEqual(w0.hasFocus(), False) + self.assertEqual(w1.hasFocus(), False) + self.assertEqual(w2.hasFocus(), True) + + w2.close(); + self.assertEqual(w0.hasFocus(), True) + self.assertEqual(w1.hasFocus(), False) + + w1.close(); + self.assertEqual(w0.hasFocus(), True) + clearWidgets(self._driver) #Looks weird, no asserts, the test is that @@ -744,6 +756,13 @@ class Widget: ''' ) + def close(self): + self.driver.execute_script( + f''' + instance.closeWidget('{self.name}'); + ''' + ) + class Window: def __init__(self, parent=None, rect=None, title=None, element=None, visible=True, opengl=0): self.driver = parent.driver diff --git a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp index 5592f0755bd..975025a1d0c 100644 --- a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp +++ b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp @@ -474,6 +474,16 @@ public: widget->setAttribute(Qt::WA_NativeWindow); } + bool closeWidget(const std::string &name) + { + TestWidget *widget = findWidget(name); + if (!widget) + return false; + + widget->close(); + return true; + } + private: using TestWidgetPtr = std::shared_ptr<TestWidget>; @@ -623,6 +633,11 @@ void activateWidget(const std::string &name) w->activateWindow(); } +bool closeWidget(const std::string &name) +{ + return WidgetStorage::getInstance()->closeWidget(name); +} + void clearWidgets() { WidgetStorage::clearInstance(); @@ -776,6 +791,7 @@ EMSCRIPTEN_BINDINGS(qwasmwindow) emscripten::function("showToolTipWidget", &showToolTipWidget); emscripten::function("setWidgetNoFocusShow", &setWidgetNoFocusShow); emscripten::function("showWidget", &showWidget); + emscripten::function("closeWidget", &closeWidget); emscripten::function("activateWidget", &activateWidget); emscripten::function("hasWidgetFocus", &hasWidgetFocus); emscripten::function("clearWidgets", &clearWidgets); |