Compare commits

..

No commits in common. "bda2c663dae94c82ce3f3b098e50c233d2782a20" and "cf21eb4b39af7ed63c96c325506506f5532a26a7" have entirely different histories.

11 changed files with 142 additions and 424 deletions

View File

@ -40,7 +40,7 @@ namespace Kernel
bool MemoryRegion::overlaps(vaddr_t address, size_t size) const bool MemoryRegion::overlaps(vaddr_t address, size_t size) const
{ {
if (address + size <= m_vaddr) if (address + size < m_vaddr)
return false; return false;
if (address >= m_vaddr + m_size) if (address >= m_vaddr + m_size)
return false; return false;

View File

@ -1,5 +1,3 @@
#include <BAN/Debug.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
@ -8,8 +6,6 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
#define DEBUG_MALLOC 0
static consteval size_t log_size_t(size_t value, size_t base) static consteval size_t log_size_t(size_t value, size_t base)
{ {
size_t result = 0; size_t result = 0;
@ -178,8 +174,6 @@ static malloc_pool_t& pool_from_node(malloc_node_t* node)
void* malloc(size_t size) void* malloc(size_t size)
{ {
dprintln_if(DEBUG_MALLOC, "malloc({})", size);
// align size to s_malloc_default_align boundary // align size to s_malloc_default_align boundary
if (size_t ret = size % s_malloc_default_align) if (size_t ret = size % s_malloc_default_align)
size += s_malloc_default_align - ret; size += s_malloc_default_align - ret;
@ -213,8 +207,6 @@ void* malloc(size_t size)
void* realloc(void* ptr, size_t size) void* realloc(void* ptr, size_t size)
{ {
dprintln_if(DEBUG_MALLOC, "realloc({}, {})", ptr, size);
if (ptr == nullptr) if (ptr == nullptr)
return malloc(size); return malloc(size);
@ -245,8 +237,6 @@ void* realloc(void* ptr, size_t size)
void free(void* ptr) void free(void* ptr)
{ {
dprintln_if(DEBUG_MALLOC, "free({})", ptr);
if (ptr == nullptr) if (ptr == nullptr)
return; return;
@ -275,8 +265,6 @@ void free(void* ptr)
void* calloc(size_t nmemb, size_t size) void* calloc(size_t nmemb, size_t size)
{ {
dprintln_if(DEBUG_MALLOC, "calloc({}, {})", nmemb, size);
size_t total = nmemb * size; size_t total = nmemb * size;
if (size != 0 && total / size != nmemb) if (size != 0 && total / size != nmemb)
{ {

View File

@ -59,7 +59,8 @@ namespace LibGUI
Window::~Window() Window::~Window()
{ {
cleanup(); munmap(m_framebuffer_smo, m_width * m_height * 4);
close(m_server_fd);
} }
BAN::ErrorOr<BAN::UniqPtr<Window>> Window::create(uint32_t width, uint32_t height, BAN::StringView title) BAN::ErrorOr<BAN::UniqPtr<Window>> Window::create(uint32_t width, uint32_t height, BAN::StringView title)
@ -101,13 +102,27 @@ namespace LibGUI
TRY(create_packet.title.append(title)); TRY(create_packet.title.append(title));
TRY(create_packet.send_serialized(server_fd)); TRY(create_packet.send_serialized(server_fd));
auto window = TRY(BAN::UniqPtr<Window>::create(server_fd)); const auto [response_type, response_data ] = TRY(recv_packet(server_fd));
if (response_type != PacketType::WindowCreateResponse)
return BAN::Error::from_literal("Server responded with invalid packet");
bool resized = false; const auto create_response = TRY(WindowPacket::WindowCreateResponse::deserialize(response_data.span()));
window->set_resize_window_event_callback([&]() { resized = true; }); void* framebuffer_addr = smo_map(create_response.smo_key);
while (!resized) if (framebuffer_addr == nullptr)
window->poll_events(); return BAN::Error::from_errno(errno);
window->set_resize_window_event_callback({}); width = create_response.width;
height = create_response.height;
BAN::Vector<uint32_t> framebuffer;
TRY(framebuffer.resize(width * height, 0xFFFFFFFF));
auto window = TRY(BAN::UniqPtr<Window>::create(
server_fd,
static_cast<uint32_t*>(framebuffer_addr),
BAN::move(framebuffer),
width,
height
));
server_closer.disable(); server_closer.disable();
@ -229,10 +244,10 @@ namespace LibGUI
return true; return true;
} }
void Window::invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height) bool Window::invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height)
{ {
if (!clamp_to_framebuffer(x, y, width, height)) if (!clamp_to_framebuffer(x, y, width, height))
return; return true;
for (uint32_t i = 0; i < height; i++) for (uint32_t i = 0; i < height; i++)
memcpy(&m_framebuffer_smo[(y + i) * m_width + x], &m_framebuffer[(y + i) * m_width + x], width * sizeof(uint32_t)); memcpy(&m_framebuffer_smo[(y + i) * m_width + x], &m_framebuffer[(y + i) * m_width + x], width * sizeof(uint32_t));
@ -244,106 +259,56 @@ namespace LibGUI
packet.height = height; packet.height = height;
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
return on_socket_error(__FUNCTION__); {
dprintln("failed to invalidate window: {}", ret.error());
return false;
} }
void Window::set_mouse_capture(bool captured) return true;
}
bool Window::set_mouse_capture(bool captured)
{ {
WindowPacket::WindowSetMouseCapture packet; WindowPacket::WindowSetMouseCapture packet;
packet.captured = captured; packet.captured = captured;
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
return on_socket_error(__FUNCTION__);
}
void Window::set_fullscreen(bool fullscreen)
{ {
WindowPacket::WindowSetFullscreen packet; dprintln("failed to set mouse capture: {}", ret.error());
packet.fullscreen = fullscreen; return false;
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
return on_socket_error(__FUNCTION__);
} }
void Window::set_position(int32_t x, int32_t y) return true;
}
bool Window::set_position(int32_t x, int32_t y)
{ {
WindowPacket::WindowSetPosition packet; WindowPacket::WindowSetPosition packet;
packet.x = x; packet.x = x;
packet.y = y; packet.y = y;
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
return on_socket_error(__FUNCTION__); {
dprintln("failed to set window position: {}", ret.error());
return false;
} }
void Window::set_attributes(Attributes attributes) return true;
}
bool Window::set_attributes(Attributes attributes)
{ {
WindowPacket::WindowSetAttributes packet; WindowPacket::WindowSetAttributes packet;
packet.attributes = attributes; packet.attributes = attributes;
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
return on_socket_error(__FUNCTION__); {
dprintln("failed to set window attributes: {}", ret.error());
return false;
}
m_attributes = attributes; m_attributes = attributes;
} return true;
void Window::request_resize(uint32_t width, uint32_t height)
{
WindowPacket::WindowSetSize packet;
packet.width = width;
packet.height = height;
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
return on_socket_error(__FUNCTION__);
}
void Window::on_socket_error(BAN::StringView function)
{
if (m_handling_socket_error)
return;
m_handling_socket_error = true;
dprintln("Socket error while running Window::{}", function);
if (!m_socket_error_callback)
exit(1);
m_socket_error_callback();
cleanup();
}
void Window::cleanup()
{
munmap(m_framebuffer_smo, m_width * m_height * 4);
close(m_server_fd);
}
BAN::ErrorOr<void> Window::handle_resize_event(const EventPacket::ResizeWindowEvent& event)
{
if (m_framebuffer_smo)
munmap(m_framebuffer_smo, m_width * m_height * 4);
m_framebuffer_smo = nullptr;
BAN::Vector<uint32_t> framebuffer;
TRY(framebuffer.resize(event.width * event.height, 0xFFFFFFFF));
void* framebuffer_addr = smo_map(event.smo_key);
if (framebuffer_addr == nullptr)
return BAN::Error::from_errno(errno);
const uint32_t min_x = BAN::Math::min(m_width, event.width);
const uint32_t min_y = BAN::Math::min(m_height, event.height);
for (uint32_t y = 0; y < min_y; y++)
for (uint32_t x = 0; x < min_x; x++)
framebuffer[y * event.width + x] = m_framebuffer[y * m_width + x];
m_framebuffer_smo = static_cast<uint32_t*>(framebuffer_addr);
m_framebuffer = BAN::move(framebuffer);
m_width = event.width;
m_height = event.height;
invalidate();
return {};
} }
#define TRY_OR_BREAK(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) break; e.release_value(); }) #define TRY_OR_BREAK(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) break; e.release_value(); })
@ -363,7 +328,7 @@ namespace LibGUI
auto packet_or_error = recv_packet(m_server_fd); auto packet_or_error = recv_packet(m_server_fd);
if (packet_or_error.is_error()) if (packet_or_error.is_error())
return on_socket_error(__FUNCTION__); break;
const auto [packet_type, packet_data] = packet_or_error.release_value(); const auto [packet_type, packet_data] = packet_or_error.release_value();
switch (packet_type) switch (packet_type)
@ -376,13 +341,6 @@ namespace LibGUI
else else
exit(0); exit(0);
break; break;
case PacketType::ResizeWindowEvent:
{
MUST(handle_resize_event(TRY_OR_BREAK(EventPacket::ResizeWindowEvent::deserialize(packet_data.span()))));
if (m_resize_window_event_callback)
m_resize_window_event_callback();
break;
}
case PacketType::KeyEvent: case PacketType::KeyEvent:
if (m_key_event_callback) if (m_key_event_callback)
m_key_event_callback(TRY_OR_BREAK(EventPacket::KeyEvent::deserialize(packet_data.span())).event); m_key_event_callback(TRY_OR_BREAK(EventPacket::KeyEvent::deserialize(packet_data.span())).event);

View File

@ -163,12 +163,9 @@ namespace LibGUI
WindowSetPosition, WindowSetPosition,
WindowSetAttributes, WindowSetAttributes,
WindowSetMouseCapture, WindowSetMouseCapture,
WindowSetSize,
WindowSetFullscreen,
DestroyWindowEvent, DestroyWindowEvent,
CloseWindowEvent, CloseWindowEvent,
ResizeWindowEvent,
KeyEvent, KeyEvent,
MouseButtonEvent, MouseButtonEvent,
MouseMoveEvent, MouseMoveEvent,
@ -185,6 +182,13 @@ namespace LibGUI
BAN::String, title BAN::String, title
); );
DEFINE_PACKET(
WindowCreateResponse,
uint32_t, width,
uint32_t, height,
long, smo_key
);
DEFINE_PACKET( DEFINE_PACKET(
WindowInvalidate, WindowInvalidate,
uint32_t, x, uint32_t, x,
@ -216,17 +220,6 @@ namespace LibGUI
bool, captured bool, captured
); );
DEFINE_PACKET(
WindowSetSize,
uint32_t, width,
uint32_t, height
);
DEFINE_PACKET(
WindowSetFullscreen,
bool, fullscreen
);
} }
namespace EventPacket namespace EventPacket
@ -240,13 +233,6 @@ namespace LibGUI
CloseWindowEvent CloseWindowEvent
); );
DEFINE_PACKET(
ResizeWindowEvent,
uint32_t, width,
uint32_t, height,
long, smo_key
);
DEFINE_PACKET_EXTRA( DEFINE_PACKET_EXTRA(
KeyEvent, KeyEvent,
using event_t = LibInput::KeyEvent, using event_t = LibInput::KeyEvent,

View File

@ -57,28 +57,21 @@ namespace LibGUI
// fill_color is used when copying data outside of window bounds // fill_color is used when copying data outside of window bounds
void copy_horizontal_slice(int32_t dst_y, int32_t src_y, uint32_t amount, uint32_t fill_color); void copy_horizontal_slice(int32_t dst_y, int32_t src_y, uint32_t amount, uint32_t fill_color);
void invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height); bool invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height);
void invalidate() { return invalidate(0, 0, width(), height()); } bool invalidate() { return invalidate(0, 0, width(), height()); }
void set_mouse_capture(bool captured); bool set_mouse_capture(bool captured);
void set_fullscreen(bool fullscreen);
void set_position(int32_t x, int32_t y); bool set_position(int32_t x, int32_t y);
Attributes get_attributes() const { return m_attributes; } Attributes get_attributes() const { return m_attributes; }
void set_attributes(Attributes attributes); bool set_attributes(Attributes attributes);
// send resize request to window server
// actual resize is only done after resize callback is called
void request_resize(uint32_t width, uint32_t height);
uint32_t width() const { return m_width; } uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; } uint32_t height() const { return m_height; }
void poll_events(); void poll_events();
void set_socket_error_callback(BAN::Function<void()> callback) { m_socket_error_callback = callback; }
void set_close_window_event_callback(BAN::Function<void()> callback) { m_close_window_event_callback = callback; } void set_close_window_event_callback(BAN::Function<void()> callback) { m_close_window_event_callback = callback; }
void set_resize_window_event_callback(BAN::Function<void()> callback) { m_resize_window_event_callback = callback; }
void set_key_event_callback(BAN::Function<void(EventPacket::KeyEvent::event_t)> callback) { m_key_event_callback = callback; } void set_key_event_callback(BAN::Function<void(EventPacket::KeyEvent::event_t)> callback) { m_key_event_callback = callback; }
void set_mouse_button_event_callback(BAN::Function<void(EventPacket::MouseButtonEvent::event_t)> callback) { m_mouse_button_event_callback = callback; } void set_mouse_button_event_callback(BAN::Function<void(EventPacket::MouseButtonEvent::event_t)> callback) { m_mouse_button_event_callback = callback; }
void set_mouse_move_event_callback(BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> callback) { m_mouse_move_event_callback = callback; } void set_mouse_move_event_callback(BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> callback) { m_mouse_move_event_callback = callback; }
@ -87,32 +80,27 @@ namespace LibGUI
int server_fd() const { return m_server_fd; } int server_fd() const { return m_server_fd; }
private: private:
Window(int server_fd) Window(int server_fd, uint32_t* framebuffer_smo, BAN::Vector<uint32_t>&& framebuffer, uint32_t width, uint32_t height)
: m_server_fd(server_fd) : m_server_fd(server_fd)
, m_framebuffer(framebuffer)
, m_framebuffer_smo(framebuffer_smo)
, m_width(width)
, m_height(height)
{ } { }
bool clamp_to_framebuffer(int32_t& x, int32_t& y, uint32_t& width, uint32_t& height) const; bool clamp_to_framebuffer(int32_t& x, int32_t& y, uint32_t& width, uint32_t& height) const;
void on_socket_error(BAN::StringView function);
void cleanup();
BAN::ErrorOr<void> handle_resize_event(const EventPacket::ResizeWindowEvent&);
private: private:
const int m_server_fd; int m_server_fd;
bool m_handling_socket_error { false };
Attributes m_attributes; Attributes m_attributes;
BAN::Vector<uint32_t> m_framebuffer; BAN::Vector<uint32_t> m_framebuffer;
uint32_t* m_framebuffer_smo { nullptr }; uint32_t* m_framebuffer_smo;
uint32_t m_width { 0 }; uint32_t m_width;
uint32_t m_height { 0 }; uint32_t m_height;
BAN::Function<void()> m_socket_error_callback;
BAN::Function<void()> m_close_window_event_callback; BAN::Function<void()> m_close_window_event_callback;
BAN::Function<void()> m_resize_window_event_callback;
BAN::Function<void(EventPacket::KeyEvent::event_t)> m_key_event_callback; BAN::Function<void(EventPacket::KeyEvent::event_t)> m_key_event_callback;
BAN::Function<void(EventPacket::MouseButtonEvent::event_t)> m_mouse_button_event_callback; BAN::Function<void(EventPacket::MouseButtonEvent::event_t)> m_mouse_button_event_callback;
BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> m_mouse_move_event_callback; BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> m_mouse_move_event_callback;

View File

@ -53,7 +53,8 @@ int main()
window->fill_rect(text_x, text_y, text_w, text_h, bg_color); window->fill_rect(text_x, text_y, text_w, text_h, bg_color);
window->draw_text(text, font, text_x, text_y, fg_color); window->draw_text(text, font, text_x, text_y, fg_color);
window->invalidate(text_x, text_y, text_w, text_h); if (!window->invalidate(text_x, text_y, text_w, text_h))
is_running = false;
}; };
while (is_running) while (is_running)

View File

@ -1,7 +1,6 @@
#include "Window.h" #include "Window.h"
#include <BAN/Debug.h> #include <BAN/Debug.h>
#include <BAN/ScopeGuard.h>
#include <LibGUI/Window.h> #include <LibGUI/Window.h>
@ -10,6 +9,20 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
Window::Window(int fd, Rectangle area, long smo_key, BAN::StringView title, const LibFont::Font& font)
: m_client_fd(fd)
, m_client_area(area)
, m_smo_key(smo_key)
{
MUST(m_title.append(title));
prepare_title_bar(font);
m_fb_addr = static_cast<uint32_t*>(smo_map(smo_key));
ASSERT(m_fb_addr);
memset(m_fb_addr, 0xFF, client_width() * client_height() * 4);
}
Window::~Window() Window::~Window()
{ {
munmap(m_fb_addr, client_width() * client_height() * 4); munmap(m_fb_addr, client_width() * client_height() * 4);
@ -20,91 +33,40 @@ Window::~Window()
close(m_client_fd); close(m_client_fd);
} }
BAN::ErrorOr<void> Window::initialize(BAN::StringView title, uint32_t width, uint32_t height) void Window::prepare_title_bar(const LibFont::Font& font)
{ {
m_title.clear(); const size_t title_bar_bytes = title_bar_width() * title_bar_height() * 4;
TRY(m_title.append(title)); uint32_t* title_bar_data = new uint32_t[title_bar_bytes];
TRY(resize(width, height)); ASSERT(title_bar_data);
return {}; for (size_t i = 0; i < title_bar_bytes; i++)
} title_bar_data[i] = 0xFFFFFFFF;
BAN::ErrorOr<void> Window::resize(uint32_t width, uint32_t height)
{
const size_t fb_bytes = width * height * 4;
long smo_key = smo_create(fb_bytes, PROT_READ | PROT_WRITE);
if (smo_key == -1)
return BAN::Error::from_errno(errno);
BAN::ScopeGuard smo_deleter([&]() { smo_delete(smo_key); });
uint32_t* fb_addr = static_cast<uint32_t*>(smo_map(smo_key));
if (fb_addr == nullptr)
return BAN::Error::from_errno(errno);
memset(fb_addr, 0xFF, fb_bytes);
BAN::ScopeGuard smo_unmapper([&]() { munmap(fb_addr, fb_bytes); });
{
const auto old_area = m_client_area;
m_client_area.width = width;
m_client_area.height = height;
auto title_bar_ret = prepare_title_bar();
m_client_area = old_area;
if (title_bar_ret.is_error())
return title_bar_ret.release_error();
}
smo_deleter.disable();
smo_unmapper.disable();
if (m_fb_addr)
munmap(m_fb_addr, client_width() * client_height() * 4);
if (m_smo_key)
smo_delete(m_smo_key);
m_fb_addr = fb_addr;
m_smo_key = smo_key;
m_client_area.width = width;
m_client_area.height = height;
return {};
}
BAN::ErrorOr<void> Window::prepare_title_bar()
{
const uint32_t font_w = m_font.width();
const uint32_t font_h = m_font.height();
const uint32_t font_p = m_font.pitch();
TRY(m_title_bar_data.resize(title_bar_width() * title_bar_height()));
for (auto& pixel : m_title_bar_data)
pixel = 0xFFFFFFFF;
const auto text_area = title_text_area(); const auto text_area = title_text_area();
for (size_t i = 0; i < m_title.size() && (i + 1) * font_w < static_cast<uint32_t>(text_area.width); i++) for (size_t i = 0; i < m_title.size() && (i + 1) * font.width() < static_cast<uint32_t>(text_area.width); i++)
{ {
const auto* glyph = m_font.glyph(m_title[i]); const auto* glyph = font.glyph(m_title[i]);
if (glyph == nullptr) if (glyph == nullptr)
continue; continue;
const int32_t y_off = (font_h < (uint32_t)title_bar_height()) ? (title_bar_height() - font_h) / 2 : 0; const int32_t y_off = (font.height() < (uint32_t)title_bar_height()) ? (title_bar_height() - font.height()) / 2 : 0;
const int32_t x_off = y_off + i * font_w; const int32_t x_off = y_off + i * font.width();
for (int32_t y = 0; (uint32_t)y < font_h; y++) for (int32_t y = 0; (uint32_t)y < font.height(); y++)
{ {
if (y + y_off >= title_bar_height()) if (y + y_off >= title_bar_height())
break; break;
for (int32_t x = 0; (uint32_t)x < font_w; x++) for (int32_t x = 0; (uint32_t)x < font.width(); x++)
{ {
if (x + x_off >= text_area.width) if (x + x_off >= text_area.width)
break; break;
const uint8_t bitmask = 1 << (font_w - x - 1); const uint8_t bitmask = 1 << (font.width() - x - 1);
if (glyph[y * font_p] & bitmask) if (glyph[y * font.pitch()] & bitmask)
m_title_bar_data[(y_off + y) * title_bar_width() + (x_off + x)] = 0xFF000000; title_bar_data[(y_off + y) * title_bar_width() + (x_off + x)] = 0xFF000000;
} }
} }
} }
return {}; if (m_title_bar_data)
delete[] m_title_bar_data;
m_title_bar_data = title_bar_data;
} }

View File

@ -4,7 +4,6 @@
#include <BAN/RefPtr.h> #include <BAN/RefPtr.h>
#include <BAN/String.h> #include <BAN/String.h>
#include <BAN/Vector.h>
#include <LibFont/Font.h> #include <LibFont/Font.h>
#include <LibGUI/Window.h> #include <LibGUI/Window.h>
@ -12,11 +11,7 @@
class Window : public BAN::RefCounted<Window> class Window : public BAN::RefCounted<Window>
{ {
public: public:
Window(int fd, const LibFont::Font& font) Window(int fd, Rectangle area, long smo_key, BAN::StringView title, const LibFont::Font& font);
: m_font(font)
, m_client_fd(fd)
{ }
~Window(); ~Window();
void set_position(Position position) void set_position(Position position)
@ -26,7 +21,6 @@ public:
} }
int client_fd() const { return m_client_fd; } int client_fd() const { return m_client_fd; }
long smo_key() const { return m_smo_key; }
int32_t client_x() const { return m_client_area.x; } int32_t client_x() const { return m_client_area.x; }
int32_t client_y() const { return m_client_area.y; } int32_t client_y() const { return m_client_area.y; }
@ -69,25 +63,19 @@ public:
Circle close_button_area() const { return { title_bar_x() + title_bar_width() - title_bar_height() / 2, title_bar_y() + title_bar_height() / 2, title_bar_height() * 3 / 8 }; } Circle close_button_area() const { return { title_bar_x() + title_bar_width() - title_bar_height() / 2, title_bar_y() + title_bar_height() / 2, title_bar_height() * 3 / 8 }; }
Rectangle title_text_area() const { return { title_bar_x(), title_bar_y(), title_bar_width() - title_bar_height(), title_bar_height() }; } Rectangle title_text_area() const { return { title_bar_x(), title_bar_y(), title_bar_width() - title_bar_height(), title_bar_height() }; }
BAN::ErrorOr<void> initialize(BAN::StringView title, uint32_t width, uint32_t height);
BAN::ErrorOr<void> resize(uint32_t width, uint32_t height);
private: private:
BAN::ErrorOr<void> prepare_title_bar(); void prepare_title_bar(const LibFont::Font& font);
private: private:
static constexpr int32_t m_title_bar_height { 20 }; static constexpr int32_t m_title_bar_height { 20 };
const LibFont::Font& m_font;
const int m_client_fd { -1 }; const int m_client_fd { -1 };
Rectangle m_client_area { 0, 0, 0, 0 }; Rectangle m_client_area { 0, 0, 0, 0 };
long m_smo_key { 0 }; long m_smo_key { 0 };
uint32_t* m_fb_addr { nullptr }; uint32_t* m_fb_addr { nullptr };
uint32_t* m_title_bar_data { nullptr };
BAN::String m_title; BAN::String m_title;
BAN::Vector<uint32_t> m_title_bar_data;
LibGUI::Window::Attributes m_attributes { LibGUI::Window::default_attributes }; LibGUI::Window::Attributes m_attributes { LibGUI::Window::default_attributes };
friend class BAN::RefPtr<Window>; friend class BAN::RefPtr<Window>;

View File

@ -46,7 +46,31 @@ void WindowServer::on_window_create(int fd, const LibGUI::WindowPacket::WindowCr
const uint32_t width = packet.width ? packet.width : m_framebuffer.width; const uint32_t width = packet.width ? packet.width : m_framebuffer.width;
const uint32_t height = packet.height ? packet.height : m_framebuffer.height; const uint32_t height = packet.height ? packet.height : m_framebuffer.height;
auto window_or_error = BAN::RefPtr<Window>::create(fd, m_font); const size_t window_fb_bytes = width * height * 4;
long smo_key = smo_create(window_fb_bytes, PROT_READ | PROT_WRITE);
if (smo_key == -1)
{
dwarnln("smo_create: {}", strerror(errno));
return;
}
BAN::ScopeGuard smo_deleter([smo_key] { smo_delete(smo_key); });
Rectangle window_area {
static_cast<int32_t>((m_framebuffer.width - width) / 2),
static_cast<int32_t>((m_framebuffer.height - height) / 2),
static_cast<int32_t>(width),
static_cast<int32_t>(height)
};
// Window::Window(int fd, Rectangle area, long smo_key, BAN::StringView title, const LibFont::Font& font)
auto window_or_error = (BAN::RefPtr<Window>::create(
fd,
window_area,
smo_key,
packet.title,
m_font
));
if (window_or_error.is_error()) if (window_or_error.is_error())
{ {
dwarnln("could not create window for client: {}", window_or_error.error()); dwarnln("could not create window for client: {}", window_or_error.error());
@ -61,27 +85,17 @@ void WindowServer::on_window_create(int fd, const LibGUI::WindowPacket::WindowCr
} }
BAN::ScopeGuard window_popper([&] { m_client_windows.pop_back(); }); BAN::ScopeGuard window_popper([&] { m_client_windows.pop_back(); });
if (auto ret = window->initialize(packet.title, width, height); ret.is_error()) LibGUI::WindowPacket::WindowCreateResponse response;
{ response.width = width;
dwarnln("could not create window for client: {}", ret.error()); response.height = height;
return; response.smo_key = smo_key;
}
window->set_position({
static_cast<int32_t>((m_framebuffer.width - window->client_width()) / 2),
static_cast<int32_t>((m_framebuffer.height - window->client_height()) / 2),
});
LibGUI::EventPacket::ResizeWindowEvent response;
response.width = window->client_width();
response.height = window->client_height();
response.smo_key = window->smo_key();
if (auto ret = response.send_serialized(fd); ret.is_error()) if (auto ret = response.send_serialized(fd); ret.is_error())
{ {
dwarnln("could not respond to window create request: {}", ret.error()); dwarnln("could not respond to window create request: {}", ret.error());
return; return;
} }
smo_deleter.disable();
window_popper.disable(); window_popper.disable();
set_focused_window(window); set_focused_window(window);
@ -125,9 +139,6 @@ void WindowServer::on_window_invalidate(int fd, const LibGUI::WindowPacket::Wind
void WindowServer::on_window_set_position(int fd, const LibGUI::WindowPacket::WindowSetPosition& packet) void WindowServer::on_window_set_position(int fd, const LibGUI::WindowPacket::WindowSetPosition& packet)
{ {
if (m_is_fullscreen_window && m_focused_window->client_fd() == fd)
return;
BAN::RefPtr<Window> target_window; BAN::RefPtr<Window> target_window;
for (auto& window : m_client_windows) for (auto& window : m_client_windows)
{ {
@ -221,86 +232,6 @@ void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacke
invalidate(cursor_area()); invalidate(cursor_area());
} }
void WindowServer::on_window_set_size(int fd, const LibGUI::WindowPacket::WindowSetSize& packet)
{
BAN::RefPtr<Window> target_window;
for (auto& window : m_client_windows)
{
if (window->client_fd() != fd)
continue;
target_window = window;
break;
}
if (!target_window)
{
dwarnln("client tried to set window size while not owning a window");
return;
}
const auto old_area = target_window->full_area();
const uint32_t width = packet.width ? packet.width : m_framebuffer.width;
const uint32_t height = packet.height ? packet.height : m_framebuffer.height;
if (auto ret = target_window->resize(width, height); ret.is_error())
{
dwarnln("could not resize client window {}", ret.error());
return;
}
LibGUI::EventPacket::ResizeWindowEvent response;
response.width = target_window->client_width();
response.height = target_window->client_height();
response.smo_key = target_window->smo_key();
if (auto ret = response.send_serialized(fd); ret.is_error())
{
dwarnln("could not respond to window resize request: {}", ret.error());
return;
}
invalidate(target_window->full_area().get_bounding_box(old_area));
}
void WindowServer::on_window_set_fullscreen(int fd, const LibGUI::WindowPacket::WindowSetFullscreen& packet)
{
if (m_is_fullscreen_window)
{
ASSERT(m_focused_window);
if (m_focused_window->client_fd() != fd)
dwarnln("client tried to set fullscreen window size while another window is already fullscreen");
else if (!packet.fullscreen)
{
m_is_fullscreen_window = false;
invalidate(m_framebuffer.area());
}
return;
}
if (!packet.fullscreen)
return;
BAN::RefPtr<Window> target_window;
for (auto& window : m_client_windows)
{
if (window->client_fd() != fd)
continue;
target_window = window;
break;
}
if (!target_window)
{
dwarnln("client tried to set window size while not owning a window");
return;
}
m_is_fullscreen_window = true;
set_focused_window(target_window);
target_window->set_position({ 0, 0 });
invalidate(m_framebuffer.area());
}
void WindowServer::on_key_event(LibInput::KeyEvent event) void WindowServer::on_key_event(LibInput::KeyEvent event)
{ {
// Mod key is not passed to clients // Mod key is not passed to clients
@ -343,7 +274,7 @@ void WindowServer::on_key_event(LibInput::KeyEvent event)
} }
// Toggle window bounce with F2 // Toggle window bounce with F2
if (!m_is_fullscreen_window && event.pressed() && event.key == LibInput::Key::F2) if (event.pressed() && event.key == LibInput::Key::F2)
m_is_bouncing_window = !m_is_bouncing_window; m_is_bouncing_window = !m_is_bouncing_window;
if (m_focused_window) if (m_focused_window)
@ -418,9 +349,6 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
return; return;
} }
} }
if (m_is_fullscreen_window)
m_is_moving_window = false;
} }
void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event) void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
@ -542,47 +470,6 @@ static uint32_t alpha_blend(uint32_t color_a, uint32_t color_b)
void WindowServer::invalidate(Rectangle area) void WindowServer::invalidate(Rectangle area)
{ {
if (m_is_fullscreen_window)
{
ASSERT(m_focused_window);
auto focused_overlap = area.get_overlap(m_focused_window->client_area());
if (!focused_overlap.has_value())
return;
area = focused_overlap.release_value();
if (m_focused_window->client_area() == m_framebuffer.area())
{
for (int32_t y = area.y; y < area.y + area.height; y++)
for (int32_t x = area.x; x < area.x + area.width; x++)
m_framebuffer.mmap[y * m_framebuffer.width + x] = m_focused_window->framebuffer()[y * m_focused_window->client_width() + x];
mark_pending_sync(area);
}
else
{
const Rectangle dst_area {
.x = area.x * m_framebuffer.width / m_focused_window->client_width(),
.y = area.y * m_framebuffer.height / m_focused_window->client_height(),
.width = BAN::Math::div_round_up(area.width * m_framebuffer.width, m_focused_window->client_width()),
.height = BAN::Math::div_round_up(area.height * m_framebuffer.height, m_focused_window->client_height())
};
for (int32_t dst_y = dst_area.y; dst_y < dst_area.y + dst_area.height; dst_y++)
{
for (int32_t dst_x = dst_area.x; dst_x < dst_area.x + dst_area.width; dst_x++)
{
const int32_t src_x = dst_x * m_focused_window->client_width() / m_framebuffer.width;
const int32_t src_y = dst_y * m_focused_window->client_height() / m_framebuffer.height;
m_framebuffer.mmap[dst_y * m_framebuffer.width + dst_x] = m_focused_window->framebuffer()[src_y * m_focused_window->client_width() + src_x];
}
}
mark_pending_sync(dst_area);
}
return;
}
auto fb_overlap = area.get_overlap(m_framebuffer.area()); auto fb_overlap = area.get_overlap(m_framebuffer.area());
if (!fb_overlap.has_value()) if (!fb_overlap.has_value())
return; return;
@ -799,13 +686,6 @@ void WindowServer::invalidate(Rectangle area)
} }
} }
mark_pending_sync(area);
}
void WindowServer::mark_pending_sync(Rectangle area)
{
// FIXME: this marks too many pages
const uintptr_t mmap_start = reinterpret_cast<uintptr_t>(m_framebuffer.mmap) + area.y * m_framebuffer.width * 4; const uintptr_t mmap_start = reinterpret_cast<uintptr_t>(m_framebuffer.mmap) + area.y * m_framebuffer.width * 4;
const uintptr_t mmap_end = mmap_start + (area.height + 1) * m_framebuffer.width * 4; const uintptr_t mmap_end = mmap_start + (area.height + 1) * m_framebuffer.width * 4;
@ -894,12 +774,6 @@ void WindowServer::remove_client_fd(int fd)
return; return;
m_client_data.remove(it); m_client_data.remove(it);
if (m_is_fullscreen_window && m_focused_window->client_fd() == fd)
{
m_is_fullscreen_window = false;
invalidate(m_framebuffer.area());
}
for (size_t i = 0; i < m_client_windows.size(); i++) for (size_t i = 0; i < m_client_windows.size(); i++)
{ {
auto window = m_client_windows[i]; auto window = m_client_windows[i];

View File

@ -35,8 +35,6 @@ public:
void on_window_set_position(int fd, const LibGUI::WindowPacket::WindowSetPosition&); void on_window_set_position(int fd, const LibGUI::WindowPacket::WindowSetPosition&);
void on_window_set_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes&); void on_window_set_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes&);
void on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture&); void on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture&);
void on_window_set_size(int fd, const LibGUI::WindowPacket::WindowSetSize&);
void on_window_set_fullscreen(int fd, const LibGUI::WindowPacket::WindowSetFullscreen&);
void on_key_event(LibInput::KeyEvent event); void on_key_event(LibInput::KeyEvent event);
void on_mouse_button(LibInput::MouseButtonEvent event); void on_mouse_button(LibInput::MouseButtonEvent event);
@ -56,9 +54,6 @@ public:
bool is_stopped() const { return m_is_stopped; } bool is_stopped() const { return m_is_stopped; }
private:
void mark_pending_sync(Rectangle area);
private: private:
Framebuffer& m_framebuffer; Framebuffer& m_framebuffer;
BAN::Vector<BAN::RefPtr<Window>> m_client_windows; BAN::Vector<BAN::RefPtr<Window>> m_client_windows;
@ -73,7 +68,6 @@ private:
bool m_is_mod_key_held { false }; bool m_is_mod_key_held { false };
bool m_is_moving_window { false }; bool m_is_moving_window { false };
bool m_is_fullscreen_window { false };
BAN::RefPtr<Window> m_focused_window; BAN::RefPtr<Window> m_focused_window;
Position m_cursor; Position m_cursor;

