1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:28:11 +00:00

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.
This commit is contained in:
Andreas Kling 2020-10-30 10:58:27 +01:00
parent 34014fa838
commit aef56159a8
32 changed files with 64 additions and 40 deletions

View file

@ -543,7 +543,7 @@ void Window::set_main_widget(Widget* widget)
set_rect(new_window_rect);
m_main_widget->set_relative_rect({ {}, new_window_rect.size() });
m_main_widget->set_window(this);
if (m_main_widget->accepts_focus())
if (m_main_widget->focus_policy() != FocusPolicy::NoFocus)
m_main_widget->set_focus(true);
}
update();
@ -720,7 +720,7 @@ void Window::start_wm_resize()
WindowServerConnection::the().post_message(Messages::WindowServer::WM_StartWindowResize(WindowServerConnection::the().my_client_id(), m_window_id));
}
Vector<Widget*> Window::focusable_widgets() const
Vector<Widget*> Window::focusable_widgets(FocusSource source) const
{
if (!m_main_widget)
return {};
@ -728,7 +728,20 @@ Vector<Widget*> Window::focusable_widgets() const
Vector<Widget*> collected_widgets;
Function<void(Widget&)> collect_focusable_widgets = [&](auto& widget) {
if (widget.accepts_focus())
bool widget_accepts_focus = false;
switch (source) {
case FocusSource::Keyboard:
widget_accepts_focus = ((unsigned)widget.focus_policy() & (unsigned)FocusPolicy::TabFocus);
break;
case FocusSource::Mouse:
widget_accepts_focus = ((unsigned)widget.focus_policy() & (unsigned)FocusPolicy::ClickFocus);
break;
case FocusSource::Programmatic:
widget_accepts_focus = widget.focus_policy() != FocusPolicy::NoFocus;
break;
}
if (widget_accepts_focus)
collected_widgets.append(&widget);
widget.for_each_child_widget([&](auto& child) {
if (!child.is_visible())
@ -853,7 +866,7 @@ void Window::set_resize_aspect_ratio(const Optional<Gfx::IntSize>& ratio)
void Window::did_add_widget(Badge<Widget>, Widget& widget)
{
if (!m_focused_widget && widget.accepts_focus())
if (!m_focused_widget && widget.focus_policy() != FocusPolicy::NoFocus)
set_focused_widget(&widget);
}