Compare commits

...

3 Commits

Author SHA1 Message Date
Bananymous 011a5f57e1 WindowServer: Add title bars and clean up code 2024-05-31 03:02:58 +03:00
Bananymous 84b3289a2a Kernel: Move Scheduler::yield() lock check after interrupts disabled
I have no idea why this solves a bug where current processor has
scheduler lock at the beginning of yield.
2024-05-31 02:56:39 +03:00
Bananymous b760892de2 Kernel: Make pselect use nanosecods instead of milliseconds 2024-05-31 02:56:17 +03:00
7 changed files with 135 additions and 55 deletions

View File

@ -1031,11 +1031,11 @@ namespace Kernel
if (arguments->sigmask) if (arguments->sigmask)
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
uint64_t timedout_ms = SystemTimer::get().ms_since_boot(); uint64_t timedout_ns = SystemTimer::get().ns_since_boot();
if (arguments->timeout) if (arguments->timeout)
{ {
timedout_ms += arguments->timeout->tv_sec * 1000; timedout_ns += arguments->timeout->tv_sec * 1'000'000'000;
timedout_ms += arguments->timeout->tv_nsec / 1'000'000; timedout_ns += arguments->timeout->tv_nsec;
} }
fd_set readfds; FD_ZERO(&readfds); fd_set readfds; FD_ZERO(&readfds);
@ -1076,7 +1076,7 @@ namespace Kernel
if (set_bits > 0) if (set_bits > 0)
break; break;
if (arguments->timeout && SystemTimer::get().ms_since_boot() >= timedout_ms) if (arguments->timeout && SystemTimer::get().ns_since_boot() >= timedout_ns)
break; break;
LockFreeGuard free(m_process_lock); LockFreeGuard free(m_process_lock);

View File

@ -133,11 +133,11 @@ namespace Kernel
void Scheduler::yield() void Scheduler::yield()
{ {
ASSERT(!m_lock.current_processor_has_lock());
auto state = Processor::get_interrupt_state(); auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled); Processor::set_interrupt_state(InterruptState::Disabled);
ASSERT(!m_lock.current_processor_has_lock());
#if ARCH(x86_64) #if ARCH(x86_64)
asm volatile( asm volatile(
"movq %%rsp, %%rcx;" "movq %%rsp, %%rcx;"

View File

@ -56,4 +56,10 @@ struct Rectangle
.height = max_y - min_y, .height = max_y - min_y,
}; };
} }
bool operator==(const Rectangle& other) const
{
return x == other.x && y == other.y && width == other.width && height == other.height;
}
}; };

View File

