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,
};
}
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)
{
m_area.x = position.x;
m_area.y = position.y;
m_client_area.x = position.x;
m_client_area.y = position.y;
}
void set_size(Position size, uint32_t* fb_addr)
{
m_area.width = size.x;
m_area.height = size.y;
m_client_area.width = size.x;
m_client_area.height = size.y;
m_fb_addr = fb_addr;
}
@ -29,17 +29,51 @@ public:
int client_fd() const { return m_client_fd; }
int32_t x() const { return m_area.x; }
int32_t y() const { return m_area.y; }
uint32_t width() const { return m_area.width; }
uint32_t height() const { return m_area.height; }
Rectangle size() const { return { 0, 0, m_area.width, m_area.height }; }
const Rectangle& area() const { return m_area; }
int32_t client_x() const { return m_client_area.x; }
int32_t client_y() const { return m_client_area.y; }
int32_t client_width() const { return m_client_area.width; }
int32_t client_height() const { return m_client_area.height; }
Rectangle client_size() const { return { 0, 0, client_width(), client_height() }; }
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; }
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:
const int m_client_fd { -1 };
uint32_t* m_fb_addr { nullptr };
Rectangle m_area { 0, 0, 0, 0 };
bool m_deleted { false };
static constexpr int32_t m_title_bar_height { 20 };
const int m_client_fd { -1 };
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;
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];
break;
@ -82,28 +82,26 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
set_focused_window(target_window);
// Handle window moving when mod key is held
if (m_is_mod_key_held && event.pressed && event.button == LibInput::MouseButton::Left && !m_is_moving_window)
// Handle window moving when mod key is held or mouse press on title bar
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;
else if (m_is_moving_window && !event.pressed)
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
LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseButtonEvent;
packet.mouse_button_event.button = event.button;
packet.mouse_button_event.pressed = event.pressed;
packet.mouse_button_event.x = m_cursor.x - m_focused_window->x();
packet.mouse_button_event.y = m_cursor.y - m_focused_window->y();
packet.mouse_button_event.x = m_cursor.x - m_focused_window->client_x();
packet.mouse_button_event.y = m_cursor.y - m_focused_window->client_y();
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
}
}
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_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)
return;
auto old_cursor = cursor_area();
m_cursor.x = new_x;
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(new_cursor.get_bounding_box(old_cursor));
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->x() + event.rel_x,
m_focused_window->y() + event.rel_y,
m_focused_window->client_x() + event.rel_x,
m_focused_window->client_y() + event.rel_y,
});
auto new_window = m_focused_window->full_area();
invalidate(old_window);
invalidate(m_focused_window->area());
invalidate(new_window);
return;
}
@ -135,8 +143,8 @@ void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
{
LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseMoveEvent;
packet.mouse_move_event.x = m_cursor.x - m_focused_window->x();
packet.mouse_move_event.y = m_cursor.y - m_focused_window->y();
packet.mouse_move_event.x = m_cursor.x - m_focused_window->client_x();
packet.mouse_move_event.y = m_cursor.y - m_focused_window->client_y();
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_windows_ordered.remove(i - 1);
MUST(m_windows_ordered.push_back(window));
invalidate(window->area());
invalidate(window->full_area());
break;
}
}
@ -184,23 +192,41 @@ void WindowServer::invalidate(Rectangle area)
{
auto& window = *pwindow;
auto overlap = window.area().get_overlap(area);
if (!overlap.has_value())
continue;
// window title bar
if (auto overlap = window.title_bar_area().get_overlap(area); overlap.has_value())
{
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();
const int32_t src_y = overlap->y - window.y();
for (int32_t y_off = 0; y_off < overlap->height; y_off++)
memcpy(
&m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x],
&window.framebuffer()[(src_y + y_off) * window.width() + src_x],
overlap->width * 4
);
// 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(
&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 overlap = cursor.get_overlap(area);
if (overlap.has_value())
auto cursor = cursor_area();
if (auto overlap = cursor.get_overlap(area); overlap.has_value())
{
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;
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 invalidate(Rectangle area);
Rectangle cursor_area() const;
private:
Framebuffer& m_framebuffer;
BAN::Vector<BAN::RefPtr<Window>> m_windows_ordered;

View File

@ -228,9 +228,10 @@ int main()
static_cast<int32_t>(packet.create.height)
}, reinterpret_cast<uint32_t*>(smo_address));
window.set_position({
static_cast<int32_t>(window.width() / 2),
static_cast<int32_t>(window.height() / 2)
static_cast<int32_t>((framebuffer.width - window.client_width()) / 2),
static_cast<int32_t>((framebuffer.height - window.client_height()) / 2)
});
window_server.invalidate(window.full_area());
break;
}
@ -241,15 +242,21 @@ int main()
dwarnln("Invalid Invalidate packet size");
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");
break;
}
window_server.invalidate({
window.x() + static_cast<int32_t>(packet.invalidate.x),
window.y() + static_cast<int32_t>(packet.invalidate.y),
window.client_x() + static_cast<int32_t>(packet.invalidate.x),
window.client_y() + static_cast<int32_t>(packet.invalidate.y),
static_cast<int32_t>(packet.invalidate.width),
static_cast<int32_t>(packet.invalidate.height),
});