WindowServer: Add title bars and clean up code

This commit is contained in:
Bananymous 2024-05-31 03:02:58 +03:00
parent 84b3289a2a
commit 011a5f57e1
5 changed files with 129 additions and 49 deletions

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:
static constexpr int32_t m_title_bar_height { 20 };
const int m_client_fd { -1 }; const int m_client_fd { -1 };
uint32_t* m_fb_addr { nullptr }; uint32_t* m_fb_addr { nullptr };
Rectangle m_area { 0, 0, 0, 0 }; Rectangle m_client_area { 0, 0, 0, 0 };
bool m_deleted { false }; 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; {
const int32_t src_x = overlap->x - window.x();
const int32_t src_y = overlap->y - window.y();
for (int32_t y_off = 0; y_off < overlap->height; y_off++) 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;
}
}
}
// window client area
if (auto overlap = window.client_area().get_overlap(area); overlap.has_value())
{
const int32_t src_x = overlap->x - window.client_x();
const int32_t src_y = overlap->y - window.client_y();
for (int32_t y_off = 0; y_off < overlap->height; y_off++)
{
memcpy( memcpy(
&m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x], &m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x],
&window.framebuffer()[(src_y + y_off) * window.width() + src_x], &window.framebuffer()[(src_y + y_off) * window.client_width() + src_x],
overlap->width * 4 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),
}); });