We can't rely exclusively on enter and leave events to update the hovered
state, since leave will not be delivered while the widget is auto-tracking
the mouse (between mousedown and mouseup.)
Since the sockets we use are non-blocking, just slap a select before the
second call to read(). This fixes some flakiness seen under load.
This should eventually work a bit differently, we could use recv() once
it has MSG_WAITALL, and we should not let WindowServer handle all the
client connections on the main thread. But for now, this works.
Fixes#24.
This could be tail-call-optimized but it's not, so we end up overflowing the
stack space if we recurse too many times. This was causing crashes when
resizing Minesweeper.
They show up as checkable GButtons in GToolBar, and with (or without) check
marks in menus.
There are a bunch of places to make use of this. This patch only takes
advantage of it in the FileManager for the view type actions.
We throw away the backing store if the window rect changes size. Since the
resizing happens asynchronously at the mercy of the WindowServer, we might
end up in set_rect() again before gaining a new backing store. So there are
no guarantees that the back/front bitmaps exist here.
Put the cursor on the left or right side of a glyph when clicking it based
on distance to middle of glyphs. This is such an obvious change that makes
a small but noticeable difference in feel. :^)
This is not very obvious and I need to come up with a better design, but for
now just make sure to call did_change() before calling set_cursor().
This is needed because set_cursor() will try to scroll the cursor into view,
and for right-aligned text, did_change() may change the content rect which
needs to be reflected by the time we call scroll_cursor_into_view().
We were forgetting to translate the painter by the frame_thickness().
With this fixed, we can also do proper vertical centering of lines for
single-line editors, and things suddenly look nicer than ever! :^)
When computing the visible content rect, constrain the result to the content
size. The content shouldn't feel responsible for painting anything outside.
When using a right-side text alignment, hook the resize event to make sure
that the content width is at least frame_inner_rect().width() wide.
This allows us to use content_width() as the anchor point for right aligned
text, rather than using the frame inner rect, which was clearly wrong in
the overflow case.
This could happen if GWindow::hide() was called while a window had pending
repaint rects. The deferred_invoke() lambda in GWindow::update() would
eventually run, but by then, hide() had cleared all pending rects.
To get truly atomic updates, add a mechanism for passing arbitrary amounts
of extra data along with WindowServer messages. This allows us to pass all
the rects in a single message.
This makes it possible for e.g GTextEditor to create a bunch of actions
with popular shortcuts like Ctrl+C, etc, without polluting the global
shortcut namespace. Widget-local actions will only activate while their
corresponding widget has focus. :^)
This patch moves to sending up to 32 rects at a time when coordinating the
painting between WindowServer and its clients. Rects are also merged into
a minimal DisjointRectSet on the server side before painting.
Interactive resize looks a lot better after this change, since we can
usually do all the repainting needed in one go.
It's now possible to edit widget properties inline in the properties window.
We're currently relying on the basic GVariant conversion functions to do
all the "parsing" but that's not gonna be good enough.
GAbstractView should be able to manage the high-level editing logic, as long
as subclasses implement content_rect(GModelIndex) so we know where to put
the editing widgets. :^)