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)
157 for (uint buttonInt = 0x1;
static_cast<uint>(eventButtons) >= buttonInt; buttonInt <<= 1) {
158 const auto button =
static_cast<Qt::MouseButton>(buttonInt);
159 if (eventButtons.testFlag(button)) {
160 QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos,
161 qtButtons, button, type);
166 static void mouseDown(JNIEnv *,
jobject , jint winId, jint x, jint y, jint mouseButtonState)
171 const QPoint localPos(x,y);
172 QWindow *window = windowFromId(winId);
174 const QPoint globalPos = window && window->handle() ?
175 window->handle()->mapToGlobal(localPos) : localPos;
176 sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonPress);
179 static void mouseUp(JNIEnv *,
jobject , jint winId, jint x, jint y, jint mouseButtonState)
181 const QPoint localPos(x,y);
182 QWindow *window = m_mouseGrabber.data();
184 window = windowFromId(winId);
186 const QPoint globalPos = window && window->handle() ?
187 window->handle()->mapToGlobal(localPos) : localPos;
189 sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonRelease);
194 static void mouseMove(JNIEnv *,
jobject , jint winId, jint x, jint y, jint mouseButtonState)
199 const QPoint localPos(x,y);
200 QWindow *window = m_mouseGrabber.data();
202 window = windowFromId(winId);
203 const QPoint globalPos = window && window->handle() ?
204 window->handle()->mapToGlobal(localPos) : localPos;
205 const Qt::MouseButtons qtButtons = toMouseButtons(mouseButtonState);
207 QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
208 qtButtons, Qt::NoButton, QEvent::MouseMove);
211 static void mouseWheel(JNIEnv *,
jobject , jint winId, jint x, jint y, jfloat hdelta, jfloat vdelta)
216 const QPoint localPos(x,y);
217 QWindow *window = m_mouseGrabber.data();
219 window = windowFromId(winId);
220 const QPoint globalPos = window && window->handle() ?
221 window->handle()->mapToGlobal(localPos) : localPos;
222 const QPoint angleDelta(hdelta * 120, vdelta * 120);
224 QWindowSystemInterface::handleWheelEvent(window,
235 const QPoint localPos(x,y);
236 QWindow *window = windowFromId(winId);
237 const QPoint globalPos = window && window->handle() ?
238 window->handle()->mapToGlobal(localPos) : localPos;
240 if (inputContext && qGuiApp)
241 QMetaObject::invokeMethod(inputContext,
"longPress", Q_ARG(
int, globalPos.x()), Q_ARG(
int, globalPos.y()));
244 static bool rightMouseFromLongPress = qEnvironmentVariableIntValue(
"QT_ANDROID_ENABLE_RIGHT_MOUSE_FROM_LONG_PRESS");
245 if (!rightMouseFromLongPress)
251 if (!m_mouseGrabber) {
252 QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
253 Qt::MouseButtons(Qt::RightButton), Qt::RightButton,
254 QEvent::MouseButtonPress);
255 QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
256 Qt::MouseButtons(Qt::NoButton), Qt::RightButton,
257 QEvent::MouseButtonRelease);
267 jfloat major, jfloat minor, jfloat rotation, jfloat pressure)
269 QEventPoint::State state = QEventPoint::State::Stationary;
272 state = QEventPoint::State::Pressed;
275 state = QEventPoint::State::Updated;
278 state = QEventPoint::State::Stationary;
281 state = QEventPoint::State::Released;
288 availableSize = platformIntegration
->screen()->availableGeometry().size();
294 qCWarning(lcQpaInputMethods,
"Touch event received for non-existing window %d", winId);
298 QPointF mappedTouchPoint;
299 if (window->handle())
300 mappedTouchPoint = window->handle()->mapToGlobalF(QPointF(x, y));
302 mappedTouchPoint = window->mapToGlobal(QPointF(x, y));
304 QWindowSystemInterface::TouchPoint touchPoint;
306 touchPoint.id = id + 1;
307 touchPoint.pressure = pressure;
308 touchPoint.rotation = qRadiansToDegrees(rotation);
309 touchPoint.normalPosition = QPointF((mappedTouchPoint.x() / availableSize.width()),
310 (mappedTouchPoint.y() / availableSize.height()));
311 touchPoint.state = state;
312 touchPoint.area = QRectF(mappedTouchPoint.x() -
double(minor * 0.5f),
313 mappedTouchPoint.y() -
double(major * 0.5f),
318 if (state == QEventPoint::State::Pressed) {
320 if (inputContext && qGuiApp)
321 QMetaObject::invokeMethod(inputContext,
"touchDown", Q_ARG(
int, mappedTouchPoint.x()), Q_ARG(
int, mappedTouchPoint.y()));
328 if (!platformIntegration)
331 QPointingDevice *touchDevice = platformIntegration->touchDevice();
333 touchDevice =
new QPointingDevice(
"Android touchscreen", 1,
334 QInputDevice::DeviceType::TouchScreen,
335 QPointingDevice::PointerType::Finger,
336 QPointingDevice::Capability::Position
337 | QPointingDevice::Capability::Area
338 | QPointingDevice::Capability::Pressure
339 | QPointingDevice::Capability::NormalizedPosition,
341 QWindowSystemInterface::registerInputDevice(touchDevice);
342 platformIntegration->setTouchDevice(touchDevice);
354 const QPointingDevice *touchDevice = getTouchDevice();
361 QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints);
370 const QPointingDevice *touchDevice = getTouchDevice();
377 QWindowSystemInterface::handleTouchCancelEvent(window, touchDevice);
382#if QT_CONFIG(tabletevent)
390 jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure)
392#if QT_CONFIG(tabletevent)
393 const QPointF localPos(x, y);
394 QWindow *window = windowFromId(winId);
395 const QPointF globalPosF = window && window->handle() ?
396 window->handle()->mapFromGlobalF(localPos) : localPos;
413 Qt::MouseButtons buttons = Qt::NoButton;
418 buttons = Qt::NoButton;
421 if (buttonState == 0)
422 buttons = Qt::LeftButton;
424 buttons = Qt::MouseButtons(buttonState);
428 qCDebug(lcQpaInputMethods) << action << pointerType << buttonState <<
'@' << x << y <<
"pressure" << pressure <<
": buttons" << buttons;
430 QWindowSystemInterface::handleTabletEvent(window, ulong(time),
431 localPos, globalPosF,
int(QInputDevice::DeviceType::Stylus), pointerType,
432 buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier);
439 if (key >= 0x00000007 && key <= 0x00000010)
440 return QKeyCombination::fromCombined(Qt::Key_0 + key - 0x00000007);
443 if (key >= 0x0000001d && key <= 0x00000036)
444 return QKeyCombination::fromCombined(Qt::Key_A + key - 0x0000001d);
447 if (key >= 0x00000083 && key <= 0x0000008e)
448 return QKeyCombination::fromCombined(Qt::Key_F1 + key - 0x00000083);
451 if (key >= 0x00000090 && key <= 0x00000099)
452 return QKeyCombination::fromCombined(Qt::KeypadModifier | Qt::Key_0 + key - 0x00000090);
458 return Qt::Key_unknown;
464 return Qt::Key_Right;
475 return Qt::Key_Hangup;
480 return Qt::Key_Asterisk;
483 return Qt::Key_NumberSign;
495 return Qt::Key_Right;
498 return Qt::Key_Enter;
501 return Qt::Key_VolumeUp;
504 return Qt::Key_VolumeDown;
507 return Qt::Key_PowerOff;
510 return Qt::Key_Camera;
513 return Qt::Key_Clear;
518 return Qt::Key_Comma;
521 return Qt::Key_Period;
529 return Qt::Key_Shift;
535 return Qt::Key_Space;
541 return Qt::Key_Explorer;
544 return Qt::Key_LaunchMail;
547 return Qt::Key_Return;
550 return Qt::Key_Backspace;
553 return Qt::Key_QuoteLeft;
556 return Qt::Key_Minus;
559 return Qt::Key_Equal;
562 return Qt::Key_BracketLeft;
565 return Qt::Key_BracketRight;
568 return Qt::Key_Backslash;
571 return Qt::Key_Semicolon;
574 return Qt::Key_Apostrophe;
577 return Qt::Key_Slash;
586 return QKeyCombination::fromCombined(0);
589 return Qt::Key_CameraFocus;
598 return QKeyCombination::fromCombined(0);
601 return Qt::Key_Search;
604 return Qt::Key_MediaTogglePlayPause;
607 return Qt::Key_MediaStop;
610 return Qt::Key_MediaNext;
613 return Qt::Key_MediaPrevious;
616 return Qt::Key_AudioRewind;
619 return Qt::Key_AudioForward;
622 return Qt::Key_MicMute;
625 return Qt::Key_PageUp;
628 return Qt::Key_PageDown;
631 return QKeyCombination::fromCombined(0);
648 return QKeyCombination::fromCombined(0);
651 return Qt::Key_Escape;
654 return Qt::Key_Delete;
658 return Qt::Key_Control;
661 return Qt::Key_CapsLock;
664 return Qt::Key_ScrollLock;
671 return QKeyCombination::fromCombined(0);
674 return Qt::Key_Print;
677 return Qt::Key_Pause;
686 return Qt::Key_Insert;
689 return Qt::Key_Forward;
692 return Qt::Key_MediaPlay;
695 return Qt::Key_MediaPause;
699 return Qt::Key_Eject;
702 return Qt::Key_MediaRecord;
707 return Qt::Key_NumLock;
712 return Qt::KeypadModifier | Qt::Key_Slash;
715 return Qt::KeypadModifier | Qt::Key_Asterisk;
718 return Qt::KeypadModifier | Qt::Key_Minus;
721 return Qt::KeypadModifier | Qt::Key_Plus;
724 return Qt::KeypadModifier | Qt::Key_Period;
727 return Qt::KeypadModifier | Qt::Key_Comma;
730 return Qt::Key_Enter;
733 return Qt::KeypadModifier | Qt::Key_Equal;
736 return Qt::Key_ParenLeft;
739 return Qt::Key_ParenRight;
742 return Qt::Key_VolumeMute;
748 return Qt::Key_ChannelUp;
751 return Qt::Key_ChannelDown;
754 return Qt::Key_ZoomIn;
757 return Qt::Key_ZoomOut;
761 return QKeyCombination::fromCombined(0);
764 return Qt::Key_Guide;
767 return QKeyCombination::fromCombined(0);
770 return Qt::Key_AddFavorite;
773 return Qt::Key_Subtitle;
776 return Qt::Key_Settings;
784 return QKeyCombination::fromCombined(0);
790 return Qt::Key_Green;
793 return Qt::Key_Yellow;
806 return QKeyCombination::fromCombined(0);
809 return Qt::Key_Calendar;
812 return Qt::Key_Music;
815 return Qt::Key_Calculator;
822 return Qt::Key_KeyboardBrightnessDown;
825 return Qt::Key_KeyboardBrightnessUp;
828 return Qt::Key_AudioCycleTrack;
831 qWarning() <<
"Unhandled key code " << key <<
'!';
832 return QKeyCombination::fromCombined(0);
838 Qt::KeyboardModifiers qmodifiers;
840 if (modifiers & 0x00000001)
841 qmodifiers |= Qt::ShiftModifier;
843 if (modifiers & 0x00000002)
844 qmodifiers |= Qt::AltModifier;
846 if (modifiers & 0x00000004)
847 qmodifiers |= Qt::MetaModifier;
849 if (modifiers & 0x00001000)
850 qmodifiers |= Qt::ControlModifier;
858 return unicode ? QString(QChar(unicode)) : QString();
861 static void keyDown(JNIEnv *,
jobject , jint key, jint unicode, jint modifier, jboolean autoRepeat)
863 QWindowSystemInterface::handleKeyEvent(0,
865 mapAndroidKey(key).toCombined(),
866 mapAndroidModifiers(modifier),
871 static void keyUp(JNIEnv *,
jobject , jint key, jint unicode, jint modifier, jboolean autoRepeat)
873 QWindowSystemInterface::handleKeyEvent(0,
875 mapAndroidKey(key).toCombined(),
876 mapAndroidModifiers(modifier),
887 if (inputContext && qGuiApp) {
888 inputContext->emitInputPanelVisibleChanged();
890 inputContext->emitKeyboardRectChanged();
891 QMetaObject::invokeMethod(inputContext,
"hideSelectionHandles", Qt::QueuedConnection);
894 qCDebug(lcQpaInputMethods) <<
"@@@ KEYBOARDVISIBILITYCHANGED" << inputContext;
899 QRect r = QRect(x, y, w, h);
900 if (r == m_softwareKeyboardRect)
904 if (inputContext && qGuiApp)
905 inputContext->emitKeyboardRectChanged();
907 qCDebug(lcQpaInputMethods) <<
"@@@ KEYBOARDRECTCHANGED" << m_softwareKeyboardRect;
912 qCDebug(lcQpaInputMethods) <<
"@@@ handleLocationChanged" << id << x << y;
914 if (inputContext && qGuiApp)
915 QMetaObject::invokeMethod(inputContext,
"handleLocationChanged", Qt::BlockingQueuedConnection,
916 Q_ARG(
int, id), Q_ARG(
int, x), Q_ARG(
int, y));
922 {
"touchBegin",
"(I)V",(
void*)touchBegin},
923 {
"touchAdd",
"(IIIZIIFFFF)V",(
void*)touchAdd},
924 {
"touchEnd",
"(II)V",(
void*)touchEnd},
925 {
"touchCancel",
"(I)V", (
void *)touchCancel},
926 {
"mouseDown",
"(IIII)V", (
void *)mouseDown},
927 {
"mouseUp",
"(IIII)V", (
void *)mouseUp},
928 {
"mouseMove",
"(IIII)V", (
void *)mouseMove},
929 {
"mouseWheel",
"(IIIFF)V", (
void *)mouseWheel},
930 {
"longPress",
"(III)V", (
void *)longPress},
931 {
"isTabletEventSupported",
"()Z", (
void *)isTabletEventSupported},
932 {
"tabletEvent",
"(IIJIIIFFF)V", (
void *)tabletEvent},
933 {
"keyDown",
"(IIIZ)V", (
void *)keyDown},
934 {
"keyUp",
"(IIIZ)V", (
void *)keyUp},
935 {
"keyboardVisibilityChanged",
"(Z)V", (
void *)keyboardVisibilityChanged},
936 {
"keyboardGeometryChanged",
"(IIII)V", (
void *)keyboardGeometryChanged},
937 {
"handleLocationChanged",
"(III)V", (
void *)handleLocationChanged},
942 if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtInputDelegate>::className(),
944 __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")