diff --git a/html_orig/jssrc/term_screen.js b/html_orig/jssrc/term_screen.js
index 9ed87d9..885d720 100644
--- a/html_orig/jssrc/term_screen.js
+++ b/html_orig/jssrc/term_screen.js
@@ -97,6 +97,9 @@ class TermScreen {
this.mouseMode = { clicks: false, movement: false };
+ // event listeners
+ this._listeners = {};
+
const self = this;
this.window = new Proxy(this._window, {
set (target, key, value, receiver) {
@@ -159,21 +162,68 @@ class TermScreen {
e.deltaY > 0 ? 1 : -1);
// prevent page scrolling
- e.preventDefault()
+ e.preventDefault();
}
});
+ this.canvas.addEventListener('contextmenu', e => {
+ // prevent mouse keys getting stuck
+ e.preventDefault();
+ })
// bind ctrl+shift+c to copy
key('⌃+⇧+c', e => {
e.preventDefault();
this.copySelectionToClipboard()
- })
+ });
+ }
+
+ on (event, listener) {
+ if (!this._listeners[event]) this._listeners[event] = [];
+ this._listeners[event].push({ listener });
+ }
+
+ once (event, listener) {
+ if (!this._listeners[event]) this._listeners[event] = [];
+ this._listeners[event].push({ listener, once: true });
+ }
+
+ off (event, listener) {
+ let listeners = this._listeners[event];
+ if (listeners) {
+ for (let i in listeners) {
+ if (listeners[i].listener === listener) {
+ listeners.splice(i, 1);
+ break;
+ }
+ }
+ }
+ }
+
+ emit (event, ...args) {
+ let listeners = this._listeners[event];
+ if (listeners) {
+ let remove = [];
+ for (let listener of listeners) {
+ try {
+ listener.listener(...args);
+ if (listener.once) remove.push(listener);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+ // this needs to be done in this roundabout way because for loops
+ // do not like arrays with changing lengths
+ for (let listener of remove) {
+ listeners.splice(listeners.indexOf(listener), 1);
+ }
+ }
}
get colors () { return this._colors }
set colors (theme) {
this._colors = theme;
- this.scheduleDraw()
+ this.scheduleDraw();
}
// schedule a draw in the next tick
@@ -197,6 +247,15 @@ class TermScreen {
}
}
+ getCellSize () {
+ let charSize = this.getCharSize();
+
+ return {
+ width: Math.ceil(charSize.width * this.window.gridScaleX),
+ height: Math.ceil(charSize.height * this.window.gridScaleY)
+ }
+ }
+
updateSize () {
this._window.devicePixelRatio = window.devicePixelRatio || 1;
@@ -212,15 +271,12 @@ class TermScreen {
const {
width, height, devicePixelRatio, gridScaleX, gridScaleY
} = this.window;
- const charSize = this.getCharSize();
-
- this.canvas.width = width * devicePixelRatio * charSize.width * gridScaleX;
- this.canvas.style.width = `${Math.ceil(width * charSize.width *
- gridScaleX)}px`;
- this.canvas.height = height * devicePixelRatio * charSize.height *
- gridScaleY;
- this.canvas.style.height = `${Math.ceil(height * charSize.height *
- gridScaleY)}px`
+ const cellSize = this.getCellSize();
+
+ this.canvas.width = width * devicePixelRatio * cellSize.width;
+ this.canvas.style.width = `${width * cellSize.width}px`;
+ this.canvas.height = height * devicePixelRatio * cellSize.height;
+ this.canvas.style.height = `${height * cellSize.height}px`
}
}
@@ -311,16 +367,20 @@ class TermScreen {
}
screenToGrid (x, y) {
- let charSize = this.getCharSize();
- let cellWidth = charSize.width * this.window.gridScaleX;
- let cellHeight = charSize.height * this.window.gridScaleY;
+ let cellSize = this.getCellSize();
return [
- Math.floor((x + cellWidth / 2) / cellWidth),
- Math.floor(y / cellHeight)
+ Math.floor((x + cellSize.width / 2) / cellSize.width),
+ Math.floor(y / cellSize.height)
];
}
+ gridToScreen (x, y) {
+ let cellSize = this.getCellSize();
+
+ return [ x * cellSize.width, y * cellSize.height ];
+ }
+
drawCell ({ x, y, charSize, cellWidth, cellHeight, text, fg, bg, attrs },
compositeAbove = false) {
const ctx = this.ctx;
@@ -377,8 +437,7 @@ class TermScreen {
} = this.window;
const charSize = this.getCharSize();
- const cellWidth = charSize.width * gridScaleX;
- const cellHeight = charSize.height * gridScaleY;
+ const { width: cellWidth, height: cellHeight } = this.getCellSize();
const screenWidth = width * cellWidth;
const screenHeight = height * cellHeight;
const screenLength = width * height;
@@ -456,7 +515,10 @@ class TermScreen {
this.cursor.x = cursorX;
this.cursor.y = cursorY;
- if (cursorMoved) this.resetCursorBlink();
+ if (cursorMoved) {
+ this.resetCursorBlink();
+ this.emit('cursor-moved');
+ }
// attributes
let attributes = parse2B(str, i);
@@ -476,6 +538,7 @@ class TermScreen {
Input.setMouseMode(trackMouseClicks, trackMouseMovement);
this.selection.selectable = !trackMouseMovement;
+ $(this.canvas).toggleClass('selectable', !trackMouseMovement);
this.mouseMode = {
clicks: trackMouseClicks,
movement: trackMouseMovement
@@ -545,7 +608,7 @@ class TermScreen {
}
this.scheduleDraw();
- if (this.onload) this.onload()
+ this.emit('load');
}
/** Apply labels to buttons and screen title (leading T removed already) */
@@ -622,7 +685,7 @@ class TermScreen {
const Screen = new TermScreen();
let didAddScreen = false;
-Screen.onload = function () {
+Screen.on('load', () => {
if (didAddScreen) return;
didAddScreen = true;
qs('#screen').appendChild(Screen.canvas);
@@ -631,4 +694,4 @@ Screen.onload = function () {
Screen.colors = themes[item.substr(6)]
}
}
-};
+});
diff --git a/html_orig/sass/pages/_term.scss b/html_orig/sass/pages/_term.scss
index 162e031..977fa7c 100755
--- a/html_orig/sass/pages/_term.scss
+++ b/html_orig/sass/pages/_term.scss
@@ -25,27 +25,8 @@ body.term {
font-size: 20px; // some font heights cause visual glitches with some font renderers. This should be configurable.
font-family: $screen-stack;
- span {
- white-space: pre;
- }
-
- > span {
- position: relative;
- cursor: pointer;
-
- &::before {
- content: " ";
- }
-
- > span {
- position:absolute;
- left: 0;
- z-index: 1;
- }
- }
-
- &.noselect {
- @include noselect();
+ canvas.selectable {
+ cursor: text;
}
}