@ -13,14 +13,14 @@ public:
void set_position(Position position) void set_position(Position position)
{ {
m_area.x = position.x; m_client_area.x = position.x;
m_area.y = position.y; m_client_area.y = position.y;
} }
void set_size(Position size, uint32_t* fb_addr) void set_size(Position size, uint32_t* fb_addr)
{ {
m_area.width = size.x; m_client_area.width = size.x;
m_area.height = size.y; m_client_area.height = size.y;
m_fb_addr = fb_addr; m_fb_addr = fb_addr;
} }
@ -29,17 +29,51 @@ public:
int client_fd() const { return m_client_fd; } int client_fd() const { return m_client_fd; }
int32_t x() const { return m_area.x; } int32_t client_x() const { return m_client_area.x; }
int32_t y() const { return m_area.y; } int32_t client_y() const { return m_client_area.y; }
uint32_t width() const { return m_area.width; } int32_t client_width() const { return m_client_area.width; }
uint32_t height() const { return m_area.height; } int32_t client_height() const { return m_client_area.height; }
Rectangle size() const { return { 0, 0, m_area.width, m_area.height }; } Rectangle client_size() const { return { 0, 0, client_width(), client_height() }; }
const Rectangle& area() const { return m_area; } Rectangle client_area() const { return m_client_area; }
int32_t title_bar_x() const { return client_x(); }
int32_t title_bar_y() const { return client_y() - title_bar_height(); }
int32_t title_bar_width() const { return client_width(); }
int32_t title_bar_height() const { return m_title_bar_height; }
Rectangle title_bar_size() const { return { 0, 0, title_bar_width(), title_bar_height() }; }
Rectangle title_bar_area() const { return { title_bar_x(), title_bar_y(), title_bar_width(), title_bar_height() }; }
int32_t full_x() const { return title_bar_x(); }
int32_t full_y() const { return title_bar_y(); }
int32_t full_width() const { return client_width(); }
int32_t full_height() const { return client_height() + title_bar_height(); }
Rectangle full_size() const { return { 0, 0, full_width(), full_height() }; }
Rectangle full_area() const { return { full_x(), full_y(), full_width(), full_height() }; }
const uint32_t* framebuffer() const { return m_fb_addr; } const uint32_t* framebuffer() const { return m_fb_addr; }
uint32_t title_bar_pixel(int32_t abs_x, int32_t abs_y, Position cursor) const
{
ASSERT(title_bar_area().contains({ abs_x, abs_y }));
Rectangle close_button = {
title_bar_x() + title_bar_width() - title_bar_height() + 1,
title_bar_y() + 1,
title_bar_height() - 2,
title_bar_height() - 2
};
if (close_button.contains({ abs_x, abs_y }))
return close_button.contains(cursor) ? 0xFF0000 : 0xA00000;
return 0xFFFFFF;
}
private: private:
const int m_client_fd { -1 }; static constexpr int32_t m_title_bar_height { 20 };
uint32_t* m_fb_addr { nullptr };
Rectangle m_area { 0, 0, 0, 0 }; const int m_client_fd { -1 };
bool m_deleted { false }; uint32_t* m_fb_addr { nullptr };
Rectangle m_client_area { 0, 0, 0, 0 };
bool m_deleted { false };
}; };

View File

