Hacker News new | more | comments | ask | show | jobs | submit login
TinyWM – A tiny window manager in around 50 lines of C (incise.org)
335 points by LaSombra 6 months ago | hide | past | web | favorite | 104 comments

I think that the real advantage of something like this is that it provides a minimal template to follow if one wants to start writing a window manager in one's language of choice (assuming that language already has some X bindings). One can start from there, & then add ICCCM, tiles, whatever else one wants.

edit 1: accidentally a word

edit 2: I'm at a loss at why this isn't considered a contribution to the conversation. Can anyone enlighten me?

I don't have a problem with your comment. FYI just wanted to let you know that the point you made is proven by the go port discussed here: https://news.ycombinator.com/item?id=17766249

I ported this to go for fun 3 years ago: https://github.com/collinglass/tinywm

Nice! Ironically the Go version is much longer, mostly due to the interop overhead (and partially due to the code style).

Spent some time trying to get this to run in a Xephyr window on an old ubuntu box, but it doesn't seem to be able to move windows or resize as advertised (whereas twm is fine, and xev sees all the keypresses).

These tiny projects are often cursed by having very few resources when something goes wrong.

Finally, a window manager for people who find dwm bloated!

Odd that you should say that...

I'm after a 'window manager' that can help me load a single X application on top of an X session that can sense the size of the screen and render the window maximised.

If you try something like

     startx /opt/openoffice4/program/soffice
from a linux console without a desktop manager set, you get an openoffice (whatever app) window that is a bit smaller than the screen and offset. Googling around suggests that you have to rely on each application to set its window size.

     startx /usr/bin/chromium --kiosk
will get you something close to what I'm after for all applications.

You can do this with i3 (or any tiling WM, I believe), since they automatically maximize any window if it's the only one on the workspace. Disable the panel/i3bar, and you would have what you seek. Start it with 'exec i3' in .xinitrc and running 'xinit' on login.

I have a work VM with a stripped out i3 that can't create new terminals other than a startup terminal with tmux (which calls shutdown now on EOF); and it can still do basic interaction with other new windows. This reduces problems with VirtualBox X integration and makes the VM simple and like a terminal with some X capabilities. I3 is really flexible for this kind of use case.

I'm not exactly sure what you're looking for, but you can use 'xdotool windowresize 0xabcd 1920 1080' to resize an arbitrary window, 'xdotool windowmove 0xabcd 0 0' to move a window, and you can use 'xwininfo -root -tree' to get a list of all windows and the window ID which you would pass to xdotool.

If you want to write it yourself in C using Xlib, you can use the 'XMoveResizeWindow' function. You could use 'XGetWindowAttributes' to get the size of the root window.

I'm just not sure if you need a window manager to handle the dialog windows. If you do, I would just use Blackbox.

The problem here is that there is no obvious process <-> window relation. Some windows have a PID property in their X11 Atoms list, but that's optional. After all, X11 clients can run remotely. And then there's the problem of clients started only by childs of the process that you want to run here.

As the other commenters have pointed out, the simplest and most robust thing might be to just resize all new windows to max and map them. Now you just have to make sure that only one window will be opened...

Isn't that what Matchbox does?

Was going to say the same. Yup, it maximizes everything by default, it was designed for small screens so it does have a titlebar but it's very small.

awesome, with a minimal configuration, will do what you want. Just create a single desktop that is tiled with a single application launched on startup

Thanks for both the recommendations but I was sort of hoping for half a dozen lines of C I could compile and run as a really thin layer. Research continues...

I used to use GOOMWWM [1], which is quite tiny and the code relatively easy to follow. Maybe you can remove the bits you don't need? Or use it for ideas to expand TinyWM to do what you need.

[1] https://github.com/seanpringle/goomwwm

Thanks for this, will have to roll my sleeves up and start hacking I think.

Is there something about a very simple window manager running one maximized window that isn't optimal?

No not really, just playing about (and learning about window display). I use KDE for 'real work'

Doesn't a geometry specification do the job? That way you don't need a window manager at all.

For anyone pondering minimal/unbloated window managers, checkout cwm [0][1]. I've been using it exclusively for quite some time now. It's quick to compile, has sane configuration and is the most ergonomic floating wm I've used. I don't see myself ever needing anything else, provided I don't see myself using a tiled wm.

[0] https://github.com/chneukirchen/cwm [1] https://man.openbsd.org/cwm.1

Thanks for sharing. I'm a GNOME user but I want to try something lighter so I'm learning everything about "windows managers". I have never heard of "cwm" before, the only "cwm" that I was aware of is the "closed world machine" [1] so I was very confused at first :) Going to try it now, I wonder how it compares with awesomewm.

[1] https://dokk.org/manpages/cwm.1

I use it too. It gets out of my way better than other window managers/desktops I've used. It's amazing how much good stuff comes out of OpenBSD despite the limited manpower.

I wrote something like this once, and had maybe 3-4 applications that I wanted to use with it. mplayer was one of them, and it broke with my straightforward and absolutely reasonable window manager. It did display only a quarter of the movies since it thought the video window was fullscreen but it was only a quarter of the screen. The reason was a bug in mplayer's source code. It did not expect to be resized once and only once and being mapped only afterwards.

Another story, I've been an icewm user for many years and I absolutely loved it. But at some point the bitrot was too much. Windows that didn't gain focus because of newer unimplemented client<->WM protocols, clients that crashed for hard to debug reasons, and so on. There are still some patches being developed for icewm that try to make it work with some newer clients. And there are workarounds on top of workarounds for fighting with Java clients, but at some point I decided it was too buggy and switched.

Writing a window manager could be such a nice project if wouldn't mean implementing terrible but necessary protocols, and fighting with all the bad X11 clients out there.

This reminds me of the mid-to-late 90s where everyone made their own window manager. You had the choice of 100s of them. But usually they lost interest after a version or two, and didn't implement much of the icccm.

There still are quite a few that are actively maintained and implement icccm.

That's something that bothers me about wayland. There really is a lot of variance when it comes to people's preferences about window decorations and focus behavior and so on. Having the applications handle it themselves is going to result in a lot of lost functionality/configurabilty.

It's already dying on X.

The new Gnome apps for instance don't respect standard interaction even when the window manager is Gnome. (For instance, if a window has a modal dialog box open, you can't move the window; I think I've also had issues with pushing windows back despite this being a configuration option.)

If you use Chromium too, it doesn't respect your settings for where the minimise/maximise/close etc buttons go until you right click somewhere and say "let me forget that your developers think they're so special they have to remind me i'm using your app every time i want to immerse myself".

Gnome people will probably say "it's a trivial bug which we will fix shortly". But in reality it's intrinsic to the design. Now instead of picking an application which does its job well and a window manager which does its job well, you have to pick an application which manages its own windows well and does its job well. All because someone thought it's prettier if title bars have menu bars in them.

Commercial linux applications are hands down the worst in this regard. I don't think I've used one yet that look and behaved well in terms of focus/menus/clipboard/events/look-and-feel. Even ones made in QT are statically linked and a different version from the distribution one so it ignores all your preferences (I think that's the reason).

The push to make everything electron just means that everyone else is having this problem now.

Ok GTK3 is just awfull but no one is taking it seriously and actually building things with it right?


As far as I can tell, not ICCCM (nor EWMH/NetWM) compliant.

This is important. But it's still great for people to see that a minimal implementation (for playing with) only takes this much code. It's good when you're learning.

this is so cool, I've been wanting to learn more about windowmanagers for a while now!

Any chance anyone knows of something similar to this but using Wayland as opposed to X?

Not a snowball's chance in hell of doing a Wayland compositor in 50 lines. OP has the benefit of the X server doing most of the work. Wayland compositors also have to do all of the rendering, input dispatching, GPU setup, etc themselves. With wlroots you could probably get pretty small, though, but you still have to do rendering et al yourself: https://github.com/swaywm/wlroots (note: I am the maintainer of this software)

I tried reading the source code for wlroot, and Sway, to figure out how hard it would be to base a "non tiling" window manager of it. It's very readable in isolation, but I struggled figuring out how stuff fits together. Maybe the issue is my limited understanding of C.

Do you have any pointers to getting started developing for with Wayland (and wlroot)?

I'll take your word for it, given who you are :) 50 lines wasn't really a hard requirement though, just minimal enough that you can sort of get a feel for the absolute basics. like equivalent capabilities to TinyWM. Sway doesn't quite fit that bill as it's more of a fully-fledged wm that you could install on machines you actually use for stuff (I'm running it on this machine for example)

ps. Thanks for creating/maintaining Sway! it's great stuff! ds.

I'll whip up an annotated, tinywm compatible Wayland compositor today if I have time. Expect a Wayland equivalent to be posted tomorrow!

And I'm glad you like sway :)

Very cool :) On that note, I think it is great how much effort you put into making wlroots, sway and wayland accessible through your blogposts and the open development process.

While I have been busy and will be busy for a few more months I look very much forward to working through your posts and learning something about wayland and sway then :)

