X11 really delivered on the promise of “run apps on other machines and display locally.” XResources let you store your configuration information in the X server. Fonts were stored in your display server or served from a font server.
X Intrinsics let you do some amazing things with keybindings, extensibility, and scripting.
And then we abandoned all of it. I realize sometimes (often?) we had a good reason, but I feel like X only got to show off its true power only briefly before we decided to make it nothing but a local display server with a lot of unused baggage.
(The only system that did better for “run apps remotely/display locally” was Plan 9, IMHO.)
A lot of these things were abandoned because there wasn’t a consistent story of what state belonged in the client and server and storing state on the server was hard. For this kind of remote desktop to be useful, you often had thin X-server terminals and a big beefy machine that ran all of the X clients. With old X fonts, the fonts you could display depended on the fonts installed on the server. If you wanted to be able to display a new font, it needed installing on every X server that you’d use to run your application. Your application, in contrast, needed installing on the one machine that would run it. If you had some workstations running a mix of local and remote applications and some thin clients running an X server and nothing locally, then you’d often get different fonts between the two. Similarly, if you used X resources for settings, your apps migrated between displays easily but your configuration settings didn’t.
The problem with X11’s remote story (and the big reason why Plan 9 was better) was that X11 was only a small part of the desktop programming environment. The display, keyboard, and mouse were all local to the machine running the X server but the filesystem, sound, printer, and so on were local to the machine running the client. If you used X as anything other than a dumb framebuffer, you ended up with state split across the two in an annoying manner.
As someone who had to set up an X font server at least once, you didn’t have to have the fonts installed on every X server, you just had to lose all will to live.
But yes, X was just one part of Project Athena. It assumed you’d authenticate via Kerberos with your user information looked up in Hesiod and display your applications via X, and I think there was an expectation that your home directory would be mounted over the network from a main location too.
Project Athena and the Andrew Project were what could have been. I don’t think anyone expected local workstations to become more powerful than the large shared minis so quickly, and nobody saw the Web transforming into what it is today.
At school I got to use an environment with X terminals, NFS mounts for user data, and NIS for authentication. It worked fairly well, and when you see something like that work, it’s hard to see the world in quite the same way afterwards.
As for the web, it’s true that it challenged this setup quite a bit, because it was hard to have enough CPU on large server machines to render web content responsively for hundreds of users. But on the other hand, it seems like we’ve past the point of sending HTML/CSS/JS to clients being optimal from a bandwidth point of view - it’s cheaper to send an h264 stream down and UI interaction back. In bandwidth constrained environments, it’s not unimaginable that it makes sense to move back in the other direction, similar to Opera Mini.
The early version of the Andrew Window Manager supported tiling using a complex algorithm based on constraint solving. They made an X11 window manager that mimicked the Andrew WM.
Let me rephrase that: I know they made an X11 window manager that mimicked Andrew but I cannot for the life of me find it. It’s old, it would’ve been maybe even X10 and not X11…
So yeah, if you know where that is, it would be a helluva find.
We didn’t abandon it; rather, we admitted that it didn’t really work and stopped trying. We spent our time in better ways.
I was the developer at Trolltech who worked most on remote X, particularly for app startup and opening windows. It sucked, and it sucked some more. It was the kind of functionality that you have to do correctly before and after lunch every day of every week, and a moment’s inattention breaks it. And people were inattentive — most developers developed with their local X server and so wouldn’t notice it if they added something that would be a break-the-app bug with even 0.1s latency, and of course they added that sooner or later.
Remote X was possible, I did use Qt across the Atlantic, but unjustifiable. It required much too much developer effort to keep working.
I wonder how much of that pain was from legacy APIs? I spent some time about 15 years ago playing with XCB when it was new and shiny and it was possible to make something very responsive on top of it (I was typically doing development on a machine about 100ms away). The composite, damage, and render extensions gave you a good set of building blocks as long as everything involved in drawing used promises and you deferred blocking as long as possible. A single synchronous API anywhere in the stack killed it. I tried getting GNUstep to use the latency hiding that XCB enabled and it was a complete waste of time because there were so many blocking calls in the higher-level APIs that the mid-level APIs undid all of the work that you did at the lower level.
If; however, you designed your mid- and higher-level drawing APIs to be asynchronous, remote X11 performed very well but getting people to adopt a completely new GUI toolkit seemed like too much effort.
That said, the way that you talk to a GPU now (if you actually care about performance) is via asynchronous APIs because bus round trips can be a bottleneck. A lot of the lessons from good remote drawing APIs are directly applicable to modern graphics hardware. With modernish X11 you can copy images to the server and then send sequences of compositing commands. With a modern GPU, you copy textures into GPU memory and then send a queue of compositing command across the bus.
We at Trolltech avoided legacy APIs, provided our users with good APIs (good enough that few people tried to go past it to the lower-level protocol), and still people had problems en masse.
If your test environment has nanoseconds of latency, you as app developer won’t notice that the inner body of a loop requires a server roundtrip, but your users will notice it very well if they have 0.1s of latency. Boring things like entering data in a form would break, because users would type at their usual speed, and the app would mishandle the input.
Enter first name, hit enter, enter last name, see that sometimes start of the last name was added to the first-name field depending on network load.
Edited to add: I’m not trying to blame here (“fucking careless lazy sods” or whatever), I’m trying to say that coping with latencies that range from nanoseconds to near-seconds is difficult. A lack of high-latency testing hurts, but it’s difficult even with the best of testing. IMO it’s quite reasonable to give up on a high-effort marginal task, the time can be spent better.
Note that a lot of the problems exist whether or not the code is part of the application process or not. If you use Windows Remote Desktop around the world, you have 100s of milliseconds of latency. If you press shift+key, it’s not uncommon to see them delivered out of order and incorrect results. (I don’t know exactly how this happens because a TCP connection implies ordering, so I suspect this is really about client message construction and server message processing.) The engine somehow has to ensure logically correct rendering while avoiding making application UI calls synchronous. Applications may not be aware of it, but the logic is still there.
We at Trolltech avoided legacy APIs, provided our users with good APIs (good enough that few people tried to go past it to the lower-level protocol), and still people had problems en masse.
I’ve never looked very closely at Qt, but I was under the impression that most of your drawing APIs were synchronous? I don’t remember promises or any other asynchronous primitives featuring in any of the APIs that I looked at.
Neither really synchronous nor really asynchronous… There are three relevant clocks, all monotonic: Time proceeds monotonically in the server, in the app and for the user, and none of the three can ever pause any of the others as would be necessary for a synchronous call, and no particular latency or stable offset is guaranteed.
So, yes, Qt is synchronous, but when people say synchronous they usually have a single-clock model in mind.
There are no promises, but what some people consider synchronous drawing primitives don’t really work. Promises would let you write code along the lines “do something, then when the server call returns, draw blah blah”. Synchronous code would be “do something; draw blah blah;”. Qt’s way is react strictly to server events: The way to draw is to draw in response to the server’s asking for that, and you don’t get to cheat and expect what the server will ask for, and you can’t avoid redrawing if the server wants you to.
We were careful about the three monotonic times, so the default handling has always been correct. But it’s very easy to do things like change the destination of keyboard input, and forget that the events that arrive at the program after the change may have been sent from the server (or from the user’s mind) either before or after the program performed the change.
A tenth of a second is a long time in a UI. People will type two keystrokes or perform a mouse action that quickly. If you want to avoid latency-induced mistakes you have to think clearly about all three clocks.
People got and continue to get a lot of mileage out of remote x. Even on windows, I believe you can use remote forwarding with putty to an x server like vcxsrv.
The biggest killer of remote x was custom toolkits (as opposed to athena and xt) and, ultimately, glx. The former is slow to proxy transparently; the latter is nigh impossible.
Yeah. I feel that the problem with Xorg isn’t necessarily Xorg itself, but instead a lot of the programmatic interfaces are kludgy, and the more complex usecases are specific enough that there has been very little documentation of them. It very likely would fulfill a lot of uses that people have no alternative for, but that knowledge has not been passed on. So instead people see it as a huge bloated mess, only partly because it is, but partly because they simply either don’t know or don’t care about those other workflows and uses.
! is a line comment in xrdb-syntax. So xterm, parsing the file as you would expect, ignores everything from the leading ! to the end of the line, including the /* and */.
But xrdb pipes its input through cpp, which parses /* comments but not ! ones. So the entire region is removed before xrdb sees it.
This is very cool; I have never seen the “open a URL without the mouse” implemented in any terminals other than urxvt, which is why I never considered switching away. Unfortunately XTerm still does much worse than urxvt with font fallbacks for non-latin character sets, (at least out of the box) so I don’t think I’ll be switching, but it’s good to have options.
The terminology terminal from Enlightenment may not be the best in many ways, but it’s super useful for irc and such, because it can overlay images on itself, so not everything has to be opened in the browser. Wish that was a thing in more terminal emulators.
And tabs, which terminology sucks at. Thus xfce4-terminal is nice for all else.
Kitty (which I’ve only learned about recently) has its own inline-image system which the author invented himself; on the one hand it’s really easy as an app programmer to emit an image for inlining (encode to png, base64 encode, wrap in an escape sequence). On the other absolutely nothing else supports it.
I don’t know what Enlightenment do but SGI devised “sixel” which a few emulators support.
Enlightenment’s the wm, terminology’s the terminal.
Checked kitty’s frontpage and the feature I’m talking about isn’t there. Simply terminology sees a url ending in jpg or some other supported format, you click it, the image is overlaid. Click to close and type the lolz to irc.
Maybe that image-inline and sixel stuff can be useful too.
I’d like a terminal emulator that doesn’t scroll on output at all, like in Plan 9, where you can type cat x and you stay at the top instead of being scrolled to the bottom of the output immediately. Basically removes (much of) the need for a pager.
I like xterm quite a bit and used it for several years. I did eventually write my own semi-clone of it though since I wanted a little more control over things for nesting and remote access… but most my “extensions” are actually features xterm itself defined!
Take a look down this list: https://www.xfree86.org/current/ctlseqs.html so many cool things, even like image support (via sixel) and clipboard integration is all there for applications. Most builds of xterm I actually have encountered though compile these out.
X11 really delivered on the promise of “run apps on other machines and display locally.” XResources let you store your configuration information in the X server. Fonts were stored in your display server or served from a font server.
X Intrinsics let you do some amazing things with keybindings, extensibility, and scripting.
And then we abandoned all of it. I realize sometimes (often?) we had a good reason, but I feel like X only got to show off its true power only briefly before we decided to make it nothing but a local display server with a lot of unused baggage.
(The only system that did better for “run apps remotely/display locally” was Plan 9, IMHO.)
A lot of these things were abandoned because there wasn’t a consistent story of what state belonged in the client and server and storing state on the server was hard. For this kind of remote desktop to be useful, you often had thin X-server terminals and a big beefy machine that ran all of the X clients. With old X fonts, the fonts you could display depended on the fonts installed on the server. If you wanted to be able to display a new font, it needed installing on every X server that you’d use to run your application. Your application, in contrast, needed installing on the one machine that would run it. If you had some workstations running a mix of local and remote applications and some thin clients running an X server and nothing locally, then you’d often get different fonts between the two. Similarly, if you used X resources for settings, your apps migrated between displays easily but your configuration settings didn’t.
The problem with X11’s remote story (and the big reason why Plan 9 was better) was that X11 was only a small part of the desktop programming environment. The display, keyboard, and mouse were all local to the machine running the X server but the filesystem, sound, printer, and so on were local to the machine running the client. If you used X as anything other than a dumb framebuffer, you ended up with state split across the two in an annoying manner.
As someone who had to set up an X font server at least once, you didn’t have to have the fonts installed on every X server, you just had to lose all will to live.
But yes, X was just one part of Project Athena. It assumed you’d authenticate via Kerberos with your user information looked up in Hesiod and display your applications via X, and I think there was an expectation that your home directory would be mounted over the network from a main location too.
Project Athena and the Andrew Project were what could have been. I don’t think anyone expected local workstations to become more powerful than the large shared minis so quickly, and nobody saw the Web transforming into what it is today.
At school I got to use an environment with X terminals, NFS mounts for user data, and NIS for authentication. It worked fairly well, and when you see something like that work, it’s hard to see the world in quite the same way afterwards.
As for the web, it’s true that it challenged this setup quite a bit, because it was hard to have enough CPU on large server machines to render web content responsively for hundreds of users. But on the other hand, it seems like we’ve past the point of sending HTML/CSS/JS to clients being optimal from a bandwidth point of view - it’s cheaper to send an h264 stream down and UI interaction back. In bandwidth constrained environments, it’s not unimaginable that it makes sense to move back in the other direction, similar to Opera Mini.
Omg what a scary thought!
Andrew was really amazing. I wish it had caught on, but if wishes were horses &c &c &c.
The early version of the Andrew Window Manager supported tiling using a complex algorithm based on constraint solving. They made an X11 window manager that mimicked the Andrew WM.
Let me rephrase that: I know they made an X11 window manager that mimicked Andrew but I cannot for the life of me find it. It’s old, it would’ve been maybe even X10 and not X11…
So yeah, if you know where that is, it would be a helluva find.
iirc scwm uses some kind of constraint-solving for window placement. but i am approx. 99% sure that that’s not what you are looking for.
it’s for that remaining 1% that i posted this message :)
We didn’t abandon it; rather, we admitted that it didn’t really work and stopped trying. We spent our time in better ways.
I was the developer at Trolltech who worked most on remote X, particularly for app startup and opening windows. It sucked, and it sucked some more. It was the kind of functionality that you have to do correctly before and after lunch every day of every week, and a moment’s inattention breaks it. And people were inattentive — most developers developed with their local X server and so wouldn’t notice it if they added something that would be a break-the-app bug with even 0.1s latency, and of course they added that sooner or later.
Remote X was possible, I did use Qt across the Atlantic, but unjustifiable. It required much too much developer effort to keep working.
I wonder how much of that pain was from legacy APIs? I spent some time about 15 years ago playing with XCB when it was new and shiny and it was possible to make something very responsive on top of it (I was typically doing development on a machine about 100ms away). The composite, damage, and render extensions gave you a good set of building blocks as long as everything involved in drawing used promises and you deferred blocking as long as possible. A single synchronous API anywhere in the stack killed it. I tried getting GNUstep to use the latency hiding that XCB enabled and it was a complete waste of time because there were so many blocking calls in the higher-level APIs that the mid-level APIs undid all of the work that you did at the lower level.
If; however, you designed your mid- and higher-level drawing APIs to be asynchronous, remote X11 performed very well but getting people to adopt a completely new GUI toolkit seemed like too much effort.
That said, the way that you talk to a GPU now (if you actually care about performance) is via asynchronous APIs because bus round trips can be a bottleneck. A lot of the lessons from good remote drawing APIs are directly applicable to modern graphics hardware. With modernish X11 you can copy images to the server and then send sequences of compositing commands. With a modern GPU, you copy textures into GPU memory and then send a queue of compositing command across the bus.
We at Trolltech avoided legacy APIs, provided our users with good APIs (good enough that few people tried to go past it to the lower-level protocol), and still people had problems en masse.
If your test environment has nanoseconds of latency, you as app developer won’t notice that the inner body of a loop requires a server roundtrip, but your users will notice it very well if they have 0.1s of latency. Boring things like entering data in a form would break, because users would type at their usual speed, and the app would mishandle the input.
Enter first name, hit enter, enter last name, see that sometimes start of the last name was added to the first-name field depending on network load.
Edited to add: I’m not trying to blame here (“fucking careless lazy sods” or whatever), I’m trying to say that coping with latencies that range from nanoseconds to near-seconds is difficult. A lack of high-latency testing hurts, but it’s difficult even with the best of testing. IMO it’s quite reasonable to give up on a high-effort marginal task, the time can be spent better.
Note that a lot of the problems exist whether or not the code is part of the application process or not. If you use Windows Remote Desktop around the world, you have 100s of milliseconds of latency. If you press shift+key, it’s not uncommon to see them delivered out of order and incorrect results. (I don’t know exactly how this happens because a TCP connection implies ordering, so I suspect this is really about client message construction and server message processing.) The engine somehow has to ensure logically correct rendering while avoiding making application UI calls synchronous. Applications may not be aware of it, but the logic is still there.
I’ve never looked very closely at Qt, but I was under the impression that most of your drawing APIs were synchronous? I don’t remember promises or any other asynchronous primitives featuring in any of the APIs that I looked at.
Neither really synchronous nor really asynchronous… There are three relevant clocks, all monotonic: Time proceeds monotonically in the server, in the app and for the user, and none of the three can ever pause any of the others as would be necessary for a synchronous call, and no particular latency or stable offset is guaranteed.
So, yes, Qt is synchronous, but when people say synchronous they usually have a single-clock model in mind.
There are no promises, but what some people consider synchronous drawing primitives don’t really work. Promises would let you write code along the lines “do something, then when the server call returns, draw blah blah”. Synchronous code would be “do something; draw blah blah;”. Qt’s way is react strictly to server events: The way to draw is to draw in response to the server’s asking for that, and you don’t get to cheat and expect what the server will ask for, and you can’t avoid redrawing if the server wants you to.
We were careful about the three monotonic times, so the default handling has always been correct. But it’s very easy to do things like change the destination of keyboard input, and forget that the events that arrive at the program after the change may have been sent from the server (or from the user’s mind) either before or after the program performed the change.
A tenth of a second is a long time in a UI. People will type two keystrokes or perform a mouse action that quickly. If you want to avoid latency-induced mistakes you have to think clearly about all three clocks.
People got and continue to get a lot of mileage out of remote x. Even on windows, I believe you can use remote forwarding with putty to an x server like vcxsrv.
The biggest killer of remote x was custom toolkits (as opposed to athena and xt) and, ultimately, glx. The former is slow to proxy transparently; the latter is nigh impossible.
Yeah. I feel that the problem with Xorg isn’t necessarily Xorg itself, but instead a lot of the programmatic interfaces are kludgy, and the more complex usecases are specific enough that there has been very little documentation of them. It very likely would fulfill a lot of uses that people have no alternative for, but that knowledge has not been passed on. So instead people see it as a huge bloated mess, only partly because it is, but partly because they simply either don’t know or don’t care about those other workflows and uses.
My three terminal drivers used are:
In that order.
I have made
xterm.sh
andurxvt.sh
wrappers to have random color theme loaded at start of each new xterm(1) or urxvt(1) process.I was too lazy to do the same about sakura(1).
For urxvt(1) I also pick a random background.
Details about random xterm(1) theme are here if you are interested:
https://vermaden.wordpress.com/2018/07/01/freebsd-desktop-part-12-configuration-openbox/
If I would have to pick only one - it would be xterm(1) for sure.
For its compatibility and configurability.
Screenshot of all three of them:
https://i.imgur.com/EpwzpYd.png
Regards.
You get my upvote for the gratuitous piping of
uname -v
intololcat
in your screenshot.Thanks :)
Actually, you can set things up more conveniently than that. I have the following in
~/.Xdefaults
:Now I can just edit that file, and the next xterm I start will use the new configuration, no special “config update” command needed.
Hm, I’m not sure I understand why this works?
!
is a line comment in xrdb-syntax. So xterm, parsing the file as you would expect, ignores everything from the leading!
to the end of the line, including the/*
and*/
.But xrdb pipes its input through
cpp
, which parses/*
comments but not!
ones. So the entire region is removed before xrdb sees it.(CC @Screwtape)
I don’t know myself, but it does.
This is very cool; I have never seen the “open a URL without the mouse” implemented in any terminals other than urxvt, which is why I never considered switching away. Unfortunately XTerm still does much worse than urxvt with font fallbacks for non-latin character sets, (at least out of the box) so I don’t think I’ll be switching, but it’s good to have options.
Kitty and foot (surely others) expose similar mechanisms to process the terminal content with external programs.
The terminology terminal from Enlightenment may not be the best in many ways, but it’s super useful for irc and such, because it can overlay images on itself, so not everything has to be opened in the browser. Wish that was a thing in more terminal emulators.
And tabs, which terminology sucks at. Thus xfce4-terminal is nice for all else.
Another thing for the xterm wishlist…
Kitty (which I’ve only learned about recently) has its own inline-image system which the author invented himself; on the one hand it’s really easy as an app programmer to emit an image for inlining (encode to png, base64 encode, wrap in an escape sequence). On the other absolutely nothing else supports it.
I don’t know what Enlightenment do but SGI devised “sixel” which a few emulators support.
iTerm2 has a nearly identical protocol for displaying images inline. ❤️
Enlightenment’s the wm, terminology’s the terminal.
Checked kitty’s frontpage and the feature I’m talking about isn’t there. Simply terminology sees a url ending in jpg or some other supported format, you click it, the image is overlaid. Click to close and type the lolz to irc.
Maybe that image-inline and sixel stuff can be useful too.
I’d like a terminal emulator that doesn’t scroll on output at all, like in Plan 9, where you can type
cat x
and you stay at the top instead of being scrolled to the bottom of the output immediately. Basically removes (much of) the need for a pager.I think the article is missing one important line:
Great post!
Xterm contains multitudes ;)
Did you know there’s a Tektronix compatible graphics terminal in there?
There is also suckless terminal –
st
– which proclaims to be less bloated and more maintainable than xterm.It is good enough for me … not needing any special configuration, aside from setting the font:
You won’t get non-essential features, like scrollback (I use
tmux
for that).It’s my understanding that XTerm has no mechanism for having fallback fonts.
I like xterm quite a bit and used it for several years. I did eventually write my own semi-clone of it though since I wanted a little more control over things for nesting and remote access… but most my “extensions” are actually features xterm itself defined!
Take a look down this list: https://www.xfree86.org/current/ctlseqs.html so many cool things, even like image support (via sixel) and clipboard integration is all there for applications. Most builds of xterm I actually have encountered though compile these out.