]> git.proxmox.com Git - mirror_xterm.js.git/commitdiff
Basic fetching of coordinates
authorDaniel Imms <tyriar@tyriar.com>
Sat, 6 May 2017 00:36:15 +0000 (17:36 -0700)
committerDaniel Imms <tyriar@tyriar.com>
Sat, 6 May 2017 00:36:15 +0000 (17:36 -0700)
src/EventEmitter.ts
src/Parser.ts
src/SelectionManager.ts [new file with mode: 0644]
src/utils/CircularList.ts
src/utils/Mouse.ts [new file with mode: 0644]
src/xterm.css
src/xterm.js

index 1db8676328edd4443e8d4a3629bf95953ee23dec..a4fd4542c3c8a97ad4e2aa9b88696a407890ccc0 100644 (file)
@@ -53,14 +53,11 @@ export class EventEmitter {
     return this.on(type, on);
   }
 
-  public emit(type): void {
+  public emit(type: string, ...args: any[]): void {
     if (!this._events[type]) {
       return;
     }
-
-    let args = Array.prototype.slice.call(arguments, 1);
     let obj = this._events[type];
-
     for (let i = 0; i < obj.length; i++) {
       obj[i].apply(this, args);
     }
index 01821a5a031b3c9819c9e0f0d3ad0d8166779855..92ff1595bea5b008a240b83aceb52fb4b04ee66e 100644 (file)
@@ -471,6 +471,8 @@ export class Parser {
         case ParserState.DCS:
           if (ch === C0.ESC || ch === C0.BEL) {
             if (ch === C0.ESC) this._position++;
+            let pt;
+            let valid;
 
             switch (this._terminal.prefix) {
               // User-Defined Keys (DECUDK).
@@ -480,8 +482,8 @@ export class Parser {
               // Request Status String (DECRQSS).
               // test: echo -e '\eP$q"p\e\\'
               case '$q':
-                let pt = this._terminal.currentParam
-                valid = false;
+                pt = this._terminal.currentParam;
+                valid = false;
 
                 switch (pt) {
                   // DECSCA
@@ -526,9 +528,8 @@ export class Parser {
               // This can cause a small glitch in vim.
               // test: echo -ne '\eP+q6b64\e\\'
               case '+q':
-                // TODO: Don't declare pt twice
-                /*let*/ pt = this._terminal.currentParam
-                , valid = false;
+                pt = this._terminal.currentParam;
+                valid = false;
 
                 this._terminal.send(C0.ESC + 'P' + +valid + '+r' + pt + C0.ESC + '\\');
                 break;
diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts
new file mode 100644 (file)
index 0000000..df9294b
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * @license MIT
+ */
+
+import { CharMeasure } from './utils/CharMeasure';
+import { CircularList } from './utils/CircularList';
+import * as Mouse from './utils/Mouse';
+
+export class SelectionManager {
+  private _selectionStart: [number, number];
+  private _selectionEnd: [number, number];
+
+  private _buffer: CircularList<any>;
+  private _rowContainer: HTMLElement;
+  private _charMeasure: CharMeasure;
+
+  private _mouseMoveListener: EventListener;
+
+  constructor(buffer: CircularList<any>, rowContainer: HTMLElement, charMeasure: CharMeasure) {
+    this._rowContainer = rowContainer;
+    this._buffer = buffer;
+    this._charMeasure = charMeasure;
+    this._attachListeners();
+  }
+
+  private _attachListeners() {
+    this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
+
+    this._buffer.on('trim', amount => this._onTrim(amount));
+    this._rowContainer.addEventListener('mousedown', event => this._onMouseDown(event));
+    this._rowContainer.addEventListener('mouseup', event => this._onMouseUp(event));
+  }
+
+  public get selectionText(): string {
+    if (!this._selectionStart || !this._selectionEnd) {
+      return null;
+    }
+    return '';
+  }
+
+  private _onTrim(amount: number) {
+    console.log('trimmed: ' + amount);
+  }
+
+  private _onMouseDown(event: MouseEvent) {
+    this._selectionStart = Mouse.getCoords(event, this._rowContainer, this._charMeasure);
+    if (this._selectionStart) {
+      this._rowContainer.addEventListener('mousemove', this._mouseMoveListener);
+    }
+  }
+
+  private _onMouseMove(event: MouseEvent) {
+    this._selectionEnd = Mouse.getCoords(event, this._rowContainer, this._charMeasure);
+  }
+
+  private _onMouseUp(event: MouseEvent) {
+    console.log('mouseup');
+    console.log('start', this._selectionStart);
+    console.log('end', this._selectionEnd);
+    if (!this._selectionStart) {
+      return;
+    }
+    this._rowContainer.removeEventListener('mousemove', this._mouseMoveListener);
+  }
+}
index b72c667fe13c5c96cdda0011402605beffa57684..909df76618549a6cfd8d7aa61216526bd86c7b3b 100644 (file)
@@ -4,12 +4,15 @@
  * @module xterm/utils/CircularList
  * @license MIT
  */
-export class CircularList<T> {
+import { EventEmitter } from '../EventEmitter';
+
+export class CircularList<T> extends EventEmitter {
   private _array: T[];
   private _startIndex: number;
   private _length: number;
 
   constructor(maxLength: number) {
+    super();
     this._array = new Array<T>(maxLength);
     this._startIndex = 0;
     this._length = 0;
@@ -83,6 +86,7 @@ export class CircularList<T> {
       if (this._startIndex === this.maxLength) {
         this._startIndex = 0;
       }
+      this.emit('trim', 1);
     } else {
       this._length++;
     }
@@ -121,8 +125,10 @@ export class CircularList<T> {
       }
 
       if (this._length + items.length > this.maxLength) {
-        this._startIndex += (this._length + items.length) - this.maxLength;
+        const countToTrim = (this._length + items.length) - this.maxLength;
+        this._startIndex += countToTrim;
         this._length = this.maxLength;
+        this.emit('trim', countToTrim);
       } else {
         this._length += items.length;
       }
@@ -139,6 +145,7 @@ export class CircularList<T> {
     }
     this._startIndex += count;
     this._length -= count;
+    this.emit('trim', count);
   }
 
   public shiftElements(start: number, count: number, offset: number): void {
@@ -162,6 +169,7 @@ export class CircularList<T> {
         while (this._length > this.maxLength) {
           this._length--;
           this._startIndex++;
+          this.emit('trim', 1);
         }
       }
     } else {
diff --git a/src/utils/Mouse.ts b/src/utils/Mouse.ts
new file mode 100644 (file)
index 0000000..7b18d41
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * @license MIT
+ */
+
+import { CharMeasure } from './CharMeasure';
+
+export function getCoords(event: MouseEvent, rowContainer: HTMLElement, charMeasure: CharMeasure): [number, number] {
+  // ignore browsers without pageX for now
+  if (event.pageX == null) {
+    return null;
+  }
+
+  let x = event.pageX;
+  let y = event.pageY;
+  let el = rowContainer;
+
+  // should probably check offsetParent
+  // but this is more portable
+  while (el && el !== self.document.documentElement) {
+    x -= el.offsetLeft;
+    y -= el.offsetTop;
+    el = 'offsetParent' in el ? <HTMLElement>el.offsetParent : <HTMLElement>el.parentElement;
+  }
+
+  // convert to cols/rows
+  x = Math.ceil(x / charMeasure.width);
+  y = Math.ceil(y / charMeasure.height);
+
+  return [x, y];
+}
index a67485e5bb3f85d79e90c53fcb30b587be53a977..72c1b8599fa8b50eb97ea2908e3c0a97675a6bd1 100644 (file)
@@ -41,6 +41,7 @@
     font-family: courier-new, courier, monospace;
     font-feature-settings: "liga" 0;
     position: relative;
+    user-select: none;
 }
 
 .terminal.focus,
index 75d0bc45ae83fc112bf5240881cd9dc753ef4e26..dd3a090d5bd32923d5988e344d301c814b1e6503 100644 (file)
@@ -20,9 +20,10 @@ import { InputHandler } from './InputHandler';
 import { Parser } from './Parser';
 import { Renderer } from './Renderer';
 import { Linkifier } from './Linkifier';
+import { SelectionManager } from './SelectionManager';
 import { CharMeasure } from './utils/CharMeasure';
 import * as Browser from './utils/Browser';
-import * as Keyboard from './utils/Keyboard';
+import * as Mouse from './utils/Mouse';
 import { CHARSETS } from './Charsets';
 
 /**
@@ -219,6 +220,7 @@ function Terminal(options) {
   this.parser = new Parser(this.inputHandler, this);
   // Reuse renderer if the Terminal is being recreated via a Terminal.reset call.
   this.renderer = this.renderer || null;
+  this.selectionManager = this.selectionManager || null;
   this.linkifier = this.linkifier || new Linkifier();
 
   // user input states
@@ -689,6 +691,7 @@ Terminal.prototype.open = function(parent, focus) {
 
   this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
   this.renderer = new Renderer(this);
+  this.selectionManager = new SelectionManager(this.lines, this.rowContainer, this.charMeasure);
 
   // Setup loop that draws to screen
   this.refresh(0, this.rows - 1);
@@ -787,7 +790,7 @@ Terminal.prototype.bindMouse = function() {
     button = getButton(ev);
 
     // get mouse coordinates
-    pos = getCoords(ev);
+    pos = Mouse.getCoords(ev, this.rowContainer, this.charMeasure);
     if (!pos) return;
 
     sendEvent(button, pos);
@@ -815,7 +818,7 @@ Terminal.prototype.bindMouse = function() {
     var button = pressed
     , pos;
 
-    pos = getCoords(ev);
+    pos = Mouse.getCoords(ev, this.rowContainer, this.charMeasure);
     if (!pos) return;
 
     // buttons marked as motions
@@ -991,48 +994,48 @@ Terminal.prototype.bindMouse = function() {
   }
 
   // mouse coordinates measured in cols/rows
-  function getCoords(ev) {
-    var x, y, w, h, el;
-
-    // ignore browsers without pageX for now
-    if (ev.pageX == null) return;
-
-    x = ev.pageX;
-    y = ev.pageY;
-    el = self.element;
-
-    // should probably check offsetParent
-    // but this is more portable
-    while (el && el !== self.document.documentElement) {
-      x -= el.offsetLeft;
-      y -= el.offsetTop;
-      el = 'offsetParent' in el
-        ? el.offsetParent
-      : el.parentNode;
-    }
+  // function getCoords(ev) {
+  //   var x, y, w, h, el;
+
+  //   // ignore browsers without pageX for now
+  //   if (ev.pageX == null) return;
+
+  //   x = ev.pageX;
+  //   y = ev.pageY;
+  //   el = self.rowContainer;
+
+  //   // should probably check offsetParent
+  //   // but this is more portable
+  //   while (el && el !== self.document.documentElement) {
+  //     x -= el.offsetLeft;
+  //     y -= el.offsetTop;
+  //     el = 'offsetParent' in el
+  //       ? el.offsetParent
+  //     : el.parentNode;
+  //   }
 
-    // convert to cols/rows
-    x = Math.ceil(x / self.charMeasure.width);
-    y = Math.ceil(y / self.charMeasure.height);
-
-    // be sure to avoid sending
-    // bad positions to the program
-    if (x < 0) x = 0;
-    if (x > self.cols) x = self.cols;
-    if (y < 0) y = 0;
-    if (y > self.rows) y = self.rows;
-
-    // xterm sends raw bytes and
-    // starts at 32 (SP) for each.
-    x += 32;
-    y += 32;
-
-    return {
-      x: x,
-      y: y,
-      type: 'wheel'
-    };
-  }
+  //   // convert to cols/rows
+  //   x = Math.ceil(x / self.charMeasure.width);
+  //   y = Math.ceil(y / self.charMeasure.height);
+
+  //   // be sure to avoid sending
+  //   // bad positions to the program
+  //   if (x < 0) x = 0;
+  //   if (x > self.cols) x = self.cols;
+  //   if (y < 0) y = 0;
+  //   if (y > self.rows) y = self.rows;
+
+  //   // xterm sends raw bytes and
+  //   // starts at 32 (SP) for each.
+  //   x += 32;
+  //   y += 32;
+
+  //   return {
+  //     x: x,
+  //     y: y,
+  //     type: 'wheel'
+  //   };
+  // }
 
   on(el, 'mousedown', function(ev) {
     if (!self.mouseEvents) return;