Luna/libui/src/Window.cpp

124 lines
3.5 KiB
C++

/**
* @file Window.cpp
* @author apio (cloudapio.eu)
* @brief UI windows.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <luna/String.h>
#include <os/SharedMemory.h>
#include <sys/mman.h>
#include <ui/App.h>
#include <ui/Window.h>
#include <ui/ipc/Server.h>
namespace ui
{
Result<Window*> Window::create(Rect rect, bool decorated)
{
auto window = TRY(make_owned<Window>());
ui::CreateWindowRequest request;
request.rect = rect;
request.decorated = decorated;
auto response = TRY(os::IPC::send_sync<ui::CreateWindowResponse>(App::the().client(), request));
auto path = COPY_IPC_STRING(response.shm_path);
u32* pixels = (u32*)TRY(os::SharedMemory::adopt(path.view(), rect.height * rect.width * 4));
window->m_canvas = ui::Canvas { rect.width, rect.height, rect.width, (u8*)pixels };
window->m_id = response.window;
Window* p = window.ptr();
App::the().register_window(move(window), {});
return p;
}
Window::~Window()
{
if (m_canvas.ptr) munmap(m_canvas.ptr, ((usize)m_canvas.width) * ((usize)m_canvas.height) * 4);
}
void Window::set_title(StringView title)
{
ui::SetWindowTitleRequest request;
request.window = m_id;
SET_IPC_STRING(request.title, title.chars());
os::IPC::send_async(App::the().client(), request);
}
void Window::update()
{
ui::InvalidateRequest request;
request.window = m_id;
os::IPC::send_async(App::the().client(), request);
}
void Window::close()
{
App& app = App::the();
ui::CloseWindowRequest request;
request.window = m_id;
os::IPC::send_async(app.client(), request);
if (this == app.main_window()) app.set_should_close(true);
app.unregister_window(this, {});
}
Result<void> Window::draw()
{
if (m_background.has_value()) m_canvas.fill(*m_background);
if (m_main_widget) TRY(m_main_widget->draw(m_canvas));
update();
return {};
}
Result<ui::EventResult> Window::handle_mouse_leave()
{
if (!m_main_widget) return ui::EventResult::DidNotHandle;
return m_main_widget->handle_mouse_leave();
}
Result<ui::EventResult> Window::handle_mouse_move(ui::Point position)
{
if (!m_main_widget) return ui::EventResult::DidNotHandle;
return m_main_widget->handle_mouse_move(position);
}
Result<ui::EventResult> Window::handle_mouse_buttons(ui::Point position, int buttons)
{
if (!m_main_widget) return ui::EventResult::DidNotHandle;
auto result = ui::EventResult::DidNotHandle;
if (buttons)
{
auto rc = TRY(m_main_widget->handle_mouse_down(position, buttons));
if (rc == ui::EventResult::DidHandle) result = rc;
}
if (m_old_mouse_buttons.has_value())
{
int old_buttons = m_old_mouse_buttons.value();
int diff = old_buttons & ~buttons;
if (diff)
{
auto rc = TRY(m_main_widget->handle_mouse_up(position, diff));
if (rc == ui::EventResult::DidHandle) result = rc;
}
}
m_old_mouse_buttons = buttons;
return result;
}
Result<ui::EventResult> Window::handle_key_event(const ui::KeyEventRequest& request)
{
if (!m_main_widget) return ui::EventResult::DidNotHandle;
return m_main_widget->handle_key_event(request);
}
}