Commit graph

45 commits

Author SHA1 Message Date
Jakub Berkop
c6bb3d452a
LibGUI: Widget::action_for_key_event() should fail for invalid shortcuts (#4137)
Previously GUI::Actions which were constructed without initializing
m_shortcut could be activated via an invalid GUI::Shortcut.

Steps to reproduce:
It was possible to enable TextEditor's markdown preview by pressing
Ctrl or Alt (Cmd/Ctrl) keys, which should not happen, as this Action
did not specify a shortcut.

This fix should apply to all other cases where actions where declared
without specifying a shortcut.
2020-11-23 18:41:15 +01:00
Tom
75f61fe3d9 AK: Make RefPtr, NonnullRefPtr, WeakPtr thread safe
This makes most operations thread safe, especially so that they
can safely be used in the Kernel. This includes obtaining a strong
reference from a weak reference, which now requires an explicit
call to WeakPtr::strong_ref(). Another major change is that
Weakable::make_weak_ref() may require the explicit target type.
Previously we used reinterpret_cast in WeakPtr, assuming that it
can be properly converted. But WeakPtr does not necessarily have
the knowledge to be able to do this. Instead, we now ask the class
itself to deliver a WeakPtr to the type that we want.

Also, WeakLink is no longer specific to a target type. The reason
for this is that we want to be able to safely convert e.g. WeakPtr<T>
to WeakPtr<U>, and before this we just reinterpret_cast the internal
WeakLink<T> to WeakLink<U>, which is a bold assumption that it would
actually produce the correct code. Instead, WeakLink now operates
on just a raw pointer and we only make those constructors/operators
available if we can verify that it can be safely cast.

In order to guarantee thread safety, we now use the least significant
bit in the pointer for locking purposes. This also means that only
properly aligned pointers can be used.
2020-11-10 19:11:52 +01:00
Andreas Kling
b11b4b29e9 LibGUI: Add Widget::has_focus_within()
This returns true if the widget has focus, or if one of its descendant
widgets does. Use this in StackWidget and TabWidget.

This also fixes HackStudio crashing on startup in StackWidget, due to
running before the window has a focused widget.
2020-10-30 23:40:23 +01:00
Andreas Kling
aef56159a8 LibGUI: Add Widget focus policies
Every widget now has a GUI::FocusPolicy that determines how it can
receive focus:

- NoFocus: The widget is not focusable (default)
- TabFocus: The widget can be focused using the tab key.
- ClickFocus: The widget can be focused by clicking on it.
- StrongFocus: Both of the above.

For widgets that have a focus proxy, getting/setting the focus policy
will affect the proxy instead.
2020-10-30 17:03:28 +01:00
Andreas Kling
e64f43c3a7 LibGUI: Fix null pointer dereference in enter/leave event handling
If an enter/leave event is delivered to a widget after it is removed
from a window, we can't just assume a window is gonna be there.

Fixes #3669.
2020-10-03 19:47:56 +02:00
AnotherTest
6902a09e47 LibGUI: Register the 'ColorInput' and 'Frame' widgets 2020-09-25 23:55:33 +02:00
Andreas Kling
e2f32b8f9d LibCore: Make Core::Object properties more dynamic
Instead of everyone overriding save_to() and set_property() and doing
a pretty asymmetric job of implementing the various properties, let's
add a bit of structure here.

Object properties are now represented by a Core::Property. Properties
are registered with a getter and setter (optional) in constructors.
I've added some convenience macros for creating and registering
properties, but this does still feel a bit bulky. We'll have to
iterate on this and see where it goes.
2020-09-15 21:46:26 +02:00
Andreas Kling
093de0e323 LibGUI: Use Core::Object::set_property() to handle JSON GUI properties
Piggyback on the existing mechanism to set individual properties.
This doesn't cover layouts or child widgets, but the per-widget own
properties can be set this way.

Any property can now be set in JSON GUI, all you need to do is handle
it in the relevant Core::Object::set_property() override. :^)
2020-09-14 16:16:36 +02:00
Andreas Kling
6fc8dedd28 LibGUI: Allow setting widget visibility from JSON GUI spec 2020-09-14 16:16:36 +02:00
Andreas Kling
6590eb8eb7 LibGUI: Complain about malformed "layout" values in JSON GUI 2020-09-14 16:16:36 +02:00
Andreas Kling
ea17b0cbb6 LibGUI: Start building a way to instantiate GUI from JSON
My original idea for GUI building tools was to have the "VisualBuilder"
app generate C++ code which in turn programmatically instantiated UI.
That never really materialized in any useful way beyond static UIs.

This is a fresh, new approach: using JSON to declare the UI and parsing
and constructing this UI at runtime. This will allow for way more
dynamic and flexible approaches to GUI development (I think.)

