Use fewer global variables in term* and softkb

cpsdqs/unified-input
cpsdqs 7 years ago
parent 8f0d6c7873
commit 5dab1c649f
Signed by untrusted user: cpsdqs
GPG Key ID: 3F59586BB7448DD1
  1. 54
      jssrc/soft_keyboard.js
  2. 30
      jssrc/term.js
  3. 10
      jssrc/term_conn.js
  4. 16
      jssrc/term_input.js
  5. 21
      jssrc/term_screen.js
  6. 14
      jssrc/term_upload.js

@ -1,6 +1,6 @@
window.initSoftKeyboard = function (screen) { window.initSoftKeyboard = function (screen, input) {
const input = qs('#softkb-input') const keyInput = qs('#softkb-input')
if (!input) return // abort, we're not on the terminal page if (!keyInput) return // abort, we're not on the terminal page
let keyboardOpen = false let keyboardOpen = false
@ -8,97 +8,101 @@ window.initSoftKeyboard = function (screen) {
if (!keyboardOpen) return if (!keyboardOpen) return
let [x, y] = screen.gridToScreen(screen.cursor.x, screen.cursor.y, true) let [x, y] = screen.gridToScreen(screen.cursor.x, screen.cursor.y, true)
input.style.transform = `translate(${x}px, ${y}px)` keyInput.style.transform = `translate(${x}px, ${y}px)`
} }
input.addEventListener('focus', () => { keyInput.addEventListener('focus', () => {
keyboardOpen = true keyboardOpen = true
updateInputPosition() updateInputPosition()
}) })
input.addEventListener('blur', () => (keyboardOpen = false)) keyInput.addEventListener('blur', () => (keyboardOpen = false))
screen.on('cursor-moved', updateInputPosition) screen.on('cursor-moved', updateInputPosition)
window.kbOpen = function openSoftKeyboard (open) { window.kbOpen = function openSoftKeyboard (open) {
keyboardOpen = open keyboardOpen = open
updateInputPosition() updateInputPosition()
if (open) input.focus() if (open) keyInput.focus()
else input.blur() else keyInput.blur()
} }
// Chrome for Android doesn't send proper keydown/keypress events with
// real key values instead of 229 “Unidentified,” so here's a workaround
// that deals with the input composition events.
let lastCompositionString = '' let lastCompositionString = ''
let compositing = false let compositing = false
// sends the difference between the last and the new composition string
let sendInputDelta = function (newValue) { let sendInputDelta = function (newValue) {
let resend = false let resend = false
if (newValue.length > lastCompositionString.length) { if (newValue.length > lastCompositionString.length) {
if (newValue.startsWith(lastCompositionString)) { if (newValue.startsWith(lastCompositionString)) {
// characters have been added at the end // characters have been added at the end
Input.sendString(newValue.substr(lastCompositionString.length)) input.sendString(newValue.substr(lastCompositionString.length))
} else resend = true } else resend = true
} else if (newValue.length < lastCompositionString.length) { } else if (newValue.length < lastCompositionString.length) {
if (lastCompositionString.startsWith(newValue)) { if (lastCompositionString.startsWith(newValue)) {
// characters have been removed at the end // characters have been removed at the end
Input.sendString('\b'.repeat(lastCompositionString.length - input.sendString('\b'.repeat(lastCompositionString.length -
newValue.length)) newValue.length))
} else resend = true } else resend = true
} else if (newValue !== lastCompositionString) resend = true } else if (newValue !== lastCompositionString) resend = true
if (resend) { if (resend) {
// the entire string changed; resend everything // the entire string changed; resend everything
Input.sendString('\b'.repeat(lastCompositionString.length) + input.sendString('\b'.repeat(lastCompositionString.length) +
newValue) newValue)
} }
lastCompositionString = newValue lastCompositionString = newValue
} }
input.addEventListener('keydown', e => { keyInput.addEventListener('keydown', e => {
if (e.key === 'Unidentified') return if (e.key === 'Unidentified') return
input.value = '' keyInput.value = ''
if (e.key === 'Backspace') { if (e.key === 'Backspace') {
e.preventDefault() e.preventDefault()
Input.sendString('\b') input.sendString('\b')
} else if (e.key === 'Enter') { } else if (e.key === 'Enter') {
e.preventDefault() e.preventDefault()
Input.sendString('\x0d') input.sendString('\x0d')
} }
}) })
input.addEventListener('keypress', e => { keyInput.addEventListener('keypress', e => {
// prevent key duplication on iOS (because Safari *does* send proper events)
e.stopPropagation() e.stopPropagation()
}) })
input.addEventListener('input', e => { keyInput.addEventListener('input', e => {
e.stopPropagation() e.stopPropagation()
if (e.isComposing) { if (e.isComposing) {
sendInputDelta(e.data) sendInputDelta(e.data)
} else { } else {
if (e.inputType === 'insertCompositionText') Input.sendString(e.data) if (e.inputType === 'insertCompositionText') input.sendString(e.data)
else if (e.inputType === 'deleteContentBackward') { else if (e.inputType === 'deleteContentBackward') {
lastCompositionString = '' lastCompositionString = ''
sendInputDelta('') sendInputDelta('')
} else if (e.inputType === 'insertText') { } else if (e.inputType === 'insertText') {
Input.sendString(e.data) input.sendString(e.data)
} }
} }
}) })
input.addEventListener('compositionstart', e => { keyInput.addEventListener('compositionstart', e => {
lastCompositionString = '' lastCompositionString = ''
compositing = true compositing = true
console.log('compositionstart')
}) })
input.addEventListener('compositionend', e => { keyInput.addEventListener('compositionend', e => {
lastCompositionString = '' lastCompositionString = ''
compositing = false compositing = false
input.value = '' keyInput.value = ''
console.log('compositionend')
}) })
screen.on('open-soft-keyboard', () => input.focus()) screen.on('open-soft-keyboard', () => keyInput.focus())
} }

@ -1,21 +1,15 @@
/** Init the terminal sub-module - called from HTML */ /** Init the terminal sub-module - called from HTML */
window.termInit = function (labels, theme) { window.termInit = function (labels, theme) {
Conn.init()
Input.init()
TermUpl.init()
const screen = new window.TermScreen() const screen = new window.TermScreen()
const conn = window.Conn(screen)
const input = window.Input(conn)
const termUpload = window.TermUpl(conn, input)
let didNotifyAboutScreen = false screen.input = input
Object.defineProperty(window, 'Screen', {
get () { conn.init()
if (!didNotifyAboutScreen) { input.init()
console.warn('Use local variables instead of window.Screen') termUpload.init()
didNotifyAboutScreen = true
}
return screen
}
})
qs('#screen').appendChild(screen.canvas) qs('#screen').appendChild(screen.canvas)
screen.load(labels, theme) // load labels and theme screen.load(labels, theme) // load labels and theme
@ -43,8 +37,12 @@ window.termInit = function (labels, theme) {
} }
} }
window.initSoftKeyboard(screen) window.initSoftKeyboard(screen, input)
if (window.attachDebugScreen) window.attachDebugScreen(screen) if (window.attachDebugScreen) window.attachDebugScreen(screen)
window.termScreen = screen // for debugging // for debugging
window.termScreen = screen
window.conn = conn
window.input = input
window.termUpl = termUpload
} }

