Android: QtActivityDelegateBase listens to focus events from child views

In order to detect gaining/losing and moving focus between windows,
implement GlobalFocusChangeListener for the root View.

Add a surfaceFocusChanged native function in QAndroidPlatformWindow in
order to follow these focus changes.

Task-number: QTBUG-118139
Change-Id: Ia9bf6249c28a420f42793a9829aef31b12757630
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 2c192c6f5fe08b014bfa90ea0452258e649d3183)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Petri Virkkunen 2024-01-25 14:11:22 +02:00 committed by Tinja Paavoseppä
parent 1712c4eeca
commit 17e546ac7f
6 changed files with 45 additions and 1 deletions

View File

@ -138,6 +138,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
r.width(), kbHeight);
return true;
});
registerGlobalFocusChangeListener(m_layout);
m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_layout));
}

View File

@ -133,6 +133,26 @@ abstract class QtActivityDelegateBase
setUpLayout();
}
protected void registerGlobalFocusChangeListener(final View view) {
view.getViewTreeObserver().addOnGlobalFocusChangeListener(this::onGlobalFocusChanged);
}
private void onGlobalFocusChanged(View oldFocus, View newFocus) {
if (newFocus instanceof QtEditText) {
final QtWindow newWindow = (QtWindow) newFocus.getParent();
QtWindow.windowFocusChanged(true, newWindow.getId());
m_inputDelegate.setFocusedView((QtEditText) newFocus);
} else {
int id = -1;
if (oldFocus instanceof QtEditText) {
final QtWindow oldWindow = (QtWindow) oldFocus.getParent();
id = oldWindow.getId();
}
QtWindow.windowFocusChanged(false, id);
m_inputDelegate.setFocusedView(null);
}
}
public void hideSplashScreen()
{
hideSplashScreen(0);

View File

@ -135,6 +135,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase implements QtNative.AppS
void setView(QtView view) {
m_view = view;
registerGlobalFocusChangeListener(m_view);
}
public void setRootWindowRef(long ref) {

View File

@ -24,6 +24,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
private final QtEditText m_editText;
private static native void setSurface(int windowId, Surface surface);
static native void windowFocusChanged(boolean hasFocus, int id);
public QtWindow(Context context, QtWindow parentWindow)
{
@ -31,6 +32,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
setId(View.generateViewId());
m_editText = new QtEditText(context);
setParent(parentWindow);
setFocusableInTouchMode(true);
QtNative.runAction(() -> {
m_gestureDetector =

View File

@ -342,10 +342,28 @@ void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint window
}
}
void QAndroidPlatformWindow::windowFocusChanged(JNIEnv *env, jobject object,
jboolean focus, jint windowId)
{
Q_UNUSED(env)
Q_UNUSED(object)
QWindow* window = QtAndroid::windowFromId(windowId);
Q_ASSERT_X(window, "QAndroidPlatformWindow", "windowFocusChanged event window should exist");
if (focus) {
QWindowSystemInterface::handleFocusWindowChanged(window);
} else if (!focus && window == qGuiApp->focusWindow()) {
// Clear focus if current window has lost focus
QWindowSystemInterface::handleFocusWindowChanged(nullptr);
}
}
bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env)
{
if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(),
{Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow)})) {
{
Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow),
Q_JNI_NATIVE_SCOPED_METHOD(windowFocusChanged, QAndroidPlatformWindow)
})) {
qCCritical(lcQpaWindow) << "RegisterNatives failed for"
<< QtJniTypes::Traits<QtJniTypes::QtWindow>::className();
return false;

View File

@ -93,6 +93,8 @@ protected:
private:
static void setSurface(JNIEnv *env, jobject obj, jint windowId, QtJniTypes::Surface surface);
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(setSurface)
static void windowFocusChanged(JNIEnv *env, jobject object, jboolean focus, jint windowId);
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(windowFocusChanged)
};
QT_END_NAMESPACE