mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +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
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");
|
RefPtr<CConfigFile> config = CConfigFile::get_for_app("Terminal");
|
||||||
auto terminal = TerminalWidget::construct(ptm_fd, true, config);
|
auto terminal = TerminalWidget::construct(ptm_fd, true, config);
|
||||||
|
terminal->on_command_exit = [&] {
|
||||||
|
app.quit(0);
|
||||||
|
};
|
||||||
terminal->on_title_change = [&](auto& title) {
|
terminal->on_title_change = [&](auto& title) {
|
||||||
window->set_title(title);
|
window->set_title(title);
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,13 +19,46 @@
|
||||||
|
|
||||||
//#define TERMINAL_DEBUG
|
//#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)
|
TerminalWidget::TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<CConfigFile> config)
|
||||||
: m_terminal(*this)
|
: m_terminal(*this)
|
||||||
, m_ptm_fd(ptm_fd)
|
|
||||||
, m_notifier(CNotifier::construct(ptm_fd, CNotifier::Read))
|
|
||||||
, m_automatic_size_policy(automatic_size_policy)
|
, m_automatic_size_policy(automatic_size_policy)
|
||||||
, m_config(move(config))
|
, m_config(move(config))
|
||||||
{
|
{
|
||||||
|
set_pty_master_fd(ptm_fd);
|
||||||
m_cursor_blink_timer = CTimer::construct();
|
m_cursor_blink_timer = CTimer::construct();
|
||||||
m_visual_beep_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
|
else
|
||||||
set_font(Font::load_from_file(font_entry));
|
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_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));
|
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)
|
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.
|
// Reset timer so cursor doesn't blink while typing.
|
||||||
m_cursor_blink_timer->stop();
|
m_cursor_blink_timer->stop();
|
||||||
m_cursor_blink_state = true;
|
m_cursor_blink_state = true;
|
||||||
|
@ -478,6 +497,8 @@ void TerminalWidget::mousedown_event(GMouseEvent& event)
|
||||||
m_selection_end = {};
|
m_selection_end = {};
|
||||||
update();
|
update();
|
||||||
} else if (event.button() == GMouseButton::Right) {
|
} else if (event.button() == GMouseButton::Right) {
|
||||||
|
if (m_ptm_fd == -1)
|
||||||
|
return;
|
||||||
auto text = GClipboard::the().data();
|
auto text = GClipboard::the().data();
|
||||||
if (text.is_empty())
|
if (text.is_empty())
|
||||||
return;
|
return;
|
||||||
|
@ -582,8 +603,10 @@ void TerminalWidget::terminal_did_resize(u16 columns, u16 rows)
|
||||||
winsize ws;
|
winsize ws;
|
||||||
ws.ws_row = rows;
|
ws.ws_row = rows;
|
||||||
ws.ws_col = columns;
|
ws.ws_col = columns;
|
||||||
int rc = ioctl(m_ptm_fd, TIOCSWINSZ, &ws);
|
if (m_ptm_fd != -1) {
|
||||||
ASSERT(rc == 0);
|
int rc = ioctl(m_ptm_fd, TIOCSWINSZ, &ws);
|
||||||
|
ASSERT(rc == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalWidget::beep()
|
void TerminalWidget::beep()
|
||||||
|
|
|
@ -18,6 +18,8 @@ public:
|
||||||
TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<CConfigFile> config);
|
TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<CConfigFile> config);
|
||||||
virtual ~TerminalWidget() override;
|
virtual ~TerminalWidget() override;
|
||||||
|
|
||||||
|
void set_pty_master_fd(int fd);
|
||||||
|
|
||||||
void create_window();
|
void create_window();
|
||||||
|
|
||||||
void flush_dirty_lines();
|
void flush_dirty_lines();
|
||||||
|
@ -44,6 +46,7 @@ public:
|
||||||
virtual bool accepts_focus() const override { return true; }
|
virtual bool accepts_focus() const override { return true; }
|
||||||
|
|
||||||
Function<void(const StringView&)> on_title_change;
|
Function<void(const StringView&)> on_title_change;
|
||||||
|
Function<void()> on_command_exit;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^GWidget
|
// ^GWidget
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue