From e682ea6f782d3bb4caa4f2bd0e3be47cbe064f4f Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Wed, 5 Nov 2014 11:44:00 +0100 Subject: Draw the accessibility focus rectangle properly Previously, the accessibility focus rectangle was only visible when it overlapped with the m_editText View of QtActivityDelegate. The reason for this is not completely verified, but this is the most likely reason: * The SurfaceView and QtLayout (ViewGroup) does not do any drawing themselves. Due to this their default value of the View::willNotDraw property is true. Because of this Android might assume there is no content for the focus indicator to surround. (This was verified with setting the willNotDraw property to false on the accessibility view); * Another possible reason could be that overlays does not work for SurfaceView. It is documented that overlays does not work for SurfaceViews, so therefore it tried to use the overlay of another view. For some reason it picked the m_editText overlay instead of the QtLayout overlay. See here about overlay: http://developer.android.com/reference/android/view/View.html#getOverlay() The solution is to add another View that covers the whole screen, which will be used solely by android to draw the accessibility focus indicator. In addition, we change the QtAccessibilityDelegate to no longer have the SurfaceView as a host, but have the m_accView as a host (the host can be freely changed, since all accessibility nodes are virtualized through the delegate anyway) For the record, this will be the current ordering of views in QtLayout: (back-to-front order): Qty Default Qty * Surface View(s) >= 1 1 * Accessibility View == 1 1 * Native View(s) >= 0 1 * m_editText View == 1 1 where the m_editText migth be interleaved among the Native Views. [ChangeLog][Android][Accessibility] Fixed an issue where the accessibility focus rectangle was not drawn properly Task-number: QTBUG-38869 Change-Id: I64d6b6ec45b27d0d93ac9dd840de764c18c55d04 Reviewed-by: Christian Stromme --- .../qtproject/qt5/android/QtActivityDelegate.java | 45 ++++++++++++++++++++-- .../src/org/qtproject/qt5/android/QtSurface.java | 20 ---------- 2 files changed, 42 insertions(+), 23 deletions(-) (limited to 'src/android') diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 3af8a7aa5d..97a632972b 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -80,6 +80,7 @@ import java.io.File; import java.io.FileWriter; import java.io.InputStreamReader; import java.io.IOException; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; @@ -126,6 +127,7 @@ public class QtActivityDelegate private boolean m_quitApp = true; private Process m_debuggerProcess = null; // debugger process private View m_dummyView = null; + private View m_accView = null; private boolean m_keyboardIsVisible = false; public boolean m_backKeyPressedSent = false; private long m_showHideTimeStamp = System.nanoTime(); @@ -1178,10 +1180,48 @@ public class QtActivityDelegate // Native views are always inserted in the end of the stack (i.e., on top). // All other views are stacked based on the order they are created. - final int index = getSurfaceCount(); - m_layout.addView(surface, index); + final int surfaceCount = getSurfaceCount(); + m_layout.addView(surface, surfaceCount); m_surfaces.put(id, surface); + + // Initialize Accessibility + // The accessibility code depends on android API level 16, so dynamically resolve it + if (android.os.Build.VERSION.SDK_INT >= 16) { + if (m_accView == null) { + try { + View accView = new View(m_activity); + accView.setId(View.NO_ID); + + // ### Keep this for debugging for a while. It allows us to visually see that our View + // ### is on top of the surface(s) + // ColorDrawable color = new ColorDrawable(0x80ff8080); //0xAARRGGBB + // accView.setBackground(color); + + final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate"; + Class qtDelegateClass = Class.forName(a11yDelegateClassName); + Constructor constructor = qtDelegateClass.getConstructor(Class.forName("android.view.View")); + Object accessibilityDelegate = constructor.newInstance(accView); + + Class a11yDelegateClass = Class.forName("android.view.View$AccessibilityDelegate"); + Method setDelegateMethod = accView.getClass().getMethod("setAccessibilityDelegate", a11yDelegateClass); + setDelegateMethod.invoke(accView, accessibilityDelegate); + + // if all is fine, add it to the layout + m_layout.addView(accView, surfaceCount + 1, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + + m_accView = accView; + } catch (ClassNotFoundException e) { + // Class not found is fine since we are compatible with Android API < 16, but the function will + // only be available with that API level. + } catch (Exception e) { + // Unknown exception means something went wrong. + Log.w("Qt A11y", "Unknown exception: " + e.toString()); + } + } + } + } public void setSurfaceGeometry(int id, int x, int y, int w, int h) { @@ -1225,7 +1265,6 @@ public class QtActivityDelegate return m_surfaces.size(); } - public void bringChildToFront(int id) { View view = m_surfaces.get(id); diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java index ca3f20f11b..34fc31b222 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java @@ -88,26 +88,6 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback public void surfaceCreated(SurfaceHolder holder) { QtNative.setSurface(getId(), holder.getSurface(), getWidth(), getHeight()); - // Initialize Accessibility - // The accessibility code depends on android API level 16, so dynamically resolve it - if (android.os.Build.VERSION.SDK_INT >= 16) { - try { - final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate"; - Class qtDelegateClass = Class.forName(a11yDelegateClassName); - Constructor constructor = qtDelegateClass.getConstructor(Class.forName("android.view.View")); - m_accessibilityDelegate = constructor.newInstance(this); - - Class a11yDelegateClass = Class.forName("android.view.View$AccessibilityDelegate"); - Method setDelegateMethod = this.getClass().getMethod("setAccessibilityDelegate", a11yDelegateClass); - setDelegateMethod.invoke(this, m_accessibilityDelegate); - } catch (ClassNotFoundException e) { - // Class not found is fine since we are compatible with Android API < 16, but the function will - // only be available with that API level. - } catch (Exception e) { - // Unknown exception means something went wrong. - Log.w("Qt A11y", "Unknown exception: " + e.toString()); - } - } } @Override -- cgit v1.2.3