Add preliminary support for Windows 8.1

This commit is contained in:
Michael Jordan 2015-01-13 13:35:40 -05:00
parent 226a7745fb
commit cb94a6c8eb
4 changed files with 306 additions and 5 deletions

View File

@ -62,4 +62,23 @@
<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" />
</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>

View File

@ -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);

View File

@ -35,5 +35,8 @@ module.exports = {
SCREEN_CHANGED : 1000,
LAYOUT_CHANGED : 1001,
ANNOUNCEMENT : 1008,
PAGE_SCROLLED : 1009
PAGE_SCROLLED : 1009,
/* Windows specific high contrast event */
HIGH_CONTRAST_CHANGED : "highcontrastchanged"
};

View File

@ -35,6 +35,9 @@ var MobileAccessibility = function() {
this._isMonoAudioEnabled = false;
this._isTouchExplorationEnabled = false;
this._usePreferredTextZoom = false;
this._isHighContrastEnabled = false;
this._highContrastScheme = undefined;
// Create new event handlers on the window (returns a channel instance)
this.channels = {
screenreaderstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.SCREEN_READER_STATUS_CHANGED),
@ -42,7 +45,8 @@ var MobileAccessibility = function() {
guidedaccessstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.GUIDED_ACCESS_STATUS_CHANGED),
invertcolorsstatuschanged : cordova.addWindowEventHandler(MobileAccessibilityNotifications.INVERT_COLORS_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) {
this.channels[key].onHasSubscribersChange = MobileAccessibility.onHasSubscribersChange;
@ -59,7 +63,8 @@ function handlers() {
mobileAccessibility.channels.invertcolorsstatuschanged.numHandlers +
mobileAccessibility.channels.monoaudiostatuschanged.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", []);
};
/**
* 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.
* @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
* @config {Boolean} [isScreenReaderRunning] Boolean to indicate screen reader status.
@ -329,7 +342,12 @@ MobileAccessibility.prototype._status = function(info) {
if (mobileAccessibility._isTouchExplorationEnabled !== info.isTouchExplorationEnabled) {
mobileAccessibility._isTouchExplorationEnabled = info.isTouchExplorationEnabled;
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);
}
}
};