Devember 2022 | Windows XP-style website(source code released)

Progress report #11

I’m working on improving the overall experience, giving it that final polish.
I’ve spent a lot of time doing “invisible” work, like changing how windows are created, or how the filemanager works(now static and uses Javascript to call CGI API, instead of CGI application + template).
My XP-style CSS now supports a bunch more stuff, works better in Firefox, and even has some features XP.css is missing(like basic menu bars/status bars/the task bar)
I’ve also polished the terminal manager, and added the beginning of my LXC UI front-end.

Tomorrow I will try to finish before the release:

  • window dragging
  • LXC UI interesting bits
  • file explorer support for opening/downloading files
  • text editor CGI API backend
  • terminal color support

If I get really ambitious, I might also:

  • finish data logging and SVG graph generation, create pretty graphs for system info/task manager
  • add a cool (shader) screen saver, maybe starfield?

I don’t know how late I’m allowed to with regard to the Devembuary deadline, but I figure if I release the source code of a working state tomorrow, it’ll be fine.

1 Like

Neat!

one change I’d recommend is a brighter color for the text in the terminal for better contrast. the dark blue text on black terminal background makes the text very hard to read.

1 Like

I hear you, I too feel like readabillity was decreased.

I was planning on re-adding the DOS code page 437 VGA font, so I’ve done that now.

The colors are basically VGA colors for now, but I will make them selectable.

1 Like

It seems like January is over in my timezone. That went by quickly…
Although my project isn’t quite finished yet(what project honestly is?), I’ve decided to release the source code on the deadline.

(Some of the code surely is ugly. Guess at some point this needs another refactor… And documentation again)

I’ll surely post more updates here, as I’ll keep working on the project.
I’ve actually implemented better window dragging and some more of the LXC UI functional bits.
My TODO currently looks like, in descending order of importance:

  • Finish LXC UI
  • Terminal: Fix colors, add menu for resize, re-theme, etc.
  • File explorer: Add “clipboard”, open/download file
  • Text editor: Use CGI API instead of template
  • Data logging and SVG graphs
  • Screensavers
1 Like

Progress report #12

With the additional time afforded by the additional devember extension till the 9th, I think I can complete my remaining TODO entries.
I’ve actually made good progress:

  • Window dragging is fixed
  • some more interesting LXC UI bits are there
  • Terminal now has full support for colors, bold, underline and reverse SGR attributes
  • Built-in CSS editor for the terminal and desktop

(In the video you can see me using the built-in CSS editor to quickly prototype an olive-green variant of the XP color scheme, and play around with some of the new terminal features)

Next up will be the file explorer and text editor(They’ll need to work together anyway). I’m confident that I can finish them during the new deadline.

After that, my stretch goals are :stuck_out_tongue:

  • Data logging and SVG graphs
  • Screensavers
  • calculator
  • These things would also integrate nicely into a generic file manager
    • hex editor
    • picture viewer
    • media player
  • Fun-to-have
    • Minesweeper
    • Paint
1 Like

Progress report #13

I’ve redone a lot of terminal code, cleaning up a lot of unneeded cruft. The CGI script now really is just a lightweight wrapper to get events and send commands to tmux control-mode(2 files).

Here is a complete tour of the terminal, and it’s features:

I feel like it’s a usable web terminal emulator now, with minimal dependencies! Basically just bash + tmux + busybox httpd.

Current terminal implementation details

I can receive asynchronous events from a simple bash CGI script by using:

# stream the output of tmux control-mode as event-stream
echo "Content-Type: text/event-stream"
echo

# create a pipe that never has any data, because stdin in closed
while true; do sleep 1; done | tmux -C attach-session -t "${session_name}" | while IFS="" read -r data; do
	echo "data: ${data}"
	echo
done

And run a command:

echo "Content-Type: text/plain"
echo

# run the tmux command
tmux -C "${command_args[@]}" < /dev/zero

From Javascript, I can get an even stream using:

let tmux_control_mode = new EventSource("/cgi-bin/tmux/control_mode.sh?session_name="+encodeURIComponent(session_name));

And run a command by sending a POST request to /cgi-bin/tmux/run_command.sh
With the e.g. body: command_str=capture_pane&arg=-p to dump the terminal content.

The rest is just protocol decoding, ANSI decoding, and wrangling with Javascript.

This re-implementation also made it easier to implement multiple windows per session, getting cursor position, stopping properly on exits/disconnects, and resizing the tmux windows.

(I’ll get to my other TODO items now…)

Progress report #14

I’ve worked a bit on the File manager and text editor. There are also a lot of other CSS fixes etc. - Will be committed to the repo soon, maybe even still today.

The text editor is now feature-complete(It doesn’t need to do much, it’s not complicated).

The file manager just needs some more actions(like copy, past, cut, new file, new folder, download, etc.)

I’ll try to finish up the file manager, then work on some of the stretch goals. Most of them should be fairly easy to implement. Let’s see how many stretch goals I can finish before the deadline :wink:

Progress report #15

This is possibly the last progress report before the deadline, so here it goes.
Here’s a video of most of the applications.

The applications are now mostly complete and are missing no obvious important features.
I’ve done a lot of improvements, and small features again, along with some more major ones.

My favorite applications now are the terminal and the file explorer. They both work great.

And I’ve done all that with just bash, CGI, HTML, CSS, and plain Javascript.
No npm, no PHP, not even jquery.

I’ve updated the GitHub with a list of features, and some install instructions:

I’d love some feedback :slight_smile:

Progress report #16

Today I’ve created a tool to stream low-latency desktop content to the browser, and stream mouse/keyboard inputs.
(If nobody tells me to stop, I’ll just keep on adding features until judgement day :stuck_out_tongue: )

It uses ffmpeg and mpjpeg(multipart-encoded jpeg), which can trivially be served by a CGI script.
I’ll add support for spawning an X server and client using Xvfb as well, so you don’t have to mirror an existing X display, and I can just create links to X11 applications on the web. This could also be used to stream a webcam with low latency. Or to live-encode videos without browser-supported codec.

The crispy-ness is in part due to the low-latency options. You can control the compression level, and disable low-latency output for better image quality.

It’s easy to implement as well, a basic CGI script could look like this:

echo "Content-type: multipart/x-mixed-replace; boundary=--ffmpeg"
echo

DISPLAY=:0 ffmpeg -loglevel fatal -framerate 15 -video_size 640x480 -f x11grab -i display_arg -c:v mjpeg -q:v 1 -f mpjpeg -

(Yes, that’s all. You could of course replace x11grab with any valid ffmpeg input)

Progress report #17

This new X11 streamer is so cool. I’ve made many improvements: It supports spawning an X11 server now, and resizing the X11 server to fit the window. This allows me to seamlessly run an X11 application in the browser. In the video you can see me use xterm and Firefox. The FPS are configurable(default used in the video was 15).

Latency is perfectly usable for remote administration, and the low-latency mode looks shit but runs great. The bandwidth for such a stream is a little high(JPEG has no i-frames, this always sends complete frames), but the CPU usage is surprisingly low.

I want to try gaming over this as well, just for fun. I’ve already added support for capturing the mouse and relative mouse movements. I just need to configure VirtualGL, so I can run some games :slight_smile:

(I’ll keep adding features until somebody tells me to stop. Wasn’t the extended deadline supposed to be the 9th? I’m not complaining or anything…)

Progress report #18

This last little while has been about cleaning up various bits and pieces in the project.
Towards this end I’m implementing several new things.

I’m replacing all CGI endpoints with a single kinda clever 64-line CGI script “cgi_command.sh”: This script decodes a command and some headers from the URL-encoded arguments, then runs replies with the headers and runs the command, optionally encodes the output using either the server-sent events event-stream mechanism, base64, or just plain text.
This basically turns any command into an “API”, and there is a 128-line JS API for making requests to that API easily.

I’ve also implemented a library for managing state in applications. This library performs argument checking on setting the state.data, and automatically updates and is automatically updated by the HTML, hash args, and window.sessionStorage/window.localStorage.
This way input elements don’t loose their state when reloading if required, and you can build fully URL-serializable application state(e.g. you can create a link to a run an application with pre-defined state).

I’m also working on separating out the X11Streamer and Terminal components into reusable components, so you can easily an X11 application or a terminal.

The video is of a small demo application I’ve written to test the new systems:

I will port over all the current applications to the new system eventually. For now I’m working on integrating this into the X11 streamer.
The current development version in git might be broken at times, let me know if anybody wants a version that actually works(I’ll feature-test and tag a release).

I’m still planning on creating networked browser-based VMs based on v86, by the way…

I desperately want a feature where a ServiceWorker can run a HTTP request to a browser VM(Part of plan is to enable hosting the entire project as a static website, by shipping a tiny Linux image with the scripts etc. installed, and booting that in the browser, to have a publicly hosted version, without allowing random users access to my server).
I’ve considered just writing an application that listens on the serial port, and responds to HTTP requests from the browser. But that seems slow and error-prone, and implementing full multiplexing with multiple event-streams and all seems unreasonable for such a hack.
The other option is adding a network stack to the Browser, and sending requests via actual IP/TCP/HTTP.
This sounds even more unreasonable, but there are some nice embedded TCP/IP stacks that can be ported easily to the browser using emscripten(I’ve read the porting guides, nobody has done that yet AFAIK).

There are currently two TCP/IP implementations I’m considering to port to the browser: uIP and lwIP(both written by the same guy Adam Dunkels)

Using uIP would mean that I only implement a minimal HTTP for getting/sending content from/to the VM, but no routing etc.
But that would probably be easier to implement and port. uIP in it’s “raw” form should basically just work if sending/receiving packets from the v86 network events when compiled via emscripten(I’d still need to write a dead-simple C program/wrapper).
You could still do possibly do routing in the VM network by using a VM as router and configuring the switch accordingly(might require a switch with MAC VLANs, but that’s easy to implement)

Using lwIP would mean that every VM gets a properly routed port, and packets will be forwarded only to the right place, instead of “broadcast” to all VMs and interfaces.
lwIP also supports some protocols directly, like HTTP, DHCP, DNS, etc. and this would expose that to the browser which is very cool.
lwIP is more difficult to port, all though I believe still very possible for a hobbyist like me.

Part of the plan is to connect multiple browser VMs, and connect external browser VMs via WebRTC, and connect external servers etc. via TAP device exposed via CGI.
This way you can effortlessly network between browser VMs, actual servers running a CGI script, and WebRTC peers, all from the comfort of your browser.
The browser VMs could also be live-migrated over such a network, and could stay up(even after a browser close) as long as a single browser tab is open somewhere within the network.

Progress report #19

Still working on things… Wasn’t this supposed to be over long ago? :stuck_out_tongue:

Anyway, I’ve reworked a lot of the back-end stuff, so nothing really cool to show of.
Except a new boot/login screen and some gaming using the X11 streamer:

A lot of stuff other than the X11 streamer is currently somewhat broken because of these reworks, but when I fix it I’ll rebuild it better(clean separation between API and UI code) and more consistent(e.g. the way arguments are passed between applications and HTML elements are updated from a central object).

And yes, the login screen is functional, assuming the server requires HTTP-Basic-style authentication, and the browser allows specifying username/password via URL.