diff --git a/devices/pc/video/video-ega-128kb-lock.xml b/devices/pc/video/video-ega-128kb-lock.xml
index 90c8e4d4d..bab466590 100644
--- a/devices/pc/video/video-ega-128kb-lock.xml
+++ b/devices/pc/video/video-ega-128kb-lock.xml
@@ -7,6 +7,7 @@
Lock Pointer
+ Full Screen
diff --git a/modules/pcjs/lib/keyboard.js b/modules/pcjs/lib/keyboard.js
index 169960751..4831cabb6 100644
--- a/modules/pcjs/lib/keyboard.js
+++ b/modules/pcjs/lib/keyboard.js
@@ -134,20 +134,20 @@ function Keyboard(parmsKbd)
this.msAutoRelease = 50;
this.msInjectDelay = 300; // number of milliseconds between injected keystrokes
+ /*
+ * HACK: We set fAllDown to false to ignore all down/up events for keys not explicitly marked as ONDOWN;
+ * even though that prevents those keys from being repeated properly (ie, at the simulation's repeat rate
+ * rather than the browser's repeat rate), it's the safest thing to do when dealing with international keyboards,
+ * because our mapping tables are designed for US keyboards, and testing all the permutations of international
+ * keyboards and web browsers is more work than I can take on right now. TODO: Dig into this some day.
+ */
+ this.fAllDown = false;
+
this.setReady();
}
Component.subclass(Component, Keyboard);
-/*
- * HACK: We set ALL_ONDOWN to false to ignore all down/up events for keys not explicitly marked as ONDOWN;
- * even though that prevents those keys from being repeated properly (ie, at the simulation's repeat rate
- * rather than the browser's repeat rate), it's the safest thing to do when dealing with international keyboards,
- * because our mapping tables are designed for US keyboards, and testing all the permutations of international
- * keyboards and web browsers is more work than I can take on right now. TODO: Dig into this some day.
- */
-Keyboard.ALL_ONDOWN = false;
-
/**
* Alphanumeric and other common (printable) ASCII codes.
*
@@ -1128,16 +1128,18 @@ Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
};
/**
- * notifyEscape(fDisabled)
+ * notifyEscape(fDisabled, fAllDown)
*
* When ESC is used by the browser to disable pointer lock, this gives us the option of mapping a different key to ESC.
*
* @this {Keyboard}
* @param {boolean} fDisabled
+ * @param {boolean} [fAllDown] (an experimental option to re-enable processing of all onkeydown/onkeyup events)
*/
-Keyboard.prototype.notifyEscape = function(fDisabled)
+Keyboard.prototype.notifyEscape = function(fDisabled, fAllDown)
{
this.fEscapeDisabled = fDisabled;
+ if (fAllDown !== undefined) this.fAllDown = fAllDown;
};
/**
@@ -2050,7 +2052,7 @@ Keyboard.prototype.onKeyDown = function(event, fDown)
/*
* Don't simulate any key not explicitly marked ONDOWN, as well as any key sequence with the CMD key held.
*/
- if (!Keyboard.ALL_ONDOWN && fPass && fDown || !!(this.bitsState & Keyboard.STATE.CMDS)) fIgnore = true;
+ if (!this.fAllDown && fPass && fDown || !!(this.bitsState & Keyboard.STATE.CMDS)) fIgnore = true;
}
if (!fPass) {
@@ -2093,7 +2095,7 @@ Keyboard.prototype.onKeyPress = function(event)
event = event || window.event;
var keyCode = event.which || event.keyCode;
- if (Keyboard.ALL_ONDOWN) {
+ if (this.fAllDown) {
var simCode = this.checkActiveKey();
if (simCode && this.isAlphaKey(simCode) && this.isAlphaKey(keyCode) && simCode != keyCode) {
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
diff --git a/modules/pcjs/lib/state.js b/modules/pcjs/lib/state.js
index ccbfbf76d..9514c32a5 100644
--- a/modules/pcjs/lib/state.js
+++ b/modules/pcjs/lib/state.js
@@ -35,7 +35,7 @@
if (typeof module !== 'undefined') {
var web = require("./../../shared/lib/weblib");
var Component = require("./../../shared/lib/component");
- var Messages = require("./messages");
+ var Messages = require("./messages");
}
/**
diff --git a/modules/pcjs/lib/video.js b/modules/pcjs/lib/video.js
index 12b6160d0..2d031f6e6 100644
--- a/modules/pcjs/lib/video.js
+++ b/modules/pcjs/lib/video.js
@@ -44,7 +44,7 @@ if (typeof module !== 'undefined') {
}
/**
- * Video(parmsVideo, canvas, context, textarea)
+ * Video(parmsVideo, canvas, context, textarea, container)
*
* The Video component can be configured with the following (parmsVideo) properties:
*
@@ -93,8 +93,9 @@ if (typeof module !== 'undefined') {
* @param {Object} [canvas]
* @param {Object} [context]
* @param {Object} [textarea]
+ * @param {Object} [container]
*/
-function Video(parmsVideo, canvas, context, textarea)
+function Video(parmsVideo, canvas, context, textarea, container)
{
Component.call(this, "Video", parmsVideo, Video, Messages.VIDEO);
@@ -192,6 +193,31 @@ function Video(parmsVideo, canvas, context, textarea)
this.fHasFocus = false;
var video = this;
+
+ /*
+ * All the gross code to handle full-screen support across all supported browsers (standards? hello?)
+ */
+ this.container = container;
+ if (this.container) {
+ this.container.doFullScreen = container['requestFullscreen'] || container['msRequestFullscreen'] || container['mozRequestFullScreen'] || container['webkitRequestFullscreen'];
+ var onFullScreenChange = function() {
+ var fFullScreen = (document['fullscreenElement'] || document['mozFullScreenElement'] || document['webkitFullscreenElement'] || document['msFullscreenElement']);
+ video.notifyFullScreen(fFullScreen? true : false);
+ };
+ if ('onfullscreenchange' in document) {
+ document.addEventListener('fullscreenchange', onFullScreenChange, false);
+ } else if ('onmozfullscreenchange' in document) {
+ document.addEventListener('mozfullscreenchange', onFullScreenChange, false);
+ } else if ('onwebkitfullscreenchange' in document) {
+ document.addEventListener('webkitfullscreenchange', onFullScreenChange, false);
+ } else if ('onmsfullscreenchange' in document) {
+ document.addEventListener('msfullscreenchange', onFullScreenChange, false);
+ }
+ }
+
+ /*
+ * All the gross code to handle pointer-locking support across all supported browsers (standards? hello?)
+ */
if (this.inputScreen) {
this.inputScreen.onfocus = function onFocusScreen() {
return video.onFocusChange(true);
@@ -2010,6 +2036,18 @@ Video.prototype.setBinding = function(sHTMLType, sBinding, control)
switch (sBinding) {
+ case "fullScreen":
+ if (this.container && this.container.doFullScreen) {
+ control.onclick = function onClickFullScreen() {
+ if (DEBUG) video.printMessage("fullScreen()");
+ video.doFullScreen();
+ };
+ } else {
+ if (DEBUG) this.log("FullScreen API not available");
+ control.parentNode.removeChild(control);
+ }
+ return true;
+
case "lockPointer":
this.sLockMessage = control.textContent;
if (this.inputScreen && this.inputScreen.lockPointer) {
@@ -2062,6 +2100,39 @@ Video.prototype.getInput = function(mouse)
return this.inputScreen;
};
+/**
+ * doFullScreen()
+ *
+ * @this {Video}
+ * @return {boolean} true if request successful, false if not (eg, failed OR not supported)
+ */
+Video.prototype.doFullScreen = function()
+{
+ var fSuccess = false;
+ if (this.container) {
+ if (this.container.doFullScreen) {
+ this.container.style.width = this.container.style.height = "100%";
+ this.container.style.backgroundColor = "black";
+ this.container.doFullScreen();
+ fSuccess = true;
+ }
+ this.setFocus();
+ }
+ return fSuccess;
+};
+
+/**
+ * notifyFullScreen(fFullScreen)
+ *
+ * @this {Video}
+ * @param {boolean} fFullScreen
+ */
+Video.prototype.notifyFullScreen = function(fFullScreen)
+{
+ this.printMessage("notifyFullScreen(" + fFullScreen + ")", true);
+ if (this.kbd) this.kbd.notifyEscape(fFullScreen);
+};
+
/**
* lockPointer()
*
@@ -3753,10 +3824,10 @@ Video.prototype.setMode = function(nMode, fForce)
Video.prototype.setPixel = function(imageData, x, y, rgb)
{
var index = (x + y * imageData.width) * rgb.length;
- imageData.data[index + 0] = rgb[0];
- imageData.data[index + 1] = rgb[1];
- imageData.data[index + 2] = rgb[2];
- imageData.data[index + 3] = rgb[3];
+ imageData.data[index] = rgb[0];
+ imageData.data[index+1] = rgb[1];
+ imageData.data[index+2] = rgb[2];
+ imageData.data[index+3] = rgb[3];
};
/**
@@ -5235,7 +5306,7 @@ Video.init = function()
* Now we can create the Video object, record it, and wire it up to the associated document elements.
*/
var eContext = eCanvas.getContext("2d");
- var video = new Video(parmsVideo, eCanvas, eContext, eTextArea /* || eInput */);
+ var video = new Video(parmsVideo, eCanvas, eContext, eTextArea /* || eInput */, eVideo);
/*
* Bind any video-specific controls (eg, the Refresh button). There are no essential controls, however;