updated to latest backend, cursor variants setting, reformat some files

cpsdqs/unified-input
Ondřej Hruška 7 years ago
parent 963bfce9cc
commit 036a58ce12
  1. 3
      jssrc/appcommon.js
  2. 40
      jssrc/soft_keyboard.js
  3. 8
      jssrc/term_input.js
  4. 116
      jssrc/term_screen.js
  5. 12
      jssrc/utils.js
  6. 9
      lang/en.php
  7. 19
      pages/cfg_term.php

@ -134,7 +134,8 @@ if (!String.fromCodePoint) {
var object = {}; var object = {};
var $defineProperty = Object.defineProperty; var $defineProperty = Object.defineProperty;
var result = $defineProperty(object, object, object) && $defineProperty; var result = $defineProperty(object, object, object) && $defineProperty;
} catch(error) {} } catch (error) {
}
return result; return result;
}()); }());
var stringFromCharCode = String.fromCharCode; var stringFromCharCode = String.fromCharCode;

@ -1,27 +1,29 @@
$.ready(() => { $.ready(() => {
const input = qs('#softkb-input') const input = qs('#softkb-input');
let keyboardOpen = false if (!input) return; // abort, we're not on the terminal page
let keyboardOpen = false;
let updateInputPosition = function () { let updateInputPosition = function () {
if (!keyboardOpen) return if (!keyboardOpen) return;
let [x, y] = Screen.gridToScreen(Screen.cursor.x, Screen.cursor.y) let [x, y] = Screen.gridToScreen(Screen.cursor.x, Screen.cursor.y);
input.style.transform = `translate(${x}px, ${y}px)` input.style.transform = `translate(${x}px, ${y}px)`
} };
input.addEventListener('focus', () => { input.addEventListener('focus', () => {
keyboardOpen = true keyboardOpen = true;
updateInputPosition() updateInputPosition()
}) });
input.addEventListener('blur', () => (keyboardOpen = false)) input.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) input.focus();
else input.blur() else input.blur()
} };
let lastCompositionString = ''; let lastCompositionString = '';
let compositing = false; let compositing = false;
@ -47,7 +49,7 @@ $.ready(() => {
newValue) newValue)
} }
lastCompositionString = newValue; lastCompositionString = newValue;
} };
input.addEventListener('keydown', e => { input.addEventListener('keydown', e => {
if (e.key === 'Unidentified') return; if (e.key === 'Unidentified') return;
@ -55,9 +57,9 @@ $.ready(() => {
e.preventDefault(); e.preventDefault();
input.value = ''; input.value = '';
if (e.key === 'Backspace') Input.sendString('\b') if (e.key === 'Backspace') Input.sendString('\b');
else if (e.key === 'Enter') Input.sendString('\x0d') else if (e.key === 'Enter') Input.sendString('\x0d')
}) });
input.addEventListener('input', e => { input.addEventListener('input', e => {
e.stopPropagation(); e.stopPropagation();
@ -66,11 +68,11 @@ $.ready(() => {
} else { } else {
if (e.data) Input.sendString(e.data); if (e.data) Input.sendString(e.data);
else if (e.inputType === 'deleteContentBackward') { else if (e.inputType === 'deleteContentBackward') {
lastCompositionString lastCompositionString = '';
sendInputDelta(''); sendInputDelta('');
} }
} }
}) });
input.addEventListener('compositionstart', e => { input.addEventListener('compositionstart', e => {
lastCompositionString = ''; lastCompositionString = '';
compositing = true; compositing = true;
@ -82,4 +84,4 @@ $.ready(() => {
}); });
Screen.on('open-soft-keyboard', () => input.focus()) Screen.on('open-soft-keyboard', () => input.focus())
}) });

@ -22,6 +22,7 @@ var Input = (function() {
mt_click: false, mt_click: false,
mt_move: false, mt_move: false,
no_keys: false, no_keys: false,
crlf_mode: false,
}; };
/** Send a literal message */ /** Send a literal message */
@ -53,7 +54,7 @@ var Input = (function() {
var keymap = { var keymap = {
'tab': '\x09', 'tab': '\x09',
'backspace': '\x08', 'backspace': '\x08',
'enter': '\x0d', 'enter': opts.crlf_mode ? '\x0d\x0a' : '\x0d',
'ctrl+enter': '\x0a', 'ctrl+enter': '\x0a',
'esc': '\x1b', 'esc': '\x1b',
'up': ca('\x1bOA', '\x1b[A'), 'up': ca('\x1bOA', '\x1b[A'),
@ -207,11 +208,12 @@ var Input = (function() {
sendString: sendStrMsg, sendString: sendStrMsg,
/** Enable alternate key modes (cursors, numpad, fn) */ /** Enable alternate key modes (cursors, numpad, fn) */
setAlts: function(cu, np, fn) { setAlts: function(cu, np, fn, crlf) {
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) { if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn || opts.crlf_mode != crlf) {
opts.cu_alt = cu; opts.cu_alt = cu;
opts.np_alt = np; opts.np_alt = np;
opts.fn_alt = fn; opts.fn_alt = fn;
opts.crlf_mode = crlf;
// rebind keys - codes have changed // rebind keys - codes have changed
_bindFnKeys(); _bindFnKeys();

@ -64,6 +64,7 @@ class TermScreen {
visible: true, visible: true,
hanging: false, hanging: false,
style: 'block', style: 'block',
blinkEnable: true,
blinkInterval: 0, blinkInterval: 0,
}; };
@ -205,17 +206,17 @@ class TermScreen {
e.preventDefault(); e.preventDefault();
selectEnd(...touchPosition); selectEnd(...touchPosition);
let touchSelectMenu = qs('#touch-select-menu') let touchSelectMenu = qs('#touch-select-menu');
touchSelectMenu.classList.add('open'); touchSelectMenu.classList.add('open');
let rect = touchSelectMenu.getBoundingClientRect() let rect = touchSelectMenu.getBoundingClientRect();
// use middle position for x and one line above for y // use middle position for x and one line above for y
let selectionPos = this.gridToScreen( let selectionPos = this.gridToScreen(
(this.selection.start[0] + this.selection.end[0]) / 2, (this.selection.start[0] + this.selection.end[0]) / 2,
this.selection.start[1] - 1 this.selection.start[1] - 1
); );
selectionPos[0] -= rect.width / 2 selectionPos[0] -= rect.width / 2;
selectionPos[1] -= rect.height / 2 selectionPos[1] -= rect.height / 2;
touchSelectMenu.style.transform = `translate(${selectionPos[0]}px, ${ touchSelectMenu.style.transform = `translate(${selectionPos[0]}px, ${
selectionPos[1]}px)` selectionPos[1]}px)`
} }
@ -242,13 +243,15 @@ class TermScreen {
e.preventDefault(); e.preventDefault();
this.emit('open-soft-keyboard'); this.emit('open-soft-keyboard');
} }
}) });
$.ready(() => { $.ready(() => {
let copyButton = qs('#touch-select-copy-btn') let copyButton = qs('#touch-select-copy-btn');
if (copyButton) {
copyButton.addEventListener('click', () => { copyButton.addEventListener('click', () => {
this.copySelectionToClipboard(); this.copySelectionToClipboard();
}); });
}
}); });
this.canvas.addEventListener('mousemove', e => { this.canvas.addEventListener('mousemove', e => {
@ -274,7 +277,7 @@ class TermScreen {
this.canvas.addEventListener('contextmenu', e => { this.canvas.addEventListener('contextmenu', e => {
// prevent mouse keys getting stuck // prevent mouse keys getting stuck
e.preventDefault(); e.preventDefault();
}) });
// bind ctrl+shift+c to copy // bind ctrl+shift+c to copy
key('⌃+⇧+c', e => { key('⌃+⇧+c', e => {
@ -333,8 +336,8 @@ class TermScreen {
} }
getColor (i) { getColor (i) {
if (i === -1) return SELECTION_FG if (i === -1) return SELECTION_FG;
if (i === -2) return SELECTION_BG if (i === -2) return SELECTION_BG;
return this.colors[i] return this.colors[i]
} }
@ -398,29 +401,32 @@ class TermScreen {
const cellSize = this.getCellSize(); const cellSize = this.getCellSize();
// real height of the canvas element in pixels // real height of the canvas element in pixels
let realWidth = width * cellSize.width let realWidth = width * cellSize.width;
let realHeight = height * cellSize.height let realHeight = height * cellSize.height;
if (fitIntoWidth && fitIntoHeight) { if (fitIntoWidth && fitIntoHeight) {
if (realWidth > fitIntoWidth || realHeight > fitIntoHeight) { if (realWidth > fitIntoWidth || realHeight > fitIntoHeight) {
let terminalAspect = realWidth / realHeight let terminalAspect = realWidth / realHeight;
let fitAspect = fitIntoWidth / fitIntoHeight let fitAspect = fitIntoWidth / fitIntoHeight;
if (terminalAspect < fitAspect) { if (terminalAspect < fitAspect) {
// align heights // align heights
realHeight = fitIntoHeight realHeight = fitIntoHeight;
realWidth = realHeight * terminalAspect realWidth = realHeight * terminalAspect
} else { }
else {
// align widths // align widths
realWidth = fitIntoWidth realWidth = fitIntoWidth;
realHeight = realWidth / terminalAspect realHeight = realWidth / terminalAspect
} }
} }
} else if (fitIntoWidth && realWidth > fitIntoWidth) { }
realHeight = fitIntoWidth / (realWidth / realHeight) else if (fitIntoWidth && realWidth > fitIntoWidth) {
realHeight = fitIntoWidth / (realWidth / realHeight);
realWidth = fitIntoWidth realWidth = fitIntoWidth
} else if (fitIntoHeight && realHeight > fitIntoHeight) { }
realWidth = fitIntoHeight * (realWidth / realHeight) else if (fitIntoHeight && realHeight > fitIntoHeight) {
realWidth = fitIntoHeight * (realWidth / realHeight);
realHeight = fitIntoHeight realHeight = fitIntoHeight
} }
@ -552,11 +558,11 @@ class TermScreen {
let underline = false; let underline = false;
let blink = false; let blink = false;
let strike = false; let strike = false;
if (attrs & 1 << 1) ctx.globalAlpha = 0.5; if (attrs & (1 << 1)) ctx.globalAlpha = 0.5;
if (attrs & 1 << 3) underline = true; if (attrs & (1 << 3)) underline = true;
if (attrs & 1 << 4) blink = true; if (attrs & (1 << 4)) blink = true;
if (attrs & 1 << 5) text = TermScreen.alphaToFraktur(text); if (attrs & (1 << 5)) text = TermScreen.alphaToFraktur(text);
if (attrs & 1 << 6) strike = true; if (attrs & (1 << 6)) strike = true;
if (!blink || this.window.blinkStyleOn) { if (!blink || this.window.blinkStyleOn) {
ctx.fillStyle = this.getColor(fg); ctx.fillStyle = this.getColor(fg);
@ -618,14 +624,18 @@ class TermScreen {
// Map of (cell index) -> boolean, whether or not a cell needs to be redrawn // Map of (cell index) -> boolean, whether or not a cell needs to be redrawn
const updateMap = new Map(); const updateMap = new Map();
const cursorActive = (this.cursor.blinkOn || !this.cursor.blinkEnable);
for (let cell = 0; cell < screenLength; cell++) { for (let cell = 0; cell < screenLength; cell++) {
let x = cell % width; let x = cell % width;
let y = Math.floor(cell / width); let y = Math.floor(cell / width);
let isCursor = this.cursor.x === x && this.cursor.y === y && let isCursor = !this.cursor.hanging
!this.cursor.hanging; && this.cursor.x === x
let invertForCursor = isCursor && this.cursor.blinkOn && && this.cursor.y === y;
this.cursor.style === 'block';
let inSelection = this.isInSelection(x, y) let invertForCursor = isCursor && cursorActive && this.cursor.style === 'block';
let inSelection = this.isInSelection(x, y);
let text = this.screen[cell]; let text = this.screen[cell];
let fg = invertForCursor ? this.screenBG[cell] : this.screenFG[cell]; let fg = invertForCursor ? this.screenBG[cell] : this.screenFG[cell];
@ -636,7 +646,7 @@ class TermScreen {
if (invertForCursor && fg === bg) bg = fg === 0 ? 7 : 0; if (invertForCursor && fg === bg) bg = fg === 0 ? 7 : 0;
if (inSelection) { if (inSelection) {
fg = -1 fg = -1;
bg = -2 bg = -2
} }
@ -695,7 +705,7 @@ class TermScreen {
this.drawnScreenAttrs[cell] = attrs; this.drawnScreenAttrs[cell] = attrs;
} }
if (isCursor && this.cursor.blinkOn && this.cursor.style !== 'block') { if (isCursor && cursorActive && this.cursor.style !== 'block') {
ctx.save(); ctx.save();
ctx.beginPath(); ctx.beginPath();
if (this.cursor.style === 'bar') { if (this.cursor.style === 'bar') {
@ -748,20 +758,21 @@ class TermScreen {
} }
// attributes // attributes
let attributes = parse2B(str, i); let attributes = parse3B(str, i);
i += 2; i += 3;
this.cursor.visible = !!(attributes & 1); this.cursor.visible = !!(attributes & 1);
this.cursor.hanging = !!(attributes & 1 << 1); this.cursor.hanging = !!(attributes & (1 << 1));
Input.setAlts( 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
!!(attributes & (1 << 12)) // crlf mode
); );
let trackMouseClicks = !!(attributes & 1 << 5); let trackMouseClicks = !!(attributes & (1 << 5));
let trackMouseMovement = !!(attributes & 1 << 6); let trackMouseMovement = !!(attributes & (1 << 6));
Input.setMouseMode(trackMouseClicks, trackMouseMovement); Input.setMouseMode(trackMouseClicks, trackMouseMovement);
this.selection.selectable = !trackMouseMovement; this.selection.selectable = !trackMouseMovement;
@ -771,12 +782,19 @@ class TermScreen {
movement: trackMouseMovement movement: trackMouseMovement
}; };
let showButtons = !!(attributes & 1 << 7); let showButtons = !!(attributes & (1 << 7));
let showConfigLinks = !!(attributes & 1 << 8); let showConfigLinks = !!(attributes & (1 << 8));
$('.x-term-conf-btn').toggleClass('hidden', !showConfigLinks); $('.x-term-conf-btn').toggleClass('hidden', !showConfigLinks);
$('#action-buttons').toggleClass('hidden', !showButtons); $('#action-buttons').toggleClass('hidden', !showButtons);
let cursorStyle = (attributes >> 9) & 0x07;
// 0 - Block blink, 2 - Block steady
// 3 - Under blink, 4 - Under steady
// 5 - I-bar blink, 6 - I-bar steady
this.cursor.style = cursorStyle<3?'block':cursorStyle<5?'line':'bar';
this.cursor.blinkEnable = cursorStyle === 0 || cursorStyle === 3 || cursorStyle === 5;
// content // content
let fg = 7; let fg = 7;
let bg = 0; let bg = 0;
@ -932,23 +950,23 @@ Screen.once('load', () => {
} }
}); });
let fitScreen = false let fitScreen = false;
function fitScreenIfNeeded () { function fitScreenIfNeeded () {
Screen.window.fitIntoWidth = fitScreen ? window.innerWidth : 0 Screen.window.fitIntoWidth = fitScreen ? window.innerWidth : 0;
Screen.window.fitIntoHeight = fitScreen ? window.innerHeight : 0 Screen.window.fitIntoHeight = fitScreen ? window.innerHeight : 0
} }
fitScreenIfNeeded(); fitScreenIfNeeded();
window.addEventListener('resize', fitScreenIfNeeded) window.addEventListener('resize', fitScreenIfNeeded);
window.toggleFitScreen = function () { window.toggleFitScreen = function () {
fitScreen = !fitScreen; fitScreen = !fitScreen;
const resizeButtonIcon = qs('#resize-button-icon') const resizeButtonIcon = qs('#resize-button-icon');
if (fitScreen) { if (fitScreen) {
resizeButtonIcon.classList.remove('icn-resize-small') resizeButtonIcon.classList.remove('icn-resize-small');
resizeButtonIcon.classList.add('icn-resize-full') resizeButtonIcon.classList.add('icn-resize-full')
} else { } else {
resizeButtonIcon.classList.remove('icn-resize-full') resizeButtonIcon.classList.remove('icn-resize-full');
resizeButtonIcon.classList.add('icn-resize-small') resizeButtonIcon.classList.add('icn-resize-small')
} }
fitScreenIfNeeded(); fitScreenIfNeeded();
} };

@ -1,11 +1,17 @@
/** Make a node */ /** Make a node */
function mk(e) {return document.createElement(e)} function mk(e) {
return document.createElement(e)
}
/** Find one by query */ /** Find one by query */
function qs(s) {return document.querySelector(s)} function qs(s) {
return document.querySelector(s)
}
/** Find all by query */ /** Find all by query */
function qsa(s) {return document.querySelectorAll(s)} function qsa(s) {
return document.querySelectorAll(s)
}
/** Convert any to bool safely */ /** Convert any to bool safely */
function bool(x) { function bool(x) {

@ -51,6 +51,7 @@ return [
'term.default_fg_bg' => 'Text / background', 'term.default_fg_bg' => 'Text / background',
'term.buttons' => 'Button labels', 'term.buttons' => 'Button labels',
'term.theme' => 'Color scheme', 'term.theme' => 'Color scheme',
'term.cursor_shape' => 'Cursor style',
'term.parser_tout_ms' => 'Parser timeout', 'term.parser_tout_ms' => 'Parser timeout',
'term.display_tout_ms' => 'Redraw delay', 'term.display_tout_ms' => 'Redraw delay',
'term.display_cooldown_ms' => 'Redraw cooldown', 'term.display_cooldown_ms' => 'Redraw cooldown',
@ -58,8 +59,16 @@ return [
'term.show_config_links' => 'Show nav links', 'term.show_config_links' => 'Show nav links',
'term.show_buttons' => 'Show buttons', 'term.show_buttons' => 'Show buttons',
'term.loopback' => 'Local Echo', 'term.loopback' => 'Local Echo',
'term.crlf_mode' => 'Enter sends CR+LF',
'term.button_msgs' => 'Button codes<br>(ASCII, dec, CSV)', 'term.button_msgs' => 'Button codes<br>(ASCII, dec, CSV)',
'cursor.block_blink' => 'Block, blinking',
'cursor.block_steady' => 'Block, steady',
'cursor.underline_blink' => 'Underline, blinking',
'cursor.underline_steady' => 'Underline, steady',
'cursor.bar_blink' => 'I-bar, blinking',
'cursor.bar_steady' => 'I-bar, steady',
// terminal color labels // terminal color labels
'color.0' => 'Black', 'color.0' => 'Black',
'color.1' => 'Red', 'color.1' => 'Red',

@ -108,6 +108,18 @@
<input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%"> <input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%">
</div> </div>
<div class="Row">
<label><?= tr("term.cursor_shape") ?></label>
<select name="cursor_shape" id="cursor_shape">
<option value="0"><?= tr("cursor.block_blink") ?></option>
<option value="2"><?= tr("cursor.block_steady") ?></option>
<option value="3"><?= tr("cursor.underline_blink") ?></option>
<option value="4"><?= tr("cursor.underline_steady") ?></option>
<option value="5"><?= tr("cursor.bar_blink") ?></option>
<option value="6"><?= tr("cursor.bar_steady") ?></option>
</select>
</div>
<div class="Row buttons"> <div class="Row buttons">
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a> <a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
</div> </div>
@ -153,6 +165,12 @@
<input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%"> <input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%">
</div> </div>
<div class="Row checkbox" >
<label><?= tr('term.crlf_mode') ?></label><!--
--><span class="box" tabindex=0 role=checkbox></span>
<input type="hidden" id="crlf_mode" name="crlf_mode" value="%crlf_mode%">
</div>
<div class="Row checkbox" > <div class="Row checkbox" >
<label><?= tr('term.show_buttons') ?></label><!-- <label><?= tr('term.show_buttons') ?></label><!--
--><span class="box" tabindex=0 role=checkbox></span> --><span class="box" tabindex=0 role=checkbox></span>
@ -179,6 +197,7 @@
<script> <script>
$('#default_fg').val(%default_fg%); $('#default_fg').val(%default_fg%);
$('#default_bg').val(%default_bg%); $('#default_bg').val(%default_bg%);
$('#cursor_shape').val(%cursor_shape%);
$('#theme').val(%theme%); $('#theme').val(%theme%);
function showColor() { function showColor() {

Loading…
Cancel
Save