Age | Commit message (Collapse) | Author |
|
And update them on relevant events.
|
|
and the CaptureInput mode. They are a source of unneeded complexity
in WindowServer and have proven prone to regressions, so this patch
replaces them with a simple input preemption scheme using Popups.
Popup windows now have ergonomics similar to menus: When open,
a popup preempts all mouse and key events for the entire window
stack; however, they are fragile and will close after WindowServer
swallows the first event outside them. This is similar to how combo
box windows and popups work in the classic Windows DE and has the
added benefit of letting the user click anywhere to dismiss a popup
without having to worry about unwanted interactions with other
widgets.
|
|
Widgets can now prevent shortcut Actions from being called, which
allows text input keydown handlers to override single key shortcuts.
|
|
This moves logic for finding a shortcut on a Window or Widget to
Action::find_action_for_shortcut instead.
|
|
This ensures that widgets always get an initial show event.
|
|
with the CaptureInput WindowMode. This mode will serve the same
function as accessories: redirecting input while allowing parent
windows to remain active.
|
|
Widget::handle_leave_event() hides the tooltip if one is shown. That's
usually fine and hides the widget's tooltip, but it can happen that
another widget managed to show a tooltip after the Leave event was
triggered and before it's processed.
Thus change handle_leave_event() to only hide the tooltip if it was show
by the widget.
Fixes the case where this could happen in the flame graph in Profiler
when moving the mouse over the tooltip window itself #14852.
|
|
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
|
|
As they may be setting themselves visible again in the process.
Fixes inability to toggle widgets on and off in some apps.
|
|
|
|
|
|
This function is intended to propagate layout changes upwards in the
widget hierarchy. Widgets that can know what to do with this
information without causing a full layout invalidation (i.e. just
because one of their child widgets changed layout/size, doesn't
necessairily mean that they have to change their layout/size) can
override this and prevent a full relayout and redraw.
|
|
These new read-only properties help with debugging layouts, by exposing
the size values that are actually used for final size determination.
|
|
Effective sizes are the ones that are actually to be used for layout.
They are just their respective propertys value, or the value returned
by the calculated_<min/preferred>_size, when the respective property
is set to shrink or fit.
The "calculated" values in turn are specific to the widget. Container
widgets for example can calculate their values depending on their
layout and child widget requirement.
Simple widgets like labels and buttons can for example calculate their
values based upon their current text.
|
|
|
|
|
|
|
|
|
|
This is a bit of a hack, but it is an easy way to finally get spacers
into GML.
This will translate well if spacers are later to become child objects of
the continer widget.
|
|
Instead of having widget/window/application create a shortcut from a
KeyEvent within their find methods, we'll just pass them a Shortcut
so that the "where to search" logic doesn't need to be duplicated
for different Shortcut types.
It also lets us handle invalid Shortcut rejection at a higher level,
with most things letting the caller be responsible for not searching
for actions with an invalid shortcut.
|
|
|
|
TabWidgets couldn't be used in GML properly, as the GML creation
routines didn't actually call the necessary functions in the TabWidget
to get a new tab added. This commit fixes that by making the name of the
tab a normal property, the previously introduced "title", which can be
trivially set from GML. Therefore, try_add_widget() loses an argument
(while try_add_tab doesn't, because it newly constructs the widget).
This allows us to get rid of the silly "fixing my widget tree after the
fact" code in Help and will make it super easy to use TabWidget in
future GML. :^)
|
|
This title is a generic user-facing name for the widget. For now, it's
only used by TabWidget for tab names.
|
|
|
|
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules
"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
|
|
This was done with CLion's automatic rename feature.
|
|
This commit introduces a couple of connected changes that are hard to
untangle, unfortunately:
- Parse GML into the AST instead of JSON
- Change the load_from_json API on Widget to load_from_gml_ast
- Remove this same API from Core::Object as it isn't used outside of
LibGUI and was a workaround for the object registration detection;
by verifying the objects we're getting and casting we can remove this
constraint.
- Format GML by calling the formating APIs on the AST itself; remove
GMLFormatter.cpp as it's not needed anymore.
After this change, GML formatting already respects comments :^)
|
|
Prefixes are very much a C thing which we don't need in C++. This commit
moves all GML-related classes in LibGUI into the GUI::GML namespace, a
change somewhat overdue.
|
|
Fixes typefaces of the same weight but different slopes being
incorrectly returned for each other by FontDatabase.
|
|
No need to have this enabled all the time.
|
|
|
|
Even though they are called content_margins,
they are actually only ever used to determine where
a Widget is supposed to be grabbable.
So all methods and members are renamed accordingly.
|
|
Previously this section of code would blindly add *anything* as a child
as long as it has been registered as an object. Since there is no
guarentee that those objects are, in fact, Widgets, this feels like a
logical fallacy.
For example, up until this change, this is perfectly valid GML:
```
@GUI::Widget {
layout: @GUI::VerticalBoxLayout {
}
@GUI::VerticalBoxLayout {
}
}
```
What exactly does it do? Who knows! It doesn't seem to *break*, but I
think we can all agree it shouldn't be valid.
Instead, we now actually verify that the registered class inherets from
GUI::Widget before adding it as a child. We also error if it's not,
which should hopefully help new GML writers from forgetting to write
'layout: ' before the layout definition and being confused as to why
it's not working.
|
|
There are only two layouts at the moment, but that could (and probably
will) change in the future. Why limit ourselves by hardcoding these
checks when we can do it dynamically instead?
|
|
|
|
This resolves #10641.
|
|
In most situations, Widget::update() is preferable, since that allows us
to coalesce repaints and avoid redundant work, reducing system load.
However, there are some cases where you really want a paint to happen
right away, to make sure that the user has a chance to see a short-lived
visual state.
|
|
This feature was problematic for several reasons:
- Tracking *all* the user activity seems like a privacy nightmare.
- LibGUI actually only supports one globally tracking widget per window,
even if no window is necessary, or if multiple callbacks are desired.
- Widgets can easily get confused whether an event is actually directed
at it, or is actually just the result of global tracking.
The third item caused an issue where right-clicking CatDog opened two
context menus instead of one.
|
|
Applets and windows would like to be able to know when the applet
area has been resized. For example, this happens asynchronously after
an applet has been resized, so we cannot then rely on the applet area
position synchronously after resizing. This adds a new message
applet_area_rect_changed and associated Event AppletAreaRectChange,
and the appropriate virtual functions.
|
|
Previously we'd synthesize an event and invoke context_menu_event()
directly. This prevented the event from bubbling even if ignored.
|
|
This reverts commit cfc9ee6f16b9c4d2b246bb2832dd436637cbeaad.
This change was wrong: The parent *does* lose hover when the mouse
cursor enters a child widget. Hover is not hierarchical, there is only a
hovered window and a hovered widget within that window.
This fixes an issue with GUI::TabWidget buttons appearing hovered
despite the mouse cursor not being over the buttons.
|
|
This reverts commit a5a32fbccef8f8f663001363a278f80ef6320efe.
This change was wrong: it's fine for a child widget to receive an enter
event despite its parent never getting one. Only the widget directly
under the mouse cursor is considered hovered for enter/leave purposes.
|
|
You can now see the outline of GUI widgets when hovering them.
For example:
$ export GUI_HOVER_DEBUG=1
$ FileManager
Then move the mouse around in the file manager. :^)
|
|
If this is not ignored by default, then one can move the mouse fast
enough to skip hovering over a parent element and hover directly over
the child, causing the parent to never receive an Enter event.
|
|
Without this change, when the mouse starts hovering over a child widget,
the parent would receive a Leave event despite the parent widget not
losing mouse hover.
|
|
Widget::is_visible_for_timer_purposes needs to also consult with the
base implementation, which ultimately checks the owning Window's
visibility and occlusion state. Widget::is_visible merely determins
whether a widget should be visible or not, regardless of the window's
state.
Fixes #8825
|
|
Before this change, parent widgets such as Buttons or Labels
were stealing drop events their parents.
I noticed it during drag-n-dropping files into visualization widgets
in Sound Player (which takes practically the entire application size
and gave impression that drop events weren't supported in the app
at all).
|
|
|
|
|
|
LibGUI widgets fully contain their child widgets, so there's no pass
the paint event on to our children if we get a paint event that doesn't
intersect with our rect.
While Gfx::Painter was already dutifully clipping out any attempts at
painting, this avoids even more pointless work.
|