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:
2025-06-28 16:26:13 +03:00
parent 521457eb92
commit e8491b34b8
12 changed files with 62 additions and 77 deletions

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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 {};
}