9 ms·
RubyWM – an X11 window manager in pure Ruby
- vidarh 3y agoHah. I didn't think this was quite HN worthy at this point - the code is still a mess, and has plenty of bugs. 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 https://github.com/mackstann/tinywm/blob/master/tinywm.c [2] https://gist.github.com/vidarh/1cdbfcdf3cfd8d25a247243963e55a66 https://gist.github.com/vidarh/1cdbfcdf3cfd8d25a247243963e55...
- yxhuvud 3y agoI raise with a wayland client in crystal: https://github.com/yxhuvud/wayland_client https://github.com/yxhuvud/wayland_client Very basic though, you'd have to provide your own functionality to print any text..
- vidarh 3y agoI see C in there; that's cheating ;) (my WM uses a pure-Ruby X11 client library - there are no external C dependencies other than those of the Ruby implementation itself). 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...
- yxhuvud 3y agoYeah, I link against C libs because reimplementing the protocol seemed like a pain in the ass. The prevailing strategy seems to be to generate code based on XML protocol specs, and I'd prefer to avoid that crap. That would probably be less painful in Ruby as then the code could just be generated at runtime based on the XML. 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.
- vidarh 3y agoOh, I absolutely don't judge you for those. Frankly part of the reason I went for a pure Ruby version instead of xlib was that the Xlib bindings for Ruby are also in an awful state, and someone else had done enough of the job on the pure Ruby bindings that it felt like it was doable incrementally as I needed various calls and not much worse than wrapping Xlib or xcb. 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).
- wiz21c 3y agoweb site looks like a blank page... :-/
- bArray 3y agoSame, the wayback machine produces this: https://web.archive.org/web/20240122090024/https://rubyflow.com/p/pb1tu2-rubywm-an-x11-window-manager-in-pure-ruby https://web.archive.org/web/20240122090024/https://rubyflow.... Which points to this GitHub: https://github.com/vidarh/rubywm/tree/master https://github.com/vidarh/rubywm/tree/master I was hoping for some screenshots and I can't seem to find any easily. Would appreciate some screenshots/recording of it working to get a taste of it!
- vidarh 3y agoThere is zero window decoration other than a 1pixel unshaped border, so there's not actually much to show, but here's an example of one of my tiling desktops w/a couple of my terminal windows running (one of the windows is st rather than my own): https://m.galaxybound.com/@vidar/111739055121708028 https://m.galaxybound.com/@vidar/111739055121708028 Here is one I did that shows a couple of file manager windows and my terminal and desktop switcher on my floating desktop: https://m.galaxybound.com/@vidar/111799111872848650 https://m.galaxybound.com/@vidar/111799111872848650
- bArray 3y ago> There is zero window decoration other than a 1pixel unshaped border, so there's not actually much to show, but here's an example of one of my tiling desktops w/a couple of my terminal windows running (one of the windows is st rather than my own): Minimalism usually means fewer problems and bugs, it's not a bad thing. > Here is one I did that shows a couple of file manager windows and my terminal and desktop switcher on my floating desktop: Looks quite nice! I would suggest to add a few pictures to the GitHub.
- vidarh 3y agoWell, at this point you get few features but still lots of bugs ;) But yes, the minimalism is very much intentional - I have no interest in letting it grow all that much, and no interest in lots of decoration (I might add support for some; especially inspired by how Katriawm does it [1] - it basically just slaps images on each side in separate windows - it's high "bang for the bucks" in terms of flexibility for very little effort) > Looks quite nice! I would suggest to add a few pictures to the GitHub. So many keeps asking, so I guess I've have to add some... [1] https://www.uninformativ.de/git/katriawm/file/README.html https://www.uninformativ.de/git/katriawm/file/README.html
- tuyiown 3y agoThis title would perfectly fit in hn 2011 archives (after thought edit: I didn't meant this as a snarky dismissal, just a funny observation)
- vidarh 3y agoI'll provide plenty more ca. 2011 level Ruby enthusiasm over the coming months - I have my editor, terminal, file manager and more to get pushed to or updated at Github.. :)
- aidog 3y agoGreat to hear! I wonder if your ruby compiler project would benefit from the now official pure ruby parser? [1] [1] https://github.com/yui-knk/lrama https://github.com/yui-knk/lrama
- vidarh 3y agoMy Ruby compiler project has unfortunately been languishing for years due to lack of time. I keep hoping to do some more on it as I got it to the point where it was self-compiling, but it's not very high on my list at the moment (my list is long) That said, lrama is "just" the parser generator, is it not? As far as I understand, the Prism parser built using Lrama still produces a C library, and requires Ruby's parse.y as input, and parse.y alone is twice the size of my entire compiler... Both Lrama and Prism are great projects, and I might've be tempted if that was a "missing piece" to turn the compiler into something production-ready, but frankly updating the parser to handle more modern syntax is the easiest bit of what remains. The really big pieces are supporting Regex's and floats (Ruby's regexp implementation is roughly the size of my entire current compiler...), and a bunch of bug fixing. Whether I'll ever find time to get it there or not, we'll see.
- aidog 3y agoInteresting. I see! MRuby (Compilable Ruby for embedded systems etc) and Webasm Ruby might be fun areas for further projects :)
- szundi 3y agoI love these peculiar projects
- BaculumMeumEst 3y agoI've been an X11 holdout since forever, but after nvidia proprietary drivers broke for the millionth time on a system upgrade, I switched over to Nouveau and the "Hyprland" tiling compositor on Wayland. It's the only setup that felt worth the upgrade to me. Setup was easy, animations are very slick (scroll down on the link below for a sample), and I've had no bugs or quirks. Highly recommend checking it out if you're bored or curious. https://hyprland.org/ https://hyprland.org/
- vidarh 3y agoIt looks great, but to me this is pretty much the opposite of what I want to use - the demo video at least is so busy, and full of transitions and other distractions. There was a time I'd absolutely have loved something like that (and had all the window effects turned on when the first compositors started arriving) and it looks very cool, but other than translucency I've progressively stripped back everything. I'll never try to compete with something like that on either effects or features. I might add some very minor eye candy. But that's fine - one of the things I've always loved about the Linux/Unix desktop is how you can get everything from the most minimalist to the effects-laden, and I've used wm's pretty much everywhere on that spectrum myself too over the years. I sympathise re: drivers - that or the browsers finally abandoning X would be the only things that'd give me enough reason to switch. But I'd be more likely to switch if I get around to scratching the itch of yet another homegrown minimalist step down the stack... (I have a weird urge to write a Frankencompositor that supports Wayland clients and enough to support an out-of-band X11 style window manager and the brutally insecure X11 style event snooping and injection; partly because it'd really irritate some Wayland purists - I'm resisting that urge for now because it'd be a massive time-suck)
- maksut 3y agoI am eyeing river wm. Because it has pluggable layout manager and controller via custom wayland protocols. Which means I can implement just those parts in my favourite lang to scratch the itch. Kudos to you going for the whole wm :)
- 3y ago
- HeckFeck 3y agoYou show me your Ruby and I reply with my Perl: https://sourceforge.net/projects/perlwm/ https://sourceforge.net/projects/perlwm/ Last updated in 2004, just needs a touch of polish and she will be as good as new.
- j4yav 3y agoBehold it in all its glory: https://perlwm.sourceforge.net/shots.html https://perlwm.sourceforge.net/shots.html
- rollcat 3y agoUsing Emacs to write Perl to configure your WM... Why not cut out the middle man, and https://github.com/ch11ng/exwm https://github.com/ch11ng/exwm
- JonChesterfield 3y agoI hope it's deliberate that the screenshots link goes to creating a new page https://github.com/ch11ng/exwm/wiki/Screenshots https://github.com/ch11ng/exwm/wiki/Screenshots I suspect full screen Emacs in gnome, while not brilliantly efficient, is close enough to this project that I may as well stick with the mostly inert gnome layer
- superkuh 3y agoAnd because it's Perl I bet it runs pefectly on Perl interpreters shipped on OSes today.
- csdvrx 3y ago> And because it's Perl I bet it runs pefectly on Perl interpreters shipped on OSes today. That's a superpower (software that will not bitrot): last month for a new project, I hesitated between C and perl but chose perl.
- 3y ago
- dingdingdang 3y agoI for one will not be running this sort of low performance setup when PhpWM would obviously be an order of magnitude faster. *it really would though
- HeckFeck 3y ago> *it really would though I imagine the vast optimisations that came in PHP7, likely at Meta and Wordpress's behest, would be to thank for that.
- wharvle 3y agoEh, it’s been fast in the real world for quite a while. I think it’s due to two main things: 1) Startup time had to be fast because of how it worked in its most common use case (yes, yes, FPM, but still) which tends to encourage or require making everything fast. 2) Writing C modules for PHP is relatively easy and it has a culture of anything halfway important being in C, going back to the early days of the language. The answer for how to be really fast with real-world workloads in almost every scripting language is basically “get out of it and into C ASAP” but PHP’s culture embraces that more than most.
- exikyut 3y agoRock: PHP X11 PoC that I poked at a couple years ago (which doesn't use libx11/libxcb, but talks directly to /tmp/.X11-unix/X0) Hard place: crowd of Wayland pitchforks thundering in the distance Effort analysis: <negative beeping> Itch: scratch? Me: annoyed twitching
- vidarh 3y agoAs you can see if you dig into my code and then look at the X protocol implementation [1], the (incomplete) pure Ruby X11 binding takes up more lines of code than the WM. I was tempted to write the code to generate it from the XML spec, but a lot of the scaffolding for the current X11 binding predated my own work and it seemed like it'd be more and more painful work to write the generator than bite the bullet and do it manually (I don't expect to/care about supporting the whole protocol anyway). So a PHP version would be totally viable, just tedious. [1] https://github.com/vidarh/ruby-x11 https://github.com/vidarh/ruby-x11
- petercooper 3y agoI run RubyFlow and it's just a community link posting site for Rubyists, so feel free to update this to the URL of the actual project if you wish: https://github.com/vidarh/rubywm/tree/master https://github.com/vidarh/rubywm/tree/master .. RubyFlow runs on a teeny tiny Heroku instance so may not be too great at handling your traffic. It's about fifteen years old though and a single Ruby file, so I should probably rewrite it! ;-)
- mberning 3y agoIt sounds perfect :)
- yebyen 3y agoIs this really the same 16 year old RubyFlow that authenticates against GitHub? I found a copy looking for the source but it looks like it is literally 16 years old, and I'm thinking there's just no way the OIDC flow has been standing intact for that amount of time without any update... really? :D
- petercooper 3y agoThe version you'll have seen is the original version that I "leaked" to someone else who wanted to run a similar site. I said they could make the code public, but I didn't want to maintain or stand by it. It underwent an entire rewrite about ten years ago which is the version that's live now and the auth flow has remained the same within that timeframe, at least, but https://github.com/omniauth/omniauth-github https://github.com/omniauth/omniauth-github does the heavy lifting and has been updated as a dependency in that time.
- yebyen 3y agoAwesome, I was fishing for open source links, I salute you thanks for sharing :)
- bradley_taunt 3y agoAlways happy to see new options in the WM space! My only gripe (and this goes for almost any open source project) is this: please include screenshots! Any program/service that has front-facing UI should have visual references, instead of making users build/run everything just to “see” it.
- vidarh 3y agoI'll see about adding, some, but see links elsewhere in this thread to a couple, and note that you can't really see much of this wm, as in the style of e.g. bspwm it has no window decorations whatsoever beyond a 1 pixel rectangle.
- joshspankit 3y agoMaybe a simple animation of one or two main actions?
- hulitu 3y ago> it has no window decorations whatsoever beyond a 1 pixel rectangle Then we don't need any screenshot. We can do this with TWM, FVWM and MWM (and others).
- entropie 3y ago> it has no window decorations whatsoever beyond a 1 pixel rectangle My favourite! As a rubyist using xmonad for years now (no real clue about haskell) I am thrilled.
- vidarh 3y agoThat's great. I still suggest caution even you try to test it, but having that a background with wms like that makes you less likely than most to hose your setup...
- jzb 3y agoAt this point HN should prompt people when submitting links. "Are there screenshots at the link? No? Go back and add them, then submit."
- gwhl 3y agoThere is/was Subtle which I used to use a long time ago: http://subforge.org/projects/subtle/ http://subforge.org/projects/subtle/
- vidarh 3y agoI think I've looked at Subtle, and it's interesting and worth a look, though it has design tradeoffs that doesn't fit me (and I wanted something entirely in Ruby rather than "just" scriptable in Ruby) But that's cool - my thought on this is that I'd rather have many tightly focused options than huge sprawling ones...
- danjoredd 3y agoDef needs screenshots. Need to know what it looks like to decide if I want to try it out or not!
- vidarh 3y agoThat's fair - but frankly if you are concerned about what it looks like, you almost certainly won't like it (and that's fine).
- hartator 3y agoGitHub search doesn't work on this repo: https://github.com/search?q=repo%3Avidarh%2Frubywm%20x11&type=code https://github.com/search?q=repo%3Avidarh%2Frubywm%20x11&typ... Sad that Microsoft is slowly degrading GitHub experience.
- YorickPeterse 3y agoOr maybe it's just a case of a job queue used for indexing new repositories being full. Not every instance of "X doesn't work" is the result of malicious intent.
- hartator 3y agoUsed to work instantaneously.
- dewey 3y agoJust like things are not instantly in the search index on Google and other websites doesn't mean someone is being evil by degrading the user experience.
- hartator 3y agoIt used to work with new repo without an indexing delay. It's not evil, but it just means they don't care.
- larusso 3y agoThanks for this. Just skimmed over the code and seems to be a very readable project.
- vidarh 3y agoThanks. I'm not happy about the WindowManager class in particular, but it's slowly getting there.
- tombert 3y agoI don’t run Linux anymore, and I am waiting for Apple to officially drop Intel support before swapping my laptop over, but one of my many software “bucket list” projects is to use a high level language to build a window manager. I was thinking about starting by porting DWM to some form of Lisp. I love seeing these kinds of projects because it further validates that such an idea is feasible.
- deleted 3y ago[deleted]
- eek2121 3y agoTHAT is awesome. Good job my dude.