After all, a Wayland WM is not just a WM, it also has to run and handle display server including talking with HW if you want any sensible performance.
Writing a Wayland compositor from scratch means writing the whole display server. Wlroots readme describes it as "about 60,000 lines of code you were going to write anyway".
For comparison my wm is <1k lines.
So they're not equivalent - writing a Wayland compositor from scratch is more like writing the whole X server first, before even starting the WM.
I could use wlroots or another compositor as a starting point. I did look at it, but I'm still on X, and have no compelling reason to switch. Yet, anyway, and that adds to the "cost" for me in terms of disruption.
Where I could translate TinyWM into a few dozen lines of Ruby in a couple of hours and switch to actually using it and build from there, and "just" suffer some nuisance that I can slowly chip away at when I have time, even getting a basic wlroots binding + minimal compositor running seemed like a far more complex project.
I'm itching to figure out how to eat my way further down the stack, but I can't justify spending time on it unless I see a viable way of doing it (relatively) piecemeal.
E.g. I can restart my wm without exiting my X session, and so without losing any open applications. That gets far more disruptive for replacing the X server (whether by another X server or a Wayland compositor), and also allows for a far faster cycle - I can spot a problem, fix it, restart the WM and keep working without having to close everything...
I think if I was to do a Waylabd compositor, a first step would be to put things like window management beyond an IPC boundary, just like with X.
Isn't that already the case, by protocol definition? At least compositor and clients talk to each other over a pipe of some sort. It is actually a bit problematic because the way it is done put noticeable restrictions on both sides on processing things in time, because if it is full then shit hit the fan.
With Wayland the compositor serves the same function as both the X server, wm, and compositor in one. There's nothing inherent stopping the addition of extensions to allow the same split as in X (but the server/compositor split probably wouldn't be worth keeping - the WM is easier to split out because it's far less latency sensitive)
> I can restart my wm without exiting my X session
Sway also has a "reload" feature that preserves all open applications.
TinyWM for X is 50 lines.
> Sway also has a "reload" feature that preserves all open applications.
As far as I understand, sway's reload just reloads the configuration. If Sway crashes, or you kill Sway's process, there's nothing left holding the sockets to the clients open, or managing the display - that's equivalent to killing the X server, not the wm.
With an X wm, as long as your x session isn't set up to quit when the wm quits, you can brutally shut down the wm, or it can crash, and the windows stay open, and you can restart your wm - or start another wm entirely - without losing any windows.
Of course, that's a new feature they're working on, only helps QT apps, and requires the toolkit to track state (and by the same virtue, looks like it would have worked fine with X11 if they wanted to). So this is more of an interesting related tidbit rather than a disagreement.
Whether X or Wayland it would certainly make experimenting less painful. Browsers doesn't matter that much given they're reasonably decent at restoring.
(Another option there is xpra - "screen for X")
Fewer and fewer reasons not to start writing an X server ;)
The cheap version of this is just using tmux/screen, but yeah honestly I suspect a lot of programs are easy to make recreate their GUI state if you care to bother, it's just that not everyone does (or should; it's a trade off and display servers aren't usually that crashy).
Afaik river does something in that direction https://github.com/riverwm/river
> Dynamic layouts generated by external, user-written executables. A default rivertile layout generator is provided.
> Scriptable configuration and control through a custom Wayland protocol and separate riverctl binary implementing it.
E.g. one of the things I disliked about bspwm was that while I could get a feed of events and act on them, I couldn't intercept and modify or reject requests, so e.g. when a new window opened, bspwm would place it, and issue an event, and before my script could reconfigure the window it'd already be visible, so to get a floating desktop the way I wanted I ended up with windows flashing up in one location and then moving.
Put another way: The plethora of Wayland compositors is a strong demonstration of how these compositors don't give sufficient control via their external APIs, or people would write window managers for one or more of those compositors instead of writing more compositors.
Very basic though, you'd have to provide your own functionality to print any text..
Though I sympathise - the sheer amount of effort to work with these, be it X11 or Wayland, is really annoying; the pure Ruby X11 gem I use is more lines of code than the window manager itself...
Also since all the prepackaged wayland libs are heavy users of functions declared as `static inline` I have to create shims for those as they are not linkable. That part is a pain in the ass but pretty simple to resolve :)
And yeah, there is so much to set up just to get a bare minimum going. I guess that would be true in X11 too.
I like that there are no other dependencies, but I'd have sacrificed that if it was sufficiently much easier than the route I ended up taking (e.g. my terminal did start out linking to Xlib and using a tiny C extension; it's since been ripped out in favour of the pure Ruby bindings, since why not now that it's available, but it was a perfectly ok solution to start with).
It is however the wm I actually use since I got frustrated with bspwm and did a very minimalist rewrite of TinyWM [1] in Ruby [2] and expanded it from there. It was painful the first few days until I'd had time to add multiple desktops and the start of a tiling mode. But at this point, it's "almost" pleasant for me.
The warnings are real, though, apart from the initial hyperbole - this is likely to break for you in all kinds of horrible ways still.
[EDIT2: As for a real example of the ways it can/will break: Right now, for some reason, after a restart without changing a single line, it's failing to grab super+buttons to move/resize windows; it doesn't really matter as I have keybindings for it and mostly use those, but, yeah, I'm doing something wrong somewhere and last time this happened the problem just went away by itself]
I use very few applications beyond (my own) terminal, (my own) polybar replacement, (my own) file manager, and a browser, and so once Chrome and my own apps mostly started working ok I've had very little incentive to make sure it behaves nicely with anything else and I know the distinction between different EWMH window types is incomplete and broken - just not in ways that usually affect my own use.
EDIT: Also a couple of quick notes on "design choices" to the extent this has been "designed" rather than accreted: As you can see in e.g. desktop.rb, quite a few places I've chosen to query and filter the top-level WindowManager class for a list of windows matching a given set of criteria. I did that on an experimental basis out of the idea that it was a waste of time to track precise state across multiple objects given that the total set of windows will always remain "small".
So the Window objects know the bare minimum state of the underlying X11 window that it needs to track, and the WindowManager class knows how to map an X11 window id to a Window object.
Other than that I avoid tracking state as much as possible, and even where I track state I try to avoid the need for full precision.
The one other place I must track state is the layout classes. Currently, only the basic tiling layout, which keeps a tree (that is currently a binary tree, but the array of nodes is there because I at one point thought I might allow more nodes) where the leaves keep track of which nodes have a defined place in the layout.
But even there, on updating the layout, I then crudely diff the currently known set of windows vs. the set of windows the layout believes are present and remove/add as needed.
I make a best effort to place new windows on map requests, but if anything breaks for any reason, the layout will "catch" up automatically and new windows will be placed. Given I use this daily while it is in flux and often broken because I've made a change and is testing it "live" on my desktop, this has turned out to be very helpful on occasion.
I can't make up my mind if this method (of constantly querying for attributes of every window) is a crude hack or quite elegant, but it works.
Many other things are not "designed". This is mostly very far from a good example of how to actually do things. E.g. "find_closest" used to pick a window to move to when you want to move directionally in a tiling layout is pretty much guaranteed to be possible to do much better with fewer lines of code once I actually get around to sitting down and thinking about it - the current version was cobbled together in a hurry because I was tired of not having the functionality and it "mostly works" as expected even though it's stupid.
[1] https://github.com/mackstann/tinywm/blob/master/tinywm.c
[2] https://gist.github.com/vidarh/1cdbfcdf3cfd8d25a247243963e55...