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 @@
+