Scroll lock

This commit is contained in:
Florian Mounier
2015-04-27 15:42:14 +02:00
parent 790a4b8072
commit 4492b59e99
7 changed files with 113 additions and 89 deletions

View File

@@ -19,7 +19,7 @@ $fg: #fff !default
$shadow: 6px !default
$shadow-alpha: .5 !default
.terminal
body
text-shadow: 0 0 $shadow rgba($fg, $shadow-alpha)
transition: 200ms
transform-origin: bottom
@@ -68,3 +68,10 @@ $shadow-alpha: .5 !default
&.stopped
-webkit-filter: brightness(50%)
filter: brightness(50%)
&.locked
&::-webkit-scrollbar-thumb
background: rgba(red, .7)
&::-webkit-scrollbar-thumb:hover
background: rgba(red, .8)

View File

@@ -25,14 +25,14 @@ body
overflow-x: hidden
overflow-y: scroll
::-webkit-scrollbar
&::-webkit-scrollbar
background: $bg
width: .75em
::-webkit-scrollbar-thumb
&::-webkit-scrollbar-thumb
background: rgba($fg, .1)
::-webkit-scrollbar-thumb:hover
&::-webkit-scrollbar-thumb:hover
background: rgba($fg, .15)
.terminal

File diff suppressed because one or more lines are too long

View File

@@ -76,26 +76,26 @@ body {
/* GNU General Public License for more details. */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
.terminal {
body {
text-shadow: 0 0 6px rgba(255, 255, 255, 0.5);
transition: 200ms;
transform-origin: bottom; }
.terminal.bell {
body.bell {
-webkit-filter: blur(2px);
filter: blur(2px); }
.terminal.skip {
body.skip {
-webkit-filter: sepia(1);
filter: sepia(1); }
.terminal.selection {
body.selection {
-webkit-filter: saturate(2);
filter: saturate(2); }
.terminal.alarm {
body.alarm {
-webkit-filter: hue-rotate(150deg);
filter: hue-rotate(150deg); }
.terminal.dead {
body.dead {
-webkit-filter: grayscale(1);
filter: grayscale(1); }
.terminal.dead:after {
body.dead:after {
content: "CLOSED";
font-size: 15em;
display: flex;
@@ -109,13 +109,17 @@ body {
transform: rotate(-45deg);
opacity: .2;
font-weight: 900; }
.terminal.copied {
body.copied {
transform: scale(1.05); }
.terminal.pasted {
body.pasted {
transform: scale(.95); }
.terminal.stopped {
body.stopped {
-webkit-filter: brightness(50%);
filter: brightness(50%); }
body.locked::-webkit-scrollbar-thumb {
background: rgba(255, 0, 0, 0.7); }
body.locked::-webkit-scrollbar-thumb:hover {
background: rgba(255, 0, 0, 0.8); }
/* *-* coding: utf-8 *-* */
/* This file is part of butterfly */
@@ -3026,15 +3030,12 @@ body {
white-space: nowrap;
overflow-x: hidden;
overflow-y: scroll; }
::-webkit-scrollbar {
body::-webkit-scrollbar {
background: #110f13;
width: .75em; }
::-webkit-scrollbar-thumb {
body::-webkit-scrollbar-thumb {
background: rgba(244, 234, 213, 0.1); }
::-webkit-scrollbar-thumb:hover {
body::-webkit-scrollbar-thumb:hover {
background: rgba(244, 234, 213, 0.15); }
.terminal {

View File

@@ -150,21 +150,19 @@
this.body = this.document.getElementsByTagName('body')[0];
this.html_escapes_enabled = this.body.getAttribute('data-allow-html') === 'yes';
this.force_width = this.body.getAttribute('data-force-unicode-width') === 'yes';
this.element = this.document.createElement('div');
this.element.className = 'terminal focus';
this.element.style.outline = 'none';
this.element.setAttribute('tabindex', 0);
this.element.setAttribute('spellcheck', 'false');
this.parent.insertBefore(this.element, this.parent.firstChild);
this.body.className = 'terminal focus';
this.body.style.outline = 'none';
this.body.setAttribute('tabindex', 0);
this.body.setAttribute('spellcheck', 'false');
div = this.document.createElement('div');
div.className = 'line';
this.element.appendChild(div);
this.body.appendChild(div);
this.children = [div];
this.compute_char_size();
this.cols = Math.floor(this.element.clientWidth / this.char_size.width);
this.cols = Math.floor(this.body.clientWidth / this.char_size.width);
this.rows = Math.floor(window.innerHeight / this.char_size.height);
px = window.innerHeight % this.char_size.height;
this.element.style['padding-bottom'] = px + "px";
this.body.style['padding-bottom'] = px + "px";
this.scrollback = 1000000;
this.buff_size = 100000;
this.visualBell = 100;
@@ -222,6 +220,7 @@
this.queue = '';
this.scrollTop = 0;
this.scrollBottom = this.rows - 1;
this.scrollLock = false;
this.applicationKeypad = false;
this.applicationCursor = false;
this.originMode = false;
@@ -279,8 +278,8 @@
this.send('\x1b[I');
}
this.showCursor();
this.element.classList.add('focus');
return this.element.classList.remove('blur');
this.body.classList.add('focus');
return this.body.classList.remove('blur');
};
Terminal.prototype.blur = function() {
@@ -290,8 +289,8 @@
if (this.sendFocus) {
this.send('\x1b[O');
}
this.element.classList.add('blur');
return this.element.classList.remove('focus');
this.body.classList.add('blur');
return this.body.classList.remove('focus');
};
Terminal.prototype.initmouse = function() {
@@ -404,7 +403,7 @@
var h, w, x, y;
x = ev.pageX;
y = ev.pageY - window.scrollY;
w = _this.element.clientWidth;
w = _this.body.clientWidth;
h = window.innerHeight;
x = Math.ceil((x / w) * _this.cols);
y = Math.ceil((y / h) * _this.rows);
@@ -479,7 +478,7 @@
if (force == null) {
force = false;
}
ref = this.element.querySelectorAll(".cursor");
ref = this.body.querySelectorAll(".cursor");
for (k = 0, len = ref.length; k < len; k++) {
cursor = ref[k];
cursor.parentNode.replaceChild(this.document.createTextNode(cursor.textContent), cursor);
@@ -608,7 +607,7 @@
group = this.document.createElement('div');
group.className = 'group';
group.innerHTML = new_out;
this.element.appendChild(group);
this.body.appendChild(group);
this.screen = this.screen.slice(-this.rows);
this.shift = 0;
lines = document.querySelectorAll('.line');
@@ -627,13 +626,15 @@
}
this.children = Array.prototype.slice.call(lines, -this.rows);
}
if (!this.scrollLock) {
return this.native_scroll_to();
}
};
Terminal.prototype._cursorBlink = function() {
var cursor;
this.cursorState ^= 1;
cursor = this.element.querySelector(".cursor");
cursor = this.body.querySelector(".cursor");
if (!cursor) {
return;
}
@@ -1269,12 +1270,12 @@
}
if (ev.altKey && ev.keyCode === 90 && !this.skipNextKey) {
this.skipNextKey = true;
this.element.classList.add('skip');
this.body.classList.add('skip');
return cancel(ev);
}
if (this.skipNextKey) {
this.skipNextKey = false;
this.element.classList.remove('skip');
this.body.classList.remove('skip');
return true;
}
switch (ev.keyCode) {
@@ -1409,6 +1410,14 @@
case 123:
key = "\x1b[24~";
break;
case 145:
this.scrollLock = !this.scrollLock;
if (this.scrollLock) {
this.body.classList.add('locked');
} else {
this.body.classList.remove('locked');
}
return cancel(ev);
default:
if (ev.ctrlKey) {
if (ev.keyCode >= 65 && ev.keyCode <= 90) {
@@ -1421,7 +1430,7 @@
clearTimeout(id);
}
}
this.element.classList.add('stopped');
this.body.classList.add('stopped');
this.stop = true;
} else if (this.stop) {
return true;
@@ -1524,10 +1533,10 @@
if (!this.visualBell) {
return;
}
this.element.classList.add(cls);
this.body.classList.add(cls);
return this.t_bell = setTimeout(((function(_this) {
return function() {
return _this.element.classList.remove(cls);
return _this.body.classList.remove(cls);
};
})(this)), this.visualBell);
};
@@ -1543,10 +1552,10 @@
old_cols = this.cols;
old_rows = this.rows;
this.compute_char_size();
this.cols = x || Math.floor(this.element.clientWidth / this.char_size.width);
this.cols = x || Math.floor(this.body.clientWidth / this.char_size.width);
this.rows = y || Math.floor(window.innerHeight / this.char_size.height);
px = window.innerHeight % this.char_size.height;
this.element.style['padding-bottom'] = px + "px";
this.body.style['padding-bottom'] = px + "px";
if ((!x && !y) && old_cols === this.cols && old_rows === this.rows) {
return;
}
@@ -1569,7 +1578,7 @@
this.setupStops(old_cols);
j = old_rows;
if (j < this.rows) {
el = this.element;
el = this.body;
while (j++ < this.rows) {
if (this.screen.length < this.rows) {
this.screen.push([this.blank_line(), true]);
@@ -2202,7 +2211,7 @@
this.vt200Mouse = params === 1000;
this.normalMouse = params > 1000;
this.mouseEvents = true;
return this.element.style.cursor = 'pointer';
return this.body.style.cursor = 'pointer';
case 1004:
return this.sendFocus = true;
case 1005:
@@ -2278,7 +2287,7 @@
this.vt200Mouse = false;
this.normalMouse = false;
this.mouseEvents = false;
return this.element.style.cursor = "";
return this.body.style.cursor = "";
case 1004:
return this.sendFocus = false;
case 1005:

File diff suppressed because one or more lines are too long

View File

@@ -56,25 +56,22 @@ class Terminal
'data-force-unicode-width') is 'yes'
# Main terminal element
@element = @document.createElement('div')
@element.className = 'terminal focus'
@element.style.outline = 'none'
@element.setAttribute 'tabindex', 0
@element.setAttribute 'spellcheck', 'false'
@parent.insertBefore @element, @parent.firstChild
@body.className = 'terminal focus'
@body.style.outline = 'none'
@body.setAttribute 'tabindex', 0
@body.setAttribute 'spellcheck', 'false'
# Adding one line to compute char size
div = @document.createElement('div')
div.className = 'line'
@element.appendChild(div)
@body.appendChild(div)
@children = [div]
@compute_char_size()
@cols = Math.floor(@element.clientWidth / @char_size.width)
@cols = Math.floor(@body.clientWidth / @char_size.width)
@rows = Math.floor(window.innerHeight / @char_size.height)
px = window.innerHeight % @char_size.height
@element.style['padding-bottom'] = "#{px}px"
@body.style['padding-bottom'] = "#{px}px"
@scrollback = 1000000
@buff_size = 100000
@@ -130,6 +127,7 @@ class Terminal
@scrollTop = 0
@scrollBottom = @rows - 1
@scrollLock = false
# modes
@applicationKeypad = false
@@ -183,16 +181,16 @@ class Terminal
focus: ->
@send('\x1b[I') if @sendFocus
@showCursor()
@element.classList.add('focus')
@element.classList.remove('blur')
@body.classList.add('focus')
@body.classList.remove('blur')
blur: ->
@cursorState = 1
@screen[@y + @shift][1] = true
@refresh()
@send('\x1b[O') if @sendFocus
@element.classList.add('blur')
@element.classList.remove('focus')
@body.classList.add('blur')
@body.classList.remove('focus')
# XTerm mouse events
# http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
@@ -327,7 +325,7 @@ class Terminal
y = ev.pageY - window.scrollY
# convert to cols/rows
w = @element.clientWidth
w = @body.clientWidth
h = window.innerHeight
x = Math.ceil((x / w) * @cols)
y = Math.ceil((y / h) * @rows)
@@ -378,7 +376,7 @@ class Terminal
cancel ev
refresh: (force=false) ->
for cursor in @element.querySelectorAll(".cursor")
for cursor in @body.querySelectorAll(".cursor")
cursor.parentNode.replaceChild(
@document.createTextNode(cursor.textContent), cursor)
new_out = ''
@@ -486,7 +484,7 @@ class Terminal
group = @document.createElement('div')
group.className = 'group'
group.innerHTML = new_out
@element.appendChild group
@body.appendChild group
@screen = @screen.slice(-@rows)
@shift = 0
@@ -501,11 +499,11 @@ class Terminal
@children = Array.prototype.slice.call(
lines, -@rows)
@native_scroll_to()
@native_scroll_to() unless @scrollLock
_cursorBlink: ->
@cursorState ^= 1
cursor = @element.querySelector(".cursor")
cursor = @body.querySelector(".cursor")
return unless cursor
if cursor.classList.contains("reverse-video")
cursor.classList.remove "reverse-video"
@@ -1186,12 +1184,12 @@ class Terminal
# May be redundant with keyPrefix
if ev.altKey and ev.keyCode is 90 and not @skipNextKey
@skipNextKey = true
@element.classList.add('skip')
@body.classList.add('skip')
return cancel(ev)
if @skipNextKey
@skipNextKey = false
@element.classList.remove('skip')
@body.classList.remove('skip')
return true
switch ev.keyCode
@@ -1341,6 +1339,15 @@ class Terminal
when 123
key = "\x1b[24~"
# Scroll lock
when 145
@scrollLock = ! @scrollLock
if @scrollLock
@body.classList.add 'locked'
else
@body.classList.remove 'locked'
return cancel(ev)
else
# a-z and space
if ev.ctrlKey
@@ -1351,7 +1358,7 @@ class Terminal
id = (setTimeout ->)
(clearTimeout id if id not in [
@t_bell, @t_queue, @t_blink]) while id--
@element.classList.add 'stopped'
@body.classList.add 'stopped'
@stop = true
else if @stop
return true
@@ -1447,19 +1454,19 @@ class Terminal
bell: (cls="bell")->
return unless @visualBell
@element.classList.add cls
@body.classList.add cls
@t_bell = setTimeout (=>
@element.classList.remove cls
@body.classList.remove cls
), @visualBell
resize: (x=null, y=null) ->
old_cols = @cols
old_rows = @rows
@compute_char_size()
@cols = x or Math.floor(@element.clientWidth / @char_size.width)
@cols = x or Math.floor(@body.clientWidth / @char_size.width)
@rows = y or Math.floor(window.innerHeight / @char_size.height)
px = window.innerHeight % @char_size.height
@element.style['padding-bottom'] = "#{px}px"
@body.style['padding-bottom'] = "#{px}px"
if (not x and not y) and old_cols == @cols and old_rows == @rows
return
@@ -1482,7 +1489,7 @@ class Terminal
# resize rows
j = old_rows
if j < @rows
el = @element
el = @body
while j++ < @rows
@screen.push [@blank_line(), true] if @screen.length < @rows
if @children.length < @rows
@@ -2229,7 +2236,7 @@ class Terminal
@vt200Mouse = params is 1000
@normalMouse = params > 1000
@mouseEvents = true
@element.style.cursor = 'pointer'
@body.style.cursor = 'pointer'
when 1004 # send focusin/focusout events
# focusin: ^[[I
# focusout: ^[[O
@@ -2383,7 +2390,7 @@ class Terminal
@vt200Mouse = false
@normalMouse = false
@mouseEvents = false
@element.style.cursor = ""
@body.style.cursor = ""
when 1004 # send focusin/focusout events
@sendFocus = false
when 1005 # utf8 ext mode mouse