@ -1,5 +1,5 @@
/** Handle connections */ /** Handle connections */
window.Conn = (function () { window.Conn = function (screen) {
let ws let ws
let heartbeatTout let heartbeatTout
let pingIv let pingIv
@ -48,7 +48,7 @@ window.Conn = (function () {
break break
default: default:
Screen.load(evt.data) screen.load(evt.data)
if (!pageShown) { if (!pageShown) {
showPage() showPage()
pageShown = true pageShown = true
@ -89,9 +89,9 @@ window.Conn = (function () {
} }
function init () { function init () {
if (_demo) { if (window._demo) {
console.log('Demo mode!') console.log('Demo mode!')
Screen.load(_demo_screen) screen.load(_demo_screen)
showPage() showPage()
return return
} }
@ -134,4 +134,4 @@ window.Conn = (function () {
send: doSend, send: doSend,
canSend: canSend // check flood control canSend: canSend // check flood control
} }
})() }

@ -14,7 +14,7 @@
* r - mb release * r - mb release
* m - mouse move * m - mouse move
*/ */
window.Input = (function () { window.Input = function (conn) {
let opts = { let opts = {
np_alt: false, np_alt: false,
cu_alt: false, cu_alt: false,
@ -27,12 +27,12 @@ window.Input = (function () {
/** Send a literal message */ /** Send a literal message */
function sendStrMsg (str) { function sendStrMsg (str) {
return Conn.send('s' + str) return conn.send('s' + str)
} }
/** Send a button event */ /** Send a button event */
function sendBtnMsg (n) { function sendBtnMsg (n) {
Conn.send('b' + Chr(n)) conn.send('b' + Chr(n))
} }
/** Fn alt choice for key message */ /** Fn alt choice for key message */
@ -256,14 +256,14 @@ window.Input = (function () {
if (!opts.mt_move) return if (!opts.mt_move) return
const b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0 const b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0
const m = packModifiersForMouse() const m = packModifiersForMouse()
Conn.send('m' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)) conn.send('m' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m))
}, },
onMouseDown: function (x, y, b) { onMouseDown: function (x, y, b) {
if (!opts.mt_click) return if (!opts.mt_click) return
if (b > 3 || b < 1) return if (b > 3 || b < 1) return
const m = packModifiersForMouse() const m = packModifiersForMouse()
Conn.send('p' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)) conn.send('p' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m))
// console.log("B ",b," M ",m); // console.log("B ",b," M ",m);
}, },
@ -271,7 +271,7 @@ window.Input = (function () {
if (!opts.mt_click) return if (!opts.mt_click) return
if (b > 3 || b < 1) return if (b > 3 || b < 1) return
const m = packModifiersForMouse() const m = packModifiersForMouse()
Conn.send('r' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)) conn.send('r' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m))
// console.log("B ",b," M ",m); // console.log("B ",b," M ",m);
}, },
@ -281,7 +281,7 @@ window.Input = (function () {
// +1 ... btn 5 (towards user) // +1 ... btn 5 (towards user)
const m = packModifiersForMouse() const m = packModifiersForMouse()
const b = (dir < 0 ? 4 : 5) const b = (dir < 0 ? 4 : 5)
Conn.send('p' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)) conn.send('p' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m))
// console.log("B ",b," M ",m); // console.log("B ",b," M ",m);
}, },
@ -293,4 +293,4 @@ window.Input = (function () {
opts.no_keys = yes opts.no_keys = yes
} }
} }
})() }

