summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEven Oscar Andersen <[email protected]>2024-10-29 09:00:08 +0100
committerEven Oscar Andersen <[email protected]>2024-11-26 16:25:11 +0100
commitef8bf4c2cf3d86a869ff8a555d4e390168864144 (patch)
tree99020819212b9c2ec2056c5cddbfbea8aa9b2c82
parent6085b9399053cd6665dc1a7b636c078992aaffe0 (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.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasminputcontext.cpp10
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasmwindowtreenode.cpp39
-rw-r--r--src/plugins/platforms/wasm/qwasmwindowtreenode.h8
-rw-r--r--tests/auto/wasm/selenium/qwasmwindow.py19
-rw-r--r--tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp16
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);