diff --git a/app/bufferizedPTY.js b/app/bufferizedPTY.js new file mode 100644 index 00000000..7597b826 --- /dev/null +++ b/app/bufferizedPTY.js @@ -0,0 +1,46 @@ +module.exports = function patchPTYModule (path) { + const mod = require(path) + const oldSpawn = mod.spawn + mod.spawn = (file, args, opt) => { + let terminal = oldSpawn(file, args, opt) + let timeout = null + let buffer = '' + let lastFlush = 0 + let nextTimeout = 0 + + const maxWindow = 250 + const minWindow = 50 + + function flush () { + if (buffer) { + terminal.emit('data-buffered', buffer) + } + lastFlush = Date.now() + buffer = '' + } + + function reschedule () { + if (timeout) { + clearTimeout(timeout) + } + nextTimeout = Date.now() + minWindow + timeout = setTimeout(() => { + timeout = null + flush() + }, minWindow) + } + + terminal.on('data', data => { + buffer += data + if (Date.now() - lastFlush > maxWindow) { + flush() + } else { + if (Date.now() > nextTimeout - (minWindow / 10)) { + reschedule() + } + } + }) + return terminal + } + return mod +} diff --git a/app/main.js b/app/main.js index 2c773708..c506e111 100644 --- a/app/main.js +++ b/app/main.js @@ -1,11 +1,9 @@ if (process.platform == 'win32' && require('electron-squirrel-startup')) process.exit(0) - const electron = require('electron') if (process.argv.indexOf('--debug') !== -1) { require('electron-debug')({enabled: true, showDevTools: 'undocked'}) } - let app = electron.app let secondInstance = app.makeSingleInstance((argv, cwd) => { @@ -44,6 +42,9 @@ setupWindowManagement = () => { } }) + app.window.on('enter-full-screen', () => app.window.webContents.send('host:window-enter-full-screen')) + app.window.on('leave-full-screen', () => app.window.webContents.send('host:window-leave-full-screen')) + app.window.on('close', (e) => { windowConfig.set('windowBoundaries', app.window.getBounds()) }) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 52b11e61..822230e1 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -1,5 +1,5 @@ title-bar( - *ngIf='!hostApp.getWindow().isFullScreen() && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"', + *ngIf='!hostApp.isFullScreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"', [class.inset]='hostApp.platform == Platform.macOS' ) @@ -7,7 +7,7 @@ title-bar( [class.tabs-on-top]='config.store.appearance.tabsLocation == "top"' ) .tab-bar( - *ngIf='!hostApp.getWindow().isFullScreen()', + *ngIf='!hostApp.isFullScreen', [class.inset]='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"' ) .tabs diff --git a/terminus-core/src/services/electron.service.ts b/terminus-core/src/services/electron.service.ts index 33d0741f..b15821d2 100644 --- a/terminus-core/src/services/electron.service.ts +++ b/terminus-core/src/services/electron.service.ts @@ -32,7 +32,11 @@ export class ElectronService { } remoteRequirePluginModule (plugin: string, module: string, globals: any): any { - return this.remoteRequire(globals.require.resolve(`${plugin}/node_modules/${module}`)) + return this.remoteRequire(this.remoteResolvePluginModule(plugin, module, globals)) + } + + remoteResolvePluginModule (plugin: string, module: string, globals: any): any { + return globals.require.resolve(`${plugin}/node_modules/${module}`) } loseFocus () { diff --git a/terminus-core/src/services/hostApp.service.ts b/terminus-core/src/services/hostApp.service.ts index 5a23fd96..e2ff6cdb 100644 --- a/terminus-core/src/services/hostApp.service.ts +++ b/terminus-core/src/services/hostApp.service.ts @@ -22,7 +22,7 @@ export class HostAppService { ready = new EventEmitter() shown = new EventEmitter() secondInstance$ = new Subject<{ argv: string[], cwd: string }>() - + isFullScreen = false private logger: Logger constructor ( @@ -44,6 +44,14 @@ export class HostAppService { this.logger.error('Unhandled exception:', err) }) + electron.ipcRenderer.on('host:window-enter-full-screen', () => this.zone.run(() => { + this.isFullScreen = true + })) + + electron.ipcRenderer.on('host:window-leave-full-screen', () => this.zone.run(() => { + this.isFullScreen = false + })) + electron.ipcRenderer.on('host:window-shown', () => { this.zone.run(() => this.shown.emit()) }) diff --git a/terminus-terminal/src/services/sessions.service.ts b/terminus-terminal/src/services/sessions.service.ts index fed4d1b2..05302328 100644 --- a/terminus-terminal/src/services/sessions.service.ts +++ b/terminus-terminal/src/services/sessions.service.ts @@ -100,7 +100,7 @@ export class Session extends BaseSession { this.open = true - this.pty.on('data', data => { + this.pty.on('data-buffered', data => { this.emitOutput(data) }) @@ -200,7 +200,8 @@ export class SessionsService { electron: ElectronService, log: LogService, ) { - nodePTY = electron.remoteRequirePluginModule('terminus-terminal', 'node-pty-tmp', global as any) + const nodePTYPath = electron.remoteResolvePluginModule('terminus-terminal', 'node-pty-tmp', global as any) + nodePTY = electron.remoteRequire('./bufferizedPTY')(nodePTYPath) this.logger = log.create('sessions') this.persistenceProviders = this.config.enabledServices(this.persistenceProviders).filter(x => x.isAvailable()) }