From d6c359645c28df9057d5594e67b28f9bf1510eb0 Mon Sep 17 00:00:00 2001 From: Jonathan Leibiusky Date: Sun, 16 Apr 2017 17:47:18 -0500 Subject: [PATCH] Font size and fullscreen (#120) * Allow to change terminal font size in settings. Allow to enter fullscreen mode with alt+enter. * Fix size issues --- www/assets/app.js | 107 +++++++++++++++++++-- www/assets/xterm-addons/fit.js | 123 ++++++++++++++++--------- www/assets/xterm-addons/fullscreen.css | 10 ++ www/assets/xterm-addons/fullscreen.js | 50 ++++++++++ www/index.html | 19 ++++ 5 files changed, 255 insertions(+), 54 deletions(-) create mode 100644 www/assets/xterm-addons/fullscreen.css create mode 100644 www/assets/xterm-addons/fullscreen.js diff --git a/www/assets/app.js b/www/assets/app.js index 1bd48f0..04b8a90 100644 --- a/www/assets/app.js +++ b/www/assets/app.js @@ -11,7 +11,7 @@ }, 500); }]); - app.controller('PlayController', ['$scope', '$log', '$http', '$location', '$timeout', '$mdDialog', '$window', 'KeyboardShortcutService', 'InstanceService', function($scope, $log, $http, $location, $timeout, $mdDialog, $window, KeyboardShortcutService, InstanceService) { + app.controller('PlayController', ['$scope', '$log', '$http', '$location', '$timeout', '$mdDialog', '$window', 'TerminalService', 'KeyboardShortcutService', 'InstanceService', function($scope, $log, $http, $location, $timeout, $mdDialog, $window, TerminalService, KeyboardShortcutService, InstanceService) { $scope.sessionId = window.location.pathname.replace('/p/', ''); $scope.instances = []; $scope.idx = {}; @@ -52,6 +52,8 @@ $scope.socket.emit('viewport resize', geometry.cols, geometry.rows); } + KeyboardShortcutService.setResizeFunc($scope.resize); + $scope.closeSession = function() { $scope.socket.emit('session close'); } @@ -195,6 +197,7 @@ if (!instance.term) { $timeout(function() { createTerminal(instance); + TerminalService.setFontSize(TerminalService.getFontSize()); instance.term.focus(); }, 0, false); return @@ -326,14 +329,14 @@ }) .component("settingsDialog", { templateUrl : "settings-modal.html", - controller : function($mdDialog, KeyboardShortcutService, $rootScope, InstanceService) { + controller : function($mdDialog, KeyboardShortcutService, $rootScope, InstanceService, TerminalService) { var $ctrl = this; - $ctrl.$onInit = function() { $ctrl.keyboardShortcutPresets = KeyboardShortcutService.getAvailablePresets(); $ctrl.selectedShortcutPreset = KeyboardShortcutService.getCurrentShortcuts(); $ctrl.instanceImages = InstanceService.getAvailableImages(); $ctrl.selectedInstanceImage = InstanceService.getDesiredImage(); + $ctrl.terminalFontSizes = TerminalService.getFontSizes(); }; $ctrl.currentShortcutConfig = function(value) { @@ -352,6 +355,15 @@ } return InstanceService.getDesiredImage(value); }; + $ctrl.currentTerminalFontSize = function(value) { + if (value !== undefined) { + // set font size + TerminalService.setFontSize(value); + return; + } + + return TerminalService.getFontSize(); + } $ctrl.close = function() { $mdDialog.cancel(); @@ -396,20 +408,30 @@ }) .run(function(InstanceService) { /* forcing pre-populating for now */ }) - .service("KeyboardShortcutService", function() { + .service("KeyboardShortcutService", ['TerminalService', function(TerminalService) { + var resizeFunc; + return { getAvailablePresets : getAvailablePresets, getCurrentShortcuts : getCurrentShortcuts, - setCurrentShortcuts : setCurrentShortcuts + setCurrentShortcuts : setCurrentShortcuts, + setResizeFunc : setResizeFunc }; + function setResizeFunc(f) { + resizeFunc = f; + } + function getAvailablePresets() { return [ - { name : "None", presets : [] }, + { name : "None", presets : [ + { description : "Toggle terminal fullscreen", command : "Alt+enter", altKey : true, keyCode : 13, action : function(context) { TerminalService.toggleFullscreen(context.terminal, resizeFunc); }} + ] }, { name : "Mac OSX", presets : [ - { description : "Clear terminal", command : "Cmd+K", metaKey : true, keyCode : 75, action : function(context) { context.terminal.clear(); }} + { description : "Clear terminal", command : "Cmd+K", metaKey : true, keyCode : 75, action : function(context) { context.terminal.clear(); }}, + { description : "Toggle terminal fullscreen", command : "Alt+enter", altKey : true, keyCode : 13, action : function(context) { TerminalService.toggleFullscreen(context.terminal, resizeFunc); }} ] } ] @@ -440,7 +462,72 @@ return "Mac OSX"; return null; } - }); + }]) + .service('TerminalService', ['$window', function($window) { + var fullscreen; + var fontSize = getFontSize(); + return { + getFontSizes : getFontSizes, + setFontSize : setFontSize, + getFontSize : getFontSize, + increaseFontSize : increaseFontSize, + decreaseFontSize : decreaseFontSize, + toggleFullscreen : toggleFullscreen + }; + function getFontSizes() { + var terminalFontSizes = []; + for (var i=3; i<40; i++) { + terminalFontSizes.push(i+'px'); + } + return terminalFontSizes; + }; + function getFontSize() { + if (!fontSize) { + return $('.terminal').css('font-size'); + } + return fontSize; + } + function setFontSize(value) { + fontSize = value; + var size = parseInt(value); + $('.terminal').css('font-size', value).css('line-height', (size + 2)+'px'); + //.css('line-height', value).css('height', value); + angular.element($window).trigger('resize'); + } + function increaseFontSize() { + var sizes = getFontSizes(); + var size = getFontSize(); + var i = sizes.indexOf(size); + if (i == -1) { + return; + } + if (i+1 > sizes.length) { + return; + } + setFontSize(sizes[i+1]); + } + function decreaseFontSize() { + var sizes = getFontSizes(); + var size = getFontSize(); + var i = sizes.indexOf(size); + if (i == -1) { + return; + } + if (i-1 < 0) { + return; + } + setFontSize(sizes[i-1]); + } + function toggleFullscreen(terminal, resize) { + if(fullscreen) { + terminal.toggleFullscreen(); + resize(fullscreen); + fullscreen = null; + } else { + fullscreen = terminal.proposeGeometry(); + terminal.toggleFullscreen(); + angular.element($window).trigger('resize'); + } + } + }]); })(); - - diff --git a/www/assets/xterm-addons/fit.js b/www/assets/xterm-addons/fit.js index f3a3396..76dc668 100644 --- a/www/assets/xterm-addons/fit.js +++ b/www/assets/xterm-addons/fit.js @@ -10,50 +10,85 @@ * @module xterm/addons/fit/fit * @license MIT */ + (function (fit) { - if (typeof exports === 'object' && typeof module === 'object') { - /* - * CommonJS environment - */ - module.exports = fit(require('../../xterm')); - } - else if (typeof define == 'function') { - /* - * Require.js is available - */ - define(['../../xterm'], fit); - } - else { - /* - * Plain browser environment - */ - fit(window.Terminal); - } + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fit(require('../../xterm')); + } else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], fit); + } else { + /* + * Plain browser environment + */ + fit(window.Terminal); + } })(function (Xterm) { - var exports = {}; - exports.proposeGeometry = function (term) { - var parentElementStyle = window.getComputedStyle(term.element.parentElement), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), elementStyle = window.getComputedStyle(term.element), elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), availableHeight = parentElementHeight - elementPaddingVer, availableWidth = parentElementWidth - elementPaddingHor, container = term.rowContainer, subjectRow = term.rowContainer.firstElementChild, contentBuffer = subjectRow.innerHTML, characterHeight, rows, characterWidth, cols, geometry; - subjectRow.style.display = 'inline'; - subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace - characterWidth = subjectRow.getBoundingClientRect().width; - subjectRow.style.display = ''; // Revert style before calculating height, since they differ. - characterHeight = parseInt(subjectRow.offsetHeight); - subjectRow.innerHTML = contentBuffer; - rows = parseInt(availableHeight / characterHeight); - cols = parseInt(availableWidth / characterWidth); - geometry = { cols: cols, rows: rows }; - return geometry; - }; - exports.fit = function (term) { - var geometry = exports.proposeGeometry(term); - term.resize(geometry.cols, geometry.rows); - }; - Xterm.prototype.proposeGeometry = function () { - return exports.proposeGeometry(this); - }; - Xterm.prototype.fit = function () { - return exports.fit(this); - }; - return exports; + var exports = {}; + + exports.proposeGeometry = function (term) { + if (!term.element.parentElement) { + return null; + } + var parentElementStyle = window.getComputedStyle(term.element.parentElement), + parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), + parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), + elementStyle = window.getComputedStyle(term.element), + elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), + elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), + availableHeight = parentElementHeight - elementPaddingVer, + availableWidth = parentElementWidth - elementPaddingHor, + container = term.rowContainer, + subjectRow = term.rowContainer.firstElementChild, + contentBuffer = subjectRow.innerHTML, + characterHeight, + rows, + characterWidth, + cols, + geometry; + + if (term.element.classList.contains('fullscreen')) { + // we are in fullscreen mode and need to use element height and width directly; + + availableHeight = parseInt(elementStyle.getPropertyValue('height')); + availableWidth = Math.max(0, parseInt(elementStyle.getPropertyValue('width')) - 17); + } + + subjectRow.style.display = 'inline'; + subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace + characterWidth = subjectRow.getBoundingClientRect().width; + subjectRow.style.display = ''; // Revert style before calculating height, since they differ. + //characterHeight = subjectRow.getBoundingClientRect().height; + characterHeight = parseInt(window.getComputedStyle(subjectRow).fontSize, 10)+2; + subjectRow.innerHTML = contentBuffer; + + rows = parseInt(availableHeight / characterHeight); + cols = parseInt(availableWidth / characterWidth); + + geometry = {cols: cols, rows: rows}; + return geometry; + }; + + exports.fit = function (term) { + var geometry = exports.proposeGeometry(term); + + if (geometry) { + term.resize(geometry.cols, geometry.rows); + } + }; + + Xterm.prototype.proposeGeometry = function () { + return exports.proposeGeometry(this); + }; + + Xterm.prototype.fit = function () { + return exports.fit(this); + }; + + return exports; }); -//# sourceMappingURL=fit.js.map \ No newline at end of file diff --git a/www/assets/xterm-addons/fullscreen.css b/www/assets/xterm-addons/fullscreen.css new file mode 100644 index 0000000..60e8c51 --- /dev/null +++ b/www/assets/xterm-addons/fullscreen.css @@ -0,0 +1,10 @@ +.xterm.fullscreen { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: auto; + height: auto; + z-index: 255; +} diff --git a/www/assets/xterm-addons/fullscreen.js b/www/assets/xterm-addons/fullscreen.js new file mode 100644 index 0000000..e8e34ea --- /dev/null +++ b/www/assets/xterm-addons/fullscreen.js @@ -0,0 +1,50 @@ +/** + * Fullscreen addon for xterm.js + * @module xterm/addons/fullscreen/fullscreen + * @license MIT + */ +(function (fullscreen) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fullscreen(require('../../xterm')); + } else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], fullscreen); + } else { + /* + * Plain browser environment + */ + fullscreen(window.Terminal); + } +})(function (Xterm) { + var exports = {}; + + /** + * Toggle the given terminal's fullscreen mode. + * @param {Xterm} term - The terminal to toggle full screen mode + * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) + */ + exports.toggleFullScreen = function (term, fullscreen) { + var fn; + + if (typeof fullscreen == 'undefined') { + fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; + } else if (!fullscreen) { + fn = 'remove'; + } else { + fn = 'add'; + } + + term.element.classList[fn]('fullscreen'); + }; + + Xterm.prototype.toggleFullscreen = function (fullscreen) { + exports.toggleFullScreen(this, fullscreen); + }; + + return exports; +}); diff --git a/www/index.html b/www/index.html index 477699e..089e506 100644 --- a/www/index.html +++ b/www/index.html @@ -5,6 +5,7 @@ + + + @@ -182,6 +200,7 @@ +