Haskell wlroots bindings

Heya! I just opened a PR that makes it easier for us to not stand on each other toes. Essentially this moves all “personal” configuration to Main.hs, and generic code to other files.

I like the idea of incrementally teasing apart tinywl, until we’ve got something useful as a daily-driver working. And from there doing things more “correctly”.

2 Likes

Hey, thanks for the PR. I left a comment with my thoughts let me know what you think. I think your PR is in line with stuff like the xmonad approach. My personal preference is to have config files be as stand alone as possible but I can see the appeal of doing it in Main. I will defer to your opinion on this.

I’ve been doing a lot of work recently, over the holidays trying to get it to a daily driver. This work has been nearly exclusively in C so I haven’t been posting much about it here. I think most people here are not interested and if I’m honest one of the challenges of working on it myself is the C code is uninteresting and will be replace eventually with Haskell.

But still in saying that it has been challenging enough to add the functionality in C with all the available examples and documentation online, trying to do this in Haskell would have slowed me to a crawl. Im happy with the recent progress. So far I have added support for:

  • Wayland clients like
    • bemenu (this is a wayland equivalent to dmenu)
    • yambar (more advanced bars like swaybar still unsupported)
    • swaybg (for background images)
    • mako (for notifications)
  • Keybinding support (configurable via Haskell)
  • Startup apps (configurable in Haskell)
  • Support for wayland client config (For example adding this removed the bar above the kitty terminal emulator)

Currently I’m trying to add support for borders which will be the last piece in a large PR I worked on over the weekend.

The name of the game is protocol support, for example with the yambar I had to add support for layers and support for the client to request a reserved area based on the client settings (this needs to be done in a wayland protocol comparable way so the support is generic and universal).

With this latest PR I will be start using this as my daily driver but it is still missing crucial support for the following.

  • Copy and Paste
  • Tiling
  • Multi monitor
  • Locking

So if it is only at a stage that the creator is starting to use it I think it still unusable for most people, I also think there will be a lot of change to the code base in the coming months.

There are also probably a number of Wayland clients not supported, so far with each that I have added I have had to do a lot of work in C to get them working and add a lot of support.

I have been using this wlr-clients repo to test support wlroots / wlr-clients · GitLab

I think the wayland client stuff is very interesting and there is definitely a need for a Haskell project focused just on creating wayland clients. The nature of the wayland protocol and its communicate mean there are some really cool opportunities possible.

For example, waypipe allows running applications on remote machines but instead of sending the raw graphical information the way I think VNC and RDP work, waypipe sends just the wayland client messages. So to the app running on the client it believes its communicating with a local compositor. Ive been experimenting with this to get a tmux like experience with the servers I run.

There is also the possibility of using wayland clients within clients, so you could perhaps use an image image viewer within your wayland client app, I think this is really promising because it could allow apps that just aggregate other apps into something new.

For me now I think the immediate future will be focused on the C side, adding support for the missing features I listed above. It makes sense to get to a minimum set of must-have features and to start using this daily myself and iron out the bugs.

I foresee a point in the coming months when the above is supported, at that point I want to start moving to a full haskell implementation. Im not sure what form that will take it may be just iteration as I move to a strict and well defined FFI interface that uses a C shared library, or it might require something else.

With regard the topic of this thread, I think the original idea was to create bindings to wlroots, then create a compositor and then the clients. I think because of the complexity It makes more sense to work on all three in parallel and focus on providing a minimum level of support for the most in demand features, instead of trying to provide blanket support from the start.

The learning from working on Wayland clients feeds into working on the compositor and vice-versa and both feed into understanding what bindings are needed.

So for house keeping I think this thread should be kept for the bindings and a discussion on the compositor done here instead Tiny-wlhs, a hybrid haskell and C Wayland compositor - #2 by l-Shane-l

6 Likes

I would like to note that waypipe is just restoring something in a more secure way that X11 always had (network transparency), and client aggregation likewise has always been possible since window IDs are a global namespace without ownership information (see for example $WINDOWID in xterm, and how some TUI web browsers use it to show images; nothing stops you from creating a whole application likewise embedded in the xterm!). Of course, the flip side of this is the almost complete lack of security implied by these abilities.

3 Likes

As far as I can see, scanner was worked out in original haskell-wayland, haskell binding to wayland, as below.

Since the XML format would have been relatively unchanging, I bet one can adapt the code to new wayland binding with ease. I recall myself trying out writing a scanner with moderate success, simply that having to use global variable irked me enough to stop. At least, it would not take much effort.

2 Likes

This is really interesting and would be a really good win. Is it something you are interested in trying? If you could even get something basic going I could quickly integrate and test it with tinywl. Honestly that would be very exciting.

I haven’t chimed into this thread yet, but for some background:

History

There at least three implementations of a wayland scanner to generate haskell bindings, of which 2 are relevant if you’re looking for a starting point.

Examples of scanners for libwayland bindings:

  • haskell-wayland (hayland) – c2hs + template haskell
  • waymonad-scanner – hsc2hs + template haskell

While the wayland protocol format (XML) hasn’t changed much, I think xdg-shell became stable since these were written. That will only matter if you’re trying to build / test the existing wlroots bindings hsroots.

General Idea

libwayland, the IPC library almost everyone uses, has its own ABI. For non-C code, we’re expected to target that rather than the “glue code” static functions generated by wayland-scanner in the .*protocol.h files. That is, we should be generating haskell functions to replicate what those static functions do.

5 Likes

So haskell-wayland only had a few minor compilation issues since TH declarations changed. There’s like 6k lines of generated code, so I’d encourage you to look through a -ddump-splices of haskell-wayland to see what all it generates.

Here’s an example wayland client swapping to these bindings from some very rough ones I made manually. The haskell-wayland bindings very much hide the raw C syntax / fields in implementation details of the shim helpers. Whether that’s desirable or not is preference for your project.

I’ll try and poke waymonad-scanner later to see if it still works and can generate working bindings for xdg-shell-protocol.

1 Like

waymonad-scanner looks like it’s still able to make server bindings, but it never got around to implementing client bindings. I threw xdg-shell.xml at it just to see and it generated interfaces, resource dispatchers, and client messaging glue code (i.e. wl_resource_post_array calls). I’m not super familiar with what’s needed on the server side, so hard to say if it’s complete.

It does look like @Abab9579 tried reviving waymonad-scanner a few months ago. Did anything useful come from that?

Given that haskell-wayland looks like it works enough for wayland.xml, I’m not super convinced it’s worth implementing a better scanner implementation at the moment. You should only really need it for additional protocols you need models for, e.g. some custom protocol in wlroots you want to use. Most of the real wlroots functions would still need manual bindings.

waymonad-scanner notes:

  • It depends on haskell-wayland, which I don’t think it needs to?
  • It also depends on hsroots which it definitely doesn’t need to.
  • object marshaling is kind of weird. It expects you to pass in the marshaling functions for object args, otherwise it just defaults to WlResource (opaque type)
  • Generated code does utilize StablePtr, which necessitates back and forth coercion to Ptr if you try to actually do anything with the functions
2 Likes