Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.15.2
-
Chromebook
-
-
8d8cbe87e (dev), e259e5b9c (6.7)
Description
Mouse events generated on android always specify the Qt::LeftButton as the button generating the event. Qt::RightButton, ... events are never generated.
The root cause is that QtNative.java does not pass the pressed buttons to mouseUp/Down in androidjniinput.cpp.
Note that the Android ACTION_UP/DOWN events do not specify the button that generated the event, but do specify the current state of the all the buttons (see MotionEvent.getButtonState(). However, by keeping track of the previous button state ourself, we can generate the correct mouse events for the newly pressed/released events.
Possible implementation
androidjniinput.cpp:
static Qt::MouseButtons m_buttons = Qt::NoButton; ... static Qt::MouseButtons mapAndroidButtons(jint buttons) { Qt::MouseButtons qbuttons; if (buttons & 0x00000001) // BUTTON_PRIMARY qbuttons |= Qt::LeftButton; if (buttons & 0x00000002) // BUTTON_SECONDARY qbuttons |= Qt::RightButton; if (buttons & 0x00000004) // BUTTON_TERTIARY qbuttons |= Qt::MiddleButton; if (buttons & 0x00000008) // BUTTON_BACK qbuttons |= Qt::BackButton; if (buttons & 0x00000010) // BUTTON_FORWARD qbuttons |= Qt::ForwardButton; if (buttons & 0x00000020) // BUTTON_STYLUS_PRIMARY qbuttons |= Qt::LeftButton; if (buttons & 0x00000040) // BUTTON_STYLUS_SECONDARY qbuttons |= Qt::RightButton; return qbuttons; } static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y, jint buttonState) { if (m_ignoreMouseEvents) return; Qt::MouseButtons qbuttons = mapAndroidButtons(buttonState); Qt::MouseButtons changedButtons = qbuttons & ~m_buttons; // extract (newly) pressed button if (changedButtons == Qt::NoButton) return; m_buttons = qbuttons; QPoint globalPos(x,y); QWindow *tlw = topLevelWindowAt(globalPos); m_mouseGrabber = tlw; QPoint localPos = tlw ? (globalPos - tlw->position()) : globalPos; static_assert (sizeof(changedButtons) <= sizeof(uint), "Unexpected Qt::MouseButtons size"); for (uint button = 0x1; (uint) changedButtons >= button; button <<= 1) { if (changedButtons & button) QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, qbuttons, (Qt::MouseButton) button, QEvent::MouseButtonPress); } } static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y, jint buttonState) { Qt::MouseButtons qbuttons = mapAndroidButtons(buttonState); Qt::MouseButtons changedButtons = m_buttons & ~qbuttons; // extract (newly) released button if (changedButtons == Qt::NoButton) return; m_buttons = qbuttons; QPoint globalPos(x,y); QWindow *tlw = m_mouseGrabber.data(); if (!tlw) tlw = topLevelWindowAt(globalPos); QPoint localPos = tlw ? (globalPos -tlw->position()) : globalPos; static_assert (sizeof(changedButtons) <= sizeof(uint), "Unexpected Qt::MouseButtons size"); for (uint button = 0x1; (uint) changedButtons >= button; button <<= 1) { if (changedButtons & button) QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, qbuttons, (Qt::MouseButton) button, QEvent::MouseButtonRelease); } m_ignoreMouseEvents = false; m_mouseGrabber = 0; } static JNINativeMethod methods[] = { ... {"mouseDown", "(IIII)V", (void *)mouseDown}, {"mouseUp", "(IIII)V", (void *)mouseUp}, ... };
QtNative.java
static public boolean sendMouseEvent(MotionEvent event, int id) { switch (event.getActionMasked()) { case MotionEvent.ACTION_UP: mouseUp(id, (int) event.getX(), (int) event.getY(), event.getButtonState()); break; case MotionEvent.ACTION_DOWN: mouseDown(id, (int) event.getX(), (int) event.getY(), event.getButtonState()); m_oldx = (int) event.getX(); m_oldy = (int) event.getY(); break; ... } ... // pointer methods public static native void mouseDown(int winId, int x, int y, int buttonState); public static native void mouseUp(int winId, int x, int y, int buttonState); ...
Attachments
Issue Links
- resulted in
-
QTBUG-130297 Cannot click buttons in ChromeOS
- Reported