From de2423de5f1449b17bdbfc3782a8ce4dee0b20e3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 26 Jan 2019 11:24:16 +0100 Subject: [PATCH] LibGUI: Flesh out focus implementation and more GTextBox work. --- LibGUI/GCheckBox.h | 1 + LibGUI/GEvent.h | 19 ++----------------- LibGUI/GListBox.h | 1 + LibGUI/GTextBox.cpp | 4 ++-- LibGUI/GTextBox.h | 3 ++- LibGUI/GWidget.cpp | 30 +++++++++++++++++++++++++----- LibGUI/GWidget.h | 4 ++++ LibGUI/GWindow.cpp | 9 +++++++-- LibGUI/GWindow.h | 4 ++++ Userland/guitest2.cpp | 6 ++++++ 10 files changed, 54 insertions(+), 27 deletions(-) diff --git a/LibGUI/GCheckBox.h b/LibGUI/GCheckBox.h index 3c5e2f3001..cee0d1bc1e 100644 --- a/LibGUI/GCheckBox.h +++ b/LibGUI/GCheckBox.h @@ -19,6 +19,7 @@ private: virtual void mousedown_event(GMouseEvent&) override; virtual const char* class_name() const override { return "GCheckBox"; } + virtual bool accepts_focus() const override { return true; } String m_caption; bool m_checked { false }; diff --git a/LibGUI/GEvent.h b/LibGUI/GEvent.h index f0b385eeb9..44e7de4dec 100644 --- a/LibGUI/GEvent.h +++ b/LibGUI/GEvent.h @@ -5,21 +5,6 @@ #include #include -static const char* eventNames[] = { - "Invalid", - "Quit", - "Show", - "Hide", - "Paint", - "MouseMove", - "MouseDown", - "MouseUp", - "KeyDown", - "KeyUp", - "Timer", - "DeferredDestroy", -}; - class GEvent { public: enum Type { @@ -37,6 +22,8 @@ public: DeferredDestroy, WindowBecameInactive, WindowBecameActive, + FocusIn, + FocusOut, }; GEvent() { } @@ -45,8 +32,6 @@ public: Type type() const { return m_type; } - const char* name() const { return eventNames[(unsigned)m_type]; } - bool is_mouse_event() const { return m_type == MouseMove || m_type == MouseDown || m_type == MouseUp; } bool is_key_event() const { return m_type == KeyUp || m_type == KeyDown; } bool is_paint_event() const { return m_type == Paint; } diff --git a/LibGUI/GListBox.h b/LibGUI/GListBox.h index 6668b424a0..1b04b4d3ca 100644 --- a/LibGUI/GListBox.h +++ b/LibGUI/GListBox.h @@ -14,6 +14,7 @@ private: virtual void paint_event(GPaintEvent&) override; virtual void mousedown_event(GMouseEvent&) override; virtual const char* class_name() const override { return "GListBox"; } + virtual bool accepts_focus() const override { return true; } Rect item_rect(int index) const; diff --git a/LibGUI/GTextBox.cpp b/LibGUI/GTextBox.cpp index 74a11324ea..27ee49413d 100644 --- a/LibGUI/GTextBox.cpp +++ b/LibGUI/GTextBox.cpp @@ -107,8 +107,8 @@ void GTextBox::keydown_event(GKeyEvent& event) case KeyCode::Key_Backspace: return handle_backspace(); case KeyCode::Key_Return: - if (onReturnPressed) - onReturnPressed(*this); + if (on_return_pressed) + on_return_pressed(*this); return; } diff --git a/LibGUI/GTextBox.h b/LibGUI/GTextBox.h index 552f66bb57..9f395ac441 100644 --- a/LibGUI/GTextBox.h +++ b/LibGUI/GTextBox.h @@ -11,7 +11,7 @@ public: String text() const { return m_text; } void set_text(String&&); - Function onReturnPressed; + Function on_return_pressed; private: virtual const char* class_name() const override { return "GTextBox"; } @@ -19,6 +19,7 @@ private: virtual void mousedown_event(GMouseEvent&) override; virtual void keydown_event(GKeyEvent&) override; virtual void timerEvent(GTimerEvent&) override; + virtual bool accepts_focus() const override { return true; } void handle_backspace(); diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp index 9ccc18279c..a650510eca 100644 --- a/LibGUI/GWidget.cpp +++ b/LibGUI/GWidget.cpp @@ -38,6 +38,9 @@ void GWidget::event(GEvent& event) case GEvent::Paint: m_has_pending_paint_event = false; return paint_event(static_cast(event)); + case GEvent::FocusIn: + case GEvent::FocusOut: + return focusin_event(event); case GEvent::Show: return show_event(static_cast(event)); case GEvent::Hide: @@ -49,7 +52,8 @@ void GWidget::event(GEvent& event) case GEvent::MouseMove: return mousemove_event(static_cast(event)); case GEvent::MouseDown: - // FIXME: Focus self if needed. + if (accepts_focus()) + set_focus(true); return mousedown_event(static_cast(event)); case GEvent::MouseUp: return mouseup_event(static_cast(event)); @@ -98,6 +102,14 @@ void GWidget::mousemove_event(GMouseEvent&) { } +void GWidget::focusin_event(GEvent&) +{ +} + +void GWidget::focusout_event(GEvent&) +{ +} + void GWidget::update() { auto* w = window(); @@ -130,15 +142,23 @@ void GWidget::set_window(GWindow* window) bool GWidget::is_focused() const { - // FIXME: Implement. - return false; + auto* win = window(); + if (!win) + return false; + return win->focused_widget() == this; } void GWidget::set_focus(bool focus) { - if (focus == is_focused()) + auto* win = window(); + if (!win) return; - // FIXME: Implement. + if (focus) { + win->set_focused_widget(this); + } else { + if (win->focused_widget() == this) + win->set_focused_widget(nullptr); + } } void GWidget::set_font(RetainPtr&& font) diff --git a/LibGUI/GWidget.h b/LibGUI/GWidget.h index 7f8e06f824..15f3e1556c 100644 --- a/LibGUI/GWidget.h +++ b/LibGUI/GWidget.h @@ -24,6 +24,8 @@ public: virtual void mousemove_event(GMouseEvent&); virtual void mousedown_event(GMouseEvent&); virtual void mouseup_event(GMouseEvent&); + virtual void focusin_event(GEvent&); + virtual void focusout_event(GEvent&); Rect relative_rect() const { return m_relative_rect; } Point relative_position() const { return m_relative_rect.location(); } @@ -39,6 +41,8 @@ public: void update(); void repaint(const Rect&); + virtual bool accepts_focus() const { return false; } + bool is_focused() const; void set_focus(bool); diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index 650c92ea47..41f086b15d 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -139,8 +139,13 @@ void GWindow::set_focused_widget(GWidget* widget) { if (m_focused_widget == widget) return; - if (m_focused_widget) + if (m_focused_widget) { + GEventLoop::main().post_event(m_focused_widget, make(GEvent::FocusOut)); m_focused_widget->update(); + } m_focused_widget = widget; - m_focused_widget->update(); + if (m_focused_widget) { + GEventLoop::main().post_event(m_focused_widget, make(GEvent::FocusIn)); + m_focused_widget->update(); + } } diff --git a/LibGUI/GWindow.h b/LibGUI/GWindow.h index fd1372e72d..12ade852b5 100644 --- a/LibGUI/GWindow.h +++ b/LibGUI/GWindow.h @@ -38,6 +38,10 @@ public: GWidget* main_widget() { return m_main_widget; } const GWidget* main_widget() const { return m_main_widget; } void set_main_widget(GWidget*); + + + GWidget* focused_widget() { return m_focused_widget; } + const GWidget* focused_widget() const { return m_focused_widget; } void set_focused_widget(GWidget*); void show(); diff --git a/Userland/guitest2.cpp b/Userland/guitest2.cpp index 3b50b8a64f..541266cfec 100644 --- a/Userland/guitest2.cpp +++ b/Userland/guitest2.cpp @@ -110,6 +110,12 @@ GWindow* make_launcher_window() auto* textbox = new GTextBox(widget); textbox->set_relative_rect({ 5, 110, 90, 20 }); + textbox->on_return_pressed = [window] (GTextBox& textbox) { + window->set_title(textbox.text()); + }; + + auto* other_textbox = new GTextBox(widget); + other_textbox->set_relative_rect({ 5, 140, 90, 20 }); window->set_focused_widget(textbox);