wow! thanks! that's beyond great! hats off to you kind Sir :)

also kudos :)

>> With wlroots you could probably get pretty small, though, but you still have to do rendering et al yourself...

Well yes and no. A wayland compositor has to blit the images of the applications which need to draw themselves into buffers. At least that's my understanding of it. The compositor isn't supposed to draw anything, it just copies things to the frame buffer. I would hope a basic compositor could be done with not too much code.

Blitting and rendering aren't too different. Blitting is pretty inefficient, too, particularly because many Wayland clients render on the GPU and give you an opaque handle to GPU resources so you don't have to copy pixels at all. And you can blit instead of using OpenGL or if you want, but it's still your job to do so on Wayland whereas on X the X server is doing it for you. You also still need to handle input, focus, multihead, etc all yourself.

> The compositor isn't supposed to draw anything, it just copies things to the frame buffer.

Depends, some of us thinks that server side decorations are better for security, because otherwise a client can fake the look of another client.

>> some of us thinks that server side decorations are better for security, because otherwise a client can fake the look of another client.

If the decorations are done server-side then all applications will look the same anyway.

Having said that, I think decorations probably are the job of the desktop environment since those are the things that a user manipulates at that level of abstraction. Moving, resizing, closing programs is a UI thing and an application really shouldn't know where it is within the desktop environment. That's actually a security concern IMHO.

> If the decorations are done server-side then all applications will look the same anyway.

Uh? You should read about QubesOS..

Would something like a middle-ware server work here? Something that handles all the backend stuff like the X-server does and provides a simple protocol that window managers could use instead of directly talking the wayland protocol? Basically wlroots as a daemon/service instead of a library.

Those who do not understand X architecture are doomed to reimplement it, poorly.

So base it on a simplified version of the X protocol?

The X protocol is Legacy Cruft and as such needs to be burned and the ashes sealed within a concrete block and buried at sea.

The whole point behind Wayland is to make a 100% clean break from X. Of course as it turns out that means reinventing and replacing all the things that made X good in the first place with something completely new, because newer=gooder. And reading old code is hard, so everything on the Linux tech stack needs to be completely reimplemented so GNOME devs can maintain it for its five-year lifecycle before it all gets thrown out and replaced with something even newer (and gooder).

How much of wlroots is devoted to dealing with the Wayland protocol, versus rendering and input handling?

Writing a heavily constrained, low-level compositor seems like an interesting project. Maybe something that only supports a single type of graphics output, and uses KMS and DRI directly.

Very little is devoted to the protocol itself, libwayland-server does most of that work for us.

While X is a giant program that offers a lot of features, Wayland is not a program but a protocol. Wayland composotors, implementations of Wayland protocol, are usually intertwined with their desktop environments. So I guess similar examples using Wayland are not as universal as using X and do not help much to learn about Wayland itself.

Still, there is a convenient Wayland compositor library that is designed for devs to build own window managers. Check wlc [1]. wlc has a nice and simple example [2] but not as short as TinyWM.

[1]: https://github.com/Cloudef/wlc

[2]: https://github.com/Cloudef/wlc/blob/master/example/example.c

X is also a protocol. It's what allows ancient clients to still render onto modern X servers.

All the simple "window managers" for Wayland seems to be tiling for some weird reason. I think Wayland adoption could be higher is if there was a simple, easy to customize basic WM that people could fork to go do their own thing. I know Weston exists, and others, but if you look at how many X11 Window Managers that have been forked of AWM or EvilWM then perhaps Weston is a little to complex.

I think "some weird reason" is that the tiny minority of users who want a WM/compositor without a DE like Gnome or KDE have already opted for minimalism and are therefore predisposed toward tiling.

The traditional stacking methodology of managing windows is particularly poor. If you have 2 windows open anything will do but it becomes ungainly with more than a handful of windows open unless you spread your windows out among multiple spaces/workspaces/virtual desktops and on each one arrange and resize windows so you can see the windows you want to view together at once.

At that point you have recreated a normal efficient way to use a tiling window manager with the additional burden of doing the tiling yourself instead of having the wm do it for you.

It seems likely that those who have an enthusiasm for this workflow are mostly working on desktop environments like gnome/plasma/lxqt.

actually i like to have lots of partially overlapping windows. every window is exactly where I left it and the frequently touched ones will have a small bit visible that i can grab on to bring the whole window to the front. if i only care about part of a window, then i can efficiently arrange my windows so only the part i care about is visible (while still interacting with it since I have focus-follows-mouse).

