From b8e69660acd46e8dfbc7a7bb74ed41d6e8b76300 Mon Sep 17 00:00:00 2001 From: Vanessa Freudenberg Date: Thu, 4 Sep 2014 19:27:50 +0200 Subject: [PATCH] Harness: add input event processing --- lib/squeak.js | 119 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 16 deletions(-) diff --git a/lib/squeak.js b/lib/squeak.js index bc1dca46..855c310a 100644 --- a/lib/squeak.js +++ b/lib/squeak.js @@ -112,25 +112,111 @@ function setupFullscreen(display, canvas, options) { } } +function recordMouseEvent(what, evt, canvas, display, eventQueue, options) { + var x = (evt.pageX - canvas.offsetLeft) * (canvas.width / canvas.offsetWidth); + y = (evt.pageY - canvas.offsetTop) * (canvas.height / canvas.offsetHeight); + // subtract display offset and clamp to display size + display.mouseX = Math.max(0, Math.min(display.width, x - display.offsetX)); + display.mouseY = Math.max(0, Math.min(display.height, y - display.offsetY)); + var buttons = display.buttons & Squeak.Mouse_All; + switch (what) { + case 'move': + break; // nothing more to do + case 'up': + buttons = 0; + break; + case 'down': + switch (evt.button) { + case 0: buttons = Squeak.Mouse_Red; break; // left + case 1: buttons = Squeak.Mouse_Yellow; break; // middle + case 2: buttons = Squeak.Mouse_Blue; break; // right + }; + if (options.swapButtons) + if (buttons == Squeak.Mouse_Yellow) buttons = Squeak.Mouse_Blue; + else if (buttons == Squeak.Mouse_Blue) buttons = Squeak.Mouse_Yellow; + break; + } + buttons += + (evt.shiftKey ? Squeak.Keyboard_Shift : 0) + + (evt.ctrlKey ? Squeak.Keyboard_Ctrl : 0) + + (evt.altKey || evt.metaKey ? Squeak.Keyboard_Cmd : 0); + display.buttons = buttons; + if (eventQueue) { + eventQueue.push([ + Squeak.EventTypeMouse, + evt.timeStamp, // converted to Squeak time in makeSqueakEvent() + display.mouseX, + display.mouseY, + display.buttons & Squeak.Mouse_All, + display.buttons >> 3, + ]); + if (display.signalInputEvent) + display.signalInputEvent(); + } +} + +function recordKeyboardEvent(key, timestamp, display, eventQueue) { + var code = (display.buttons >> 3) << 8 | key; + if (code === display.vm.interruptKeycode) { + display.vm.interruptPending = true; + } else if (eventQueue) { + eventQueue.push([ + Squeak.EventTypeKeyboard, + timestamp, // converted to Squeak time in makeSqueakEvent() + key, // MacRoman + Squeak.EventKeyChar, + display.buttons >> 3, + 0, // Unicode + ]); + if (display.signalInputEvent) + display.signalInputEvent(); + } else { + // no event queue, queue keys the old-fashioned way + display.keys.push(code); + } +} + +function makeSqueakEvent(evt, sqEvtBuf, sqTimeOffset) { + sqEvtBuf[0] = evt[0]; + sqEvtBuf[1] = (evt[1] - sqTimeOffset) & Squeak.MillisecondClockMask; + for (var i = 2; i < evt.length; i++) + sqEvtBuf[i] = evt[i]; +} + function createSqueakDisplay(canvas, options) { options = options || {}; + var eventQueue = null; var display = { context: canvas.getContext("2d"), fullscreen: false, + offsetX: 0, + offsetY: 0, + width: -1, + height: -1, mouseX: 0, mouseY: 0, buttons: 0, keys: [], clipboardString: '', clipboardStringChanged: false, + signalInputEvent: null, // function set by VM + getNextEvent: function firstTime(firstEvtBuf, firstOffset) { + eventQueue = []; + display.getNextEvent = function getNextEvent(evtBuf, timeOffset) { + var evt = eventQueue.shift(); + if (evt) makeSqueakEvent(evt, evtBuf, timeOffset); + else evtBuf[0] = Squeak.EventTypeNone; + }; + display.getNextEvent(firstEvtBuf, firstOffset); + }, }; - var checkFullscreen = setupFullscreen(display, canvas); + var checkFullscreen = setupFullscreen(display, canvas, options); display.clear = function() { canvas.width = canvas.width; }; display.showBanner = function(msg, style) { style = style || {}; - var ctx = canvas.getContext("2d"); + var ctx = display.context; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = style.color || "#F90"; ctx.font = style.font || 'bold 48px sans-serif'; @@ -156,52 +242,53 @@ function createSqueakDisplay(canvas, options) { canvas.onmousedown = function(evt) { checkFullscreen(); canvas.focus(); - var button = (options.swapButtons ? [4, 1, 2] : [4, 2, 1])[evt.button]; - display.buttons = display.buttons & ~7 | button; + recordMouseEvent('down', evt, canvas, display, eventQueue, options); + display.vm.interpret(100); evt.preventDefault(); return false; }; canvas.onmouseup = function(evt) { + recordMouseEvent('up', evt, canvas, display, eventQueue, options); + display.vm.interpret(100); checkFullscreen(); - display.buttons = display.buttons & ~7; evt.preventDefault(); }; canvas.onmousemove = function(evt) { - // scale events to actual canvas extent - display.mouseX = (evt.pageX - this.offsetLeft) * (this.width / this.offsetWidth); - display.mouseY = (evt.pageY - this.offsetTop) * (this.height / this.offsetHeight); + recordMouseEvent('move', evt, canvas, display, eventQueue, options); + evt.preventDefault(); }; canvas.oncontextmenu = function() { return false; }; canvas.ontouchstart = function(evt) { canvas.focus(); - display.buttons = 4; canvas.ontouchmove(evt); }; canvas.ontouchmove = function(evt) { canvas.onmousemove(evt.touches[0]); }; canvas.ontouchend = function(evt) { - display.buttons = 0; canvas.ontouchmove(evt); }; canvas.ontouchcancel = function(evt) { - display.buttons = 0; }; canvas.onkeypress = function(evt) { - display.keys.push(evt.charCode); + recordKeyboardEvent(evt.charCode, evt.timeStamp, display, eventQueue); evt.preventDefault(); }; canvas.onkeydown = function(evt) { checkFullscreen(); var code = ({46:127, 8:8, 45:5, 9:9, 13:13, 27:27, 36:1, 35:4, 33:11, 34:12, 37:28, 39:29, 38:30, 40:31})[evt.keyCode]; - if (code) {display.keys.push(code); return evt.preventDefault()}; + if (code) { // special key pressed + recordKeyboardEvent(code, evt.timeStamp, display, eventQueue); + return evt.preventDefault(); + } var modifier = ({16:8, 17:16, 91:64, 18:64})[evt.keyCode]; - if (modifier) { + if (modifier) { // modifier pressed display.buttons |= modifier; - if (modifier > 8) display.keys = []; + if (modifier > 8) // special + display.keys = []; // flush queued key presses return evt.preventDefault(); } if ((evt.metaKey || evt.altKey) && evt.which) { @@ -209,7 +296,7 @@ function createSqueakDisplay(canvas, options) { if (code >= 65 && code <= 90) if (!evt.shiftKey) code += 32; else if (evt.keyIdentifier && evt.keyIdentifier.slice(0,2) == 'U+') code = parseInt(evt.keyIdentifier.slice(2), 16); - display.keys.push(code) + recordKeyboardEvent(code, evt.timeStamp, display, eventQueue); return evt.preventDefault(); } };