diff --git a/src/android/jar/src/org/qtproject/qt/android/EditPopupMenu.java b/src/android/jar/src/org/qtproject/qt/android/EditPopupMenu.java index e9838bc5bee..ca79bfd3804 100644 --- a/src/android/jar/src/org/qtproject/qt/android/EditPopupMenu.java +++ b/src/android/jar/src/org/qtproject/qt/android/EditPopupMenu.java @@ -7,6 +7,7 @@ package org.qtproject.qt.android; import android.app.Activity; import android.content.Context; import android.graphics.Point; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -16,22 +17,23 @@ import android.widget.PopupWindow; class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayoutChangeListener, EditContextView.OnClickListener { - private final View m_layout; private final EditContextView m_view; + private final QtEditText m_editText; + private PopupWindow m_popup = null; private final Activity m_activity; private int m_posX; private int m_posY; private int m_buttons; - private QtEditText m_currentEditText = null; // TODO, get rid of this reference - EditPopupMenu(Activity activity, View layout) + EditPopupMenu(QtEditText editText) { - m_activity = activity; - m_view = new EditContextView(activity, this); + m_activity = (Activity) editText.getContext(); + m_view = new EditContextView(m_activity, this); m_view.addOnLayoutChangeListener(this); - m_layout = layout; + m_editText = editText; + m_editText.getViewTreeObserver().addOnPreDrawListener(this); } private void initOverlay() @@ -39,19 +41,16 @@ class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayout if (m_popup != null) return; - Context context = m_layout.getContext(); - m_popup = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle); + m_popup = new PopupWindow(m_activity, null, android.R.attr.textSelectHandleWindowStyle); m_popup.setSplitTouchEnabled(true); m_popup.setClippingEnabled(false); m_popup.setContentView(m_view); m_popup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); m_popup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); - - m_layout.getViewTreeObserver().addOnPreDrawListener(this); } // Show the handle at a given position (or move it if it is already shown) - void setPosition(final int x, final int y, final int buttons, final QtEditText editText) + void setPosition(final int x, final int y, final int buttons) { initOverlay(); @@ -59,7 +58,7 @@ class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayout Point viewSize = m_view.getCalculatedSize(); final int[] layoutLocation = new int[2]; - m_layout.getLocationOnScreen(layoutLocation); + m_editText.getLocationOnScreen(layoutLocation); // These values are used for handling split screen case final int[] activityLocation = new int[2]; @@ -73,15 +72,21 @@ class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayout x2 -= viewSize.x / 2 ; y2 -= viewSize.y; - if (y2 < 0 && editText != null) { - y2 = editText.getSelectionHandleBottom(); + if (y2 < 0) + y2 = m_editText.getSelectionHandleBottom(); + + if (y2 <= 0) { + try { + QtLayout parentLayout = (QtLayout) m_editText.getParent(); + parentLayout.requestLayout(); + } catch (ClassCastException e) { + Log.w(QtNative.QtTAG, "QtEditText " + m_editText + " parent is not a QtLayout, " + + "requestLayout() skipped"); + } } - if (y2 <= 0) - m_layout.requestLayout(); - - if (m_layout.getWidth() < x + viewSize.x / 2) - x2 = m_layout.getWidth() - viewSize.x; + if (m_editText.getWidth() < x + viewSize.x / 2) + x2 = m_editText.getWidth() - viewSize.x; if (x2 < 0) x2 = 0; @@ -89,12 +94,11 @@ class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayout if (m_popup.isShowing()) m_popup.update(x2, y2, -1, -1); else - m_popup.showAtLocation(m_layout, 0, x2, y2); + m_popup.showAtLocation(m_editText, 0, x2, y2); m_posX = x; m_posY = y; m_buttons = buttons; - m_currentEditText = editText; } void hide() { @@ -110,7 +114,7 @@ class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayout // For example if the keyboard appears. // Adjust the position of the handle accordingly if (m_popup != null && m_popup.isShowing()) - setPosition(m_posX, m_posY, m_buttons, m_currentEditText); + setPosition(m_posX, m_posY, m_buttons); return true; } @@ -121,7 +125,7 @@ class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayout { if ((right - left != oldRight - oldLeft || bottom - top != oldBottom - oldTop) && m_popup != null && m_popup.isShowing()) - setPosition(m_posX, m_posY, m_buttons, m_currentEditText); + setPosition(m_posX, m_posY, m_buttons); } @Override diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java index 9dacc4b3e70..7491dc5c90d 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -140,7 +140,6 @@ class QtActivityDelegate extends QtActivityDelegateBase r.width(), kbHeight); return true; }); - m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_layout)); } @Override diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEditText.java b/src/android/jar/src/org/qtproject/qt/android/QtEditText.java index 144ad2e8784..d00fc76d860 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEditText.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEditText.java @@ -61,12 +61,15 @@ class QtEditText extends View private CursorHandle m_leftSelectionHandle; private CursorHandle m_rightSelectionHandle; + final private EditPopupMenu m_editPopupMenu; + QtEditText(Context context, QtInputConnectionListener listener) { super(context); setFocusable(true); setFocusableInTouchMode(true); m_qtInputConnectionListener = listener; + m_editPopupMenu = new EditPopupMenu(this); } private void setImeOptions(int imeOptions) @@ -299,8 +302,19 @@ class QtEditText extends View m_cursorHandle.hide(); m_cursorHandle = null; } + mode |= CursorHandleShowEdit; break; } + + if (!QtClipboardManager.hasClipboardText(getContext())) + editButtons &= ~EditContextView.PASTE_BUTTON; + + final boolean setEditPopupPosition = (mode & QtEditText.CursorHandleShowEdit) == + QtEditText.CursorHandleShowEdit && editButtons != 0; + if (setEditPopupPosition) + m_editPopupMenu.setPosition(editX, editY, editButtons); + else + m_editPopupMenu.hide(); } private boolean isDisablePredictiveTextWorkaround(int inputHints) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java index fb996e1c654..3da520c31b3 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java @@ -105,7 +105,6 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase BackendRegister.unregisterBackend(QtMenuInterface.class); BackendRegister.unregisterBackend(QtInputInterface.class); } - updateInputDelegate(); } } @@ -151,21 +150,9 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase public void setView(QtView view) { m_view = view; - updateInputDelegate(); } // QtEmbeddedViewInterface implementation end - private void updateInputDelegate() { - // If the QtView has attached to the window before Qt libs have been loaded, - // the input delegate will be null - if (m_inputDelegate == null) - return; - if (m_view == null) - m_inputDelegate.setEditPopupMenu(null); - else - m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_view)); - } - private void createRootWindow() { if (m_view != null && !m_windowLoaded) { QtView.createRootWindow(m_view, m_view.getLeft(), m_view.getTop(), m_view.getWidth(), diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java index 980bc7da47b..3075d49ee03 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java @@ -52,8 +52,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt private int m_landscapeKeyboardHeight = 0; private int m_probeKeyboardHeightDelayMs = 50; - private EditPopupMenu m_editPopupMenu; - private int m_softInputMode = 0; private static Boolean m_tabletEventSupported = null; @@ -149,12 +147,13 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt mode is one of QAndroidInputContext::CursorHandleShowMode */ @Override - public void updateHandles(Activity activity, QtLayout layout, int mode, - int editX, int editY, int editButtons, + public void updateHandles(int mode, int editX, int editY, int editButtons, int x1, int y1, int x2, int y2, boolean rtl) { - QtNative.runAction(() -> updateHandleImpl(activity, layout, mode, editX, editY, editButtons, - x1, y1, x2, y2, rtl)); + QtNative.runAction(() -> { + if (m_currentEditText != null) + m_currentEditText.updateHandles(mode, editX, editY, editButtons, x1, y1, x2, y2, rtl); + }); } @Override @@ -247,11 +246,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt return m_currentEditText; } - void setEditPopupMenu(EditPopupMenu editPopupMenu) - { - m_editPopupMenu = editPopupMenu; - } - private void keyboardVisibilityUpdated(boolean visibility) { m_isKeyboardHidingAnimationOngoing = false; @@ -352,37 +346,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt }, m_probeKeyboardHeightDelayMs); } - private void updateHandleImpl(Activity activity, QtLayout layout, int mode, - int editX, int editY, int editButtons, - int x1, int y1, int x2, int y2, boolean rtl) - { - if (m_currentEditText != null) - m_currentEditText.updateHandles(mode, editX, editY, editButtons, x1, y1, x2, y2, rtl); - - switch (mode & 0xff) - { - case QtEditText.CursorHandleNotShown: - if (m_editPopupMenu != null) - m_editPopupMenu.hide(); - break; - case QtEditText.CursorHandleShowSelection: - mode |= QtEditText.CursorHandleShowEdit; - break; - } - - if (!QtClipboardManager.hasClipboardText(activity)) - editButtons &= ~EditContextView.PASTE_BUTTON; - - if (m_editPopupMenu != null) { - if ((mode & QtEditText.CursorHandleShowEdit) == QtEditText.CursorHandleShowEdit && - editButtons != 0) { - m_editPopupMenu.setPosition(editX, editY, editButtons, m_currentEditText); - } else { - m_editPopupMenu.hide(); - } - } - } - boolean onKeyDown(int keyCode, KeyEvent event) { m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java index af90e230ab1..afe57e51e77 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java @@ -15,7 +15,7 @@ interface QtInputInterface { void hideSoftwareKeyboard(); boolean isSoftwareKeyboardVisible(); int getSelectionHandleWidth(); - void updateHandles(Activity activity, QtLayout layout, int mode, int editX, int editY, - int editButtons, int x1, int y1, int x2, int y2, boolean rtl); + void updateHandles(int mode, int editX, int editY, int editButtons, + int x1, int y1, int x2, int y2, boolean rtl); QtInputConnection.QtInputConnectionListener getInputConnectionListener(); } diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 732791bc8a0..a0faedcc5b2 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -91,8 +91,7 @@ namespace QtAndroidInput { AndroidBackendRegister *reg = QtAndroid::backendRegister(); reg->callInterface( - "updateHandles", QtAndroidPrivate::activity(), - qtLayout().object(), mode, editMenuPos.x(), editMenuPos.y(), + "updateHandles", mode, editMenuPos.x(), editMenuPos.y(), editButtons, cursor.x(), cursor.y(), anchor.x(), anchor.y(), rtl); }