mirror of
https://gitee.com/shuto-github/phonegap-mobile-accessibility.git
synced 2026-04-19 00:01:32 +08:00
Add preliminary support for Windows 8.1
This commit is contained in:
+19
@@ -62,4 +62,23 @@
|
|||||||
<source-file src="src/android/com/phonegap/plugin/mobileaccessibility/KitKatMobileAccessibilityHelper.java" target-dir="src/com/phonegap/plugin/mobileaccessibility" />
|
<source-file src="src/android/com/phonegap/plugin/mobileaccessibility/KitKatMobileAccessibilityHelper.java" target-dir="src/com/phonegap/plugin/mobileaccessibility" />
|
||||||
<asset src="www/android" target="plugins/com.phonegap.plugin.mobile-accessibility/android" />
|
<asset src="www/android" target="plugins/com.phonegap.plugin.mobile-accessibility/android" />
|
||||||
</platform>
|
</platform>
|
||||||
|
|
||||||
|
<!-- windows -->
|
||||||
|
<platform name="windows">
|
||||||
|
<js-module src="src/windows/mobile-accessibility-proxy.js" name="MobileAccessibilityProxy">
|
||||||
|
<merges target="" />
|
||||||
|
</js-module>
|
||||||
|
|
||||||
|
<config-file target="package.phone.appxmanifest" parent="/Package/Capabilities">
|
||||||
|
<DeviceCapability Name="microphone" />
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<config-file target="package.windows.appxmanifest" parent="/Package/Capabilities">
|
||||||
|
<DeviceCapability Name="microphone" />
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<config-file target="package.windows80.appxmanifest" parent="/Package/Capabilities">
|
||||||
|
<DeviceCapability Name="microphone" />
|
||||||
|
</config-file>
|
||||||
|
</platform>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*global Windows:true*/
|
||||||
|
|
||||||
|
var cordova = require('cordova'),
|
||||||
|
accessibilitySettings,
|
||||||
|
uiSettings,
|
||||||
|
callbackContext,
|
||||||
|
fontScale = 1,
|
||||||
|
styleElement,
|
||||||
|
bodyStyleDeclaration,
|
||||||
|
audio,
|
||||||
|
synth;
|
||||||
|
|
||||||
|
function getAccessibilitySettings() {
|
||||||
|
if (!accessibilitySettings) {
|
||||||
|
accessibilitySettings = new Windows.UI.ViewManagement.AccessibilitySettings();
|
||||||
|
}
|
||||||
|
return accessibilitySettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUISettings() {
|
||||||
|
if (!uiSettings) {
|
||||||
|
uiSettings = new Windows.UI.ViewManagement.UISettings();
|
||||||
|
}
|
||||||
|
return uiSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFontScale() {
|
||||||
|
if (!uiSettings) {
|
||||||
|
uiSettings = getUISettings();
|
||||||
|
}
|
||||||
|
var scale = uiSettings.textScaleFactor;
|
||||||
|
// console.log("getFontScale " + scale);
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTextZoom() {
|
||||||
|
var zoom = Math.round(fontScale * 100);
|
||||||
|
// console.log("getTextZoom " + zoom);
|
||||||
|
return zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createStyleElement() {
|
||||||
|
if (!styleElement) {
|
||||||
|
styleElement = document.createElement("style");
|
||||||
|
styleElement.type = "text/css";
|
||||||
|
document.head.appendChild(styleElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTextZoom(zoom) {
|
||||||
|
// console.log("setTextZoom " + zoom);
|
||||||
|
fontScale = zoom/100;
|
||||||
|
|
||||||
|
createStyleElement();
|
||||||
|
|
||||||
|
if (bodyStyleDeclaration) {
|
||||||
|
styleElement.removeChild(bodyStyleDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyStyleDeclaration = document.createTextNode("body {-ms-text-size-adjust: " + zoom + "%}");
|
||||||
|
|
||||||
|
styleElement.appendChild(bodyStyleDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onHighContrastChanged(event) {
|
||||||
|
cordova.fireWindowEvent(MobileAccessibilityNotifications.HIGH_CONTRAST_CHANGED,
|
||||||
|
getMobileAccessibilityStatus());
|
||||||
|
sendMobileAccessibilityStatusChangedCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMobileAccessibilityStatusChangedCallback() {
|
||||||
|
console.log("sendMobileAccessibilityStatusChangedCallback");
|
||||||
|
if (callbackContext && typeof callbackContext === "function") {
|
||||||
|
callbackContext(getMobileAccessibilityStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMobileAccessibilityStatus() {
|
||||||
|
return {
|
||||||
|
isScreenReaderRunning: false,
|
||||||
|
isClosedCaptioningEnabled: false,
|
||||||
|
isHighContrastEnabled: accessibilitySettings.highContrast,
|
||||||
|
highContrastScheme: (accessibilitySettings.highContrast ? accessibilitySettings.highContrastScheme : undefined)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
start:function(win, fail, args) {
|
||||||
|
if (typeof win === "function") {
|
||||||
|
callbackContext = win;
|
||||||
|
}
|
||||||
|
if (!accessibilitySettings) {
|
||||||
|
accessibilitySettings = getAccessibilitySettings();
|
||||||
|
}
|
||||||
|
accessibilitySettings.addEventListener("highcontrastchanged", onHighContrastChanged);
|
||||||
|
|
||||||
|
if (!uiSettings) {
|
||||||
|
uiSettings = getUISettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stop:function(win, fail, args) {
|
||||||
|
if (accessibilitySettings) {
|
||||||
|
accessibilitySettings.removeEventListener("highcontrastchanged", onHighContrastChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (synth) {
|
||||||
|
synth.close();
|
||||||
|
synth = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audio) {
|
||||||
|
audio = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbackContext) {
|
||||||
|
callbackContext = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isScreenReaderRunning:function(win, fail, args) {
|
||||||
|
console && console.error && console.error("Error : Windows 8.1 does not yet have a way to detect that Narrator is running.");
|
||||||
|
fail && setTimeout(function() {
|
||||||
|
fail(new Error("Windows Phone 8.1 does not yet have a way to detect that Narrator is running."));
|
||||||
|
}, 0);
|
||||||
|
if (win && typeof win === "function") {
|
||||||
|
win(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isClosedCaptioningEnabled:function(win, fail, args) {
|
||||||
|
console && console.error && console.error("Error : MobileAccessibility.isClosedCaptioningEnabled is not yet implemented on Windows 8.1.");
|
||||||
|
fail && setTimeout(function() {
|
||||||
|
fail(new Error("MobileAccessibility.isClosedCaptioningEnabled is not yet implemented on Windows 8.1."));
|
||||||
|
}, 0);
|
||||||
|
if (win && typeof win === "function") {
|
||||||
|
win(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isHighContrastEnabled:function(win, fail, args) {
|
||||||
|
if (!accessibilitySettings) {
|
||||||
|
accessibilitySettings = getAccessibilitySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win && typeof win === "function") {
|
||||||
|
win(accessibilitySettings.highContrast);
|
||||||
|
}
|
||||||
|
return accessibilitySettings.highContrast;
|
||||||
|
},
|
||||||
|
getHighContrastScheme:function(win, fail, args) {
|
||||||
|
if (!accessibilitySettings) {
|
||||||
|
accessibilitySettings = getAccessibilitySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
var highContrastScheme = accessibilitySettings.highContrast ? accessibilitySettings.highContrastScheme : undefined;
|
||||||
|
|
||||||
|
if (win) {
|
||||||
|
win(highContrastScheme);
|
||||||
|
}
|
||||||
|
return highContrastScheme;
|
||||||
|
},
|
||||||
|
getTextZoom:function(win, fail, args) {
|
||||||
|
var zoom = Math.round(fontScale * 100);
|
||||||
|
|
||||||
|
if (win) {
|
||||||
|
win(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
},
|
||||||
|
setTextZoom:function(win, fail, args) {
|
||||||
|
var zoom = args[0];
|
||||||
|
setTextZoom(args[0]);
|
||||||
|
|
||||||
|
if (win) {
|
||||||
|
win(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
},
|
||||||
|
updateTextZoom:function(win, fail, args) {
|
||||||
|
var scale = getFontScale(),
|
||||||
|
zoom;
|
||||||
|
if (scale !== fontScale) {
|
||||||
|
fontScale = scale;
|
||||||
|
}
|
||||||
|
zoom = getTextZoom();
|
||||||
|
setTextZoom(zoom);
|
||||||
|
|
||||||
|
if (win) {
|
||||||
|
win(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
},
|
||||||
|
postNotification:function(win, fail, args) {
|
||||||
|
var str = args[1];
|
||||||
|
|
||||||
|
if (str && typeof str === "string") {
|
||||||
|
// The object for controlling and playing audio.
|
||||||
|
if (!audio) {
|
||||||
|
audio = new Audio();
|
||||||
|
} else if (audio.pause) {
|
||||||
|
audio.pause();
|
||||||
|
audio.src = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object for controlling the speech synthesis engine (voice).
|
||||||
|
if (!synth) {
|
||||||
|
synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str && str.length && str !== "\u200b") {
|
||||||
|
|
||||||
|
// Generate the audio stream from plain text.
|
||||||
|
synth.synthesizeTextToStreamAsync(str).then(function (markersStream) {
|
||||||
|
|
||||||
|
// Convert the stream to a URL Blob.
|
||||||
|
var blob = MSApp.createBlobFromRandomAccessStream(markersStream.contentType, markersStream);
|
||||||
|
// Send the Blob to the audio object.
|
||||||
|
audio.src = URL.createObjectURL(blob, { oneTimeOnly: true });
|
||||||
|
// Start at beginning when speak is hit
|
||||||
|
markersStream.seek(0);
|
||||||
|
audio.AutoPlay = Boolean(true);
|
||||||
|
|
||||||
|
// Audio on completed
|
||||||
|
audio.onended = function () {
|
||||||
|
if (win) {
|
||||||
|
win({
|
||||||
|
stringValue: str,
|
||||||
|
wasSuccessful: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
audio.play();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
require("cordova/exec/proxy").add("MobileAccessibility", module.exports);
|
||||||
@@ -35,5 +35,8 @@ module.exports = {
|
|||||||
SCREEN_CHANGED : 1000,
|
SCREEN_CHANGED : 1000,
|
||||||
LAYOUT_CHANGED : 1001,
|
LAYOUT_CHANGED : 1001,
|
||||||
ANNOUNCEMENT : 1008,
|
ANNOUNCEMENT : 1008,
|
||||||
PAGE_SCROLLED : 1009
|
PAGE_SCROLLED : 1009,
|
||||||
|
|
||||||
|
/* Windows specific high contrast event */
|
||||||
|
HIGH_CONTRAST_CHANGED : "highcontrastchanged"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ var MobileAccessibility = function() {
|
|||||||
this._isMonoAudioEnabled = false;
|
this._isMonoAudioEnabled = false;
|
||||||
this._isTouchExplorationEnabled = false;
|
this._isTouchExplorationEnabled = false;
|
||||||
this._usePreferredTextZoom = false;
|
this._usePreferredTextZoom = false;
|
||||||
|
this._isHighContrastEnabled = false;
|
||||||
|
this._highContrastScheme = undefined;
|
||||||
|
|
||||||
// Create new event handlers on the window (returns a channel instance)
|
// Create new event handlers on the window (returns a channel instance)
|
||||||
this.channels = {
|
this.channels = {
|
||||||
screenreaderstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.SCREEN_READER_STATUS_CHANGED),
|
screenreaderstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.SCREEN_READER_STATUS_CHANGED),
|
||||||
@@ -42,7 +45,8 @@ var MobileAccessibility = function() {
|
|||||||
guidedaccessstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.GUIDED_ACCESS_STATUS_CHANGED),
|
guidedaccessstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.GUIDED_ACCESS_STATUS_CHANGED),
|
||||||
invertcolorsstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.INVERT_COLORS_STATUS_CHANGED),
|
invertcolorsstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.INVERT_COLORS_STATUS_CHANGED),
|
||||||
monoaudiostatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.MONO_AUDIO_STATUS_CHANGED),
|
monoaudiostatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.MONO_AUDIO_STATUS_CHANGED),
|
||||||
touchexplorationstatechanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED)
|
touchexplorationstatechanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED),
|
||||||
|
highcontrastchanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.HIGH_CONTRAST_CHANGED)
|
||||||
};
|
};
|
||||||
for (var key in this.channels) {
|
for (var key in this.channels) {
|
||||||
this.channels[key].onHasSubscribersChange = MobileAccessibility.onHasSubscribersChange;
|
this.channels[key].onHasSubscribersChange = MobileAccessibility.onHasSubscribersChange;
|
||||||
@@ -59,7 +63,8 @@ function handlers() {
|
|||||||
mobileAccessibility.channels.invertcolorsstatuschanged.numHandlers +
|
mobileAccessibility.channels.invertcolorsstatuschanged.numHandlers +
|
||||||
mobileAccessibility.channels.monoaudiostatuschanged.numHandlers +
|
mobileAccessibility.channels.monoaudiostatuschanged.numHandlers +
|
||||||
mobileAccessibility.channels.guidedaccessstatuschanged.numHandlers +
|
mobileAccessibility.channels.guidedaccessstatuschanged.numHandlers +
|
||||||
mobileAccessibility.channels.touchexplorationstatechanged.numHandlers;
|
mobileAccessibility.channels.touchexplorationstatechanged.numHandlers +
|
||||||
|
mobileAccessibility.channels.highcontrastchanged.numHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,6 +211,14 @@ MobileAccessibility.prototype.isTouchExplorationEnabled = function(callback) {
|
|||||||
exec(callback, null, "MobileAccessibility", "isTouchExplorationEnabled", []);
|
exec(callback, null, "MobileAccessibility", "isTouchExplorationEnabled", []);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous call to native MobileAccessibility to determine if High Contrast is enabled on Windows.
|
||||||
|
* @param {function} callback A callback method to receive the asynchronous result from the native MobileAccessibility.
|
||||||
|
*/
|
||||||
|
MobileAccessibility.prototype.isHighContrastEnabled = function(callback) {
|
||||||
|
exec(callback, null, "MobileAccessibility", "isHighContrastEnabled", []);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronous call to native MobileAccessibility to return the current text zoom percent value for the WebView.
|
* Asynchronous call to native MobileAccessibility to return the current text zoom percent value for the WebView.
|
||||||
* @param {function} callback A callback method to receive the asynchronous result from the native MobileAccessibility.
|
* @param {function} callback A callback method to receive the asynchronous result from the native MobileAccessibility.
|
||||||
@@ -293,7 +306,7 @@ MobileAccessibility.prototype.stop = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback from native MobileAccessibility returning an which describes the status of MobileAccessibility features.
|
* Callback from native MobileAccessibility returning an object which describes the status of MobileAccessibility features.
|
||||||
*
|
*
|
||||||
* @param {Object} info
|
* @param {Object} info
|
||||||
* @config {Boolean} [isScreenReaderRunning] Boolean to indicate screen reader status.
|
* @config {Boolean} [isScreenReaderRunning] Boolean to indicate screen reader status.
|
||||||
@@ -329,7 +342,12 @@ MobileAccessibility.prototype._status = function(info) {
|
|||||||
if (mobileAccessibility._isTouchExplorationEnabled !== info.isTouchExplorationEnabled) {
|
if (mobileAccessibility._isTouchExplorationEnabled !== info.isTouchExplorationEnabled) {
|
||||||
mobileAccessibility._isTouchExplorationEnabled = info.isTouchExplorationEnabled;
|
mobileAccessibility._isTouchExplorationEnabled = info.isTouchExplorationEnabled;
|
||||||
cordova.fireWindowEvent(MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED, info);
|
cordova.fireWindowEvent(MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED, info);
|
||||||
}
|
}
|
||||||
|
if (mobileAccessibility._isHighContrastEnabled !== info.isHighContrastEnabled) {
|
||||||
|
mobileAccessibility._isHighContrastEnabled = info.isHighContrastEnabled;
|
||||||
|
mobileAccessibility._highContrastScheme = info.highContrastScheme;
|
||||||
|
cordova.fireWindowEvent(MobileAccessibilityNotifications.HIGH_CONTRAST_CHANGED, info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user