7#include <QtGui/qtguiglobal.h>
13#include <qpa/qplatformwindow.h>
14#include <qpa/qwindowsysteminterface.h>
18#include <QGuiApplication>
23Q_LOGGING_CATEGORY(lcQpaInputMethods,
"qt.qpa.input.methods");
41 void updateSelection(
int selStart,
int selEnd,
int candidatesStart,
int candidatesEnd)
43 qCDebug(lcQpaInputMethods) <<
">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd;
45 reg->callInterface<QtJniTypes::QtInputInterface,
void>(
"updateSelection", selStart, selEnd,
46 candidatesStart, candidatesEnd);
52 reg->callInterface<QtJniTypes::QtInputInterface,
void>(
53 "showSoftwareKeyboard", QtAndroidPrivate::activity(),
54 left, top, width, height, inputHints,
56 qCDebug(lcQpaInputMethods) <<
"@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
62 reg->callInterface<QtJniTypes::QtInputInterface>(
"resetSoftwareKeyboard");
63 qCDebug(lcQpaInputMethods) <<
"@@@ RESETSOFTWAREKEYBOARD";
69 reg->callInterface<QtJniTypes::QtInputInterface>(
"hideSoftwareKeyboard");
70 qCDebug(lcQpaInputMethods) <<
"@@@ HIDESOFTWAREKEYBOARD";
76 return reg->callInterface<QtJniTypes::QtInputInterface, jboolean>(
77 "isSoftwareKeyboardVisible");
82 return m_softwareKeyboardRect;
88 return reg->callInterface<QtJniTypes::QtInputInterface, jint>(
"getSelectionHandleWidth");
94 reg->callInterface<QtJniTypes::QtInputInterface,
void>(
95 "updateHandles", mode, editMenuPos.x(), editMenuPos.y(),
96 editButtons, cursor.x(), cursor.y(), anchor.x(), anchor.y(), rtl);
113 const auto buttons =
static_cast<AndroidMouseButtons>(j_buttons);
114 Qt::MouseButtons mouseButtons;
116 mouseButtons.setFlag(Qt::LeftButton);
119 mouseButtons.setFlag(Qt::RightButton);
122 mouseButtons.setFlag(Qt::MiddleButton);
125 mouseButtons.setFlag(Qt::BackButton);
128 mouseButtons.setFlag(Qt::ForwardButton);
131 mouseButtons.setFlag(Qt::LeftButton);
134 mouseButtons.setFlag(Qt::RightButton);
137 if (Q_UNLIKELY(buttons != 0 && mouseButtons == Qt::NoButton)) {
138 qWarning() <<
"Unhandled button value:" << buttons <<
"Falling back to Qt::LeftButton";
139 mouseButtons = Qt::LeftButton;
145 jint mouseButtonState, QEvent::Type type)
147 const Qt::MouseButtons qtButtons = toMouseButtons(mouseButtonState);
148 const bool mouseReleased = type == QEvent::MouseButtonRelease && qtButtons == Qt::NoButton;
149 const Qt::MouseButtons eventButtons = mouseReleased ? m_lastSeenButtons : qtButtons;
152 static_assert (
sizeof(eventButtons) <=
sizeof(uint),
"Qt::MouseButtons size changed. Adapt code.");
154 if (eventButtons == Qt::NoButton) {
155 QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos, qtButtons, Qt::NoButton, type);
158 for (uint buttonInt = 0x1;
static_cast<uint>(eventButtons) >= buttonInt; buttonInt <<= 1) {
159 const auto button =
static_cast<Qt::MouseButton>(buttonInt);
160 if (eventButtons.testFlag(button)) {
161 QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos,
162 qtButtons, button, type);
167 static void mouseDown(JNIEnv *,
jobject , jint winId, jint x, jint y, jint mouseButtonState)
172 const QPoint localPos(x,y);
173 QWindow *window = windowFromId(winId);
175 const QPoint globalPos = window && window->handle() ?
176 window->handle()->mapToGlobal(localPos) : localPos;
177 sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonPress);
180 static void mouseUp(JNIEnv *,
jobject , jint winId, jint x, jint y, jint mouseButtonState)
182 const QPoint localPos(x,y);
183 QWindow *window = m_mouseGrabber.data();
185 window = windowFromId(winId);
187 const QPoint globalPos = window && window->handle() ?
188 window->handle()->mapToGlobal(localPos) : localPos;
190 sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonRelease);
195 static void mouseMove(JNIEnv *,
jobject , jint winId, jint x, jint y, jint mouseButtonState)
200 const QPoint localPos(x,y);
201 QWindow *window = m_mouseGrabber.data();
203 window = windowFromId(winId);
204 const QPoint globalPos = window && window->handle() ?
205 window->handle()->mapToGlobal(localPos) : localPos;
206 sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseMove);
209 static void mouseWheel(JNIEnv *,
jobject , jint winId, jint x, jint y, jfloat hdelta, jfloat vdelta)
214 const QPoint localPos(x,y);
215 QWindow *window = m_mouseGrabber.data();
217 window = windowFromId(winId);
218 const QPoint globalPos = window && window->handle() ?
219 window->handle()->mapToGlobal(localPos) : localPos;
220 const QPoint angleDelta(hdelta * 120, vdelta * 120);
222 QWindowSystemInterface::handleWheelEvent(window,
233 const QPoint globalPos(x,y);
234 QWindow *window = windowFromId(winId);
235 const QPoint localPos = window && window->handle() ?
236 window->handle()->mapFromGlobal(globalPos) : globalPos;
238 if (inputContext && qGuiApp)
239 QMetaObject::invokeMethod(inputContext,
"longPress", Q_ARG(
int, globalPos.x()), Q_ARG(
int, globalPos.y()));
242 static bool rightMouseFromLongPress = qEnvironmentVariableIntValue(
"QT_ANDROID_ENABLE_RIGHT_MOUSE_FROM_LONG_PRESS");
243 if (!rightMouseFromLongPress)
249 if (!m_mouseGrabber) {
250 QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
251 Qt::MouseButtons(Qt::RightButton), Qt::RightButton,
252 QEvent::MouseButtonPress);
253 QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
254 Qt::MouseButtons(Qt::NoButton), Qt::RightButton,
255 QEvent::MouseButtonRelease);
265 jfloat major, jfloat minor, jfloat rotation, jfloat pressure)
267 QEventPoint::State state = QEventPoint::State::Stationary;
270 state = QEventPoint::State::Pressed;
273 state = QEventPoint::State::Updated;
276 state = QEventPoint::State::Stationary;
279 state = QEventPoint::State::Released;
286 availableSize = platformIntegration
->screen()->availableGeometry().size();
292 qCWarning(lcQpaInputMethods,
"Touch event received for non-existing window %d", winId);
296 QPointF mappedTouchPoint;
297 if (window->handle())
298 mappedTouchPoint = window->handle()->mapToGlobalF(QPointF(x, y));
300 mappedTouchPoint = window->mapToGlobal(QPointF(x, y));
302 QWindowSystemInterface::TouchPoint touchPoint;
304 touchPoint.id = id + 1;
305 touchPoint.pressure = pressure;
306 touchPoint.rotation = qRadiansToDegrees(rotation);
307 touchPoint.normalPosition = QPointF((mappedTouchPoint.x() / availableSize.width()),
308 (mappedTouchPoint.y() / availableSize.height()));
309 touchPoint.state = state;
310 touchPoint.area = QRectF(mappedTouchPoint.x() -
double(minor * 0.5f),
311 mappedTouchPoint.y() -
double(major * 0.5f),
316 if (state == QEventPoint::State::Pressed) {
318 if (inputContext && qGuiApp)
319 QMetaObject::invokeMethod(inputContext,
"touchDown", Q_ARG(
int, mappedTouchPoint.x()), Q_ARG(
int, mappedTouchPoint.y()));
326 if (!platformIntegration)
329 QPointingDevice *touchDevice = platformIntegration->touchDevice();
331 touchDevice =
new QPointingDevice(
"Android touchscreen", 1,
332 QInputDevice::DeviceType::TouchScreen,
333 QPointingDevice::PointerType::Finger,
334 QPointingDevice::Capability::Position
335 | QPointingDevice::Capability::Area
336 | QPointingDevice::Capability::Pressure
337 | QPointingDevice::Capability::NormalizedPosition,
339 QWindowSystemInterface::registerInputDevice(touchDevice);
340 platformIntegration->setTouchDevice(touchDevice);
352 const QPointingDevice *touchDevice = getTouchDevice();
359 QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints);
368 const QPointingDevice *touchDevice = getTouchDevice();
375 QWindowSystemInterface::handleTouchCancelEvent(window, touchDevice);
380#if QT_CONFIG(tabletevent)
388 jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure)
390#if QT_CONFIG(tabletevent)
391 const QPointF localPos(x, y);
392 QWindow *window = windowFromId(winId);
393 const QPointF globalPosF = window && window->handle() ?
394 window->handle()->mapFromGlobalF(localPos) : localPos;
411 Qt::MouseButtons buttons = Qt::NoButton;
416 buttons = Qt::NoButton;
419 if (buttonState == 0)
420 buttons = Qt::LeftButton;
422 buttons = Qt::MouseButtons(buttonState);
426 qCDebug(lcQpaInputMethods) << action << pointerType << buttonState <<
'@' << x << y <<
"pressure" << pressure <<
": buttons" << buttons;
428 QWindowSystemInterface::handleTabletEvent(window, ulong(time),
429 localPos, globalPosF,
int(QInputDevice::DeviceType::Stylus), pointerType,
430 buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier);
437 if (key >= 0x00000007 && key <= 0x00000010)
438 return QKeyCombination::fromCombined(Qt::Key_0 + key - 0x00000007);
441 if (key >= 0x0000001d && key <= 0x00000036)
442 return QKeyCombination::fromCombined(Qt::Key_A + key - 0x0000001d);
445 if (key >= 0x00000083 && key <= 0x0000008e)
446 return QKeyCombination::fromCombined(Qt::Key_F1 + key - 0x00000083);
449 if (key >= 0x00000090 && key <= 0x00000099)
450 return QKeyCombination::fromCombined(Qt::KeypadModifier | Qt::Key_0 + key - 0x00000090);
456 return Qt::Key_unknown;
462 return Qt::Key_Right;
473 return Qt::Key_Hangup;
478 return Qt::Key_Asterisk;
481 return Qt::Key_NumberSign;
493 return Qt::Key_Right;
496 return Qt::Key_Enter;
499 return Qt::Key_VolumeUp;
502 return Qt::Key_VolumeDown;
505 return Qt::Key_PowerOff;
508 return Qt::Key_Camera;
511 return Qt::Key_Clear;
516 return Qt::Key_Comma;
519 return Qt::Key_Period;
527 return Qt::Key_Shift;
533 return Qt::Key_Space;
539 return Qt::Key_Explorer;
542 return Qt::Key_LaunchMail;
545 return Qt::Key_Return;
548 return Qt::Key_Backspace;
551 return Qt::Key_QuoteLeft;
554 return Qt::Key_Minus;
557 return Qt::Key_Equal;
560 return Qt::Key_BracketLeft;
563 return Qt::Key_BracketRight;
566 return Qt::Key_Backslash;
569 return Qt::Key_Semicolon;
572 return Qt::Key_Apostrophe;
575 return Qt::Key_Slash;
584 return QKeyCombination::fromCombined(0);
587 return Qt::Key_CameraFocus;
596 return QKeyCombination::fromCombined(0);
599 return Qt::Key_Search;
602 return Qt::Key_MediaTogglePlayPause;
605 return Qt::Key_MediaStop;
608 return Qt::Key_MediaNext;
611 return Qt::Key_MediaPrevious;
614 return Qt::Key_AudioRewind;
617 return Qt::Key_AudioForward;
620 return Qt::Key_MicMute;
623 return Qt::Key_PageUp;
626 return Qt::Key_PageDown;
629 return QKeyCombination::fromCombined(0);
646 return QKeyCombination::fromCombined(0);
649 return Qt::Key_Escape;
652 return Qt::Key_Delete;
656 return Qt::Key_Control;
659 return Qt::Key_CapsLock;
662 return Qt::Key_ScrollLock;
669 return QKeyCombination::fromCombined(0);
672 return Qt::Key_Print;
675 return Qt::Key_Pause;
684 return Qt::Key_Insert;
687 return Qt::Key_Forward;
690 return Qt::Key_MediaPlay;
693 return Qt::Key_MediaPause;
697 return Qt::Key_Eject;
700 return Qt::Key_MediaRecord;
705 return Qt::Key_NumLock;
710 return Qt::KeypadModifier | Qt::Key_Slash;
713 return Qt::KeypadModifier | Qt::Key_Asterisk;
716 return Qt::KeypadModifier | Qt::Key_Minus;
719 return Qt::KeypadModifier | Qt::Key_Plus;
722 return Qt::KeypadModifier | Qt::Key_Period;
725 return Qt::KeypadModifier | Qt::Key_Comma;
728 return Qt::Key_Enter;
731 return Qt::KeypadModifier | Qt::Key_Equal;
734 return Qt::Key_ParenLeft;
737 return Qt::Key_ParenRight;
740 return Qt::Key_VolumeMute;
746 return Qt::Key_ChannelUp;
749 return Qt::Key_ChannelDown;
752 return Qt::Key_ZoomIn;
755 return Qt::Key_ZoomOut;
759 return QKeyCombination::fromCombined(0);
762 return Qt::Key_Guide;
765 return QKeyCombination::fromCombined(0);
768 return Qt::Key_AddFavorite;
771 return Qt::Key_Subtitle;
774 return Qt::Key_Settings;
782 return QKeyCombination::fromCombined(0);
788 return Qt::Key_Green;
791 return Qt::Key_Yellow;
804 return QKeyCombination::fromCombined(0);
807 return Qt::Key_Calendar;
810 return Qt::Key_Music;
813 return Qt::Key_Calculator;
820 return Qt::Key_KeyboardBrightnessDown;
823 return Qt::Key_KeyboardBrightnessUp;
826 return Qt::Key_AudioCycleTrack;
829 qWarning() <<
"Unhandled key code " << key <<
'!';
830 return QKeyCombination::fromCombined(0);
836 Qt::KeyboardModifiers qmodifiers;
838 if (modifiers & 0x00000001)
839 qmodifiers |= Qt::ShiftModifier;
841 if (modifiers & 0x00000002)
842 qmodifiers |= Qt::AltModifier;
844 if (modifiers & 0x00000004)
845 qmodifiers |= Qt::MetaModifier;
847 if (modifiers & 0x00001000)
848 qmodifiers |= Qt::ControlModifier;
856 return unicode ? QString(QChar(unicode)) : QString();
859 static void keyDown(JNIEnv *,
jobject , jint key, jint unicode, jint modifier, jboolean autoRepeat)
861 QWindowSystemInterface::handleKeyEvent(0,
863 mapAndroidKey(key).toCombined(),
864 mapAndroidModifiers(modifier),
869 static void keyUp(JNIEnv *,
jobject , jint key, jint unicode, jint modifier, jboolean autoRepeat)
871 QWindowSystemInterface::handleKeyEvent(0,
873 mapAndroidKey(key).toCombined(),
874 mapAndroidModifiers(modifier),
885 if (inputContext && qGuiApp) {
886 inputContext->emitInputPanelVisibleChanged();
888 inputContext->emitKeyboardRectChanged();
889 QMetaObject::invokeMethod(inputContext,
"hideSelectionHandles", Qt::QueuedConnection);
892 qCDebug(lcQpaInputMethods) <<
"@@@ KEYBOARDVISIBILITYCHANGED" << inputContext;
897 QRect r = QRect(x, y, w, h);
898 if (r == m_softwareKeyboardRect)
902 if (inputContext && qGuiApp)
903 inputContext->emitKeyboardRectChanged();
905 qCDebug(lcQpaInputMethods) <<
"@@@ KEYBOARDRECTCHANGED" << m_softwareKeyboardRect;
910 qCDebug(lcQpaInputMethods) <<
"@@@ handleLocationChanged" << id << x << y;
912 if (inputContext && qGuiApp)
913 QMetaObject::invokeMethod(inputContext,
"handleLocationChanged", Qt::BlockingQueuedConnection,
914 Q_ARG(
int, id), Q_ARG(
int, x), Q_ARG(
int, y));
920 {
"touchBegin",
"(I)V",(
void*)touchBegin},
921 {
"touchAdd",
"(IIIZIIFFFF)V",(
void*)touchAdd},
922 {
"touchEnd",
"(II)V",(
void*)touchEnd},
923 {
"touchCancel",
"(I)V", (
void *)touchCancel},
924 {
"mouseDown",
"(IIII)V", (
void *)mouseDown},
925 {
"mouseUp",
"(IIII)V", (
void *)mouseUp},
926 {
"mouseMove",
"(IIII)V", (
void *)mouseMove},
927 {
"mouseWheel",
"(IIIFF)V", (
void *)mouseWheel},
928 {
"longPress",
"(III)V", (
void *)longPress},
929 {
"isTabletEventSupported",
"()Z", (
void *)isTabletEventSupported},
930 {
"tabletEvent",
"(IIJIIIFFF)V", (
void *)tabletEvent},
931 {
"keyDown",
"(IIIZ)V", (
void *)keyDown},
932 {
"keyUp",
"(IIIZ)V", (
void *)keyUp},
933 {
"keyboardVisibilityChanged",
"(Z)V", (
void *)keyboardVisibilityChanged},
934 {
"keyboardGeometryChanged",
"(IIII)V", (
void *)keyboardGeometryChanged},
935 {
"handleLocationChanged",
"(III)V", (
void *)handleLocationChanged},
940 if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtInputDelegate>::className(),
942 __android_log_print(ANDROID_LOG_FATAL,
"Qt",
"RegisterNatives failed");
static QAndroidInputContext * androidInputContext()
\inmodule QtCore\reentrant
Combined button and popup list for selecting options.
QBasicMutex * platformInterfaceMutex()
QAndroidPlatformIntegration * androidPlatformIntegration()
AndroidBackendRegister * backendRegister()
QWindow * windowFromId(int windowId)
Q_DECLARE_JNI_CLASS(MotionEvent, "android/view/MotionEvent")