Skip to content

Releases: nullgemm/globuf

v0.5.4

25 May 10:54
Compare
Choose a tag to compare

New release to set in stone a few major changes. Let's start with the most exciting one!

At long last, after some eleven years (!) of pondering, the X11 EGL transparency fixes were finally merged in Mesa a few weeks ago. Let's take a moment to thank the project maintainers for their outstanding resilience and willpower handling this particular issue : good job everyone! After learning the news, I immediately grabbed bleeding-edge Mesa binaries and implemented EGL transparency in Globuf, fixing #18. Obviously, our library will fall back to setting up an opaque context for the years to come in case transparent ones are not available. We don't really have a choice here since old Mesa versions might be staying around for some time and most users will have to wait for the next stable version of Mesa to get the fix anyway.

Now for the other major change... Did I just say "Globuf"? Yes I did, after several months of pondering (different scale) I decided renaming the project was a necessary evil. I was careful to choose a similar name with the same number of characters, and "Globuf" was the best compromise I was able to find: maybe it sounds a bit goofy, but it still makes sense for the project and what it represents. Fixing X11 EGL transparency was a perfect excuse for pushing this change and making a new release.

We're getting close to the end of these release notes; let's talk about the project's future. The plans have not changed since last time, no release is planned for the near future. I've been writing another library since v0.5.3, but working 70 hours a week is no longer something I can do or want to do, so development is moving on at a much more reasonable pace. At some point this library will be done and I will come back to Globuf with the same "don't kill yourself" approach (or maybe contributors will appear, who knows?) and we'll reach a point where it makes sense to issue a bugfix release. I'm still hopeful when more pieces of my secret puzzle are done we'll be able to attract contributors. Until then, take care and thanks for reading.

v0.5.3

30 Oct 21:40
Compare
Choose a tag to compare

And it's a wrap! Globox now supports Wayland, again with all the companion libraries ready and all backends implemented. Development went rather smoothly, although some ideas collected along the way to improve our use of the protocol cost us a few deep dives into the display system's design. In the end it's for the better, since these efforts got us an extra clean API for this platform, with few structure-specific getters.

I didn't talk much about this in the past but with this iteration of Globox I tried to make it possible to write companion libraries without having to get a lot of specific low-level structures from Globox. At first this seems unavoidable, and to be honest coming up with a good design for a windowing library with a strong portability focus is already so hard I wouldn't blame anyone for not trying to. But it was the third time I started writing such a library from scratch, so I had some experience and a few ideas to try to make it possible, and quickly this became one of the many small reasons that finally convinced me a second re-write would be interesting. If you take a look at one of the complex examples in the repo, you will notice the amount of initialization data for each companion library was indeed reduced, and quite dramatically since their AppKit and Win32 backends simply do not require anything. Only good-old (but mostly old) X11 has to be fed some basic structures, kept to a minimum. For the new Wayland backends however, we do not usually supply structures, but functions!

Indeed, the Wayland versions of our companion libraries can't get all the data they need by themselves, but luckily the Wayland protocol makes it possible to negotiate protocols and surface features. Using the functions provided by Globox from companion libraries, it is possible to register callbacks to tap into these exchanges and get all the data we need. This is huge, because without such a system, implementing new companion libraries with Wayland support would require making some additions to Globox as well, in the lines of negotiating support for a new protocol internally and providing new getters for the specific structures it introduces. Quite underwhelming. With this new system, everything's easier Wayland-side. I did have to introduce a new Globox API call however, because I did not foresee how Globox feature negotiation would play with our Wayland registration pass-through. It's a bit sad but really not a big deal, you just have to call globox_window_confirm after globox_window_create now, and all the companion libraries initialization (and interaction with internal stuff in general) has to be done in between them instead of before globox_window_start. The feature config callback is also only called from globox_window_confirm now.

I also made some changes to our build system so the distributed binaries are cleaner: only public API symbols are marked as general for the ELF and PE formats now (MACH-O doesn't need this). To achieve that we perform a first linking step before archiving objects: the goal here is to resolve symbols between objects that will end up in the same static library unit before making the remaining ones local, with the exception of public API symbols that should stay accessible to users of the library and are kept general. This should help prevent name clashes that could result from the library's static-but-modular architecture. If you are wondering how it is even possible to implement such a trick at this stage, very good question: the answer is it was all planned from the beginning :)

I was able to test triple-monitor Wayland DPIshit reports by plugging all my stone-age tech together, and I'm happy to report it works wonderfully - X11 and AppKit were tested on two monitors only, and as you know Win32 doesn't support multi-monitor EDID info retrieval... The other companion libraries work fine as well, some more work will be required to have all backends behave exactly in the same way, but that shouldn't be a lot of work.

There's still a lot to improve in Globox (starting with fixing bugs) but at last we have all platforms, all backends and all features implemented for the first time. The architecture is finally acceptable, the library is more modular than ever, and we didn't use hacks. While we are still clearly in alpha for now, it's time for this version to be the one in the master branch. I think it's fair to consider this third attempt as a success!

That being said, I decided to slow down on Globox from now on, and focus more on other projects. You can expect a few commits here and there since I will definitely be using Globox for these, but clearly changes won't come at the same crazy pace as before. During the past year and a half, I've been burning the midnight oil to make that new version feature-complete before 2024, haunted by this deadline that for several reasons will most likely mean the end of time-consuming personal projects for me. I'm happy we made it! But I'm also very tired as this project has become way, way too big for me to handle alone. Luckily I had thought about setting up a continuous integration system to help alleviate some of the most tedious work, but even this is barely enough now. This release took me three whole days to pull off. Three whole days of doing nothing but working on the release for 10 hours a day, polishing our build system and testing all generated binaries in as many configurations as possible. For now we only produce alpha releases, but I fear the day we will have to distribute 1.0, hopefully other people will have joined me by then. Until this time, I will try to make small fixes as I go, squashing bugs one by one (I will be opening issues for those in the coming weeks).

Thank you all for your support, it means a lot ❤️

v0.5.2

08 Aug 20:42
Compare
Choose a tag to compare
v0.5.2 Pre-release
Pre-release

I failed at taking a break... which means it's already time for another alpha release! This time for Windows, and again with everything ready, backends, examples and companion libs. Development went rather smoothly, although my initial plan to support Acrylic blur using Microsoft's private APIs wasn't quite successful.

As I described in the previous release notes, I originally intended to implement the new Windows platforms for Globox and its companion libs in C++, mainly to make it easier to replicate Acrylic blur with DirectComposition and Direct2D. Unfortunately, MinGW does not seem to provide up-to-date headers for these APIs, which means we'd have to patch the existing ones... Not quite an acceptable solution in my opinion. In the end I took the difficult decision to not implement background blur on Windows, as the only other way to achieve this would be to rely on the older compositing tricks demonstrated in the previous versions of Globox, which simply do not give a qualitative enough result.

It's really sad since Globox proudly advertised support for cross-platform blur in its previous iterations, but I think it is the right decision. Writing the earlier versions of this library has taught me we can't always succeed in the fight for portability when proprietary platforms are involved. For this new version of Globox, I decided to only support MinGW and focus more on maintainability, and supporting Acrylic blur (not to mention using private APIs that could break at any time) is just not possible with these constraints.

In more enjoyable news, this new version of the Windows platform works much better than the previous ones! It's been rock solid even under Wine in most of my tests. Wiring everything according to the new multi-threaded design of Globox was not a very pleasant task, but in the end I think we got a pretty good result. This is quite a relief, since the Win32 API was clearly not built to handle parallel execution and there are a million ways to shoot yourself in the foot trying to do that, but being paranoid about synchronization and carrying out extensive tests paid off in this case. The MSDN documentation is actually quite helpful about it, and does give good tips to avoid making everything explode when sharing Win32 objects.

Some changes to the interactive move and resize Globox feature had to be made in order to guarantee a consistent behavior across platforms, since Windows is more restrictive than others on that matter. There are more minor fixes to X11 and AppKit as well in this release but nothing important, mostly some cleanup made along the way.

This time I also spent a few hours to try to fix the Windows console output issues that have always plagued the complex examples. Keyboard input is usually printed glyph-by-glyph in these, thanks to our Willis companion library, with complete composition support. On Windows however, the output has always been invalid, but my code seemed to work fine as the character codes it returns are right. Well it turns out this is just another unfortunate consequence of legacy support: Microsoft's printf functions do handle UTF-8 output, but exclusively through wide-character strings, which is not documented anywhere and has been driving people crazy for around 20 years now if the various forum posts I found are to be believed. In the end I made the complex examples print a warning about this when compiled for Windows, since copying bytes in wide characters one-by-one just to fix that would not make a lot of sense.

Another quirk I found when testing multi-monitor support is we can't get the physical size of secondary monitors. Again there is simply nothing we can do about it, solutions exist but require privileges or straight-up reading the registry, hoping for the best...

I am also sorry to report some parts of my CI system for macOS broke, and I'm afraid it will slowly but surely get worse with time. I can't build my cross-compiling toolchain from Alpine Linux anymore, and with Alice stepping down as a package maintainer for this distro the future is not bright. I was also not able to create a proper setup for Windows/Vulkan because the required packages are not available. As a result, this release's Windows binaries were generated from Windows and its AppKit binaries from my Hackintosh.