it's far more useful than a taskbar or expose, since they keep moving what i'm using. the taskbar is a particularly poor design since all i have is a title and at that point i'm just guessing and hoping.

tiling window managers and raise-on-focus systems don't particularly appeal to me because they require me to see the whole of a window. tiling window managers probably have a way to ensure a window is exactly where i left it but it seems antithetical to the alleged advantages. (doesn't "automatically manage your windows" mean "automatically decide where to put a window, and move them around based on the size of other windows"?)

Some wm automatically arrange windows in a layout others example i3wm just split the screen between windows on a given screen/workspace.

Note that a workspace in this instance is only one monitor in a multi monitor configuration.

By default a single window workspace it takes up all the space. Opening another gives you a new window to the right of the first each half the width of the screen.

On a tall not wide screen it would appear below the first each half the height of the screen.

You can have splitv and splith containers as well as vertical or horizontal tabbed layouts of any kind of windows.

Dialog windows are automatically floating.

You can have containers by containers or nested as you please example 3 horizontal tabs each split in half if you like.

I use a mix of wmutils[0] and windowchef[1] and they're great, lots of little programs (some < 10 LoC) but also some cool stuff like mouse support and borders etc. I've only ever had trouble with JAVA apps which is a simple fix (_JAVA_AWT_WM_NONREPARENTING=1)

This is a screenshot of my Linux desktop [2], I use these on OpenBSD as well without too much issue.

[0] https://github.com/wmutils [1] https://github.com/tudurom/windowchef [2] https://i.redd.it/ql1id3rocnq01.png

Very clean screenshot.

How does your setup fare with GL/Vulkan, Chrome?


Found that one out after some digging, seems weird to me that AWT manages to screw this up, to this day, maybe I'll understand what cool trick they do which makes this a problem.

> I use these on OpenBSD as well without too much issue.

Portability is a major benefit of these little window managers, I even ran my dwm fork on Minix3 (on real hardware!), with some minor Make changes [0] as a bored teenager.

[0]: https://github.com/xorgy/ldwm/blob/master/config.minix3.mk

Too bad it uses the old Xlib instead of XCB.

Wow 82 sloc. That just way too much bloat.

This was a reference for me while initially developing nobox: https://github.com/serprex/nobox/blob/master/nobox.c

Strange to use 0x0 instead of NULL in XOpenDisplay().

Is the xlib here as framework really the right backend? I have not much skill in this area so I can't say. In web development when someone claims he's written the shortest version of A and imports library B then usually the actually important code is written in B and he simply used A to configure the library to give the corresponding outputs he desires. Like "I wrote the shortest calculator ever: import Windows.Calculator; new Windows.Calculator();"

xlib is effectively as low-level a library as a WM might possibly use. This is like writing a calculator using the raw Win32 API, not some calculator library.

What about XCB?

well, I said "effectively" didn't I...? ;)

XCB is, per wikipedia, "comparable, but slightly lower-level"; read that with emphasis on "slightly". It's certainly better than xlib, and if you were to write a real WM from scratch these days you should probably use it, but I think bringing it up is sort of besides the point in this conversation: OP was wondering if any sort of cheating was going on by including an X protocol library, and the answer is "no": neither xlib nor XCB would be appreciably providing any sort of abstraction around the concept of "X window manager".

If it were more involved to write a WM, then I'd say that would be an opportunity for a library to fill the gap ...

I wish there was a screenshot, just to gauge what it could do without installing.

It doesn't actually draw anything, it just provides a means to move your windows around and change their z-order.

Kill your current window manager, that's what it looks like.

  > Move windows interactively with Alt+Button1 drag (left mouse button)
  > Resize windows interactively with Alt+Button3 drag (right mouse button)
  > Raise windows with Alt+F1 (not high on usability I know, but I needed a keybinding in there somewhere)
  > Focus windows with the mouse pointer (X does this on its own)

You really don't need a screen shot. It is well described. Its 50 lines of code, you can read them in a matter of seconds and determine it is simply your programs plopped on the screen, no chrome, no borders, nothing, other than the contents of the programs you started.

"You really don't need a screen shot."


"no borders"

Well, actually, I would like to see that ... which is to say, I would like to see some GUI apps without borders, etc., since it is something I have never seen before.

Check out some screenshots of ratpoison, dwm or something similar. Granted, dwm sticks a 1px border on windows by default, but it'll give you an idea of how it looks.

https://www.nongnu.org/ratpoison/ https://dwm.suckless.org/

You can already have this on window managers like i3wm.

Very cool, thanks.

In the second paragraph, the page lists the feature set. Basically, you have a keyboard binding to focus a window, and two mouse bindings to move and resize windows.

Basically even less than twm.


Does it annoy anyone else when someone says something like "I wrote X in 50 lines of C"

And then the first non-comment line is: #include <X11/Xlib.h>

Which itself is over 4000 lines and includes tons more code.. It's a pretty meaningless metric.

Writing X in 50 lines is almost always a statement more about the ecosystem X exists in than about the cleverness of the author of X. This headline tells us that the building a window manager can be done almost entirely with code that's already part of the window system, and requiring very little new code to achieve basic functionality.

It also tells us the term "window manager" is equivalent to a few X11 calls.

I'm a lot more annoyed by programs requiring entire desktop environments such as Gnome or, even worse, KDE to do things which would be perfectly doable without that dependency. Those 50 lines probably won't become most people's favorite WM, but could be among the best places to look how to start writing one.

I learned this the hard way when I realized CUPS (printing services) is a dependency on almost any major desktop app. I thought "I don't own a printer, probably will never need one, let's remove this superfluous printer software" only to find it's so ingrained in applications it may as well be a part of the OS. In all fairness, it is convenient to be able to print to pdf sometimes

I think it depends on what the dependency actually is. Here it is expected that you would include this header.

When someone does a python one liner that just calls a library or something that relies on boost, the point is lost for anyone hoping to have a minimal example.

> Which itself is over 4000 lines and includes tons more code.. It's a pretty meaningless metric.

Hardly. Including standard libraries in the line count wouldn't mean much, unless you're the compiler.

Doing it this way lets you know how many lines are likely to have problems. Not to mention how much code the guy wrote.

This isn't just some standard library though, and what do you mean by "wouldn't mean much, unless you're the compiler"? ...

The code in X11 libraries is infinitely closer to a window manager than what this guy wrote. This is barely anything at all added to work that other people did already.

And? It doesn't claim otherwise, and nicely shows off what's built in and what a window manager does.

#include "TheRestOfTheFuckingOwl.h"

And all of this runs on a 1M+ loc kernel ;)

Exactly. Nothing is built in a vacuum. It’s also running on top of cpu firmware, etc

There are some counterexamples that worked, though. In Verisoft, they did a whole stack from verified CPU to microkernel to simple OS and compiler. Everything was necessarily simple.


The high-assurance community also did a low-complexity GUI:


Yeah, it annoys me when it's actually 50 lines of C code and it's more than 50 opcodes /s

...as opposed to other window managers that are several orders of magnitude more code, also not including Xlib.h?

This "classic troll comment" appears with reasonable frequency in the demoscene: "your 4 kilobyte binary depends on gigabytes of OS libraries" --- and is countered the same way: "as opposed to a multi-gigabyte application also depending on same."

From what I understand, it's precisely a "wm" for Window manager and you'll see a list of other wm.


Just as web developers could write x lines of code that run on any web browsers and engines.

Header files are generally declarations, not executable code, and for a program that's 50 lines long, it probably doesn't even have room to use all 4000 lines of declarations. It looks like it uses three structs and about three members of each of those structs, a half-dozen function calls, and a handful of constants, so you could write it without the include in under 100 lines.

A more meaningful objection is that you link with -lX11, which is a significant amount of actual code. But apart from "what about libc and the kernel" counterarguments, the X protocol is actually pretty straightforward - I'd bet you could write this with just socket syscalls in about as many lines of code, too. (Which is to say, an embedded system without libX11 could implement a window manager for a remote machine given just ~100 lines of C or similar and a TCP stack, and the TCP stack is only required because it's remote, anyway.)

With your reasoning, the one should use only kernel interrupts and go even without glibc; because even simple printf() would require thousands of lines pulled from stdio.h

X11 is part of the system, just like glibc...

I disagree. I think most people distinguish between "end developer" code and libraries. I always find projects like this interesting and useful as they can be decent starting points to getting to know something.

I feel that way when people write anything in a functional programming language.

"Here's this lovely new functional language!... written in Haskell, using Haskell's entire runtime as a basis."

It's meaningful. X11 is a part of the structure of reality now, it's not going anywhere. Why can't you assume it?

It’s not meaningless though. Every language and platform has a stdlib. It’s interesting what can be done with them.

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact