Android: Fix hover-event handling.

The accessibility delegate needs to intercept the hover events before
the view gets them, but since the dispatchHoverEvent() method was added
in API level 14 and we build with API level < 14, we can't call the
super class implementation (e.g., when the event isn't handled by
the accessibility delegate). In the previous implementation we where
trying to solve this by using the reflection API, but that does not
provide a solution to call the super class implementation
(Note: It's possible with JDK 7 or newer), so the code would call
itself recursively and we would eventually get a stack overflow
exception.

This change uses the OnHoverListener class to intercept the hover
events, this way we avoid "overriding" the dispatchHoverEvent() method
in QtSurface and therefore avoid the problem it causes.

Task-number: QTBUG-38905
Change-Id: I8b3cbad718d8524042397bb877e39e3005bfb4ce
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
This commit is contained in:
Christian Strømme 2014-06-16 13:35:21 +02:00 committed by Christian Stromme
parent 8f96ce3733
commit 50cf698b76
2 changed files with 12 additions and 19 deletions

View File

@ -53,6 +53,7 @@ import android.text.TextUtils;
import android.view.accessibility.*;
import android.view.MotionEvent;
import android.view.View.OnHoverListener;
import android.content.Context;
@ -85,9 +86,19 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
// the offset of the view on screen into account (eg status bar on top)
private final int[] m_globalOffset = new int[2];
private class HoverEventListener implements View.OnHoverListener
{
@Override
public boolean onHover(View v, MotionEvent event)
{
return dispatchHoverEvent(event);
}
}
public QtAccessibilityDelegate(View host)
{
m_view = host;
m_view.setOnHoverListener(new HoverEventListener());
m_manager = (AccessibilityManager) host.getContext()
.getSystemService(Context.ACCESSIBILITY_SERVICE);
@ -103,7 +114,7 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
// For "explore by touch" we need all movement events here first
// (user moves finger over screen to discover items on screen).
public boolean dispatchHoverEvent(MotionEvent event)
private boolean dispatchHoverEvent(MotionEvent event)
{
if (!m_manager.isTouchExplorationEnabled()) {
return false;

View File

@ -110,24 +110,6 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
}
}
public boolean dispatchHoverEvent(MotionEvent event) {
// Always attempt to dispatch hover events to accessibility first.
if (m_accessibilityDelegate != null) {
try {
Method dispHoverA11y = m_accessibilityDelegate.getClass().getMethod("dispatchHoverEvent", MotionEvent.class);
boolean ret = (Boolean) dispHoverA11y.invoke(m_accessibilityDelegate, event);
if (ret)
return true;
SurfaceView view = (SurfaceView) this;
Method dispHoverView = view.getClass().getMethod("dispatchHoverEvent", MotionEvent.class);
return (Boolean) dispHoverView.invoke(view, event);
} catch (Exception e) {
Log.w("Qt A11y", "EXCEPTION in dispatchHoverEvent for Accessibility: " + e);
}
}
return false;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{