Kernel/LibC: Rework TIOC{G,S}WINSZ more linux like
Userspace can freely set terminal size, kernel just updates it when for example new font is loaded. Also SIGWINCH is now sent by kernel instead of userspace.
This commit is contained in:
parent
521457eb92
commit
e8491b34b8
|
@ -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<long> 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<PseudoTerminalMaster> m_master;
|
||||
uint32_t m_width { 0 };
|
||||
uint32_t m_height { 0 };
|
||||
|
||||
friend class PseudoTerminalMaster;
|
||||
friend class BAN::RefPtr<PseudoTerminalSlave>;
|
||||
|
|
|
@ -42,9 +42,6 @@ namespace Kernel
|
|||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<SerialTTY>> 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;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <LibInput/KeyEvent.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
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<size_t> read_impl(off_t, BAN::ByteSpan) final override;
|
||||
virtual BAN::ErrorOr<size_t> 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;
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace Kernel
|
|||
: m_palette(palette)
|
||||
{}
|
||||
virtual ~TerminalDriver() {}
|
||||
|
||||
virtual uint32_t width() const = 0;
|
||||
virtual uint32_t height() const = 0;
|
||||
|
||||
|
|
|
@ -19,9 +19,6 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> 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:
|
||||
|
|
|
@ -204,20 +204,4 @@ namespace Kernel
|
|||
return master->m_buffer_size < master->m_buffer->size();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> PseudoTerminalSlave::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
const auto* winsize = static_cast<struct winsize*>(argument);
|
||||
m_width = winsize->ws_col;
|
||||
m_height = winsize->ws_row;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return TTY::ioctl_impl(request, argument);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<BAN::RefPtr<SerialTTY>> 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);
|
||||
|
|
|
@ -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<long> TTY::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
|
@ -198,8 +205,14 @@ namespace Kernel
|
|||
case TIOCGWINSZ:
|
||||
{
|
||||
auto* winsize = static_cast<struct winsize*>(argument);
|
||||
winsize->ws_col = width();
|
||||
winsize->ws_row = height();
|
||||
*winsize = m_winsize;
|
||||
return 0;
|
||||
}
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
const auto* winsize = static_cast<const struct winsize*>(argument);
|
||||
m_winsize = *winsize;
|
||||
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<uint32_t>(m_height, new_height); y++)
|
||||
for (uint32_t x = 0; x < BAN::Math::min<uint32_t>(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<uint32_t>(m_height, new_height); y++)
|
||||
for (uint32_t x = 0; x < BAN::Math::min<uint32_t>(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 {};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<unsigned short>(rows()),
|
||||
.ws_col = static_cast<unsigned short>(cols()),
|
||||
.ws_xpixel = static_cast<unsigned short>(m_window->width()),
|
||||
.ws_ypixel = static_cast<unsigned short>(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<unsigned short>(rows()),
|
||||
.ws_col = static_cast<unsigned short>(cols()),
|
||||
.ws_xpixel = static_cast<unsigned short>(m_window->width()),
|
||||
.ws_ypixel = static_cast<unsigned short>(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());
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue