124 lines
3.5 KiB
C++
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);
|
|
}
|
|
}
|