mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibVT: Make TerminalWidget logically focusable when not a main widget
TerminalWidget was relying on the "window became active/inactive" events from WindowServer to update its own internal focus state. Unfortunately those events are only sent to the window's main widget, so this was not working when the TerminalWidget was embedded deeper in a widget tree. This patch hooks the focusin and focusout events and uses those to set the focus state when received. This makes TerminalWidget behave nicely in both configurations. This design is kind of a workaround for this awkward focus architecture and we should figure out something better in the long term.
This commit is contained in:
parent
8b4903e733
commit
5b30aa8b02
Notes:
sideshowbarker
2024-07-19 11:35:36 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/5b30aa8b021
2 changed files with 41 additions and 19 deletions
|
@ -1,7 +1,7 @@
|
|||
#include "TerminalWidget.h"
|
||||
#include "XtermColors.h"
|
||||
#include <AK/String.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <Kernel/KeyCode.h>
|
||||
#include <LibDraw/Font.h>
|
||||
|
@ -101,20 +101,38 @@ Rect TerminalWidget::row_rect(u16 row)
|
|||
return rect;
|
||||
}
|
||||
|
||||
void TerminalWidget::set_logical_focus(bool focus)
|
||||
{
|
||||
m_has_logical_focus = focus;
|
||||
if (!m_has_logical_focus) {
|
||||
m_cursor_blink_timer->stop();
|
||||
} else {
|
||||
m_cursor_blink_state = true;
|
||||
m_cursor_blink_timer->start();
|
||||
}
|
||||
invalidate_cursor();
|
||||
update();
|
||||
}
|
||||
|
||||
void TerminalWidget::focusin_event(CEvent& event)
|
||||
{
|
||||
set_logical_focus(true);
|
||||
return GFrame::focusin_event(event);
|
||||
}
|
||||
|
||||
void TerminalWidget::focusout_event(CEvent& event)
|
||||
{
|
||||
set_logical_focus(false);
|
||||
return GFrame::focusout_event(event);
|
||||
}
|
||||
|
||||
void TerminalWidget::event(CEvent& event)
|
||||
{
|
||||
if (event.type() == GEvent::WindowBecameActive || event.type() == GEvent::WindowBecameInactive) {
|
||||
m_in_active_window = event.type() == GEvent::WindowBecameActive;
|
||||
if (!m_in_active_window) {
|
||||
m_cursor_blink_timer->stop();
|
||||
} else {
|
||||
m_cursor_blink_state = true;
|
||||
m_cursor_blink_timer->start();
|
||||
}
|
||||
invalidate_cursor();
|
||||
update();
|
||||
}
|
||||
return GWidget::event(event);
|
||||
if (event.type() == GEvent::WindowBecameActive)
|
||||
set_logical_focus(true);
|
||||
else if (event.type() == GEvent::WindowBecameInactive)
|
||||
set_logical_focus(false);
|
||||
return GFrame::event(event);
|
||||
}
|
||||
|
||||
void TerminalWidget::keydown_event(GKeyEvent& event)
|
||||
|
@ -239,7 +257,6 @@ void TerminalWidget::paint_event(GPaintEvent& event)
|
|||
else if (has_only_one_background_color)
|
||||
painter.fill_rect(row_rect, lookup_color(line.attributes[0].background_color).with_alpha(m_opacity));
|
||||
|
||||
|
||||
// The terminal insists on thinking characters and
|
||||
// bytes are the same thing. We want to still draw
|
||||
// emojis in *some* way, but it won't be completely
|
||||
|
@ -265,9 +282,8 @@ void TerminalWidget::paint_event(GPaintEvent& event)
|
|||
VT::Attribute attribute;
|
||||
|
||||
for (u16 column = this_char_column; column < next_char_column; ++column) {
|
||||
should_reverse_fill_for_cursor_or_selection |=
|
||||
m_cursor_blink_state
|
||||
&& m_in_active_window
|
||||
should_reverse_fill_for_cursor_or_selection |= m_cursor_blink_state
|
||||
&& m_has_logical_focus
|
||||
&& row == row_with_cursor
|
||||
&& column == m_terminal.cursor_column();
|
||||
should_reverse_fill_for_cursor_or_selection |= selection_contains({ row, column });
|
||||
|
@ -295,7 +311,7 @@ void TerminalWidget::paint_event(GPaintEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_in_active_window && row_with_cursor < m_terminal.rows()) {
|
||||
if (!m_has_logical_focus && row_with_cursor < m_terminal.rows()) {
|
||||
auto& cursor_line = line_for_visual_row(row_with_cursor);
|
||||
if (m_terminal.cursor_row() < (m_terminal.rows() - rows_from_history)) {
|
||||
auto cell_rect = glyph_rect(row_with_cursor, m_terminal.cursor_column()).inflated(0, m_line_spacing);
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
|
||||
bool is_scrollable() const;
|
||||
|
||||
virtual bool accepts_focus() const override { return true; }
|
||||
|
||||
private:
|
||||
// ^GWidget
|
||||
virtual void event(CEvent&) override;
|
||||
|
@ -52,6 +54,8 @@ private:
|
|||
virtual void mouseup_event(GMouseEvent&) override;
|
||||
virtual void mousewheel_event(GMouseEvent&) override;
|
||||
virtual void doubleclick_event(GMouseEvent&) override;
|
||||
virtual void focusin_event(CEvent&) override;
|
||||
virtual void focusout_event(CEvent&) override;
|
||||
|
||||
// ^TerminalClient
|
||||
virtual void beep() override;
|
||||
|
@ -59,6 +63,8 @@ private:
|
|||
virtual void terminal_did_resize(u16 columns, u16 rows) override;
|
||||
virtual void terminal_history_changed() override;
|
||||
|
||||
void set_logical_focus(bool);
|
||||
|
||||
Rect glyph_rect(u16 row, u16 column);
|
||||
Rect row_rect(u16 row);
|
||||
|
||||
|
@ -86,7 +92,7 @@ private:
|
|||
|
||||
int m_ptm_fd { -1 };
|
||||
|
||||
bool m_in_active_window { false };
|
||||
bool m_has_logical_focus { false };
|
||||
|
||||
RefPtr<CNotifier> m_notifier;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue