That first design was the wrong idea. Instead, have VBWidget instantiate
a GWidget of the appropriate type and parent it to the VBForm.
We then use a new "greedy hit-testing" mechanism in GWidget to prevent any
mouse events from reaching the VBForm's children.
To paint the grabbers above the child widgets, I added a slightly hackish
but kind of neat second_paint_event() that is called after a widget has
painted all of his children. :^)
When resizing a window, we often end up having to paint some part of it
without coverage in the current backing store. This patch makes those cases
look nicer by having a fallback background color for each window, passed
along with the CreateWindow client message.
This is essentially a combo widget containing a single-line GTextEditor
and two buttons for increment and decrement. The GTextEditor::on_change
callback is hooked to prevent non-numeric input but it's not entirely
perfect since that callback is asynchronous. This will work until we have
some more sophisticated input validation mechanism though.
I added focus rects to these widgets because I had just started working on
focus support and I was excited but it doesn't really make sense for these
things to have focus rects. :^)
While I was here I also optimized the repaint code to only update the edited
glyph in the glyph map when editing its pixels.
These events are identical, so it's silly to send both. Just broadcast
window state changes everywhere instead, it doesn't matter when it was
added as clients are learning about this asynchronously anyway.
I originally thought I would do this inside WindowServer, but let's try to
make it as a standalone app that communicates with WindowServer instead.
That will allow us to use LibGUI. :^)
This is useful for static locals that never need to be destroyed:
Thing& Thing::the()
{
static Eternal<Thing> the;
return the;
}
The object will be allocated in data segment memory and will never have
its destructor invoked.
This really brings the UI to life in a pleasant way. It's a bit annoying
that you can't initiate a resize by clicking on the shading of a splitter
resizer that actually belongs to the neighboring GFrame, I'm not sure how
to fix that yet but I'll think of something.