|
116 | 116 | Object.extend(Squeak, |
117 | 117 | "version", { |
118 | 118 | // system attributes |
119 | | - vmVersion: "SqueakJS 1.2.2", |
120 | | - vmDate: "2024-06-22", // Maybe replace at build time? |
| 119 | + vmVersion: "SqueakJS 1.2.3", |
| 120 | + vmDate: "2024-09-28", // Maybe replace at build time? |
121 | 121 | vmBuild: "unknown", // or replace at runtime by last-modified? |
122 | 122 | vmPath: "unknown", // Replace at runtime |
123 | 123 | vmFile: "vm.js", |
|
10090 | 10090 | clipBoardPromise |
10091 | 10091 | .then(() => this.vm.popNandPush(1, this.makeStString(this.display.clipboardString))) |
10092 | 10092 | .catch(() => this.vm.popNandPush(1, this.vm.nilObj)) |
10093 | | - .finally(() => unfreeze()); |
| 10093 | + .finally(unfreeze); |
10094 | 10094 | } else { |
10095 | 10095 | if (typeof(this.display.clipboardString) !== 'string') return false; |
10096 | 10096 | this.vm.popNandPush(1, this.makeStString(this.display.clipboardString)); |
|
10140 | 10140 | this.display.signalInputEvent = function() { |
10141 | 10141 | this.signalSemaphoreWithIndex(this.inputEventSemaIndex); |
10142 | 10142 | }.bind(this); |
10143 | | - this.display.signalInputEvent(); |
10144 | 10143 | return this.popNIfOK(argCount); |
10145 | 10144 | }, |
10146 | 10145 | primitiveInputWord: function(argCount) { |
|
56815 | 56814 | input.setAttribute("autocapitalize", "off"); |
56816 | 56815 | input.setAttribute("spellcheck", "false"); |
56817 | 56816 | input.style.position = "absolute"; |
56818 | | - input.style.width = "0"; |
56819 | | - input.style.height = "0"; |
56820 | | - input.style.opacity = "0"; |
56821 | | - input.style.pointerEvents = "none"; |
| 56817 | + input.style.left = "-1000px"; |
56822 | 56818 | canvas.parentElement.appendChild(input); |
56823 | 56819 | // touch-keyboard buttons |
56824 | 56820 | if ('ontouchstart' in document) { |
|
56829 | 56825 | canvas.parentElement.appendChild(keyboardButton); |
56830 | 56826 | keyboardButton.onmousedown = function(evt) { |
56831 | 56827 | // show on-screen keyboard |
56832 | | - input.focus(); |
| 56828 | + input.focus({ preventScroll: true }); |
56833 | 56829 | evt.preventDefault(); |
56834 | 56830 | }; |
56835 | 56831 | keyboardButton.ontouchstart = keyboardButton.onmousedown; |
|
56863 | 56859 | cmdButton.ontouchcancel = cmdButton.ontouchend; |
56864 | 56860 | } else { |
56865 | 56861 | // keep focus on input field |
56866 | | - input.onblur = function() { input.focus(); }; |
56867 | | - input.focus(); |
| 56862 | + input.onblur = function() { input.focus({ preventScroll: true }); }; |
| 56863 | + input.focus({ preventScroll: true }); |
56868 | 56864 | } |
56869 | 56865 | display.isMac = navigator.userAgent.includes("Mac"); |
56870 | 56866 | // emulate keypress events |
|
56898 | 56894 | deadChars = deadChars.concat(chars); |
56899 | 56895 | } |
56900 | 56896 | } |
56901 | | - if (!deadChars.length) input.value = ""; // clear input |
| 56897 | + if (!deadChars.length) resetInput(); |
56902 | 56898 | }; |
56903 | 56899 | input.onkeydown = function(evt) { |
56904 | 56900 | checkFullscreen(); |
@@ -56961,21 +56957,43 @@ |
56961 | 56957 | if (!display.vm) return true; |
56962 | 56958 | recordModifiers(evt, display); |
56963 | 56959 | }; |
| 56960 | + function resetInput() { |
| 56961 | + input.value = "**"; |
| 56962 | + input.selectionStart = 1; |
| 56963 | + input.selectionEnd = 1; |
| 56964 | + } |
| 56965 | + resetInput(); |
| 56966 | + // hack to generate arrow keys when moving the cursor (e.g. via spacebar on iPhone) |
| 56967 | + // we're not getting any events for that but the cursor (selection) changes |
| 56968 | + if ('ontouchstart' in document) { |
| 56969 | + let count = 0; // count how often the interval has run after the first move |
| 56970 | + setInterval(() => { |
| 56971 | + const direction = input.selectionStart - 1; |
| 56972 | + if (direction === 0) { |
| 56973 | + count = 0; |
| 56974 | + return; |
| 56975 | + } |
| 56976 | + // move cursor once, then not for 500ms, then every 250ms |
| 56977 | + if (count === 0 || count > 2) { |
| 56978 | + const key = direction < 1 ? 28 : 29; // arrow left or right |
| 56979 | + recordKeyboardEvent(key, Date.now(), display); |
| 56980 | + } |
| 56981 | + input.selectionStart = 1; |
| 56982 | + input.selectionEnd = 1; |
| 56983 | + count++; |
| 56984 | + }, 250); |
| 56985 | + } |
56964 | 56986 | // more copy/paste |
56965 | 56987 | if (navigator.clipboard) { |
56966 | 56988 | // new-style copy/paste (all modern browsers) |
56967 | | - display.readFromSystemClipboard = () => navigator.clipboard.readText() |
| 56989 | + display.readFromSystemClipboard = () => display.handlingEvent && |
| 56990 | + navigator.clipboard.readText() |
56968 | 56991 | .then(text => display.clipboardString = text) |
56969 | | - .catch(err => { |
56970 | | - if (!display.handlingEvent) console.warn("reading from clipboard outside event handler"); |
56971 | | - console.error("readFromSystemClipboard" + err.message); |
56972 | | - }); |
56973 | | - display.writeToSystemClipboard = () => navigator.clipboard.writeText(display.clipboardString) |
| 56992 | + .catch(err => console.error("readFromSystemClipboard " + err.message)); |
| 56993 | + display.writeToSystemClipboard = () => display.handlingEvent && |
| 56994 | + navigator.clipboard.writeText(display.clipboardString) |
56974 | 56995 | .then(() => display.clipboardStringChanged = false) |
56975 | | - .catch(err => { |
56976 | | - if (!display.handlingEvent) console.warn("writing to clipboard outside event handler"); |
56977 | | - console.error("writeToSystemClipboard" + err.message); |
56978 | | - }); |
| 56996 | + .catch(err => console.error("writeToSystemClipboard " + err.message)); |
56979 | 56997 | } else { |
56980 | 56998 | // old-style copy/paste |
56981 | 56999 | document.oncopy = function(evt, key) { |
|
0 commit comments