View File

@ -165,19 +165,6 @@ int main()
atexit([]() { tty_ctrl(STDIN_FILENO, TTY_CMD_SET, TTY_FLAG_ENABLE_INPUT); }); atexit([]() { tty_ctrl(STDIN_FILENO, TTY_CMD_SET, TTY_FLAG_ENABLE_INPUT); });
constexpr int non_terminating_signals[] {
SIGCHLD,
SIGCONT,
SIGSTOP,
SIGTSTP,
SIGTTIN,
SIGTTOU,
};
for (int sig = _SIGMIN; sig <= _SIGMAX; sig++)
signal(sig, exit);
for (int sig : non_terminating_signals)
signal(sig, SIG_DFL);
MUST(LibInput::KeyboardLayout::initialize()); MUST(LibInput::KeyboardLayout::initialize());
MUST(LibInput::KeyboardLayout::get().load_from_file("/usr/share/keymaps/us.keymap"_sv)); MUST(LibInput::KeyboardLayout::get().load_from_file("/usr/share/keymaps/us.keymap"_sv));
@ -367,14 +354,6 @@ int main()
if (auto ret = LibGUI::WindowPacket::WindowSetMouseCapture::deserialize(client_data.packet_buffer.span()); !ret.is_error()) if (auto ret = LibGUI::WindowPacket::WindowSetMouseCapture::deserialize(client_data.packet_buffer.span()); !ret.is_error())
window_server.on_window_set_mouse_capture(fd, ret.release_value()); window_server.on_window_set_mouse_capture(fd, ret.release_value());
break; break;
case LibGUI::PacketType::WindowSetSize:
if (auto ret = LibGUI::WindowPacket::WindowSetSize::deserialize(client_data.packet_buffer.span()); !ret.is_error())
window_server.on_window_set_size(fd, ret.release_value());
break;
case LibGUI::PacketType::WindowSetFullscreen:
if (auto ret = LibGUI::WindowPacket::WindowSetFullscreen::deserialize(client_data.packet_buffer.span()); !ret.is_error())
window_server.on_window_set_fullscreen(fd, ret.release_value());
break;
default: default:
dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data())); dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data()));
} }