diff --git a/kernel/include/kernel/Terminal/PseudoTerminal.h b/kernel/include/kernel/Terminal/PseudoTerminal.h index 2a241cb2..c3566308 100644 --- a/kernel/include/kernel/Terminal/PseudoTerminal.h +++ b/kernel/include/kernel/Terminal/PseudoTerminal.h @@ -59,9 +59,6 @@ namespace Kernel public: BAN::StringView name() const override { return m_name; } - uint32_t height() const override { return m_height; } - uint32_t width() const override { return m_width; } - void clear() override; protected: @@ -72,8 +69,6 @@ namespace Kernel bool can_write_impl() const override; bool has_hungup_impl() const override { return !m_master.valid(); } - BAN::ErrorOr ioctl_impl(int, void*) override; - private: PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t, uid_t, gid_t); ~PseudoTerminalSlave(); @@ -83,8 +78,6 @@ namespace Kernel const uint32_t m_number; BAN::WeakPtr m_master; - uint32_t m_width { 0 }; - uint32_t m_height { 0 }; friend class PseudoTerminalMaster; friend class BAN::RefPtr; diff --git a/kernel/include/kernel/Terminal/Serial.h b/kernel/include/kernel/Terminal/Serial.h index 4a4b2f5c..fa9f1d59 100644 --- a/kernel/include/kernel/Terminal/Serial.h +++ b/kernel/include/kernel/Terminal/Serial.h @@ -42,9 +42,6 @@ namespace Kernel public: static BAN::ErrorOr> create(Serial); - uint32_t width() const override; - uint32_t height() const override; - void clear() override { putchar_impl('\e'); putchar_impl('['); putchar_impl('2'); putchar_impl('J'); } void update() override; diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index 3ff63695..2ddebe5d 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -8,6 +8,7 @@ #include #include +#include namespace Kernel { @@ -53,9 +54,6 @@ namespace Kernel virtual bool is_tty() const override { return true; } - virtual uint32_t height() const = 0; - virtual uint32_t width() const = 0; - virtual dev_t rdev() const final override { return m_rdev; } virtual void clear() = 0; @@ -80,6 +78,8 @@ namespace Kernel virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) final override; virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) final override; + void update_winsize(unsigned short cols, unsigned short rows); + private: bool putchar(uint8_t ch); void do_backspace(); @@ -109,6 +109,8 @@ namespace Kernel }; Buffer m_output; + winsize m_winsize {}; + protected: RecursiveSpinLock m_write_lock; ThreadBlocker m_write_blocker; diff --git a/kernel/include/kernel/Terminal/TerminalDriver.h b/kernel/include/kernel/Terminal/TerminalDriver.h index 6eb964df..81bd82c7 100644 --- a/kernel/include/kernel/Terminal/TerminalDriver.h +++ b/kernel/include/kernel/Terminal/TerminalDriver.h @@ -35,6 +35,7 @@ namespace Kernel : m_palette(palette) {} virtual ~TerminalDriver() {} + virtual uint32_t width() const = 0; virtual uint32_t height() const = 0; diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index 9fbdf927..fd9970b6 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -19,9 +19,6 @@ namespace Kernel BAN::ErrorOr set_font(LibFont::Font&&) override; - uint32_t height() const override { return m_height; } - uint32_t width() const override { return m_width; } - void clear() override; protected: diff --git a/kernel/kernel/Terminal/PseudoTerminal.cpp b/kernel/kernel/Terminal/PseudoTerminal.cpp index 0dd737d1..43f30fe1 100644 --- a/kernel/kernel/Terminal/PseudoTerminal.cpp +++ b/kernel/kernel/Terminal/PseudoTerminal.cpp @@ -204,20 +204,4 @@ namespace Kernel return master->m_buffer_size < master->m_buffer->size(); } - BAN::ErrorOr PseudoTerminalSlave::ioctl_impl(int request, void* argument) - { - switch (request) - { - case TIOCSWINSZ: - { - const auto* winsize = static_cast(argument); - m_width = winsize->ws_col; - m_height = winsize->ws_row; - return 0; - } - } - - return TTY::ioctl_impl(request, argument); - } - } diff --git a/kernel/kernel/Terminal/Serial.cpp b/kernel/kernel/Terminal/Serial.cpp index 467fd990..01c92ded 100644 --- a/kernel/kernel/Terminal/Serial.cpp +++ b/kernel/kernel/Terminal/Serial.cpp @@ -181,7 +181,9 @@ namespace Kernel }, 0600, 0, 0) , m_name(MUST(BAN::String::formatted("ttyS{}", s_next_tty_number++))) , m_serial(serial) - {} + { + update_winsize(m_serial.width(), m_serial.height()); + } BAN::ErrorOr> SerialTTY::create(Serial serial) { @@ -254,16 +256,6 @@ namespace Kernel handle_input_byte(*ptr++); } - uint32_t SerialTTY::width() const - { - return m_serial.width(); - } - - uint32_t SerialTTY::height() const - { - return m_serial.height(); - } - bool SerialTTY::putchar_impl(uint8_t ch) { m_serial.putchar(ch); diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index ea088089..345da62a 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -184,6 +184,13 @@ namespace Kernel return {}; } + void TTY::update_winsize(unsigned short cols, unsigned short rows) + { + m_winsize.ws_col = cols; + m_winsize.ws_row = rows; + (void)Process::kill(-m_foreground_pgrp, SIGWINCH); + } + BAN::ErrorOr TTY::ioctl_impl(int request, void* argument) { switch (request) @@ -198,8 +205,14 @@ namespace Kernel case TIOCGWINSZ: { auto* winsize = static_cast(argument); - winsize->ws_col = width(); - winsize->ws_row = height(); + *winsize = m_winsize; + return 0; + } + case TIOCSWINSZ: + { + const auto* winsize = static_cast(argument); + m_winsize = *winsize; + (void)Process::kill(-m_foreground_pgrp, SIGWINCH); return 0; } } diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index ebb11faf..c2e5d37c 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -53,6 +53,7 @@ namespace Kernel { m_width = m_terminal_driver->width(); m_height = m_terminal_driver->height(); + update_winsize(m_width, m_height); m_buffer = new Cell[m_width * m_height]; ASSERT(m_buffer); @@ -71,34 +72,38 @@ namespace Kernel if (!m_terminal_driver->has_font()) return BAN::Error::from_errno(EINVAL); - SpinLockGuard _(m_write_lock); - - TRY(m_terminal_driver->set_font(BAN::move(font))); - - uint32_t new_width = m_terminal_driver->width(); - uint32_t new_height = m_terminal_driver->height(); - - if (m_width != new_width || m_height != new_height) { - Cell* new_buffer = new Cell[new_width * new_height]; - ASSERT(new_buffer); + SpinLockGuard _(m_write_lock); - for (uint32_t i = 0; i < new_width * m_height; i++) - new_buffer[i] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' }; + TRY(m_terminal_driver->set_font(BAN::move(font))); - for (uint32_t y = 0; y < BAN::Math::min(m_height, new_height); y++) - for (uint32_t x = 0; x < BAN::Math::min(m_width, new_width); x++) - new_buffer[y * new_width + x] = m_buffer[y * m_width + x]; + uint32_t new_width = m_terminal_driver->width(); + uint32_t new_height = m_terminal_driver->height(); - delete[] m_buffer; - m_buffer = new_buffer; - m_width = new_width; - m_height = new_height; + if (m_width != new_width || m_height != new_height) + { + Cell* new_buffer = new Cell[new_width * new_height]; + ASSERT(new_buffer); + + for (uint32_t i = 0; i < new_width * m_height; i++) + new_buffer[i] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' }; + + for (uint32_t y = 0; y < BAN::Math::min(m_height, new_height); y++) + for (uint32_t x = 0; x < BAN::Math::min(m_width, new_width); x++) + new_buffer[y * new_width + x] = m_buffer[y * m_width + x]; + + delete[] m_buffer; + m_buffer = new_buffer; + m_width = new_width; + m_height = new_height; + } + + for (uint32_t y = 0; y < m_height; y++) + for (uint32_t x = 0; x < m_width; x++) + render_from_buffer(x, y); } - for (uint32_t y = 0; y < m_height; y++) - for (uint32_t x = 0; x < m_width; x++) - render_from_buffer(x, y); + update_winsize(m_width, m_height); return {}; } diff --git a/userspace/libraries/LibC/include/sys/ioctl.h b/userspace/libraries/LibC/include/sys/ioctl.h index a4d90990..74ea0ed0 100644 --- a/userspace/libraries/LibC/include/sys/ioctl.h +++ b/userspace/libraries/LibC/include/sys/ioctl.h @@ -41,6 +41,8 @@ struct winsize { unsigned short ws_row; unsigned short ws_col; + unsigned short ws_xpixel; /* unused by kernel */ + unsigned short ws_ypixel; /* unused by kernel */ }; #define TIOCGWINSZ 50 #define TIOCSWINSZ 51 diff --git a/userspace/programs/Terminal/Terminal.cpp b/userspace/programs/Terminal/Terminal.cpp index dd7285be..f2bb8685 100644 --- a/userspace/programs/Terminal/Terminal.cpp +++ b/userspace/programs/Terminal/Terminal.cpp @@ -128,9 +128,12 @@ void Terminal::run() m_window->set_min_size(m_font.width() * 8, m_font.height() * 2); { - winsize winsize; - winsize.ws_col = cols(); - winsize.ws_row = rows(); + winsize winsize { + .ws_row = static_cast(rows()), + .ws_col = static_cast(cols()), + .ws_xpixel = static_cast(m_window->width()), + .ws_ypixel = static_cast(m_window->height()), + }; if (ioctl(m_shell_info.pts_master, TIOCSWINSZ, &winsize) == -1) perror("ioctl"); } @@ -170,6 +173,8 @@ void Terminal::run() const winsize winsize { .ws_row = static_cast(rows()), .ws_col = static_cast(cols()), + .ws_xpixel = static_cast(m_window->width()), + .ws_ypixel = static_cast(m_window->height()), }; if (ioctl(m_shell_info.pts_master, TIOCSWINSZ, &winsize) == -1) { @@ -183,12 +188,6 @@ void Terminal::run() perror("tcgetpgrp"); return; } - - if (kill(-fgpgrp, SIGWINCH) == -1) - { - perror("kill"); - return; - } }); const int max_fd = BAN::Math::max(m_shell_info.pts_master, m_window->server_fd()); diff --git a/userspace/programs/less/main.cpp b/userspace/programs/less/main.cpp index 3e672e43..2fae45a1 100644 --- a/userspace/programs/less/main.cpp +++ b/userspace/programs/less/main.cpp @@ -328,7 +328,7 @@ int main(int argc, char** argv) tcsetattr(kb_fd, TCSANOW, &termios); } - winsize ws { .ws_row = 0, .ws_col = 0 }; + winsize ws {}; if (isatty(STDOUT_FILENO)) { if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0)