Skip to content

Commit b8e6966

Browse files
committed
Harness: add input event processing
1 parent 96d7dba commit b8e6966

File tree

1 file changed

+103
-16
lines changed

1 file changed

+103
-16
lines changed

lib/squeak.js

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -112,25 +112,111 @@ function setupFullscreen(display, canvas, options) {
112112
}
113113
}
114114

115+
function recordMouseEvent(what, evt, canvas, display, eventQueue, options) {
116+
var x = (evt.pageX - canvas.offsetLeft) * (canvas.width / canvas.offsetWidth);
117+
y = (evt.pageY - canvas.offsetTop) * (canvas.height / canvas.offsetHeight);
118+
// subtract display offset and clamp to display size
119+
display.mouseX = Math.max(0, Math.min(display.width, x - display.offsetX));
120+
display.mouseY = Math.max(0, Math.min(display.height, y - display.offsetY));
121+
var buttons = display.buttons & Squeak.Mouse_All;
122+
switch (what) {
123+
case 'move':
124+
break; // nothing more to do
125+
case 'up':
126+
buttons = 0;
127+
break;
128+
case 'down':
129+
switch (evt.button) {
130+
case 0: buttons = Squeak.Mouse_Red; break; // left
131+
case 1: buttons = Squeak.Mouse_Yellow; break; // middle
132+
case 2: buttons = Squeak.Mouse_Blue; break; // right
133+
};
134+
if (options.swapButtons)
135+
if (buttons == Squeak.Mouse_Yellow) buttons = Squeak.Mouse_Blue;
136+
else if (buttons == Squeak.Mouse_Blue) buttons = Squeak.Mouse_Yellow;
137+
break;
138+
}
139+
buttons +=
140+
(evt.shiftKey ? Squeak.Keyboard_Shift : 0) +
141+
(evt.ctrlKey ? Squeak.Keyboard_Ctrl : 0) +
142+
(evt.altKey || evt.metaKey ? Squeak.Keyboard_Cmd : 0);
143+
display.buttons = buttons;
144+
if (eventQueue) {
145+
eventQueue.push([
146+
Squeak.EventTypeMouse,
147+
evt.timeStamp, // converted to Squeak time in makeSqueakEvent()
148+
display.mouseX,
149+
display.mouseY,
150+
display.buttons & Squeak.Mouse_All,
151+
display.buttons >> 3,
152+
]);
153+
if (display.signalInputEvent)
154+
display.signalInputEvent();
155+
}
156+
}
157+
158+
function recordKeyboardEvent(key, timestamp, display, eventQueue) {
159+
var code = (display.buttons >> 3) << 8 | key;
160+
if (code === display.vm.interruptKeycode) {
161+
display.vm.interruptPending = true;
162+
} else if (eventQueue) {
163+
eventQueue.push([
164+
Squeak.EventTypeKeyboard,
165+
timestamp, // converted to Squeak time in makeSqueakEvent()
166+
key, // MacRoman
167+
Squeak.EventKeyChar,
168+
display.buttons >> 3,
169+
0, // Unicode
170+
]);
171+
if (display.signalInputEvent)
172+
display.signalInputEvent();
173+
} else {
174+
// no event queue, queue keys the old-fashioned way
175+
display.keys.push(code);
176+
}
177+
}
178+
179+
function makeSqueakEvent(evt, sqEvtBuf, sqTimeOffset) {
180+
sqEvtBuf[0] = evt[0];
181+
sqEvtBuf[1] = (evt[1] - sqTimeOffset) & Squeak.MillisecondClockMask;
182+
for (var i = 2; i < evt.length; i++)
183+
sqEvtBuf[i] = evt[i];
184+
}
185+
115186
function createSqueakDisplay(canvas, options) {
116187
options = options || {};
188+
var eventQueue = null;
117189
var display = {
118190
context: canvas.getContext("2d"),
119191
fullscreen: false,
192+
offsetX: 0,
193+
offsetY: 0,
194+
width: -1,
195+
height: -1,
120196
mouseX: 0,
121197
mouseY: 0,
122198
buttons: 0,
123199
keys: [],
124200
clipboardString: '',
125201
clipboardStringChanged: false,
202+
signalInputEvent: null, // function set by VM
203+
getNextEvent: function firstTime(firstEvtBuf, firstOffset) {
204+
eventQueue = [];
205+
display.getNextEvent = function getNextEvent(evtBuf, timeOffset) {
206+
var evt = eventQueue.shift();
207+
if (evt) makeSqueakEvent(evt, evtBuf, timeOffset);
208+
else evtBuf[0] = Squeak.EventTypeNone;
209+
};
210+
display.getNextEvent(firstEvtBuf, firstOffset);
211+
},
126212
};
127-
var checkFullscreen = setupFullscreen(display, canvas);
213+
var checkFullscreen = setupFullscreen(display, canvas, options);
128214
display.clear = function() {
129215
canvas.width = canvas.width;
130216
};
131217
display.showBanner = function(msg, style) {
132218
style = style || {};
133-
var ctx = canvas.getContext("2d");
219+
var ctx = display.context;
134220
ctx.clearRect(0, 0, canvas.width, canvas.height);
135221
ctx.fillStyle = style.color || "#F90";
136222
ctx.font = style.font || 'bold 48px sans-serif';
@@ -156,60 +242,61 @@ function createSqueakDisplay(canvas, options) {
156242
canvas.onmousedown = function(evt) {
157243
checkFullscreen();
158244
canvas.focus();
159-
var button = (options.swapButtons ? [4, 1, 2] : [4, 2, 1])[evt.button];
160-
display.buttons = display.buttons & ~7 | button;
245+
recordMouseEvent('down', evt, canvas, display, eventQueue, options);
246+
display.vm.interpret(100);
161247
evt.preventDefault();
162248
return false;
163249
};
164250
canvas.onmouseup = function(evt) {
251+
recordMouseEvent('up', evt, canvas, display, eventQueue, options);
252+
display.vm.interpret(100);
165253
checkFullscreen();
166-
display.buttons = display.buttons & ~7;
167254
evt.preventDefault();
168255
};
169256
canvas.onmousemove = function(evt) {
170-
// scale events to actual canvas extent
171-
display.mouseX = (evt.pageX - this.offsetLeft) * (this.width / this.offsetWidth);
172-
display.mouseY = (evt.pageY - this.offsetTop) * (this.height / this.offsetHeight);
257+
recordMouseEvent('move', evt, canvas, display, eventQueue, options);
258+
evt.preventDefault();
173259
};
174260
canvas.oncontextmenu = function() {
175261
return false;
176262
};
177263
canvas.ontouchstart = function(evt) {
178264
canvas.focus();
179-
display.buttons = 4;
180265
canvas.ontouchmove(evt);
181266
};
182267
canvas.ontouchmove = function(evt) {
183268
canvas.onmousemove(evt.touches[0]);
184269
};
185270
canvas.ontouchend = function(evt) {
186-
display.buttons = 0;
187271
canvas.ontouchmove(evt);
188272
};
189273
canvas.ontouchcancel = function(evt) {
190-
display.buttons = 0;
191274
};
192275
canvas.onkeypress = function(evt) {
193-
display.keys.push(evt.charCode);
276+
recordKeyboardEvent(evt.charCode, evt.timeStamp, display, eventQueue);
194277
evt.preventDefault();
195278
};
196279
canvas.onkeydown = function(evt) {
197280
checkFullscreen();
198281
var code = ({46:127, 8:8, 45:5, 9:9, 13:13, 27:27, 36:1, 35:4,
199282
33:11, 34:12, 37:28, 39:29, 38:30, 40:31})[evt.keyCode];
200-
if (code) {display.keys.push(code); return evt.preventDefault()};
283+
if (code) { // special key pressed
284+
recordKeyboardEvent(code, evt.timeStamp, display, eventQueue);
285+
return evt.preventDefault();
286+
}
201287
var modifier = ({16:8, 17:16, 91:64, 18:64})[evt.keyCode];
202-
if (modifier) {
288+
if (modifier) { // modifier pressed
203289
display.buttons |= modifier;
204-
if (modifier > 8) display.keys = [];
290+
if (modifier > 8) // special
291+
display.keys = []; // flush queued key presses
205292
return evt.preventDefault();
206293
}
207294
if ((evt.metaKey || evt.altKey) && evt.which) {
208295
code = evt.which;
209296
if (code >= 65 && code <= 90) if (!evt.shiftKey) code += 32;
210297
else if (evt.keyIdentifier && evt.keyIdentifier.slice(0,2) == 'U+')
211298
code = parseInt(evt.keyIdentifier.slice(2), 16);
212-
display.keys.push(code)
299+
recordKeyboardEvent(code, evt.timeStamp, display, eventQueue);
213300
return evt.preventDefault();
214301
}
215302
};

0 commit comments

Comments
 (0)