]> git.proxmox.com Git - mirror_xterm.js.git/commitdiff
Progress with #120
authorParis <paris@sourcelair.com>
Thu, 16 Jun 2016 08:41:41 +0000 (11:41 +0300)
committerParis <paris@sourcelair.com>
Thu, 16 Jun 2016 08:41:41 +0000 (11:41 +0300)
src/xterm.js

index d454c4bf433a3d9fae4e4296a2f121f1c527968b..96e89e3be884fdf8a4f9204e82338f3b9ec5626c 100644 (file)
       /**
        * Whether there is a full terminal refresh queued
        */
-      this.queuedRefresh = false;
 
       this.cursorState = 0;
       this.cursorHidden = false;
 
       this.tabs;
       this.setupStops();
-      this.debounceRefresh();
     }
 
     inherits(Terminal, EventEmitter);
       return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);
     };
 
-    /**
-     * Allow refresh to execute only approximately 30 times a second. For commands that pass a
-     * significant amount of output to the write function, this prevents the terminal from maxing
-     * out the CPU and making the UI unresponsive. While commands can still run beyond what they do
-     * on the terminal, it is far better with a debounce in place as every single terminal
-     * manipulation does not need to be constructed in the DOM.
-     *
-     * A side-effect of this is that it makes ^C to interrupt a process seem more responsive.
-     */
-    Terminal.prototype.debounceRefresh = function () {
-      var self = this;
-      window.setInterval(function () {
-        self.isRefreshing = false;
-        if (self.queuedRefresh) {
-          self.queuedRefresh = false;
-          // Do a full refresh in case multiple refreshes were requested.
-          self.refresh(0, self.rows - 1);
-        }
-      }, 34);
-    };
-
     /**
      * Colors
      */
     });
 
     /**
-     * Focus the terminal.
+     * Focus the terminal. Delegates focus handling to the terminal's DOM element.
      *
      * @public
      */
     Terminal.prototype.focus = function() {
-      if (document.activeElement === this.element) {
-        return;
-      }
+      return this.element.focus();
+    };
 
-      if (this.sendFocus) {
-        this.send('\x1b[I');
-      }
+    /**
+     * Binds the desired focus behavior on a given terminal object.
+     *
+     * @static
+     */
+    Terminal.bindFocus = function (term) {
+      on(term.element, 'focus', function (ev) {
+        if (term.sendFocus) {
+          term.send('\x1b[I');
+        }
 
-      this.showCursor();
-      this.element.focus();
+        term.showCursor();
+        Terminal.focus = term;
+        term.emit('focus', {terminal: term});
+      });
     };
 
+    /**
+     * Blur the terminal. Delegates blur handling to the terminal's DOM element.
+     *
+     * @public
+     */
     Terminal.prototype.blur = function() {
-      if (Terminal.focus !== this) {
-        return;
-      }
-
-      this.cursorState = 0;
-      this.refresh(this.y, this.y);
-      this.element.blur();
+      return terminal.element.blur();
+    };
 
-      if (this.sendFocus) {
-        this.send('\x1b[O');
-      }
-      Terminal.focus = null;
+    /**
+     * Binds the desired blur behavior on a given terminal object.
+     *
+     * @static
+     */
+    Terminal.bindBlur = function (term) {
+      on(term.element, 'blur', function (ev) {
+        if (term.sendFocus) {
+          term.send('\x1b[O');
+        }
+        Terminal.focus = null;
+        term.emit('blur', {terminal: term});
+      });
     };
 
     /**
       Terminal.bindCopy(this);
       Terminal.bindCut(this);
       Terminal.bindDrop(this);
+      Terminal.bindFocus(this);
+      Terminal.bindBlur(this);
     };
 
        /**
       this.element.classList.add('xterm-theme-' + this.theme);
       this.element.setAttribute('tabindex', 0);
       this.element.spellcheck = 'false';
-      this.element.onfocus = function() {
-        self.emit('focus', {terminal: this});
-      };
-      this.element.onblur = function() {
-        self.emit('blur', {terminal: this});
-      };
 
       /*
       * Create the container that will hold the lines of the terminal and then
      *
      * @param {number} start The row to start from (between 0 and terminal's height terminal - 1)
      * @param {number} end The row to end at (between fromRow and terminal's height terminal - 1)
+     * @param {boolean} queue Whether the refresh should ran right now or be queued
      *
      * @public
      */
-    Terminal.prototype.refresh = function(start, end) {
-      var x, y, i, line, out, ch, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement;
+    Terminal.prototype.refresh = function(start, end, queue) {
+      var self = this;
+
+      // queue defaults to true
+      queue = (typeof queue == 'undefined') ? true : queue;
 
-      if (this.isRefreshing) {
-        this.queuedRefresh = true;
+      /**
+       * The refresh queue allows refresh to execute only approximately 30 times a second. For
+       * commands that pass a significant amount of output to the write function, this prevents the
+       * terminal from maxing out the CPU and making the UI unresponsive. While commands can still
+       * run beyond what they do on the terminal, it is far better with a debounce in place as
+       * every single terminal manipulation does not need to be constructed in the DOM.
+       *
+       * A side-effect of this is that it makes ^C to interrupt a process seem more responsive.
+       */
+      if (queue) {
+        // If refresh should be queued, order the refresh and return.
+        if (this._refreshIsQueued) {
+          // If a refresh has already been queued, just order a full refresh next
+          this._fullRefreshNext = true;
+        } else {
+          setTimeout(function () {
+            self.refresh(start, end, false);
+          }, 34)
+          this._refreshIsQueued = true;
+        }
         return;
       }
-      this.isRefreshing = true;
+
+      // If refresh should be run right now (not be queued), release the lock
+      this._refreshIsQueued = false;
+
+      // If multiple refreshes were requested, make a full refresh.
+      if (this._fullRefreshNext) {
+        start = 0;
+        end = this.rows - 1;
+        this._fullRefreshNext = false // reset lock
+      }
+
+      var x, y, i, line, out, ch, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement;
 
       if (end - start >= this.rows / 2) {
         parent = this.element.parentNode;