Assumed Audience: Programmers interested in GUIs.
Epistemic Status: Fairly confident, but these ideas are not implemented.
So just over three months ago, I wrote about a new architecture for a GUI framework. Since then, I’ve had a smart man challenge me on several points, and the result, while still broadly the same, has a few more details I’d like to share.
This friend doesn’t like frameworks, so he took immediate issue with my proposal since it was for a framework.
Now, I don’t like frameworks either, but my thinking wasn’t fully fleshed out. I knew a framework was necessary; nevertheless, I had a vague feeling that this type of framework would be okay.
So we talked like professionals having a disagreement, and it bore fruit because he told me the personal experience behind his opinion.
The experience, broadly, was that he had to use a framework that would only accept events from particular sources, and he had sources that were not one of those particular ones. In addition, the framework did not make it easy to dynamically add or remove event sources.
This is the framework curse: it controls everything, but it is inflexible.
And in that situation, what was he supposed to do?
The only answer was to run his event sources with separate threads and convert those events into events accepted by the framework. And while it worked, it was not pretty.
The reason it took me so long to understand him is that I already had a dynamic event loop in my code. With his help, I made it better, but I already had one at the outset.
My event loop uses callbacks, and those callbacks can add or remove event sources dynamically. In addition, it essentially accepts any event source that you can turn into a file descriptor.
It’s marvelous, if I do say so myself.
Anyway, when I finally realized his problem with frameworks, I adjusted my event loop to match his wants.
Once I did, I quickly realized I had an excellent event loop for a framework: one that still allowed a framework, but that allowed the client enough flexibility to add its own stuff.
One example I gave him was that you could add a regular network socket, and every time your app receives data on it, that counts as an event that could trigger a redraw to update a progress bar or something.
Another example: you could add D-Bus connections to the event loop.
Another: you could use a self-pipe to send an event when the previous frame appeared on screen. Or maybe even the frame that updated a particular animation.
On Windows, you could even add a handle to a child process, and the event loop would tell you when the child exited.
Perhaps the framework doesn’t support Wacom tablets by default; no matter, add your own callbacks for their file descriptors.
Those are only examples; the possibilities are endless.
But why does this break the framework curse?
Well, essentially, it only keeps control over what all GUI software needs and farms the rest out to clients.
What is common?
- An event loop.
- Rendering frames.
What is not common?
- Event sources.
- How events are processed.
- When rendering happens.
And these remain under control of the client.
So while my framework design is still a framework and not a library, maybe it would still be flexible enough.
But as I mentioned, I don’t really have motivation to work on these ideas. I guess the world is (mostly) stuck with the false dichotomy of libraries vs. frameworks.