I've been wanting to do this for a long time. It's time we start being
consistent about how this stuff works.
The new convention is:
- "LibFoo" is a userspace library that provides the "Foo" namespace.
That's it :^) This was pretty tedious to convert and I didn't even
start on LibGUI yet. But it's coming up next.
As suggested by Joshua, this commit adds the 2-clause BSD license as a
comment block to the top of every source file.
For the first pass, I've just added myself for simplicity. I encourage
everyone to add themselves as copyright holders of any file they've
added or modified in some significant way. If I've added myself in
error somewhere, feel free to replace it with the appropriate copyright
holder instead.
Going forward, all new source files should include a license header.
LibCore timers now have a TimerShouldFireWhenNotVisible flag which is
set to "No" by default.
If "No", the timer will not be fired by the event loop if it's within
a CObject tree whose nearest GWindow ancestor is currently not visible
for timer purposes. (Specificially, this means that the window is
either minimized or fully occluded, and so does not want to fire timers
just to update the UI.)
This is another nice step towards a calm and serene operating system.
Compiling LibCore on macOS is needed if one wants to compile host tools (like IPCCompiler) on a non Linux host. These changes could be possibly reverted once "event loop" functionality and "base library" (Vector, String etc.) will be split in two separate libraries,
updating all relevant projects.
GEventLoop was just a dummy subclass of CEventLoop anyway. The only
thing it actually did was make sure a GWindowServerConnectionw was
instantiated. We now take care of that in GApplication instead.
CEventLoop is now non-virtual and a little less confusing. :^)
Okay, I've spent a whole day on this now, and it finally kinda works!
With this patch, CObject and all of its derived classes are reference
counted instead of tree-owned.
The previous, Qt-like model was nice and familiar, but ultimately also
outdated and difficult to reason about.
CObject-derived types should now be stored in RefPtr/NonnullRefPtr and
each class can be constructed using the forwarding construct() helper:
auto widget = GWidget::construct(parent_widget);
Note that construct() simply forwards all arguments to an existing
constructor. It is inserted into each class by the C_OBJECT macro,
see CObject.h to understand how that works.
CObject::delete_later() disappears in this patch, as there is no longer
a single logical owner of a CObject.
With this patch, CEvents no longer stop at the target object, but will
bubble up the ancestor chain as long as CEvent::is_accepted() is false.
To the set accepted flag, call CEvent::accept().
To clear the accepted flag, call CEvent::ignore().
Events start out in the accepted state, so if you want them to bubble
up, you have to call ignore() on them.
Using this mechanism, we now ignore non-tabbing keydown events in
GWidget, causing them to bubble up through the widget's ancestors. :^)
RPC clients now send JSON-encoded requests to the RPC server.
The connection also stays alive instead of disconnecting automatically
after the initial CObject graph dump.
JSON payloads are preceded by a single host-order encoded 32-bit int
containing the length of the payload.
So far, we have three RPC commands:
- Identify
- GetAllObjects
- Disconnect
We'll be adding more of these as we go along. :^)
All programs that have a CEventLoop now allow local socket connections
via /tmp/rpc.PID and will dump a serialized JSON array of all the live
CObjects in the program onto connecting sockets.
Also added a small /bin/rpcdump tool that connects to an RPC socket and
produces a raw dump of the JSON that comes out.
This ensures the pipe fds don't leak into child processes.
This manifested as the Shell (and all processes started
from the shell) having two mysterious FIFOs open. This
was happening because of the Terminal, which the shell
was spawned form, leaking its CEventLoop wake pipe fds.
If we had already processed a couple of queued events by the time we were
told to un-nest the event loop, we'd put the entire current batch at the
head of the outer queue. This meant that we might end up trying to process
the same events multiple times.
Let's not do that. :^)
Add a trivial CSafeSyscall template that calls a callback until it stops
returning EINTR, and use it everywhere we use select() now.
Thanks to Andreas for the suggestion of using a template parameter for
the syscall function to invoke.
This way, CNotifier can mutate state to its little heart's content
without destroying the world when the global CNotifier hash changes
during delivery.
This patch generalizes the concept used in Piano to wake up the event loop
so it can react to something happening on a secondary thread.
Basically, there's a pipe who is always part of the file descriptor set we
pass to select(), and calling wake() simply writes a little to that pipe.
Don't process any more events. We already prepend the remaining events in
this loop to the outer loop if needed.
If there were any more events queued after the exit request, the iteration
code would make an invalid access into 'queued_events'.
Fixes#300.