To end on a positive note, I can confirm Globox fullscreen windows benefit from exclusive fullscreen promotion! This works for the Vulkan and OpenGL backends: Microsoft made some changes some time ago in their compositor to detect borderless fullscreen windows and automatically promote them to exclusive fullscreen when nothing else is showing up on top. You can tell it happens in our case because the window suddenly looses its transparency and you can no longer see the desktop through it. Pretty cool!

I think this is it, I have some stuff planned for the next month and a half so taking a break is not an option this time, but I will be back with our last desktop platform: Wayland! Until then have a nice summer you all ;)

v0.5.1

03 Jun 15:59
Compare
Choose a tag to compare
v0.5.1 Pre-release
Pre-release

And here comes the macOS platform :) All backends, all examples, all companion libs - everything's here! As expected using Objective-C made it a lot easier to implement, but systems programming is always special on Apple platforms so the design phase thankfully spiced up the whole process with a few delicious headaches.

More specifically, you will find in the example/helpers folder a new appkit.m source file: it holds example code for a minimal macOS application, the construct macOS expects graphical programs to rely on in order to integrate properly in their desktop ecosystem. This is for instance what controls the bar displayed on top of the screen and the menu appearing when you click the app's icon in the dock. Previously I created the application with the window, inside Globox. However I realized coming back to this problem an application could very well control several windows. Because of that, I decided to move it out of the library and have it part of the examples, which allows you to create multiple windows for a single application using Globox.

