Let’s redesign the desktop UX
A few weeks back I’ve seen a post about how an organized file system is not the way many people today use computers. Instead, they manipulate their data in the way of fragments (think documents, links, open tabs, images), which they move, save and copy-paste around without explicit intent to ever see them again. In the case when they do, they have little recollection of where the fragment is, but rather what was it about. What they need is a good search engine oven all fragments their computer has seen, instead of a way to organize every piece of information into files and directories.
This got me thinking, and so I have found a few similar redesigns of the desktop computer experience.
Fragments would be useful, but number 1 complaint to the post on Hacker News was “you are not organized, that’s why file system does not appeal to you”. That’s true, fragments are not the way to organize anything (especially if the system is deleting old fragments!), which is why there has to another way of storing data.
Another problem from the same basket came with realization, that every program I run has access to all my files. Even simple commands like
cut and build scripts of projects I am checking out could, in theory and practice, access my home directory, ssh keys, personal documents and configuration files. And that’s even without superuser privileges!
Also, programs are constantly cluttering my home directory with hidden (
.zoom/) and visible (
snap/) directories. My current solution is to give-in into clutter of Pictures, Documents, Videos, Downloads and many program-specific files. Instead, I create my own
Work_Firm_B directories over which I have all the control and none of the clutter.
The solution is radical: let’s abandon the single file system and instead allow user to create so-called repositories. They would:
- Act as a secluded file system, referenced by a name.
- Would not be freely accessible and would require user consent for each file separately. More general “browsing” access would be granted only to file explorer applications.
- Could be a base unit for back-up, synchronization or version control (hence the name).
When smart phones made their appearance, mobile operating systems introduced quite a few innovations over the desktop. Namely, OS-governed concept of application. It’s comparable to a “desktop program”, but it:
- Runs with limited permissions granted by the user. This includes networking, storage access and device access.
- Defines its own launchable apps with metadata (localized name, icon, etc.) and background services.
- Can easily be installed, updated and removed.
Desktop platforms do solve some of these: Windows .exe solves 2., package managers solve 3., containerization software solves 1., systemd and .desktop files solve 2. But these are different approaches, glued together, and as a whole they lack confluence.
So, let’s try to create desktop applications as seamless, designed concept.
The single file system is also not the best approach for programs, because they expect specific files to exist on a shared medium, accessed by everyone. We’ve all experienced how this goes wrong.
So instead, let’s give applications their isolated file system. It would also be wise to separate the stored data:
- installation could be shared between users and would be read-only to prevent corruption.
- configuration would contain user-specific data that could be transferred between installations.
- cache would be user-specific content, deletable at any moment.
- temporary would be deleted at system (or application) shutdown.
This way, we have more control over the data and can quickly delete cache when storage is full, backup user configurations or manage installations.
- .vimrc is configuration
- /etc/nginx/nginx.conf is configuration
- .ssh/ is configuration
- Spotify’s login credentials are configuration
- Spotify’s music cache is obviously cache
- game save files are configuration (or are moved into one of user’s repositories)
But what about the dependencies? Well it would be reasonable that each application would state its dependencies beforehand, so package manager can prepare them during installation. Such dependencies could be called a library and would basically be a read-only file system attached to the installation file system.
And the runtime dependencies? Like communicating with GUI or ssh user agent? Well, this is a different story. Because in UNIX, everything is a file, IPC (interprocess call) can be made trough UNIX socket. Think TCP port, but faster. Because we don’t have a single FS, we cannot reference these sockets. To the rescue comes the idea of generalizing the “everything is a file” to “everything is a URL” (or is a resource accessible via URL) employed at Redox. This means that
fopen takes a URL instead of a path and first resolves the schema of the syscall. When using the default
file: schema, everything is the same, but to access GUI, Redox uses
orbital: (Orbital is its windowing system).
Entry point declaration
As described, we need to somehow define application’s metadata and a way to launch it. This is needed for GUIs to display the list of applications with localized names, grouped by category and searchable by description.
With a single FS and Linux, this was achieved via .desktop files at a few standardized locations. Again we have to resort to a IPC calls to an “application registry”, which would populate its list during package installations and then respond to GUIs.
Similarly, shells in Linux (e.g. bash) search directories in the PATH env variable to resolve the user’s command and execute a program. And just as GUIs, shells would have to call the app registry and ask which application provide CLI. Additionally, application’s manifest could include information about required arguments to facilitate auto-complete.
Death by thousand tabs
I believe that tabs within applications lead to unnecessary UX structures that at best confuse inexperienced users at worst give power users headaches jumping between applications and their tabs.
An open window (or a terminal) should be a combination of an application and its content (fragment). For example Microsoft Word + a document, or Google Chrome + a tab, or Adobe Photoshop + an image, or IntelliJ + a project, or a game + a save file.
Desktop environments already have the tools to organize windows if you are into that, so there should not be a need for every application to create its own tabbing system.
To go one step further, application entry points could include input stream declarations. It would say something like, “Word can only run with a document fragment” and “calculator runs only without fragment” and “Chrome runs without a fragment (it has a start page) or with a website fragment”.
This way, before launching Word, the system would ask “new fragment or one of these?”. Such declarations also provide information what application are able to open certain fragments (aka. “open with” menu).
Just like on current platforms, heavy applications could divide core logic into a separate shared process (background service) so opening new fragments (website tabs, game saves) would not have to start up the shared service again.
It’s time to define what a fragment is more robustly. In essence, it is a file and its metadata concerning the user, such as keywords, description, file type, source of the data, date of creation, last update and the name of the fragment. Some of these are already present in modern file systems, but are often used for other purposes. File name is composed of actual name and extension, which imposes file type. This setup is not ideal, and it has been introducing butchered code for naming files for the last three decades.
By default, all accessed fragments would not have a defined storage location but would reside “on this computer”. Their metadata would have a “forgettable” flag, indicating that it may be deleted if the system decides to do so. When in need of organization, users would pin fragments into a repository, providing a “file system”-like experience.
As of now, I believe that this metadata of the fragment should not be passed to the application, since applications should work on the content and not metadata. But they may suggest some metadata such as type, keywords or description when emitting output stream. This means that applications may produce fragments or just plain binary files.
Is this a new OS?
Writing a post is easy, but implementing all that was written is not. I am not sure how one would even start. Fork Linux kernel? Containerization software on Linux? A microkernel that already has a good IPC support?
If I would just rust to get a working prototype, it would choose containerization on Linux, but that would not be a permanent solution due to performance issues and the fact that I would not sleep well if I knew that I introduced a new layer to a simple desktop setup.
But hey, these are radical ideas, we need test out the waters first.