@ -79,6 +79,13 @@ window.TermScreen = class TermScreen {
console.warn('No AudioContext!') console.warn('No AudioContext!')
} }
// dummy
this.input = new Proxy({}, {
get () {
return () => console.warn('TermScreen#input not set!')
}
})
this.cursor = { this.cursor = {
x: 0, x: 0,
y: 0, y: 0,
@ -200,7 +207,7 @@ window.TermScreen = class TermScreen {
if ((this.selection.selectable || e.altKey) && e.button === 0) { if ((this.selection.selectable || e.altKey) && e.button === 0) {
selectStart(e.offsetX, e.offsetY) selectStart(e.offsetX, e.offsetY)
} else { } else {
Input.onMouseDown(...this.screenToGrid(e.offsetX, e.offsetY), this.input.onMouseDown(...this.screenToGrid(e.offsetX, e.offsetY),
e.button + 1) e.button + 1)
} }
}) })
@ -306,20 +313,20 @@ window.TermScreen = class TermScreen {
this.canvas.addEventListener('mousemove', e => { this.canvas.addEventListener('mousemove', e => {
if (!selecting) { if (!selecting) {
Input.onMouseMove(...this.screenToGrid(e.offsetX, e.offsetY)) this.input.onMouseMove(...this.screenToGrid(e.offsetX, e.offsetY))
} }
}) })
this.canvas.addEventListener('mouseup', e => { this.canvas.addEventListener('mouseup', e => {
if (!selecting) { if (!selecting) {
Input.onMouseUp(...this.screenToGrid(e.offsetX, e.offsetY), this.input.onMouseUp(...this.screenToGrid(e.offsetX, e.offsetY),
e.button + 1) e.button + 1)
} }
}) })
this.canvas.addEventListener('wheel', e => { this.canvas.addEventListener('wheel', e => {
if (this.mouseMode.clicks) { if (this.mouseMode.clicks) {
Input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY), this.input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY),
e.deltaY > 0 ? 1 : -1) e.deltaY > 0 ? 1 : -1)
// prevent page scrolling // prevent page scrolling
@ -1078,7 +1085,7 @@ window.TermScreen = class TermScreen {
this.cursor.visible = !!(attributes & 1) this.cursor.visible = !!(attributes & 1)
this.cursor.hanging = !!(attributes & (1 << 1)) this.cursor.hanging = !!(attributes & (1 << 1))
Input.setAlts( this.input.setAlts(
!!(attributes & (1 << 2)), // cursors alt !!(attributes & (1 << 2)), // cursors alt
!!(attributes & (1 << 3)), // numpad alt !!(attributes & (1 << 3)), // numpad alt
!!(attributes & (1 << 4)), // fn keys alt !!(attributes & (1 << 4)), // fn keys alt
@ -1109,7 +1116,7 @@ window.TermScreen = class TermScreen {
this.resetCursorBlink() this.resetCursorBlink()
} }
Input.setMouseMode(trackMouseClicks, trackMouseMovement) this.input.setMouseMode(trackMouseClicks, trackMouseMovement)
this.selection.selectable = !trackMouseMovement this.selection.selectable = !trackMouseMovement
$(this.canvas).toggleClass('selectable', !trackMouseMovement) $(this.canvas).toggleClass('selectable', !trackMouseMovement)
this.mouseMode = { this.mouseMode = {
@ -1267,7 +1274,7 @@ window.TermScreen = class TermScreen {
load (str, theme = -1) { load (str, theme = -1) {
const content = str.substr(1) const content = str.substr(1)
if (theme >= 0 && theme < themes.length) { if (theme >= 0 && theme < themes.length) {
Screen.palette = themes[theme] this.palette = themes[theme]
} }
switch (str[0]) { switch (str[0]) {

@ -1,5 +1,5 @@
/** File upload utility */ /** File upload utility */
window.TermUpl = (function () { window.TermUpl = function (conn, input) {
let lines, // array of lines without newlines let lines, // array of lines without newlines
line_i, // current line index line_i, // current line index
fuTout, // timeout handle for line sending fuTout, // timeout handle for line sending
@ -16,14 +16,14 @@ window.TermUpl = (function () {
fuStatus('Ready...') fuStatus('Ready...')
Modal.show('#fu_modal', onClose) Modal.show('#fu_modal', onClose)
$('#fu_form').toggleClass('busy', false) $('#fu_form').toggleClass('busy', false)
Input.blockKeys(true) input.blockKeys(true)
} }
function onClose () { function onClose () {
console.log('Upload modal closed.') console.log('Upload modal closed.')
clearTimeout(fuTout) clearTimeout(fuTout)
line_i = 0 line_i = 0
Input.blockKeys(false) input.blockKeys(false)
} }
function fuStatus (msg) { function fuStatus (msg) {
@ -65,7 +65,7 @@ window.TermUpl = (function () {
return return
} }
if (!Conn.canSend()) { if (!conn.canSend()) {
// postpone // postpone
fuTout = setTimeout(fuSendLine, 1) fuTout = setTimeout(fuSendLine, 1)
return return
@ -84,7 +84,7 @@ window.TermUpl = (function () {
inline_pos += MAX_LINE_LEN inline_pos += MAX_LINE_LEN
} }
if (!Input.sendString(chunk)) { if (!input.sendString(chunk)) {
fuStatus('FAILED!') fuStatus('FAILED!')
return return
} }
@ -101,7 +101,7 @@ window.TermUpl = (function () {
} }
function closeWhenReady () { function closeWhenReady () {
if (!Conn.canSend()) { if (!conn.canSend()) {
// stuck in XOFF still, wait to process... // stuck in XOFF still, wait to process...
fuStatus('Waiting for Tx buffer...') fuStatus('Waiting for Tx buffer...')
setTimeout(closeWhenReady, 100) setTimeout(closeWhenReady, 100)
@ -143,4 +143,4 @@ window.TermUpl = (function () {
start: fuSend, start: fuSend,
open: fuOpen open: fuOpen
} }
})() }

Loading…
Cancel
Save