This was a hard decision to take, because as I have detailed in the past AppKit basically requires that you let it steal the main thread in order for it to spin its own secret loops and logic - the result of a bad design decision said to be dating back to the days of NeXT. For us, this means a program ported to work on macOS has to start an application in the main and create a new thread to run its code aside.
As you can tell though, the examples were barely touched (it's the goal after all). This is because we can simply redefine the actual main of our program to bear another name and call it from a secondary thread created in the AppKit-specific example code! It works perfectly, and we don't even have to change how our code is organized for it to work on macOS. Cool right?

This iteration is clearly a lot cleaner than the previous ones in every possible way. I only had to use the Objective-C runtime once in the cursoryx companion library because Apple makes certain system cursors private. This can be disabled when compiling cursoryx though, in case you want something free of any undocumented API use - in which case some cursors will simply be replaced by fallbacks. I'd say using these private cursors is pretty safe however, since this is what Apple does in WebCore/WebKit/Safari to support CSS3 cursors...

Vulkan works using MoltenVK and the OpenGL backend currently supports OpenGL ES through ANGLE. I had originally planned to use MGL which implements desktop OpenGL 4 using Metal, but reading the code I noticed it still used Apple's old OpenGL API to get some info, which is a blocker for me. In theory OpenGL-on-Zink-on-Vulkan-on-MoltenVK-on-Metal should be possible, but the code to do so through EGL does not exist yet in Mesa, although some people have been working on enabling this recently. Maybe one day :) Of course all contexts support background blur.

Because I do not own any Apple hardware however (this entire thing was developed on a hackintosh) I am not able to test it as thoroughly as I'd like, but it should support retina screens just fine (I will make sure it does when I can access a true mac again, hopefully in a few weeks). One thing I made sure to test however is monitor detection using dpishit, and it seems to be working fine.

Now I have to say there is still room for improvement on this platform, especially when it comes to maximization, which does not support rendering the window's content during the animation. I have no idea how to do this, so it will have to be fixed later. Another important missing feature is proper object destruction, which I skipped because it can be fixed using Objectice-C autorelease pools. I'm very sorry this is not done properly but I had to work hard to make this all happen and I'm getting a bit tired. We're clearly 99.9% here though, so le'ts celebrate (and maybe take a break this time) before moving on to our next target: Windows.

Just like the macOS backend was a nice incentive to learn Objective-C, I will take that opportunity to come back to C++ and perfect my knowledge of its modern features in the process. Previous versions of Globox used 100% C99 for the Windows part, but I plan on using DirectComposition to provide high-quality background blur this time, and this requires using C++.

N.B.: The archives do not contain natively compiled macos binaries, only cross-compiled ones since this is easier for now. If cross-compiling becomes hard or impossible I will switch to providing native binaries of course.

v0.5.0

25 Mar 17:53
Compare
Choose a tag to compare
v0.5.0 Pre-release
Pre-release

Well, this took longer than expected. It's been 4 months already, but at last we can celebrate the completion of all X11 backends with another tasty alpha release! This new version 0.5.0 brings you GLX, EGL, and even Vulkan! All the examples are functioning, in their simple and complex variant. Vulkan's was so heavy I chose to move most of the code in a separate helper source file, but for that price you get extensive debugging info on both your GPU and what's going on in the example itself.

The OpenGL backends (GLX and EGL) were pretty easy to implement, but I got stuck trying to make transparency work with GLX. Eventually I moved on with Vulkan, hoping implementing transparency for this backend would hint me into the right direction to fix it for GLX. This is indeed what happened, so now I can proudly say Globox supports creating transparent windows for GLX and Vulkan (you really have to see Plasma's background blur on GLX and Vulkan contexts to truly appreciate that).

Unfortunately, EGL does not support transparent contexts. This issue was reported on Mesa's bugtracker long ago, and a patch has even been worked on for several years now, but it seems we're still pretty far from having this problem resolved. We'll make sure to implement EGL transprency when it's supported though!

Because the Vulkan API already abstracts the display systems it supports to some extent, our Vulkan backend is shockingly empty, and was put together in just a few hours. However, the example we provide was not as easy to create. It took me 4 attempts to get it right and working, but in the end I think it has that intrinsic value I was searching for, being a clean self-contained Vulkan example in C99.

With X11 behind us, I can now focus on my next target: macOS. Unlike the previous versions of Globox, this iteration's macOS backends will be written in Objective-C. In the past I used C99 and the Objective-C runtime to hack AppKit and make all sorts of weird tests, but I don't think it is a good idea to follow this path. Now it is true I could use Swift, since it is clearly the future on Apple systems, and I think it is reasonable to suspect they might end up writing an entire operating system in that language out of pure faith at some point. However I can't make a choice based on what might be, in that regard, and currently macOS is still entirely written in Objective-C. Moreover, this language was created specifically to enable a unique vision of computing, and macOS was therefore designed around the principles and features Objective-C adds on top of C, so it is very hard to work without it when writing a low-level windowing library.

This will take some time since I have to actually learn Objective-C this time and implement a macOS backend for all the companion libraries used in the complex examples, but luckily the examples, especially the Vulkan one, should work with minimal changes (that's the whole point after all). However, since Vulkan and OpenGL are not supported by Apple, I will have to use metal implementations of these APIs, namely MoltenVK and MGL. This could take a while as well, but I expect the choice of using Objective-C to make it easier than it was for previous versions of Globox. Until then, enjoy good'ol X11 :P

v0.4.0

25 Nov 23:49
Compare
Choose a tag to compare
v0.4.0 Pre-release
Pre-release

It's time for a new alpha release of globox! I am currently re-writing it from the ground-up along with its companion libraries. Since cursoryx, dpishit and willis each have an alpha release for their brand-new x11 backend already, I decided to do the same for globox. Now unlike the former three globox does not need this to be tested properly since its example is included in its own repo, but I wanted to celebrate the completion of the x11 software backend in some way.

This was an exhausting but interesting five months of programming. I set the bar a lot higher than with previous iterations for this backend and getting it done in such a short time period wouldn't have been possible without all the research that was done for the prior versions - all this was not entirely in vain in the end!

In addition to these five months of writing code and fixing bugs, designing the new architecture took almost an entire month of thinking, as I had to dive back into other backends to try to find the best compromise to support all platforms properly with as few hacks as possible. So far I'm quite happy with this design, it didn't change too much during the implementation and makes everything a lot more flexible and extensible should one need to implement some platform-specific functionalities.

I strategically started with X11 because it's probably the worst display system out there, but this does not mean I don't take it seriously. This backend was tested extensively under a lot of different desktop environments. All XCB errors should be handled properly. The code was analyzed with several advanced tools. There are still a few things I might implement later, like faked VSync and aggressive buffer allocation optimizations, but it should already be pretty solid.

With this behind us, development should be less energy-intensive now, since the common parts of the library are already implemented and the API design seems to be working as intended. I will now move on to writing the GLX, EGL and Vulkan backends. Thank you for caring about this :)

v0.3.0

08 Dec 17:48
Compare
Choose a tag to compare

In this new major release we made a lot of changes to Globox.

First, native window frames are no longer supported, and the API was changed accordingly. I want to make it very clear I do prefer server-side decorations: these changes were made for technical reasons, not because of my personal opinion on the matter. Sadly, some key features of Globox prevent us from using native decorations without serious issues, and getting rid of them is the only fix possible.

This means Client-Side Decorations must be implemented in order to get a window frame when using Globox. A new set of examples was added in example/complex to show how, with the help of Willis, Cursoryx and DPIshit for handling input events, setting the mouse cursor and finding the display density. The original examples that now simply create a frameless window without using any other dependency were moved to example/simple.

The build system was also greatly improved:

  • Makefile generation scripts can now be automated using arguments
  • MSVC paths and version numbers are automatically detected under Windows with the help of powershell
  • all scripts were checked using shellcheck
  • it is now possible to build static binaries with MinGW

Lots of bugs were fixed, and the windows are more stable overall now native window frame support has been removed. There is still a lot to be done on Globox, feel free to help grow the project by taking a look at the issues and contributing!

v0.2.13

14 Aug 10:05
Compare
Choose a tag to compare

With this release, Globox is no longer exprimental 🎉

Only one functional modification was made to allow the developer to close the window programmatically, which was missing from the API.
All the other changes are bug fixes, performed with the help of our recently introduced Continuous Integration system.

That's right! After a month of grinding, we can finally compile and test Globox automatically using dockerfiles.
Right now we support compiling x11 and wayland with gcc, windows with mingw and macos with osxcross.
I initially planned to use Qemu'd concourse workers to automate Apple-SDK and MSVC compiling,
but after finalizing the dockerized tasks I am already on the edge of insanity and must postpone it.

The testing images allow us to run the following programs:

  • cppcheck
  • infer (for wayland and x11)
  • clang's sanitizers (for wayland and x11 but not for the glx backend)
  • valgrind (for x11 but not for the glx backend)

Of course the build system changed a lot in the process:

  • clear helper scripts are now available in make/lib and make/example
  • it is now possible to specify an ar version when compiling for macOS, using the AR environment variable
  • we do not link libGLX for X11/GLX anymore, because I realized while making the Alpine dockerized builds that
    some distros simply do not provide package-config information for libGLX. Instead, we now rely on a cool trick
    I learned a few years ago to solve the problem: linking libGL, which is guaranteed to link libGLX by its strange specs
    (more details in the relevant commit)

The binaries in this release's zip file are optimized and no longer contain debug symbols.
Thanks to the people who reacted to previous releases with emojis, it was really heartwarming.
Thanks to Nathan J. for still being my friend after two years of constant ranting about display systems.
Thanks again to my teacher at IMAC, Mr. Biri, for allowing me start developing Globox as a school project.

v0.2.12

15 Jul 16:58
Compare
Choose a tag to compare
v0.2.12 Pre-release
Pre-release

This release downgrades the minimal wl_seat version to 4 in order to support Gnome and Enlightenment. It also removes xdg-decoration support because it can't be synchronized and supporting its asynchronous usage would require API changes that can't be replicated on other display systems while maintaining portability. The exact reasons can be found in the relevant commit message.

v0.2.11

13 Jul 17:31
Compare
Choose a tag to compare
v0.2.11 Pre-release
Pre-release

This release introduces globox_platform_prepare_buffer, which should be called before drawing. It is used to fix the biggest synchronization issue under Wayland, where re-drawing too fast in software mode could result in visual glitches.

This is because Globox was intended as a heavily optimized library and re-uses the same buffer as much as possible, which can be done without compromise on most display systems, but isn't possible with Wayland's core protocols : most Wayland example programs, like those from the wayland book, allocate one buffer per frame for this reason.

Globox didn't take this into account because I had a few ideas to try to work around the issue, but the unfortunate reality is that none of them worked out as expected, so I had to step back and introduce globox_platform_prepare_buffer as well as re-write the Wayland software backend to allocate a new buffer per frame just like most clients out there. For the record, here is what I considered doing:

  • Synchronizing on wl_buffer.release: this works under Weston and Sway because they release the buffer as soon as it has been copied. In practice this is a bad idea because the standard does not guarantee this behaviour, and of course Kwin and EFL (the usual offenders) do not release the buffer immediately.
  • Synchronizing with the zwp_linux_explicit_synchronization protocol: this works perfectly, but this protocol is only supported by Weston, and not in nested mode.
  • Waiting for wl_surface.get_release to be implemented: a new functionality intended to fix this synchronization issue was suggested for inclusion is the core protocol, but this was only two months ago at the time of writing so it is clearly very far away from being a reality.

Until zwp_linux_explicit_synchronization or wl_surface.get_release are properly implemented everywhere, Globox will then use one buffer per frame, saving the buffer destruction requests for processing synchronously while always keeping the last buffer alive to prevent the window's content from randomly disappearing because of our custom rendering system.

With this setup, the KDE reverse-shearing fix isn't necessary anymore so its define was removed. Because we must allocate a new buffer on each frame anyway, the power-of-two buffer resizing optimization was removed as well.