mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 12:05:15 +00:00
LibVT+Terminal: Give TerminalWidget a hook for EOF on the pty
Instead of quitting the application immediately when the pty gives an EOF, fire an on_command_exit hook so the TerminalWidget client can decide for himself what to do.
This commit is contained in:
parent
a6b153abf1
commit
cd1eee6604
Notes:
sideshowbarker
2024-07-19 11:35:11 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/cd1eee66049
3 changed files with 52 additions and 23 deletions
|
@ -163,6 +163,9 @@ int main(int argc, char** argv)
|
|||
|
||||
RefPtr<CConfigFile> config = CConfigFile::get_for_app("Terminal");
|
||||
auto terminal = TerminalWidget::construct(ptm_fd, true, config);
|
||||
terminal->on_command_exit = [&] {
|
||||
app.quit(0);
|
||||
};
|
||||
terminal->on_title_change = [&](auto& title) {
|
||||
window->set_title(title);
|
||||
};
|
||||
|
|
|
@ -19,13 +19,46 @@
|
|||
|
||||
//#define TERMINAL_DEBUG
|
||||
|
||||
void TerminalWidget::set_pty_master_fd(int fd)
|
||||
{
|
||||
m_ptm_fd = fd;
|
||||
if (m_ptm_fd == -1) {
|
||||
m_notifier = nullptr;
|
||||
return;
|
||||
}
|
||||
m_notifier = CNotifier::construct(m_ptm_fd, CNotifier::Read);
|
||||
m_notifier->on_ready_to_read = [this] {
|
||||
u8 buffer[BUFSIZ];
|
||||
ssize_t nread = read(m_ptm_fd, buffer, sizeof(buffer));
|
||||
if (nread < 0) {
|
||||
dbgprintf("Terminal read error: %s\n", strerror(errno));
|
||||
perror("read(ptm)");
|
||||
GApplication::the().quit(1);
|
||||
return;
|
||||
}
|
||||
if (nread == 0) {
|
||||
dbgprintf("Terminal: EOF on master pty, firing on_command_exit hook.\n");
|
||||
if (on_command_exit)
|
||||
on_command_exit();
|
||||
int rc = close(m_ptm_fd);
|
||||
if (rc < 0) {
|
||||
perror("close");
|
||||
}
|
||||
set_pty_master_fd(-1);
|
||||
return;
|
||||
}
|
||||
for (ssize_t i = 0; i < nread; ++i)
|
||||
m_terminal.on_char(buffer[i]);
|
||||
flush_dirty_lines();
|
||||
};
|
||||
}
|
||||
|
||||
TerminalWidget::TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<CConfigFile> config)
|
||||
: m_terminal(*this)
|
||||
, m_ptm_fd(ptm_fd)
|
||||
, m_notifier(CNotifier::construct(ptm_fd, CNotifier::Read))
|
||||
, m_automatic_size_policy(automatic_size_policy)
|
||||
, m_config(move(config))
|
||||
{
|
||||
set_pty_master_fd(ptm_fd);
|
||||
m_cursor_blink_timer = CTimer::construct();
|
||||
m_visual_beep_timer = CTimer::construct();
|
||||
|
||||
|
@ -54,25 +87,6 @@ TerminalWidget::TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<CC
|
|||
else
|
||||
set_font(Font::load_from_file(font_entry));
|
||||
|
||||
m_notifier->on_ready_to_read = [this] {
|
||||
u8 buffer[BUFSIZ];
|
||||
ssize_t nread = read(m_ptm_fd, buffer, sizeof(buffer));
|
||||
if (nread < 0) {
|
||||
dbgprintf("Terminal read error: %s\n", strerror(errno));
|
||||
perror("read(ptm)");
|
||||
GApplication::the().quit(1);
|
||||
return;
|
||||
}
|
||||
if (nread == 0) {
|
||||
dbgprintf("Terminal: EOF on master pty, closing.\n");
|
||||
GApplication::the().quit(0);
|
||||
return;
|
||||
}
|
||||
for (ssize_t i = 0; i < nread; ++i)
|
||||
m_terminal.on_char(buffer[i]);
|
||||
flush_dirty_lines();
|
||||
};
|
||||
|
||||
m_line_height = font().glyph_height() + m_line_spacing;
|
||||
|
||||
m_terminal.set_size(m_config->read_num_entry("Window", "Width", 80), m_config->read_num_entry("Window", "Height", 25));
|
||||
|
@ -138,6 +152,11 @@ void TerminalWidget::event(CEvent& event)
|
|||
|
||||
void TerminalWidget::keydown_event(GKeyEvent& event)
|
||||
{
|
||||
if (m_ptm_fd == -1) {
|
||||
event.ignore();
|
||||
return GFrame::keydown_event(event);
|
||||
}
|
||||
|
||||
// Reset timer so cursor doesn't blink while typing.
|
||||
m_cursor_blink_timer->stop();
|
||||
m_cursor_blink_state = true;
|
||||
|
@ -478,6 +497,8 @@ void TerminalWidget::mousedown_event(GMouseEvent& event)
|
|||
m_selection_end = {};
|
||||
update();
|
||||
} else if (event.button() == GMouseButton::Right) {
|
||||
if (m_ptm_fd == -1)
|
||||
return;
|
||||
auto text = GClipboard::the().data();
|
||||
if (text.is_empty())
|
||||
return;
|
||||
|
@ -582,8 +603,10 @@ void TerminalWidget::terminal_did_resize(u16 columns, u16 rows)
|
|||
winsize ws;
|
||||
ws.ws_row = rows;
|
||||
ws.ws_col = columns;
|
||||
int rc = ioctl(m_ptm_fd, TIOCSWINSZ, &ws);
|
||||
ASSERT(rc == 0);
|
||||
if (m_ptm_fd != -1) {
|
||||
int rc = ioctl(m_ptm_fd, TIOCSWINSZ, &ws);
|
||||
ASSERT(rc == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalWidget::beep()
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<CConfigFile> config);
|
||||
virtual ~TerminalWidget() override;
|
||||
|
||||
void set_pty_master_fd(int fd);
|
||||
|
||||
void create_window();
|
||||
|
||||
void flush_dirty_lines();
|
||||
|
@ -44,6 +46,7 @@ public:
|
|||
virtual bool accepts_focus() const override { return true; }
|
||||
|
||||
Function<void(const StringView&)> on_title_change;
|
||||
Function<void()> on_command_exit;
|
||||
|
||||
private:
|
||||
// ^GWidget
|
||||
|
|
Loading…
Add table
Reference in a new issue