Accessibility for Android
This enables both modes for TalkBack, explore-by-touch and the normal swiping mode. It is partially inspired by the BarGraphView example of the Google/Android Eyes-Free project. Note that for any accessibility to work you'll need a device with api level 16 at least. Using reflection we should be able to dynamically pick up the classes if we have the high enough api level. Change-Id: I11b93bead451483782a1711434d45c8f9a35996f Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
parent
59b6a67b94
commit
3abecf2ee9
2
src/android/accessibility/accessibility.pro
Normal file
2
src/android/accessibility/accessibility.pro
Normal file
@ -0,0 +1,2 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = jar
|
7
src/android/accessibility/jar/AndroidManifest.xml
Normal file
7
src/android/accessibility/jar/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
package="org.qtproject.qt5.android.accessibility">
|
||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||
</manifest>
|
3
src/android/accessibility/jar/bundledjar.pro
Normal file
3
src/android/accessibility/jar/bundledjar.pro
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = QtAndroidAccessibility-bundled
|
||||
CONFIG += bundled_jar_file
|
||||
include(jar.pri)
|
2
src/android/accessibility/jar/distributedjar.pro
Normal file
2
src/android/accessibility/jar/distributedjar.pro
Normal file
@ -0,0 +1,2 @@
|
||||
TARGET = QtAndroidAccessibility
|
||||
include(jar.pri)
|
14
src/android/accessibility/jar/jar.pri
Normal file
14
src/android/accessibility/jar/jar.pri
Normal file
@ -0,0 +1,14 @@
|
||||
CONFIG += java
|
||||
DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
|
||||
API_VERSION = android-16
|
||||
|
||||
PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/accessibility
|
||||
|
||||
JAVACLASSPATH += $$PWD/src/
|
||||
JAVASOURCES += \
|
||||
$$PATHPREFIX/QtAccessibilityDelegate.java \
|
||||
$$PATHPREFIX/QtNativeAccessibility.java
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_PREFIX]/jar
|
||||
INSTALLS += target
|
2
src/android/accessibility/jar/jar.pro
Normal file
2
src/android/accessibility/jar/jar.pro
Normal file
@ -0,0 +1,2 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS += bundledjar.pro distributedjar.pro
|
@ -0,0 +1,343 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Android port of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
package org.qtproject.qt5.android.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import android.view.accessibility.*;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
||||
{
|
||||
private static final String TAG = "Qt A11Y";
|
||||
|
||||
// Qt uses the upper half of the unsiged integers
|
||||
// all low positive ints should be fine.
|
||||
public static final int INVALID_ID = 333; // half evil
|
||||
|
||||
// The platform might ask for the class implementing the "view".
|
||||
// Pretend to be an inner class of the QtSurface.
|
||||
private static final String DEFAULT_CLASS_NAME = "$VirtualChild";
|
||||
|
||||
private final View m_view;
|
||||
private final AccessibilityManager m_manager;
|
||||
|
||||
// The accessible object that currently has the "accessibility focus"
|
||||
// usually indicated by a yellow rectangle on screen.
|
||||
private int m_focusedVirtualViewId = INVALID_ID;
|
||||
// When exploring the screen by touch, the item "hovered" by the finger.
|
||||
private int m_hoveredVirtualViewId = INVALID_ID;
|
||||
|
||||
// Cache coordinates of the view to know the global offset
|
||||
// this is because the Android platform window does not take
|
||||
// the offset of the view on screen into account (eg status bar on top)
|
||||
private final int[] m_globalOffset = new int[2];
|
||||
|
||||
public QtAccessibilityDelegate(View host)
|
||||
{
|
||||
m_view = host;
|
||||
m_manager = (AccessibilityManager) host.getContext()
|
||||
.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
|
||||
// Enable Qt Accessibility so that notifications are enabled
|
||||
QtNativeAccessibility.setActive(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeProvider getAccessibilityNodeProvider(View host)
|
||||
{
|
||||
return m_nodeProvider;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (!m_manager.isTouchExplorationEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int virtualViewId = QtNativeAccessibility.hitTest(event.getX(), event.getY());
|
||||
if (virtualViewId == INVALID_ID) {
|
||||
virtualViewId = View.NO_ID;
|
||||
}
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
setHoveredVirtualViewId(virtualViewId);
|
||||
break;
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
setHoveredVirtualViewId(virtualViewId);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean sendEventForVirtualViewId(int virtualViewId, int eventType)
|
||||
{
|
||||
if ((virtualViewId == INVALID_ID) || !m_manager.isEnabled()) {
|
||||
Log.w(TAG, "sendEventForVirtualViewId for invalid view");
|
||||
return false;
|
||||
}
|
||||
|
||||
final ViewGroup group = (ViewGroup) m_view.getParent();
|
||||
if (group == null) {
|
||||
Log.w(TAG, "Could not send AccessibilityEvent because group was null. This should really not happen.");
|
||||
return false;
|
||||
}
|
||||
|
||||
final AccessibilityEvent event;
|
||||
event = getEventForVirtualViewId(virtualViewId, eventType);
|
||||
return group.requestSendAccessibilityEvent(m_view, event);
|
||||
}
|
||||
|
||||
public void invalidateVirtualViewId(int virtualViewId)
|
||||
{
|
||||
sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
}
|
||||
|
||||
private void setHoveredVirtualViewId(int virtualViewId)
|
||||
{
|
||||
if (m_hoveredVirtualViewId == virtualViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int previousVirtualViewId = m_hoveredVirtualViewId;
|
||||
m_hoveredVirtualViewId = virtualViewId;
|
||||
sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
|
||||
sendEventForVirtualViewId(previousVirtualViewId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
|
||||
}
|
||||
|
||||
private AccessibilityEvent getEventForVirtualViewId(int virtualViewId, int eventType)
|
||||
{
|
||||
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
|
||||
|
||||
event.setEnabled(true);
|
||||
event.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
|
||||
|
||||
event.setContentDescription(QtNativeAccessibility.descriptionForAccessibleObject(virtualViewId));
|
||||
if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription()))
|
||||
Log.w(TAG, "AccessibilityEvent with empty description");
|
||||
|
||||
event.setPackageName(m_view.getContext().getPackageName());
|
||||
event.setSource(m_view, virtualViewId);
|
||||
return event;
|
||||
}
|
||||
|
||||
private void dumpNodes(int parentId)
|
||||
{
|
||||
Log.i(TAG, "A11Y hierarchy: " + parentId + " parent: " + QtNativeAccessibility.parentId(parentId));
|
||||
Log.i(TAG, " desc: " + QtNativeAccessibility.descriptionForAccessibleObject(parentId) + " rect: " + QtNativeAccessibility.screenRect(parentId));
|
||||
Log.i(TAG, " NODE: " + getNodeForVirtualViewId(parentId));
|
||||
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(parentId);
|
||||
for (int i = 0; i < ids.length; ++i) {
|
||||
Log.i(TAG, parentId + " has child: " + ids[i]);
|
||||
dumpNodes(ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo getNodeForView()
|
||||
{
|
||||
// Since we don't want the parent to be focusable, but we can't remove
|
||||
// actions from a node, copy over the necessary fields.
|
||||
final AccessibilityNodeInfo result = AccessibilityNodeInfo.obtain(m_view);
|
||||
final AccessibilityNodeInfo source = AccessibilityNodeInfo.obtain(m_view);
|
||||
m_view.onInitializeAccessibilityNodeInfo(source);
|
||||
|
||||
// Get the actual position on screen, taking the status bar into account.
|
||||
m_view.getLocationOnScreen(m_globalOffset);
|
||||
final int offsetX = m_globalOffset[0];
|
||||
final int offsetY = m_globalOffset[1];
|
||||
|
||||
// Copy over parent and screen bounds.
|
||||
final Rect m_tempParentRect = new Rect();
|
||||
source.getBoundsInParent(m_tempParentRect);
|
||||
result.setBoundsInParent(m_tempParentRect);
|
||||
|
||||
final Rect m_tempScreenRect = new Rect();
|
||||
source.getBoundsInScreen(m_tempScreenRect);
|
||||
m_tempScreenRect.offset(offsetX, offsetY);
|
||||
result.setBoundsInScreen(m_tempScreenRect);
|
||||
|
||||
// Set up the parent view, if applicable.
|
||||
final ViewParent parent = m_view.getParent();
|
||||
if (parent instanceof View) {
|
||||
result.setParent((View) parent);
|
||||
}
|
||||
|
||||
result.setVisibleToUser(source.isVisibleToUser());
|
||||
result.setPackageName(source.getPackageName());
|
||||
result.setClassName(source.getClassName());
|
||||
|
||||
// Spit out the entire hierarchy for debugging purposes
|
||||
// dumpNodes(-1);
|
||||
|
||||
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(-1);
|
||||
for (int i = 0; i < ids.length; ++i)
|
||||
result.addChild(m_view, ids[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo getNodeForVirtualViewId(int virtualViewId)
|
||||
{
|
||||
final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain();
|
||||
|
||||
node.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
|
||||
node.setPackageName(m_view.getContext().getPackageName());
|
||||
|
||||
node.setSource(m_view, virtualViewId);
|
||||
QtNativeAccessibility.populateNode(virtualViewId, node);
|
||||
if (TextUtils.isEmpty(node.getText()) && TextUtils.isEmpty(node.getContentDescription()))
|
||||
Log.w(TAG, "AccessibilityNodeInfo with empty contentDescription: " + virtualViewId);
|
||||
|
||||
int parentId = QtNativeAccessibility.parentId(virtualViewId);
|
||||
node.setParent(m_view, parentId);
|
||||
|
||||
Rect screenRect = QtNativeAccessibility.screenRect(virtualViewId);
|
||||
final int offsetX = m_globalOffset[0];
|
||||
final int offsetY = m_globalOffset[1];
|
||||
screenRect.offset(offsetX, offsetY);
|
||||
node.setBoundsInScreen(screenRect);
|
||||
|
||||
Rect rectInParent = screenRect;
|
||||
Rect parentScreenRect = QtNativeAccessibility.screenRect(parentId);
|
||||
rectInParent.offset(-parentScreenRect.left, -parentScreenRect.top);
|
||||
node.setBoundsInParent(rectInParent);
|
||||
|
||||
// Manage internal accessibility focus state.
|
||||
if (m_focusedVirtualViewId == virtualViewId) {
|
||||
node.setAccessibilityFocused(true);
|
||||
node.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
|
||||
} else {
|
||||
node.setAccessibilityFocused(false);
|
||||
node.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
|
||||
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(virtualViewId);
|
||||
for (int i = 0; i < ids.length; ++i)
|
||||
node.addChild(m_view, ids[i]);
|
||||
return node;
|
||||
}
|
||||
|
||||
private AccessibilityNodeProvider m_nodeProvider = new AccessibilityNodeProvider()
|
||||
{
|
||||
@Override
|
||||
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId)
|
||||
{
|
||||
if (virtualViewId == View.NO_ID) {
|
||||
return getNodeForView();
|
||||
}
|
||||
return getNodeForVirtualViewId(virtualViewId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAction(int virtualViewId, int action, Bundle arguments)
|
||||
{
|
||||
boolean handled = false;
|
||||
//Log.i(TAG, "PERFORM ACTION: " + action + " on " + virtualViewId);
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
|
||||
// Only handle the FOCUS action if it's placing focus on
|
||||
// a different view that was previously focused.
|
||||
if (m_focusedVirtualViewId != virtualViewId) {
|
||||
m_focusedVirtualViewId = virtualViewId;
|
||||
m_view.invalidate();
|
||||
sendEventForVirtualViewId(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
|
||||
if (m_focusedVirtualViewId == virtualViewId) {
|
||||
m_focusedVirtualViewId = INVALID_ID;
|
||||
}
|
||||
// Since we're managing focus at the parent level, we are
|
||||
// likely to receive a FOCUS action before a CLEAR_FOCUS
|
||||
// action. We'll give the benefit of the doubt to the
|
||||
// framework and always handle FOCUS_CLEARED.
|
||||
m_view.invalidate();
|
||||
sendEventForVirtualViewId(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
||||
handled = true;
|
||||
break;
|
||||
default:
|
||||
// Let the node provider handle focus for the view node.
|
||||
if (virtualViewId == View.NO_ID) {
|
||||
return m_view.performAccessibilityAction(action, arguments);
|
||||
}
|
||||
}
|
||||
handled |= performActionForVirtualViewId(virtualViewId, action, arguments);
|
||||
|
||||
return handled;
|
||||
}
|
||||
};
|
||||
|
||||
protected boolean performActionForVirtualViewId(int virtualViewId, int action, Bundle arguments)
|
||||
{
|
||||
// Log.i(TAG, "ACTION " + action + " on " + virtualViewId);
|
||||
// dumpNodes(virtualViewId);
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_CLICK:
|
||||
boolean success = QtNativeAccessibility.clickAction(virtualViewId);
|
||||
if (success)
|
||||
sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Android port of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
package org.qtproject.qt5.android.accessibility;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
class QtNativeAccessibility
|
||||
{
|
||||
static native void setActive(boolean enable);
|
||||
static native int[] childIdListForAccessibleObject(int objectId);
|
||||
static native int parentId(int objectId);
|
||||
static native String descriptionForAccessibleObject(int objectId);
|
||||
static native Rect screenRect(int objectId);
|
||||
static native int hitTest(float x, float y);
|
||||
static native boolean clickAction(int objectId);
|
||||
|
||||
static native void populateNode(int objectId, AccessibilityNodeInfo node);
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = jar java
|
||||
SUBDIRS = jar java accessibility
|
||||
|
@ -55,17 +55,23 @@ import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
||||
{
|
||||
private Bitmap m_bitmap = null;
|
||||
private boolean m_started = false;
|
||||
private boolean m_usesGL = false;
|
||||
private GestureDetector m_gestureDetector;
|
||||
private Object m_accessibilityDelegate = null;
|
||||
|
||||
public QtSurface(Context context, int id)
|
||||
{
|
||||
super(context);
|
||||
setFocusable(true);
|
||||
setFocusable(false);
|
||||
setFocusableInTouchMode(false);
|
||||
|
||||
getHolder().addCallback(this);
|
||||
getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
|
||||
setId(id);
|
||||
@ -107,6 +113,44 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
||||
|
||||
if (m_usesGL)
|
||||
holder.setFormat(PixelFormat.RGBA_8888);
|
||||
|
||||
|
||||
// Initialize Accessibility
|
||||
// The accessibility code depends on android API level 16, so dynamically resolve it
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -17,12 +17,14 @@ win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
|
||||
QMAKE_DOCS = $$PWD/doc/qtcore.qdocconf
|
||||
|
||||
ANDROID_JAR_DEPENDENCIES = \
|
||||
jar/QtAndroid.jar
|
||||
jar/QtAndroid.jar \
|
||||
jar/QtAndroidAccessibility.jar
|
||||
ANDROID_LIB_DEPENDENCIES = \
|
||||
plugins/platforms/android/libqtforandroid.so \
|
||||
libs/libgnustl_shared.so
|
||||
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
|
||||
jar/QtAndroid-bundled.jar
|
||||
jar/QtAndroid-bundled.jar \
|
||||
jar/QtAndroidAccessibility-bundled.jar
|
||||
|
||||
load(qt_module)
|
||||
|
||||
|
@ -60,7 +60,9 @@ QAccessible::Id QAccessibleCache::acquireId() const
|
||||
static QAccessible::Id lastUsedId = FirstId;
|
||||
|
||||
while (idToInterface.contains(lastUsedId)) {
|
||||
if (lastUsedId == UINT_MAX) // (wrap back when when we reach UINT_MAX)
|
||||
// (wrap back when when we reach UINT_MAX - 1)
|
||||
// -1 because on Android -1 is taken for the "View" so just avoid it completely for consistency
|
||||
if (lastUsedId == UINT_MAX - 1)
|
||||
lastUsedId = FirstId;
|
||||
else
|
||||
++lastUsedId;
|
||||
|
260
src/plugins/platforms/android/src/androidjniaccessibility.cpp
Normal file
260
src/plugins/platforms/android/src/androidjniaccessibility.cpp
Normal file
@ -0,0 +1,260 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "androidjniaccessibility.h"
|
||||
#include "androidjnimain.h"
|
||||
#include "qandroidplatformintegration.h"
|
||||
#include "qpa/qplatformaccessibility.h"
|
||||
#include "qguiapplication.h"
|
||||
#include "qwindow.h"
|
||||
#include "qrect.h"
|
||||
#include "private/qaccessible2_p.h"
|
||||
|
||||
#include "qdebug.h"
|
||||
|
||||
static const char m_qtTag[] = "QtA11y";
|
||||
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
|
||||
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
|
||||
|
||||
namespace QtAndroidAccessibility
|
||||
{
|
||||
static void setActive(JNIEnv */*env*/, jobject /*thiz*/, jboolean active)
|
||||
{
|
||||
QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration();
|
||||
if (platformIntegration)
|
||||
platformIntegration->accessibility()->setActive(active);
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_WARN, m_qtTag, "Could not activate platform accessibility.");
|
||||
}
|
||||
|
||||
QAccessibleInterface *interfaceFromId(jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = 0;
|
||||
if (objectId == -1) {
|
||||
QWindow *win = qApp->focusWindow();
|
||||
if (win)
|
||||
iface = win->accessibleRoot();
|
||||
} else {
|
||||
iface = QAccessible::accessibleInterface(objectId);
|
||||
}
|
||||
return iface;
|
||||
}
|
||||
|
||||
static jintArray childIdListForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface) {
|
||||
jintArray jArray = env->NewIntArray(jsize(iface->childCount()));
|
||||
for (int i = 0; i < iface->childCount(); ++i) {
|
||||
QAccessibleInterface *child = iface->child(i);
|
||||
if (child) {
|
||||
QAccessible::Id ifaceId = QAccessible::uniqueId(child);
|
||||
jint jid = ifaceId;
|
||||
env->SetIntArrayRegion(jArray, i, 1, &jid);
|
||||
}
|
||||
}
|
||||
return jArray;
|
||||
}
|
||||
|
||||
return env->NewIntArray(jsize(0));
|
||||
}
|
||||
|
||||
static jint parentId(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface) {
|
||||
QAccessibleInterface *parent = iface->parent();
|
||||
if (parent) {
|
||||
if (parent->role() == QAccessible::Application)
|
||||
return -1;
|
||||
return QAccessible::uniqueId(parent);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jobject screenRect(JNIEnv *env, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QRect rect;
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface && iface->isValid()) {
|
||||
rect = iface->rect();
|
||||
}
|
||||
|
||||
jclass rectClass = env->FindClass("android/graphics/Rect");
|
||||
jmethodID ctor = env->GetMethodID(rectClass, "<init>", "(IIII)V");
|
||||
jobject jrect = env->NewObject(rectClass, ctor, rect.left(), rect.top(), rect.right(), rect.bottom());
|
||||
return jrect;
|
||||
}
|
||||
|
||||
static jint hitTest(JNIEnv */*env*/, jobject /*thiz*/, jfloat x, jfloat y)
|
||||
{
|
||||
QAccessibleInterface *root = interfaceFromId(-1);
|
||||
if (root) {
|
||||
QAccessibleInterface *child = root->childAt((int)x, (int)y);
|
||||
QAccessibleInterface *lastChild = 0;
|
||||
while (child && (child != lastChild)) {
|
||||
lastChild = child;
|
||||
child = child->childAt((int)x, (int)y);
|
||||
}
|
||||
if (lastChild)
|
||||
return QAccessible::uniqueId(lastChild);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jboolean clickAction(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
// qDebug() << "A11Y: CLICK: " << objectId;
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface && iface->actionInterface()) {
|
||||
if (iface->actionInterface()->actionNames().contains(QAccessibleActionInterface::pressAction()))
|
||||
iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
|
||||
else
|
||||
iface->actionInterface()->doAction(QAccessibleActionInterface::toggleAction());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
|
||||
clazz = env->FindClass(CLASS_NAME); \
|
||||
if (!clazz) { \
|
||||
__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_classErrorMsg, CLASS_NAME); \
|
||||
return JNI_FALSE; \
|
||||
}
|
||||
|
||||
//__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE);
|
||||
|
||||
#define CALL_METHOD(OBJECT, METHOD_NAME, METHOD_SIGNATURE, VALUE) \
|
||||
{ \
|
||||
jclass clazz = env->GetObjectClass(OBJECT); \
|
||||
jmethodID method = env->GetMethodID(clazz, METHOD_NAME, METHOD_SIGNATURE); \
|
||||
if (!method) { \
|
||||
__android_log_print(ANDROID_LOG_WARN, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \
|
||||
return; \
|
||||
} \
|
||||
env->CallVoidMethod(OBJECT, method, VALUE); \
|
||||
}
|
||||
|
||||
|
||||
static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QString desc;
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface && iface->isValid()) {
|
||||
desc = iface->text(QAccessible::Name);
|
||||
if (desc.isEmpty())
|
||||
desc = iface->text(QAccessible::Description);
|
||||
|
||||
desc += QChar(' ') + QString::fromUtf8(qAccessibleRoleString(iface->role()));
|
||||
}
|
||||
|
||||
jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
|
||||
return jdesc;
|
||||
}
|
||||
|
||||
static void populateNode(JNIEnv *env, jobject /*thiz*/, jint objectId, jobject node)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (!iface || !iface->isValid()) {
|
||||
__android_log_print(ANDROID_LOG_WARN, m_qtTag, "Accessibility: populateNode for Invalid ID");
|
||||
return;
|
||||
}
|
||||
QAccessible::State state = iface->state();
|
||||
|
||||
QString desc = iface->text(QAccessible::Name);
|
||||
if (desc.isEmpty())
|
||||
desc = iface->text(QAccessible::Description);
|
||||
if ((iface->role() != QAccessible::NoRole) &&
|
||||
(iface->role() != QAccessible::Client) &&
|
||||
(iface->role() != QAccessible::Pane)) {
|
||||
desc += QChar(' ') + QString::fromUtf8(qAccessibleRoleString(iface->role()));
|
||||
}
|
||||
|
||||
CALL_METHOD(node, "setEnabled", "(Z)V", !state.disabled)
|
||||
//CALL_METHOD(node, "setFocusable", "(Z)V", state.focusable)
|
||||
CALL_METHOD(node, "setFocusable", "(Z)V", true)
|
||||
//CALL_METHOD(node, "setFocused", "(Z)V", state.focused)
|
||||
CALL_METHOD(node, "setCheckable", "(Z)V", state.checkable)
|
||||
CALL_METHOD(node, "setChecked", "(Z)V", state.checked)
|
||||
CALL_METHOD(node, "setVisibleToUser", "(Z)V", !state.invisible)
|
||||
|
||||
if (iface->actionInterface()) {
|
||||
QStringList actions = iface->actionInterface()->actionNames();
|
||||
bool clickable = actions.contains(QAccessibleActionInterface::pressAction());
|
||||
bool toggle = actions.contains(QAccessibleActionInterface::toggleAction());
|
||||
if (clickable || toggle) {
|
||||
CALL_METHOD(node, "setClickable", "(Z)V", clickable)
|
||||
CALL_METHOD(node, "addAction", "(I)V", 16) // ACTION_CLICK defined in AccessibilityNodeInfo
|
||||
}
|
||||
}
|
||||
|
||||
jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
|
||||
//CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc)
|
||||
CALL_METHOD(node, "setContentDescription", "(Ljava/lang/CharSequence;)V", jdesc)
|
||||
}
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
{"setActive","(Z)V",(void*)setActive},
|
||||
{"childIdListForAccessibleObject", "(I)[I", (jintArray)childIdListForAccessibleObject},
|
||||
{"parentId", "(I)I", (void*)parentId},
|
||||
{"descriptionForAccessibleObject", "(I)Ljava/lang/String;", (jstring)descriptionForAccessibleObject},
|
||||
{"screenRect", "(I)Landroid/graphics/Rect;", (jobject)screenRect},
|
||||
{"hitTest", "(FF)I", (void*)hitTest},
|
||||
{"populateNode", "(ILandroid/view/accessibility/AccessibilityNodeInfo;)V", (void*)populateNode},
|
||||
{"clickAction", "(I)Z", (void*)clickAction},
|
||||
};
|
||||
|
||||
bool registerNatives(JNIEnv *env)
|
||||
{
|
||||
jclass clazz;
|
||||
FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/accessibility/QtNativeAccessibility");
|
||||
jclass appClass = static_cast<jclass>(env->NewGlobalRef(clazz));
|
||||
|
||||
if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
|
||||
__android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
51
src/plugins/platforms/android/src/androidjniaccessibility.h
Normal file
51
src/plugins/platforms/android/src/androidjniaccessibility.h
Normal file
@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ANDROIDJNIACCESSIBILITY_H
|
||||
#define ANDROIDJNIACCESSIBILITY_H
|
||||
#include <jni.h>
|
||||
|
||||
namespace QtAndroidAccessibility
|
||||
{
|
||||
bool registerNatives(JNIEnv *env);
|
||||
}
|
||||
|
||||
#endif // ANDROIDJNIINPUT_H
|
@ -55,6 +55,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "androidjnimain.h"
|
||||
#include "androidjniaccessibility.h"
|
||||
#include "androidjniinput.h"
|
||||
#include "androidjniclipboard.h"
|
||||
#include "androidjnimenu.h"
|
||||
@ -793,7 +794,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|
||||
if (!registerNatives(env)
|
||||
|| !QtAndroidInput::registerNatives(env)
|
||||
|| !QtAndroidClipboard::registerNatives(env)
|
||||
|| !QtAndroidMenu::registerNatives(env)) {
|
||||
|| !QtAndroidMenu::registerNatives(env)
|
||||
|| !QtAndroidAccessibility::registerNatives(env)) {
|
||||
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
|
||||
return -1;
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "qandroidplatformaccessibility.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QAndroidPlatformAccessibility::QAndroidPlatformAccessibility()
|
||||
{}
|
||||
|
||||
QAndroidPlatformAccessibility::~QAndroidPlatformAccessibility()
|
||||
{}
|
||||
|
||||
void QAndroidPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent */*event*/)
|
||||
{
|
||||
// FIXME send events
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef QANDROIDPLATFORMACCESSIBILITY_H
|
||||
#define QANDROIDPLATFORMACCESSIBILITY_H
|
||||
|
||||
#include <qpa/qplatformaccessibility.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformAccessibility: public QPlatformAccessibility
|
||||
{
|
||||
public:
|
||||
QAndroidPlatformAccessibility();
|
||||
~QAndroidPlatformAccessibility();
|
||||
|
||||
virtual void notifyAccessibilityUpdate(QAccessibleEvent *event);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -50,6 +50,7 @@
|
||||
#include "qandroidplatformservices.h"
|
||||
#include "qandroidplatformfontdatabase.h"
|
||||
#include "qandroidplatformclipboard.h"
|
||||
#include "qandroidplatformaccessibility.h"
|
||||
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
|
||||
|
||||
#ifndef ANDROID_PLUGIN_OPENGL
|
||||
@ -87,6 +88,9 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA
|
||||
|
||||
QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶mList)
|
||||
: m_touchDevice(0)
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
, m_accessibility(0)
|
||||
#endif
|
||||
{
|
||||
Q_UNUSED(paramList);
|
||||
|
||||
@ -259,6 +263,15 @@ void QAndroidPlatformIntegration::setDefaultDesktopSize(int gw, int gh)
|
||||
m_defaultGeometryHeight = gh;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const
|
||||
{
|
||||
if (!m_accessibility)
|
||||
m_accessibility = new QAndroidPlatformAccessibility();
|
||||
return m_accessibility;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ANDROID_PLUGIN_OPENGL
|
||||
void QAndroidPlatformIntegration::setDesktopSize(int width, int height)
|
||||
|
@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QDesktopWidget;
|
||||
class QAndroidPlatformServices;
|
||||
class QAndroidSystemLocale;
|
||||
class QPlatformAccessibility;
|
||||
|
||||
#ifdef ANDROID_PLUGIN_OPENGL
|
||||
class QAndroidOpenGLPlatformWindow;
|
||||
@ -113,6 +114,10 @@ public:
|
||||
QPlatformNativeInterface *nativeInterface() const;
|
||||
QPlatformServices *services() const;
|
||||
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
virtual QPlatformAccessibility *accessibility() const;
|
||||
#endif
|
||||
|
||||
QVariant styleHint(StyleHint hint) const;
|
||||
|
||||
QStringList themeNames() const;
|
||||
@ -156,6 +161,9 @@ private:
|
||||
QAndroidPlatformServices *m_androidPlatformServices;
|
||||
QPlatformClipboard *m_androidPlatformClipboard;
|
||||
QAndroidSystemLocale *m_androidSystemLocale;
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
mutable QPlatformAccessibility *m_accessibility;
|
||||
#endif
|
||||
|
||||
mutable QAndroidInputContext m_platformInputContext;
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ INCLUDEPATH += $$PWD/../../../../3rdparty/android/src
|
||||
|
||||
SOURCES += $$PWD/androidplatformplugin.cpp \
|
||||
$$PWD/androidjnimain.cpp \
|
||||
$$PWD/androidjniaccessibility.cpp \
|
||||
$$PWD/androidjniinput.cpp \
|
||||
$$PWD/androidjnimenu.cpp \
|
||||
$$PWD/androidjniclipboard.cpp \
|
||||
@ -18,6 +19,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
|
||||
$$PWD/qandroidplatformservices.cpp \
|
||||
$$PWD/qandroidassetsfileenginehandler.cpp \
|
||||
$$PWD/qandroidinputcontext.cpp \
|
||||
$$PWD/qandroidplatformaccessibility.cpp \
|
||||
$$PWD/qandroidplatformfontdatabase.cpp \
|
||||
$$PWD/qandroidplatformclipboard.cpp \
|
||||
$$PWD/qandroidplatformtheme.cpp \
|
||||
@ -29,12 +31,14 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
|
||||
|
||||
HEADERS += $$PWD/qandroidplatformintegration.h \
|
||||
$$PWD/androidjnimain.h \
|
||||
$$PWD/androidjniaccessibility.h \
|
||||
$$PWD/androidjniinput.h \
|
||||
$$PWD/androidjnimenu.h \
|
||||
$$PWD/androidjniclipboard.h \
|
||||
$$PWD/qandroidplatformservices.h \
|
||||
$$PWD/qandroidassetsfileenginehandler.h \
|
||||
$$PWD/qandroidinputcontext.h \
|
||||
$$PWD/qandroidplatformaccessibility.h \
|
||||
$$PWD/qandroidplatformfontdatabase.h \
|
||||
$$PWD/qandroidplatformclipboard.h \
|
||||
$$PWD/qandroidplatformtheme.h \
|
||||
|
Loading…
Reference in New Issue
Block a user