The basic idea is that you pass a JSON string to Widget::load_from_json
and it takes care of the rest.

This first version supports basic box layouts and instantiation of
arbitrary widgets, as long as those widgets have been registered.

This code has some pretty rough edges right now as it's evolving and
we need to figure out a lot of things about how it should work.
Nevertheless, it feels pretty cool. :^)
2020-09-14 16:16:36 +02:00
Andreas Kling
3c580233d1 LibGUI: Improve widget registration mechanism a bit
Allow registering widgets from namespaces other than GUI. :^)
Also add a few widgets.
2020-09-14 16:16:36 +02:00
Andreas Kling
cf429a788c LibGUI: Add Widget override cursor concept
We got ourselves into a mess by making widgets override the window
cursor whenever they wanted a custom cursor. This patch introduces a
better solution to that issue: per-widget override cursors.

Each widget now has an override cursor that overrides the window
cursor when that widget is hovered.
2020-09-11 14:26:37 +02:00
Andreas Kling
a265d40d6e LibGUI: Allow widgets to clip their child widgets
This patch adds Widget::children_clip_rect() which can be overridden
to tighten clipping of a widget's children. The default implementation
simply returns Widget::rect().
2020-08-26 00:51:35 +02:00
Andreas Kling
af16552624 LibGUI: Add Widget focus proxies
A Widget can now have a focus proxy widget. Questions about focus are
redirected to the proxy if present. This is useful if a widget could
logically get focus, but wants one of its child widgets to actually
handle it.
2020-08-26 00:51:35 +02:00
Andreas Kling
e374eb3035 LibGUI+WindowServer: Remove ResizeEvent::old_size()
Turns out nobody was using this information anyway, so let's not go
through all the trouble of plumbing it from WindowServer to LibGUI.

Fixes #3247.
2020-08-22 13:11:25 +02:00
Linus Groh
47d7faa998 LibGUI: Update active tooltip when source widget changes the label
Application::show_tooltip() now keeps track of the application's active
tooltip source widget so it can be updated while being shown when the
same widget updates its tooltip label.
Application::hide_tooltip() will unset the tooltip source widget,
respectively.

This is pretty useful for the ResourceGraph applet's tooltips!

Also re-use the Application::TooltipWindow's rect position in its
set_tooltip() method to avoid flickering from the window temporarily
being moved to 100, 100 and the position adjusted moments later.
2020-08-15 13:45:08 +02:00
Andreas Kling
75b8f4e4e6 LibGUI: Make focus events more aware of why focus is changing
This patch adds GUI::FocusEvent which has a GUI::FocusSource.
The focus source is one of three things:

- Programmatic
- Mouse
- Keyboard

This allows receivers of focus events to implement different behaviors
depending on how they receive/lose focus.
2020-08-15 00:05:45 +02:00
Linus Groh
e77991e63a LibGUI: Fix Widget::screen_relative_rect() for WindowType::MenuApplet
This was using window()->position(), which is unset for windows with
WindowType::MenuApplet. Now it checks the window type and then uses
rect_in_menubar() for MenuApplet windows and rect() for everything else.

This makes tooltips show up for MenuApplet windows, previously they were
positioned off-screen :^)
2020-08-14 10:28:03 +02:00
Andreas Kling
e0b8b4ac67 LibCore+LibGUI: Switch to using AK::is and AK::downcast 2020-07-26 17:51:00 +02:00
Tom
ec3737510d WindowServer: Add accessory windows
Accessory windows are windows that, when activated, will activate
their parent and bring all other accessory windows of that parent
to the front of the window stack. Accessory windows can only be
active input windows. The accessory window's parent is always the
active window regardless of whether it is also the active input
window.

In order to route input correctly, input is now sent to the active
input window, which can be any accessory window or their parent,
or any regular window.
2020-07-15 17:15:45 +02:00
Peter Elliott
0fd31ef598 LibGUI: Ignore KeyUp events by default
fixed #2576
2020-07-11 18:51:41 +02:00
Andreas Kling
ca93c22ae2 LibGUI: Turn GUI::Application::the() into a pointer
During app teardown, the Application object may be destroyed before
something else, and so having Application::the() return a reference was
obscuring the truth about its lifetime.

This patch makes the API more honest by returning a pointer. While
this makes call sites look a bit more sketchy, do note that the global
Application pointer only becomes null during app teardown.
2020-07-04 16:54:55 +02:00
Andreas Kling
116cf92156 LibGfx: Rename Rect,Point,Size => IntRect,IntPoint,IntSize
This fits nicer with FloatRect,FloatPoint,FloatSize and gives a much
better visual clue about what type of metric is being used.
2020-06-10 10:59:04 +02:00
Andreas Kling
4806cd122d LibGUI: Focus the first focusable widget added to a window
It feels really awkward if nothing is focused when opening a window.
2020-05-21 17:26:09 +02:00
Andreas Kling
39d55d1d76 LibGUI: Add a way to highlight the focused widget for debugging
You can now pass --gui-focus-debug to any GUI::Application and it will
draw a cyan rectangle around the currently focused widget.
2020-05-12 15:48:31 +02:00
Andreas Kling
575b674081 LibGUI: Add missing window() null check when widget's child is removed
Before notifying our window that a child was removed, we should first
check that we actually have a window! :^)
2020-05-12 14:06:25 +02:00
Andreas Kling
9d6c85e6a6 LibGUI: Remove ancient code for debugging widget underdraw 2020-05-12 13:43:37 +02:00
Andreas Kling
0f0d73d1b5 LibGUI: Make the "enabled" widget state propagate to child widgets
This simplifies building composite widgets by not having to worry about
updating widget subtrees.
2020-05-08 13:49:58 +02:00
Andreas Kling
42f0b2522b LibGUI: Introduce widget content margins + improve splitters
A GUI::Widget can now set an optional content margin (4x0 by default.)
Pixels in the content margin will be ignored for hit testing purposes.

Use this to allow frame-like widgets (like GUI::Frame!) to ignore any
mouse events in the frame area, and instead let those go to parent.

This allows GUI::Splitter to react "sooner" to mouse events that were
previously swallowed by the child widgets instead of ending up in the
splitter. The net effect is that 2 more pixels on each side of a
splitter handle are now interactive and usable for splitting! :^)
2020-04-24 19:05:02 +02:00
Tibor Nagy
9e6e731a78 LibGUI: Remove G prefix from macros 2020-03-19 23:17:34 +01:00
Oriko
2a32330257 LibGUI: Add a ThemeChange event 2020-03-16 13:39:34 +01:00
Andreas Kling
3edcaa9b99 LibGUI: Implement set_property() on Widget and AbstractButton
This makes it possible for an RPC client to modify some interesting
widget properties.
2020-03-05 15:50:22 +01:00
Andreas Kling
4d5e144a6b LibGUI: Forget some of Window's widgets eagerly on widget unparenting
Previously the focused widget would only get cleared on replacement or
on destruction (being a WeakPtr and all.) This could lead to window
dispatching events to a focused widget after it had been removed from
the window's widget tree.

The same issue existed for the hovered widget, etc. So this patch
makes sure that we eagerly clear the various widget pointers in Window
immediately when they are removed from the window's widget tree.
2020-03-05 15:48:57 +01:00
Andreas Kling
e23c5b7e83 LibGUI+Inspector: Highlight the currently remotely inspected widget
This patch adds a magenta rectangle around the currently inspected
widget. This allows you to browse an app's widget tree somewhat
visually using the Inspector. :^)
2020-03-05 14:42:05 +01:00
Andreas Kling
849fdc1c0b LibGUI: Make Layout a Core::Object and add basic serialization
This allows you to view layouts (as data) in Inspector.
2020-03-05 09:22:43 +01:00
Andreas Kling
6fa104ffd3 LibGUI: Ignore keyboard and mouse events in disabled widgets 2020-03-04 23:47:27 +01:00
Andreas Kling
e4f433dddd LibGUI: Remove unused GUI::Widget::click_event() 2020-03-04 21:21:46 +01:00
Andreas Kling
ceec1a7d38 AK: Make Vector use size_t for its size and capacity 2020-02-25 14:52:35 +01:00
Andreas Kling
c5d913970a LibGUI: Remove parent parameter to GUI::Widget constructor 2020-02-23 12:27:53 +01:00
Andreas Kling
e1ff4fa034 LibGUI: Remove more header dependencies from Widget.h 2020-02-15 00:24:14 +01:00
Andreas Kling
34c7322d77 LibGUI: Remove some header dependencies from Widget.h 2020-02-14 23:53:11 +01:00
Andreas Kling
3ce80bec97 WindowServer+LibGUI: Add a "drag move" event
This allows windows/widgets to learn when something is being dragged
over them. They can then repaint themselves somehow to indicate that
they are willing to accept a drop.

Currently this is piggybacking somewhat on the mouse event mechanism
in WindowServer. I'm not sure that's the best design but it seemed
easier to do it this way right now.
2020-02-13 21:43:32 +01:00
Andreas Kling
f4fa758959 LibGUI: Add a Widget::did_layout() that gets called after layout
This will allow widgets to implement post-layout behaviors.
2020-02-11 11:53:38 +01:00
Andreas Kling
6a9cc66b97 LibGUI: Remove leading G from filenames 2020-02-06 20:33:02 +01:00
Renamed from Libraries/LibGUI/GWidget.cpp (Browse further)