WindowServer: Add title bars and clean up code
This commit is contained in:
parent
84b3289a2a
commit
011a5f57e1
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue