From 5bc0ad879b7b9cdc3c8617478512ba80affc5d79 Mon Sep 17 00:00:00 2001 From: thomas Date: Tue, 11 Jul 2017 21:15:33 +0200 Subject: [PATCH] Set xterm-color for cursor element Prevent focus from getting lost when in vt mouse mode Fix: cursor style not applied on init, set a class for block cursor Make all cursors work under all conditions (focused, unfocused, blink) Unify cursor rendering with normal rendering code Make sure underline AND blink can be used in co-existence Always show outlined block cursor in unfocused state --- src/Renderer.ts | 122 ++++++++++++++++++++++++------------------------ src/xterm.css | 43 +++++++---------- src/xterm.js | 6 ++- 3 files changed, 84 insertions(+), 87 deletions(-) diff --git a/src/Renderer.ts b/src/Renderer.ts index db4d6a6..165594f 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -170,16 +170,13 @@ export class Renderer { let data: any = line[i][0]; const ch = line[i][1]; const ch_width: any = line[i][2]; + const isCursor: boolean = i === x; if (!ch_width) { continue; } - if (i === x) { - data = -1; - } - - if (data !== attr) { - if (attr !== this._terminal.defAttr) { + if (data !== attr || isCursor) { + if (attr !== this._terminal.defAttr && !isCursor) { if (innerHTML) { currentElement.innerHTML = innerHTML; innerHTML = ''; @@ -187,7 +184,7 @@ export class Renderer { documentFragment.appendChild(currentElement); currentElement = null; } - if (data !== this._terminal.defAttr) { + if (data !== this._terminal.defAttr || isCursor) { if (innerHTML && !currentElement) { currentElement = this._spanElementObjectPool.acquire(); } @@ -199,71 +196,73 @@ export class Renderer { documentFragment.appendChild(currentElement); } currentElement = this._spanElementObjectPool.acquire(); - if (data === -1) { + + let bg = data & 0x1ff; + let fg = (data >> 9) & 0x1ff; + let flags = data >> 18; + + if (isCursor) { currentElement.classList.add('reverse-video'); currentElement.classList.add('terminal-cursor'); - } else { - let bg = data & 0x1ff; - let fg = (data >> 9) & 0x1ff; - let flags = data >> 18; - - if (flags & FLAGS.BOLD) { - if (!brokenBold) { - currentElement.classList.add('xterm-bold'); - } - // See: XTerm*boldColors - if (fg < 8) { - fg += 8; - } - } + } - if (flags & FLAGS.UNDERLINE) { - currentElement.classList.add('xterm-underline'); + if (flags & FLAGS.BOLD) { + if (!brokenBold) { + currentElement.classList.add('xterm-bold'); } - - if (flags & FLAGS.BLINK) { - currentElement.classList.add('xterm-blink'); + // See: XTerm*boldColors + if (fg < 8) { + fg += 8; } + } - // If inverse flag is on, then swap the foreground and background variables. - if (flags & FLAGS.INVERSE) { - let temp = bg; - bg = fg; - fg = temp; - // Should inverse just be before the above boldColors effect instead? - if ((flags & 1) && fg < 8) { - fg += 8; - } - } + if (flags & FLAGS.UNDERLINE) { + currentElement.classList.add('xterm-underline'); + } - if (flags & FLAGS.INVISIBLE) { - currentElement.classList.add('xterm-hidden'); - } + if (flags & FLAGS.BLINK) { + currentElement.classList.add('xterm-blink'); + } - /** - * Weird situation: Invert flag used black foreground and white background results - * in invalid background color, positioned at the 256 index of the 256 terminal - * color map. Pin the colors manually in such a case. - * - * Source: https://github.com/sourcelair/xterm.js/issues/57 - */ - if (flags & FLAGS.INVERSE) { - if (bg === 257) { - bg = 15; - } - if (fg === 256) { - fg = 0; - } + // If inverse flag is on, then swap the foreground and background variables. + if (flags & FLAGS.INVERSE) { + let temp = bg; + bg = fg; + fg = temp; + // Should inverse just be before the above boldColors effect instead? + if ((flags & 1) && fg < 8) { + fg += 8; } + } - if (bg < 256) { - currentElement.classList.add(`xterm-bg-color-${bg}`); - } + if (flags & FLAGS.INVISIBLE && !isCursor) { + currentElement.classList.add('xterm-hidden'); + } - if (fg < 256) { - currentElement.classList.add(`xterm-color-${fg}`); + /** + * Weird situation: Invert flag used black foreground and white background results + * in invalid background color, positioned at the 256 index of the 256 terminal + * color map. Pin the colors manually in such a case. + * + * Source: https://github.com/sourcelair/xterm.js/issues/57 + */ + if (flags & FLAGS.INVERSE) { + if (bg === 257) { + bg = 15; + } + if (fg === 256) { + fg = 0; } } + + if (bg < 256) { + currentElement.classList.add(`xterm-bg-color-${bg}`); + } + + if (fg < 256) { + currentElement.classList.add(`xterm-color-${fg}`); + } + } } @@ -295,7 +294,10 @@ export class Renderer { } } - attr = data; + // The cursor needs its own element, therefore we set attr to -1 + // which will cause the next character to be rendered in a new element + attr = isCursor ? -1 : data; + } if (innerHTML && !currentElement) { diff --git a/src/xterm.css b/src/xterm.css index 6d6f48f..89daf9e 100644 --- a/src/xterm.css +++ b/src/xterm.css @@ -89,53 +89,40 @@ text-decoration: none; } -.terminal.focus:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor { - background-color: #fff; - color: #000; +.terminal .terminal-cursor { + position: relative; } .terminal:not(.focus) .terminal-cursor { outline: 1px solid #fff; outline-offset: -1px; - background-color: transparent; } -.terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink-on .terminal-cursor { - background-color: transparent; - color: inherit; +.terminal.xterm-cursor-style-block.focus:not(.xterm-cursor-blink-on) .terminal-cursor { + background-color: #fff; + color: #000; } -.terminal.xterm-cursor-style-bar .terminal-cursor, -.terminal.xterm-cursor-style-underline .terminal-cursor { - position: relative; -} -.terminal.xterm-cursor-style-bar .terminal-cursor::before, -.terminal.xterm-cursor-style-underline .terminal-cursor::before { - content: ""; - display: block; +.terminal.focus.xterm-cursor-style-bar:not(.xterm-cursor-blink-on) .terminal-cursor::before, +.terminal.focus.xterm-cursor-style-underline:not(.xterm-cursor-blink-on) .terminal-cursor::before { + content: ''; position: absolute; background-color: #fff; } -.terminal.xterm-cursor-style-bar .terminal-cursor::before { + +.terminal.focus.xterm-cursor-style-bar:not(.xterm-cursor-blink-on) .terminal-cursor::before { top: 0; - bottom: 0; left: 0; + bottom: 0; width: 1px; } -.terminal.xterm-cursor-style-underline .terminal-cursor::before { + +.terminal.focus.xterm-cursor-style-underline:not(.xterm-cursor-blink-on) .terminal-cursor::before { bottom: 0; left: 0; right: 0; height: 1px; } -.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before, -.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before { - background-color: transparent; -} -.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before, -.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before { - background-color: #fff; -} .terminal .composition-view { background: #000; @@ -217,6 +204,10 @@ text-decoration: blink; } +.terminal .xterm-blink.xterm-underline { + text-decoration: blink underline; +} + .terminal .xterm-hidden { visibility: hidden; } diff --git a/src/xterm.js b/src/xterm.js index a3f425d..1bb44a9 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -429,7 +429,7 @@ Terminal.prototype.setOption = function(key, value) { switch (key) { case 'cursorBlink': this.setCursorBlinking(value); break; case 'cursorStyle': - // Style 'block' applies with no class + this.element.classList.toggle(`xterm-cursor-style-block`, value === 'block'); this.element.classList.toggle(`xterm-cursor-style-underline`, value === 'underline'); this.element.classList.toggle(`xterm-cursor-style-bar`, value === 'bar'); break; @@ -639,6 +639,7 @@ Terminal.prototype.open = function(parent, focus) { this.element.classList.add('terminal'); this.element.classList.add('xterm'); this.element.classList.add('xterm-theme-' + this.theme); + this.element.classList.add(`xterm-cursor-style-${this.options.cursorStyle}`); this.setCursorBlinking(this.options.cursorBlink); this.element.setAttribute('tabindex', 0); @@ -1025,6 +1026,9 @@ Terminal.prototype.bindMouse = function() { } on(el, 'mousedown', function(ev) { + // prevent the focus on the textarea from getting lost + ev.preventDefault(); + if (!self.mouseEvents) return; // send the button -- 2.39.2