Skip to content

Commit

Permalink
systemBooted callback + auto resize in guest
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkar598 committed Jun 23, 2024
1 parent 540ab5d commit a51b39f
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 19 deletions.
25 changes: 19 additions & 6 deletions src/app/components/terminal/terminal.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@angular/core';
import { Terminal } from '@xterm/xterm';
import { FitAddon } from 'xterm-addon-fit';
import { TerminalDimensions } from '../../../vm/emulator.service';

@Component({
selector: 'app-terminal',
Expand All @@ -23,26 +24,38 @@ export class TerminalComponent implements AfterViewInit, OnDestroy {

@Output()
public input = new EventEmitter<string>();
@Output()
public resize = new EventEmitter<TerminalDimensions>();

private terminal = new Terminal();
private fit = new FitAddon();
private observer = new ResizeObserver(() => {
this.fit.fit();
});
private fitAddon = new FitAddon();
private observer = new ResizeObserver(() => this.fit());

constructor() {
this.terminal.onData((value) => this.input.emit(value));
this.terminal.loadAddon(this.fit);
this.terminal.loadAddon(this.fitAddon);
}

public write(value: string) {
this.terminal.write(value);
}

private fit() {
this.fitAddon.fit();
const dimensions = this.fitAddon.proposeDimensions();
console.log(dimensions);
if (!dimensions) {
console.warn('Cannot resolve dimensions');
return;
}

this.resize.emit(dimensions);
}

ngAfterViewInit(): void {
this.terminal.open(this.container.nativeElement);
this.observer.observe(this.container.nativeElement);
this.fit.fit();
this.fit();
}

ngOnDestroy(): void {
Expand Down
1 change: 1 addition & 0 deletions src/app/pages/editor-page/editor-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<app-terminal
#terminal
(input)="emulator.sendPort(Port.Console, $event)"
(resize)="emulator.resizePort(Port.Console, $event)"
/>
</app-panel>
<app-panel title="Screen log" as-split-area>
Expand Down
1 change: 1 addition & 0 deletions src/vm/commandQueue.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export class CommandQueueService {
if (this.initialized)
throw Error('Controller initialized twice. It probably crashed.');
console.debug('Controller initialized.');
this.emulator.resolveSystemBooted();
this.initialized = true;
this.resultBuffer = '';
this.tickQueue();
Expand Down
34 changes: 29 additions & 5 deletions src/vm/emulator.service.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
import { EventEmitter, Injectable, Output } from '@angular/core';
import type {
MsgResizePort,
MsgSendPort,
WorkerMsgWithoutCID,
WorkerResponseMsg,
} from './emulator.worker';
import { environment } from '../environments/environment';
import { Port, vmRemoteUrlSearchParameter } from '../utils/literalConstants';

export interface TerminalDimensions {
rows: number;
cols: number;
}

const encoder = new TextEncoder();

@Injectable({
providedIn: 'root',
})
export class EmulatorService {
@Output()
public resetOutputConsole = new EventEmitter<void>();
public readonly resetOutputConsole = new EventEmitter<void>();
@Output()
public receivedOutput = new EventEmitter<[Port, string]>();
public readonly receivedOutput = new EventEmitter<[Port, string]>();

private readonly worker;

private readonly asyncCallbacks = new Map<number, Function>();

private worker;
public resolveSystemBooted!: Function;
public readonly systemBooted = new Promise<void>(
(resolve) => (this.resolveSystemBooted = resolve),
);

private asyncCallbacks = new Map<number, Function>();
private readonly savedDimensions = new Map<Port, TerminalDimensions>();

constructor() {
this.systemBooted.then(() => {
for (const [port, dims] of this.savedDimensions) {
this.resizePort(port, dims);
}
});

interface FakeWorker {
new (url: URL): Worker;
}
Expand Down Expand Up @@ -73,11 +92,16 @@ export class EmulatorService {
public sendPort(...data: MsgSendPort['data']) {
this.sendCommand({ command: 'sendPort', data });
}
public resizePort(...data: MsgResizePort['data']) {
this.savedDimensions.set(data[0], data[1]);
this.sendCommand({ command: 'resizePort', data });
}
public pause() {
return this.sendCommandAsync({ command: 'pause' });
}
public start() {
return this.sendCommandAsync({ command: 'start' });
this.sendCommand({ command: 'start' });
return this.systemBooted;
}
public sendFile(name: string, content: Uint8Array | string) {
if (typeof content === 'string') content = encoder.encode(content);
Expand Down
26 changes: 18 additions & 8 deletions src/vm/emulator.worker.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
/// <reference lib="webworker" />
import { Port, vmRemoteUrlSearchParameter } from '../utils/literalConstants';
import type { TerminalDimensions } from './emulator.service';

importScripts('./lib/libv86.js');

export interface MsgSendPort {
command: 'sendPort';
data: [Port, string];
}
export interface MsgResizePort {
command: 'resizePort';
data: [Port, TerminalDimensions];
}
export interface MsgStart {
command: 'start';
data?: undefined;
Expand All @@ -23,6 +28,7 @@ export interface MsgSendFile {

export type WorkerMsgWithoutCID =
| MsgSendPort
| MsgResizePort
| MsgStart
| MsgPause
| MsgSendFile;
Expand Down Expand Up @@ -132,19 +138,23 @@ const emulator = new V86({
onmessage = ({ data: e }: MessageEvent<WorkerMsg>) => {
switch (e.command) {
case 'sendPort': {
const [port, value] = e.data;
emulator.bus.send(
`virtio-console${e.data[0]}-input-bytes`,
[...e.data[1]].map((x) => x.charCodeAt(0)),
`virtio-console${port}-input-bytes`,
[...value].map((x) => x.charCodeAt(0)),
);
break;
}
case 'resizePort': {
const [port, dimensions] = e.data;
emulator.bus.send(`virtio-console${port}-resize`, [
dimensions.cols,
dimensions.rows,
]);
break;
}
case 'start': {
emulator.run().then(() => {
postMessage({
command: 'asyncResponse',
commandID: e.commandID,
} satisfies WorkerResponseMsg);
});
void emulator.run();
break;
}
case 'pause': {
Expand Down

0 comments on commit a51b39f

Please sign in to comment.