@ -69,7 +69,7 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
BAN::RefPtr<Window> target_window; BAN::RefPtr<Window> target_window;
for (size_t i = m_windows_ordered.size(); i > 0; i--) for (size_t i = m_windows_ordered.size(); i > 0; i--)
{ {
if (m_windows_ordered[i - 1]->area().contains(m_cursor)) if (m_windows_ordered[i - 1]->full_area().contains(m_cursor))
{ {
target_window = m_windows_ordered[i - 1]; target_window = m_windows_ordered[i - 1];
break; break;
@ -82,28 +82,26 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
set_focused_window(target_window); set_focused_window(target_window);
// Handle window moving when mod key is held // Handle window moving when mod key is held or mouse press on title bar
if (m_is_mod_key_held && event.pressed && event.button == LibInput::MouseButton::Left && !m_is_moving_window) if (event.pressed && event.button == LibInput::MouseButton::Left && !m_is_moving_window && (target_window->title_bar_area().contains(m_cursor) || m_is_mod_key_held))
m_is_moving_window = true; m_is_moving_window = true;
else if (m_is_moving_window && !event.pressed) else if (m_is_moving_window && !event.pressed)
m_is_moving_window = false; m_is_moving_window = false;
else else if (target_window->client_area().contains(m_cursor))
{ {
// NOTE: we always have target window if code reaches here // NOTE: we always have target window if code reaches here
LibGUI::EventPacket packet; LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseButtonEvent; packet.type = LibGUI::EventPacket::Type::MouseButtonEvent;
packet.mouse_button_event.button = event.button; packet.mouse_button_event.button = event.button;
packet.mouse_button_event.pressed = event.pressed; packet.mouse_button_event.pressed = event.pressed;
packet.mouse_button_event.x = m_cursor.x - m_focused_window->x(); packet.mouse_button_event.x = m_cursor.x - m_focused_window->client_x();
packet.mouse_button_event.y = m_cursor.y - m_focused_window->y(); packet.mouse_button_event.y = m_cursor.y - m_focused_window->client_y();
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0); send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
} }
} }
void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event) void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
{ {
Rectangle old_cursor { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height };
const int32_t new_x = BAN::Math::clamp(m_cursor.x + event.rel_x, 0, m_framebuffer.width); const int32_t new_x = BAN::Math::clamp(m_cursor.x + event.rel_x, 0, m_framebuffer.width);
const int32_t new_y = BAN::Math::clamp(m_cursor.y - event.rel_y, 0, m_framebuffer.height); const int32_t new_y = BAN::Math::clamp(m_cursor.y - event.rel_y, 0, m_framebuffer.height);
@ -112,22 +110,32 @@ void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
if (event.rel_x == 0 && event.rel_y == 0) if (event.rel_x == 0 && event.rel_y == 0)
return; return;
auto old_cursor = cursor_area();
m_cursor.x = new_x; m_cursor.x = new_x;
m_cursor.y = new_y; m_cursor.y = new_y;
auto new_cursor = cursor_area();
// TODO: Really no need to loop over every window
for (auto& window : m_windows_ordered)
{
auto title_bar = window->title_bar_area();
if (title_bar.get_overlap(old_cursor).has_value() || title_bar.get_overlap(new_cursor).has_value())
invalidate(title_bar);
}
Rectangle new_cursor { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height };
invalidate(old_cursor.get_bounding_box(old_cursor)); invalidate(old_cursor.get_bounding_box(old_cursor));
invalidate(new_cursor.get_bounding_box(old_cursor)); invalidate(new_cursor.get_bounding_box(old_cursor));
if (m_is_moving_window) if (m_is_moving_window)
{ {
auto old_window = m_focused_window->area(); auto old_window = m_focused_window->full_area();
m_focused_window->set_position({ m_focused_window->set_position({
m_focused_window->x() + event.rel_x, m_focused_window->client_x() + event.rel_x,
m_focused_window->y() + event.rel_y, m_focused_window->client_y() + event.rel_y,
}); });
auto new_window = m_focused_window->full_area();
invalidate(old_window); invalidate(old_window);
invalidate(m_focused_window->area()); invalidate(new_window);
return; return;
} }
@ -135,8 +143,8 @@ void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
{ {
LibGUI::EventPacket packet; LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseMoveEvent; packet.type = LibGUI::EventPacket::Type::MouseMoveEvent;
packet.mouse_move_event.x = m_cursor.x - m_focused_window->x(); packet.mouse_move_event.x = m_cursor.x - m_focused_window->client_x();
packet.mouse_move_event.y = m_cursor.y - m_focused_window->y(); packet.mouse_move_event.y = m_cursor.y - m_focused_window->client_y();
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0); send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
} }
} }
@ -164,7 +172,7 @@ void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
m_focused_window = window; m_focused_window = window;
m_windows_ordered.remove(i - 1); m_windows_ordered.remove(i - 1);
MUST(m_windows_ordered.push_back(window)); MUST(m_windows_ordered.push_back(window));
invalidate(window->area()); invalidate(window->full_area());
break; break;
} }
} }
@ -184,23 +192,41 @@ void WindowServer::invalidate(Rectangle area)
{ {
auto& window = *pwindow; auto& window = *pwindow;
auto overlap = window.area().get_overlap(area); // window title bar
if (!overlap.has_value()) if (auto overlap = window.title_bar_area().get_overlap(area); overlap.has_value())
continue; {
for (int32_t y_off = 0; y_off < overlap->height; y_off++)
{
for (int32_t x_off = 0; x_off < overlap->width; x_off++)
{
uint32_t pixel = window.title_bar_pixel(
overlap->x + x_off,
overlap->y + y_off,
m_cursor
);
m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x + x_off] = pixel;
}
}
}
const int32_t src_x = overlap->x - window.x(); // window client area
const int32_t src_y = overlap->y - window.y(); if (auto overlap = window.client_area().get_overlap(area); overlap.has_value())
for (int32_t y_off = 0; y_off < overlap->height; y_off++) {
memcpy( const int32_t src_x = overlap->x - window.client_x();
&m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x], const int32_t src_y = overlap->y - window.client_y();
&window.framebuffer()[(src_y + y_off) * window.width() + src_x], for (int32_t y_off = 0; y_off < overlap->height; y_off++)
overlap->width * 4 {
); memcpy(
&m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x],
&window.framebuffer()[(src_y + y_off) * window.client_width() + src_x],
overlap->width * 4
);
}
}
} }
Rectangle cursor { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height }; auto cursor = cursor_area();
auto overlap = cursor.get_overlap(area); if (auto overlap = cursor.get_overlap(area); overlap.has_value())
if (overlap.has_value())
{ {
for (int32_t dy = overlap->y - cursor.y; dy < overlap->height; dy++) for (int32_t dy = overlap->y - cursor.y; dy < overlap->height; dy++)
{ {
@ -222,3 +248,8 @@ void WindowServer::invalidate(Rectangle area)
mmap_start &= ~(uintptr_t)0xFFF; mmap_start &= ~(uintptr_t)0xFFF;
msync(reinterpret_cast<void*>(mmap_start), mmap_end - mmap_start, MS_SYNC); msync(reinterpret_cast<void*>(mmap_start), mmap_end - mmap_start, MS_SYNC);
} }
Rectangle WindowServer::cursor_area() const
{
return { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height };
}

View File

@ -32,6 +32,8 @@ public:
void set_focused_window(BAN::RefPtr<Window> window); void set_focused_window(BAN::RefPtr<Window> window);
void invalidate(Rectangle area); void invalidate(Rectangle area);
Rectangle cursor_area() const;
private: private:
Framebuffer& m_framebuffer; Framebuffer& m_framebuffer;
BAN::Vector<BAN::RefPtr<Window>> m_windows_ordered; BAN::Vector<BAN::RefPtr<Window>> m_windows_ordered;

View File

@ -228,9 +228,10 @@ int main()
static_cast<int32_t>(packet.create.height) static_cast<int32_t>(packet.create.height)
}, reinterpret_cast<uint32_t*>(smo_address)); }, reinterpret_cast<uint32_t*>(smo_address));
window.set_position({ window.set_position({
static_cast<int32_t>(window.width() / 2), static_cast<int32_t>((framebuffer.width - window.client_width()) / 2),
static_cast<int32_t>(window.height() / 2) static_cast<int32_t>((framebuffer.height - window.client_height()) / 2)
}); });
window_server.invalidate(window.full_area());
break; break;
} }
@ -241,15 +242,21 @@ int main()
dwarnln("Invalid Invalidate packet size"); dwarnln("Invalid Invalidate packet size");
break; break;
} }
if (packet.invalidate.x + packet.invalidate.width > window.width() || packet.invalidate.y + packet.invalidate.height > window.height())
if (packet.invalidate.width == 0 || packet.invalidate.height == 0)
break;
const int32_t br_x = packet.invalidate.x + packet.invalidate.width - 1;
const int32_t br_y = packet.invalidate.y + packet.invalidate.height - 1;
if (!window.client_size().contains({ br_x, br_y }))
{ {
dwarnln("Invalid Invalidate packet parameters"); dwarnln("Invalid Invalidate packet parameters");
break; break;
} }
window_server.invalidate({ window_server.invalidate({
window.x() + static_cast<int32_t>(packet.invalidate.x), window.client_x() + static_cast<int32_t>(packet.invalidate.x),
window.y() + static_cast<int32_t>(packet.invalidate.y), window.client_y() + static_cast<int32_t>(packet.invalidate.y),
static_cast<int32_t>(packet.invalidate.width), static_cast<int32_t>(packet.invalidate.width),
static_cast<int32_t>(packet.invalidate.height), static_cast<int32_t>(packet.invalidate.height),
}); });