A library we all use today, but to do right everywhere is almost impossible to do. Windowing, the act of displaying a window on a display. Pretty much everything we use today use it.
Windowing as a topic comprises of much more concepts than just a window. You see, a window needs to be rendered somewhere and that is a display. There is also contexts, either a frame buffer or some other like OpenGL or DirectX one.
Almost everything in windowing is specific to a thread and not to a process. From drawing in a context to a display reference. But there does tend to be process oriented data like the OSX process menu.
From an implementation standpoint, systems libraries will probably be thread safe. But that doesn't they know how or can use the handle(s) you may give it.
This is where in practice with windowing we must discuss event loops. They are the key point to which events go from the system, transformed and then sent to your callback.
So event loops, the great carrier of information. Thread local, running on each thread where there is a window. A common occurance is to have the source (aka well), transform system messages(WM_PAINT) into a more useful library dependent type like Window_Paint. Since you're not writing against the system library, you're developing against a more common API. Of course this does mean Unicode decoding/encoding also must take place here. Which could be a bit complicated depending upon what the system API expects.
Having a great fancy event loop abstraction is good and all. But you need to be careful regarding drawing. Draw too often and you'll cpu will spike! But draw too infrequentyly and you'll find out dated information to be what you hope for! Be a little random with your drawing, and you'll have users rather annoyed with how choppy it could be.
To prevent your little (or fancy) event loop abstraction from becomming a pain, set a time out! This way you can make sure your draw function executes at least every x milliseconds. If you don't want it to execute every time, you can of course chuck a time counter (like StopWatch) and do a simple greater than comparison for your given min time between calls.
Not all event loop abstractions support this, but it can be quite useful if it does, is to support priorities and allowing one consumer to either steal an event or transform it into another. An example of this would be a consumer which forces a window to become a child of another. Such as a highlight window (for auto completion) in an IDE to remain over the same spot even if the parent window moves.
On to a real library!
Enough talk about the theory, now here is S.P.E.W.. My personal little lib. It isn't the only one I've implemented, but this is the latest version. Much more complete, from all the hard lessons learned. It's ultimate goals is a bit more than just windowing. Since windowing, sockets and timers all tend to get lumped together event loop wise, at the thread/system level.
So SPEW has a dedicated event loop abstraction. Nothing very new here. It was based off of glib's. It supports transformation, prioritisation and multiple sources+consumers. With filtering.
Next there is windowing support. This is seperated into three sections. Definitions, features and implementation. Definitions are the interfaces of e.g. window, display. Features are interfaces+free-functions which provide support for capabilties that are platform dependent like screenshots or menus. Finally the implementation is completely seperate in another sub package. Allowing you to swap it out with another. Contexts like OpenGL and Framebuffer, get assigned during an optional construction phase. The default is a Framebuffer.
Following up from windowing is sockets and timers support. In SPEW the default implementation utilizes LibUV for both. On Windows it supports alternatively WinAPI timers which can be enabled on request to minimize CPU timer for a thread (it can wake upon an event from the system). For LibUV there are automatic sleeping method, but it will never be good compared to a system supported one. Currently only Windows is supported.