Add mouse events, ⌃⇧C to copy, alt-select override
Also prevent body scroll when the terminal is scrollable
This commit is contained in:
@@ -108,6 +108,8 @@ class TermScreen {
|
|||||||
end: [0, 0]
|
end: [0, 0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.mouseMode = { clicks: false, movement: false }
|
||||||
|
|
||||||
const self = this
|
const self = this
|
||||||
this.window = new Proxy(this._window, {
|
this.window = new Proxy(this._window, {
|
||||||
set (target, key, value, receiver) {
|
set (target, key, value, receiver) {
|
||||||
@@ -128,12 +130,15 @@ class TermScreen {
|
|||||||
|
|
||||||
let selecting = false
|
let selecting = false
|
||||||
this.canvas.addEventListener('mousedown', e => {
|
this.canvas.addEventListener('mousedown', e => {
|
||||||
if (this.selection.selectable) {
|
if (this.selection.selectable || e.altKey) {
|
||||||
let x = e.offsetX
|
let x = e.offsetX
|
||||||
let y = e.offsetY
|
let y = e.offsetY
|
||||||
selecting = true
|
selecting = true
|
||||||
this.selection.start = this.selection.end = this.screenToGrid(x, y)
|
this.selection.start = this.selection.end = this.screenToGrid(x, y)
|
||||||
this.scheduleDraw()
|
this.scheduleDraw()
|
||||||
|
} else {
|
||||||
|
Input.onMouseDown(...this.screenToGrid(e.offsetX, e.offsetY),
|
||||||
|
e.button + 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
window.addEventListener('mousemove', e => {
|
window.addEventListener('mousemove', e => {
|
||||||
@@ -150,6 +155,32 @@ class TermScreen {
|
|||||||
Object.assign(this.selection, this.getNormalizedSelection())
|
Object.assign(this.selection, this.getNormalizedSelection())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this.canvas.addEventListener('mousemove', e => {
|
||||||
|
if (!selecting) {
|
||||||
|
Input.onMouseMove(...this.screenToGrid(e.offsetX, e.offsetY))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.canvas.addEventListener('mouseup', e => {
|
||||||
|
if (!selecting) {
|
||||||
|
Input.onMouseUp(...this.screenToGrid(e.offsetX, e.offsetY),
|
||||||
|
e.button + 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.canvas.addEventListener('wheel', e => {
|
||||||
|
if (this.mouseMode.clicks) {
|
||||||
|
Input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY),
|
||||||
|
e.deltaY > 0 ? 1 : -1)
|
||||||
|
|
||||||
|
// prevent page scrolling
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// bind ctrl+shift+c to copy
|
||||||
|
key('⌃+⇧+c', e => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.copySelectionToClipboard()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get colors () { return this._colors }
|
get colors () { return this._colors }
|
||||||
@@ -243,7 +274,6 @@ class TermScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isInSelection (col, line) {
|
isInSelection (col, line) {
|
||||||
if (!this.selection.selectable) return false
|
|
||||||
let { start, end } = this.getNormalizedSelection()
|
let { start, end } = this.getNormalizedSelection()
|
||||||
let colAfterStart = start[0] <= col
|
let colAfterStart = start[0] <= col
|
||||||
let colBeforeEnd = col < end[0]
|
let colBeforeEnd = col < end[0]
|
||||||
@@ -256,6 +286,44 @@ class TermScreen {
|
|||||||
else return start[1] < line && line < end[1]
|
else return start[1] < line && line < end[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSelectedText () {
|
||||||
|
const screenLength = this.window.width * this.window.height
|
||||||
|
let lines = []
|
||||||
|
let previousLineIndex = -1
|
||||||
|
|
||||||
|
for (let cell = 0; cell < screenLength; cell++) {
|
||||||
|
let x = cell % this.window.width
|
||||||
|
let y = Math.floor(cell / this.window.width)
|
||||||
|
|
||||||
|
if (this.isInSelection(x, y)) {
|
||||||
|
if (previousLineIndex !== y) {
|
||||||
|
previousLineIndex = y
|
||||||
|
lines.push('')
|
||||||
|
}
|
||||||
|
lines[lines.length - 1] += this.screen[cell]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
copySelectionToClipboard () {
|
||||||
|
let selectedText = this.getSelectedText()
|
||||||
|
// don't copy anything if nothing is selected
|
||||||
|
if (!selectedText) return
|
||||||
|
let textarea = document.createElement('textarea')
|
||||||
|
document.body.appendChild(textarea)
|
||||||
|
textarea.value = selectedText
|
||||||
|
textarea.select()
|
||||||
|
if (document.execCommand('copy')) {
|
||||||
|
Notify.show(`Copied to clipboard`)
|
||||||
|
} else {
|
||||||
|
// unsuccessful copy
|
||||||
|
// TODO: do something?
|
||||||
|
}
|
||||||
|
document.body.removeChild(textarea)
|
||||||
|
}
|
||||||
|
|
||||||
screenToGrid (x, y) {
|
screenToGrid (x, y) {
|
||||||
let charSize = this.getCharSize()
|
let charSize = this.getCharSize()
|
||||||
let cellWidth = charSize.width * this.window.gridScaleX
|
let cellWidth = charSize.width * this.window.gridScaleX
|
||||||
@@ -421,6 +489,11 @@ class TermScreen {
|
|||||||
let trackMouseMovement = !!(attributes & 1 << 6)
|
let trackMouseMovement = !!(attributes & 1 << 6)
|
||||||
|
|
||||||
Input.setMouseMode(trackMouseClicks, trackMouseMovement)
|
Input.setMouseMode(trackMouseClicks, trackMouseMovement)
|
||||||
|
this.selection.selectable = !trackMouseMovement
|
||||||
|
this.mouseMode = {
|
||||||
|
clicks: trackMouseClicks,
|
||||||
|
movement: trackMouseMovement
|
||||||
|
}
|
||||||
|
|
||||||
let showButtons = !!(attributes & 1 << 7)
|
let showButtons = !!(attributes & 1 << 7)
|
||||||
let showConfigLinks = !!(attributes & 1 << 8)
|
let showConfigLinks = !!(attributes & 1 << 8)
|
||||||
|
|||||||
Reference in New Issue
Block a user