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 Change-Id: I3b36a3e200ba9d4b0791865e75235ddfb72bcaa5 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io> (cherry picked from commit ef8bf4c2cf3d86a869ff8a555d4e390168864144) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
a1c74e054c
commit
0c60d2c066
@ -62,6 +62,8 @@ Qt::Key webKeyToQtKey(const std::string &code, const std::string &key, bool isDe
|
|||||||
return Qt::Key_unknown;
|
return Qt::Key_unknown;
|
||||||
}
|
}
|
||||||
} else if (auto mapping = QWasmKeyTranslator::mapWebKeyTextToQtKey(key.c_str())) {
|
} 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;
|
return *mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,16 +352,16 @@ void QWasmInputContext::setFocusObject(QObject *object)
|
|||||||
if (m_focusObject && !m_preeditString.isEmpty())
|
if (m_focusObject && !m_preeditString.isEmpty())
|
||||||
commitPreeditAndClear();
|
commitPreeditAndClear();
|
||||||
|
|
||||||
if (inputMethodAccepted()) {
|
if (object) {
|
||||||
m_inputElement.call<void>("focus");
|
m_inputElement.call<void>("focus");
|
||||||
m_usingTextInput = true;
|
m_usingTextInput = inputMethodAccepted();
|
||||||
|
|
||||||
m_focusObject = object;
|
m_focusObject = object;
|
||||||
} else {
|
} else if (m_focusObject) {
|
||||||
m_inputElement.call<void>("blur");
|
m_inputElement.call<void>("blur");
|
||||||
m_usingTextInput = false;
|
m_usingTextInput = false;
|
||||||
|
|
||||||
m_focusObject = nullptr;
|
m_focusObject = nullptr;
|
||||||
|
} else {
|
||||||
|
m_usingTextInput = false;
|
||||||
}
|
}
|
||||||
QPlatformInputContext::setFocusObject(object);
|
QPlatformInputContext::setFocusObject(object);
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,8 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
|
|||||||
|
|
||||||
QWasmWindow::~QWasmWindow()
|
QWasmWindow::~QWasmWindow()
|
||||||
{
|
{
|
||||||
|
shutdown();
|
||||||
|
|
||||||
emscripten::val::module_property("specialHTMLTargets").delete_(canvasSelector());
|
emscripten::val::module_property("specialHTMLTargets").delete_(canvasSelector());
|
||||||
m_canvasContainer.call<void>("removeChild", m_canvas);
|
m_canvasContainer.call<void>("removeChild", m_canvas);
|
||||||
m_context2d = emscripten::val::undefined();
|
m_context2d = emscripten::val::undefined();
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "qwasmwindowtreenode.h"
|
#include "qwasmwindowtreenode.h"
|
||||||
|
|
||||||
#include "qwasmwindow.h"
|
#include "qwasmwindow.h"
|
||||||
|
#include "qwasmscreen.h"
|
||||||
|
|
||||||
|
uint64_t QWasmWindowTreeNode::s_nextActiveIndex = 0;
|
||||||
|
|
||||||
QWasmWindowTreeNode::QWasmWindowTreeNode()
|
QWasmWindowTreeNode::QWasmWindowTreeNode()
|
||||||
: m_childStack(std::bind(&QWasmWindowTreeNode::onTopWindowChanged, this))
|
: m_childStack(std::bind(&QWasmWindowTreeNode::onTopWindowChanged, this))
|
||||||
@ -12,6 +15,39 @@ QWasmWindowTreeNode::QWasmWindowTreeNode()
|
|||||||
|
|
||||||
QWasmWindowTreeNode::~QWasmWindowTreeNode() = default;
|
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,
|
void QWasmWindowTreeNode::onParentChanged(QWasmWindowTreeNode *previousParent,
|
||||||
QWasmWindowTreeNode *currentParent,
|
QWasmWindowTreeNode *currentParent,
|
||||||
QWasmWindowStack::PositionPreference positionPreference)
|
QWasmWindowStack::PositionPreference positionPreference)
|
||||||
@ -73,6 +109,9 @@ void QWasmWindowTreeNode::setAsActiveNode()
|
|||||||
{
|
{
|
||||||
if (parentNode())
|
if (parentNode())
|
||||||
parentNode()->setActiveChildNode(asWasmWindow());
|
parentNode()->setActiveChildNode(asWasmWindow());
|
||||||
|
|
||||||
|
// At the end, this is a recursive function
|
||||||
|
m_activeIndex = ++s_nextActiveIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmWindowTreeNode::bringToTop()
|
void QWasmWindowTreeNode::bringToTop()
|
||||||
|
@ -38,14 +38,22 @@ protected:
|
|||||||
void setAsActiveNode();
|
void setAsActiveNode();
|
||||||
void bringToTop();
|
void bringToTop();
|
||||||
void sendToBottom();
|
void sendToBottom();
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
const QWasmWindowStack &childStack() const { return m_childStack; }
|
const QWasmWindowStack &childStack() const { return m_childStack; }
|
||||||
QWasmWindow *activeChild() const { return m_activeChild; }
|
QWasmWindow *activeChild() const { return m_activeChild; }
|
||||||
|
|
||||||
|
uint64_t getActiveIndex() const {
|
||||||
|
return m_activeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onTopWindowChanged();
|
void onTopWindowChanged();
|
||||||
void setActiveChildNode(QWasmWindow *activeChild);
|
void setActiveChildNode(QWasmWindow *activeChild);
|
||||||
|
|
||||||
|
uint64_t m_activeIndex = 0;
|
||||||
|
static uint64_t s_nextActiveIndex;
|
||||||
|
|
||||||
QWasmWindowStack m_childStack;
|
QWasmWindowStack m_childStack;
|
||||||
QWasmWindow *m_activeChild = nullptr;
|
QWasmWindow *m_activeChild = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -68,6 +68,18 @@ class WidgetTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(w2.hasFocus(), False)
|
self.assertEqual(w2.hasFocus(), False)
|
||||||
self.assertEqual(w3.hasFocus(), True)
|
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)
|
clearWidgets(self._driver)
|
||||||
|
|
||||||
#Looks weird, no asserts, the test is that
|
#Looks weird, no asserts, the test is that
|
||||||
@ -691,6 +703,13 @@ class Widget:
|
|||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.driver.execute_script(
|
||||||
|
f'''
|
||||||
|
instance.closeWidget('{self.name}');
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
class Window:
|
class Window:
|
||||||
def __init__(self, parent=None, rect=None, title=None, element=None, visible=True, opengl=0):
|
def __init__(self, parent=None, rect=None, title=None, element=None, visible=True, opengl=0):
|
||||||
self.driver = parent.driver
|
self.driver = parent.driver
|
||||||
|
@ -455,6 +455,16 @@ public:
|
|||||||
m_spinBoxes[name] = spinBox;
|
m_spinBoxes[name] = spinBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool closeWidget(const std::string &name)
|
||||||
|
{
|
||||||
|
TestWidget *widget = findWidget(name);
|
||||||
|
if (!widget)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
widget->close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using TestWidgetPtr = std::shared_ptr<TestWidget>;
|
using TestWidgetPtr = std::shared_ptr<TestWidget>;
|
||||||
|
|
||||||
@ -603,6 +613,11 @@ void activateWidget(const std::string &name)
|
|||||||
w->activateWindow();
|
w->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool closeWidget(const std::string &name)
|
||||||
|
{
|
||||||
|
return WidgetStorage::getInstance()->closeWidget(name);
|
||||||
|
}
|
||||||
|
|
||||||
void clearWidgets()
|
void clearWidgets()
|
||||||
{
|
{
|
||||||
WidgetStorage::clearInstance();
|
WidgetStorage::clearInstance();
|
||||||
@ -751,6 +766,7 @@ EMSCRIPTEN_BINDINGS(qwasmwindow)
|
|||||||
emscripten::function("showToolTipWidget", &showToolTipWidget);
|
emscripten::function("showToolTipWidget", &showToolTipWidget);
|
||||||
emscripten::function("setWidgetNoFocusShow", &setWidgetNoFocusShow);
|
emscripten::function("setWidgetNoFocusShow", &setWidgetNoFocusShow);
|
||||||
emscripten::function("showWidget", &showWidget);
|
emscripten::function("showWidget", &showWidget);
|
||||||
|
emscripten::function("closeWidget", &closeWidget);
|
||||||
emscripten::function("activateWidget", &activateWidget);
|
emscripten::function("activateWidget", &activateWidget);
|
||||||
emscripten::function("hasWidgetFocus", &hasWidgetFocus);
|
emscripten::function("hasWidgetFocus", &hasWidgetFocus);
|
||||||
emscripten::function("clearWidgets", &clearWidgets);
|
emscripten::function("clearWidgets", &clearWidgets);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user