summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/androidjniinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/android/androidjniinput.cpp')
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp200
1 files changed, 102 insertions, 98 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index 00e6b7ca51..07f2786cc6 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -24,120 +24,64 @@ Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods");
using namespace QtAndroid;
Q_DECLARE_JNI_CLASS(QtLayout, "org/qtproject/qt/android/QtLayout")
+Q_DECLARE_JNI_CLASS(QtLayoutInterface, "org/qtproject/qt/android/QtLayoutInterface")
+Q_DECLARE_JNI_CLASS(QtInputInterface, "org/qtproject/qt/android/QtInputInterface")
namespace QtAndroidInput
{
static bool m_ignoreMouseEvents = false;
+ static Qt::MouseButtons m_buttons = Qt::NoButton;
+
static QRect m_softwareKeyboardRect;
static QList<QWindowSystemInterface::TouchPoint> m_touchPoints;
static QPointer<QWindow> m_mouseGrabber;
- GenericMotionEventListener::~GenericMotionEventListener() {}
- namespace {
- struct GenericMotionEventListeners {
- QMutex mutex;
- QList<QtAndroidInput::GenericMotionEventListener *> listeners;
- };
- }
- Q_GLOBAL_STATIC(GenericMotionEventListeners, g_genericMotionEventListeners)
-
- static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event)
- {
- jboolean ret = JNI_FALSE;
- QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- for (auto *listener : std::as_const(g_genericMotionEventListeners()->listeners))
- ret |= listener->handleGenericMotionEvent(event);
- return ret;
- }
-
- KeyEventListener::~KeyEventListener() {}
- namespace {
- struct KeyEventListeners {
- QMutex mutex;
- QList<QtAndroidInput::KeyEventListener *> listeners;
- };
- }
- Q_GLOBAL_STATIC(KeyEventListeners, g_keyEventListeners)
-
- static jboolean dispatchKeyEvent(JNIEnv *, jclass, jobject event)
- {
- jboolean ret = JNI_FALSE;
- QMutexLocker locker(&g_keyEventListeners()->mutex);
- for (auto *listener : std::as_const(g_keyEventListeners()->listeners))
- ret |= listener->handleKeyEvent(event);
- return ret;
- }
-
- void registerGenericMotionEventListener(QtAndroidInput::GenericMotionEventListener *listener)
- {
- QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- g_genericMotionEventListeners()->listeners.push_back(listener);
- }
-
- void unregisterGenericMotionEventListener(QtAndroidInput::GenericMotionEventListener *listener)
- {
- QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- g_genericMotionEventListeners()->listeners.removeOne(listener);
- }
-
- void registerKeyEventListener(QtAndroidInput::KeyEventListener *listener)
- {
- QMutexLocker locker(&g_keyEventListeners()->mutex);
- g_keyEventListeners()->listeners.push_back(listener);
- }
-
- void unregisterKeyEventListener(QtAndroidInput::KeyEventListener *listener)
- {
- QMutexLocker locker(&g_keyEventListeners()->mutex);
- g_keyEventListeners()->listeners.removeOne(listener);
- }
-
QJniObject qtLayout()
{
- return qtActivityDelegate().callMethod<QtJniTypes::QtLayout>("getQtLayout");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ return reg->callInterface<QtJniTypes::QtLayoutInterface, QtJniTypes::QtLayout>(
+ "getQtLayout");
}
void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd)
{
qCDebug(lcQpaInputMethods) << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd;
- qtInputDelegate().callMethod<void>("updateSelection",
- selStart,
- selEnd,
- candidatesStart,
- candidatesEnd);
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>("updateSelection", selStart, selEnd,
+ candidatesStart, candidatesEnd);
}
void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
{
- qtInputDelegate().callMethod<void>("showSoftwareKeyboard",
- QtAndroidPrivate::activity(),
- qtLayout().object<QtJniTypes::QtLayout>(),
- left,
- top,
- width,
- height,
- inputHints,
- enterKeyType);
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>(
+ "showSoftwareKeyboard", QtAndroidPrivate::activity(),
+ qtLayout().object<QtJniTypes::QtLayout>(), left, top, width, height, inputHints,
+ enterKeyType);
qCDebug(lcQpaInputMethods) << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
}
void resetSoftwareKeyboard()
{
- qtInputDelegate().callMethod<void>("resetSoftwareKeyboard");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>("resetSoftwareKeyboard");
qCDebug(lcQpaInputMethods) << "@@@ RESETSOFTWAREKEYBOARD";
}
void hideSoftwareKeyboard()
{
- qtInputDelegate().callMethod<void>("hideSoftwareKeyboard");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>("hideSoftwareKeyboard");
qCDebug(lcQpaInputMethods) << "@@@ HIDESOFTWAREKEYBOARD";
}
bool isSoftwareKeyboardVisible()
{
- return qtInputDelegate().callMethod<jboolean>("isSoftwareKeyboardVisible");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ return reg->callInterface<QtJniTypes::QtInputInterface, jboolean>(
+ "isSoftwareKeyboardVisible");
}
QRect softwareKeyboardRect()
@@ -147,20 +91,85 @@ namespace QtAndroidInput
int getSelectHandleWidth()
{
- return qtInputDelegate().callMethod<jint>("getSelectHandleWidth");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ return reg->callInterface<QtJniTypes::QtInputInterface, jint>("getSelectHandleWidth");
}
void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
{
- qtInputDelegate().callMethod<void>("updateHandles",
- QtAndroidPrivate::activity(),
- qtLayout().object<QtJniTypes::QtLayout>(),
- mode, editMenuPos.x(), editMenuPos.y(), editButtons,
- cursor.x(), cursor.y(),
- anchor.x(), anchor.y(), rtl);
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>(
+ "updateHandles", QtAndroidPrivate::activity(),
+ qtLayout().object<QtJniTypes::QtLayout>(), mode, editMenuPos.x(), editMenuPos.y(),
+ editButtons, cursor.x(), cursor.y(), anchor.x(), anchor.y(), rtl);
+ }
+
+ // from https://developer.android.com/reference/android/view/MotionEvent#getButtonState()
+ enum AndroidMouseButton {
+ BUTTON_PRIMARY = 0x00000001,
+ BUTTON_SECONDARY = 0x00000002,
+ BUTTON_TERTIARY = 0x00000004,
+ BUTTON_BACK = 0x00000008,
+ BUTTON_FORWARD = 0x00000010,
+ BUTTON_STYLUS_PRIMARY = 0x00000020,
+ BUTTON_STYLUS_SECONDARY = 0x00000040,
+ };
+ Q_DECLARE_FLAGS(AndroidMouseButtons, AndroidMouseButton)
+
+ static Qt::MouseButtons toMouseButtons(jint j_buttons)
+ {
+ const auto buttons = static_cast<AndroidMouseButtons>(j_buttons);
+ Qt::MouseButtons mouseButtons;
+ if (buttons.testFlag(BUTTON_PRIMARY))
+ mouseButtons.setFlag(Qt::LeftButton);
+
+ if (buttons.testFlag(BUTTON_SECONDARY))
+ mouseButtons.setFlag(Qt::RightButton);
+
+ if (buttons.testFlag(BUTTON_TERTIARY))
+ mouseButtons.setFlag(Qt::MiddleButton);
+
+ if (buttons.testFlag(BUTTON_BACK))
+ mouseButtons.setFlag(Qt::BackButton);
+
+ if (buttons.testFlag(BUTTON_FORWARD))
+ mouseButtons.setFlag(Qt::ForwardButton);
+
+ if (buttons.testFlag(BUTTON_STYLUS_PRIMARY))
+ mouseButtons.setFlag(Qt::LeftButton);
+
+ if (buttons.testFlag(BUTTON_STYLUS_SECONDARY))
+ mouseButtons.setFlag(Qt::RightButton);
+
+ // Fall back to left button
+ if (Q_UNLIKELY(buttons != 0 && mouseButtons == Qt::NoButton)) {
+ qWarning() << "Unhandled button value:" << buttons << "Falling back to Qt::LeftButton";
+ mouseButtons = Qt::LeftButton;
+ }
+ return mouseButtons;
+ }
+
+ static void sendMouseButtonEvents(QWindow *topLevel, QPoint localPos, QPoint globalPos,
+ jint mouseButtonState, QEvent::Type type)
+ {
+ const Qt::MouseButtons mouseButtons = toMouseButtons(mouseButtonState);
+ const Qt::MouseButtons changedButtons = mouseButtons & ~m_buttons;
+
+ if (changedButtons == Qt::NoButton)
+ return;
+
+ static_assert (sizeof(changedButtons) <= sizeof(uint), "Qt::MouseButtons size changed. Adapt code.");
+
+ for (uint buttonInt = 0x1; static_cast<uint>(changedButtons) >= buttonInt; buttonInt <<= 1) {
+ const auto button = static_cast<Qt::MouseButton>(buttonInt);
+ if (changedButtons.testFlag(button)) {
+ QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos,
+ mouseButtons, button, type);
+ }
+ }
}
- static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y)
+ static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState)
{
if (m_ignoreMouseEvents)
return;
@@ -169,13 +178,11 @@ namespace QtAndroidInput
QWindow *window = windowFromId(winId);
m_mouseGrabber = window;
const QPoint localPos = window && window->handle() ?
- window->handle()->mapFromGlobal(globalPos) : globalPos;
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
- Qt::MouseButtons(Qt::LeftButton),
- Qt::LeftButton, QEvent::MouseButtonPress);
+ window->handle()->mapFromGlobal(globalPos) : globalPos;
+ sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonPress);
}
- static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y)
+ static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState)
{
const QPoint globalPos(x,y);
QWindow *window = m_mouseGrabber.data();
@@ -184,9 +191,8 @@ namespace QtAndroidInput
const QPoint localPos = window && window->handle() ?
window->handle()->mapFromGlobal(globalPos) : globalPos;
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
- Qt::MouseButtons(Qt::NoButton),
- Qt::LeftButton, QEvent::MouseButtonRelease);
+
+ sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonRelease);
m_ignoreMouseEvents = false;
m_mouseGrabber.clear();
}
@@ -900,8 +906,8 @@ namespace QtAndroidInput
{"touchAdd","(IIIZIIFFFF)V",(void*)touchAdd},
{"touchEnd","(II)V",(void*)touchEnd},
{"touchCancel", "(I)V", (void *)touchCancel},
- {"mouseDown", "(III)V", (void *)mouseDown},
- {"mouseUp", "(III)V", (void *)mouseUp},
+ {"mouseDown", "(IIII)V", (void *)mouseDown},
+ {"mouseUp", "(IIII)V", (void *)mouseUp},
{"mouseMove", "(III)V", (void *)mouseMove},
{"mouseWheel", "(IIIFF)V", (void *)mouseWheel},
{"longPress", "(III)V", (void *)longPress},
@@ -912,8 +918,6 @@ namespace QtAndroidInput
{"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged},
{"keyboardGeometryChanged", "(IIII)V", (void *)keyboardGeometryChanged},
{"handleLocationChanged", "(III)V", (void *)handleLocationChanged},
- {"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast<void *>(dispatchGenericMotionEvent)},
- {"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast<void *>(dispatchKeyEvent)},
};
bool registerNatives(QJniEnvironment &env)