light/modules/window/src/linux/window.cpp

228 lines
5.8 KiB
C++
Raw Normal View History

2025-07-05 13:28:41 +03:30
#include <GLFW/glfw3.h>
#include <input/events/char.hpp>
#include <input/events/event.hpp>
#include <input/events/keyboard.hpp>
#include <input/events/mouse.hpp>
#include <input/events/window.hpp>
2025-07-11 01:42:56 +03:30
#include <window/linux/window.hpp>
2025-07-05 13:28:41 +03:30
2025-07-11 00:05:48 +03:30
namespace lt {
2025-07-05 13:28:41 +03:30
2025-07-11 01:42:56 +03:30
Window::~Window()
= default;
2025-07-11 01:42:56 +03:30
auto Window::create(const std::function<void(Event &)> &callback) -> Scope<Window>
2025-07-05 13:28:41 +03:30
{
return create_scope<lWindow>(callback);
2025-07-05 13:28:41 +03:30
}
lWindow::lWindow(std::function<void(Event &)> callback)
: m_handle(glfwCreateWindow(1u, 1u, "", nullptr, nullptr)), m_event_callback(std::move(std::move(callback)))
2025-07-05 13:28:41 +03:30
{
// init glfw
2025-07-11 02:12:55 +03:30
ensure(glfwInit(), "lWindow::lWindow: failed to initialize 'glfw'");
2025-07-05 13:28:41 +03:30
// create window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
2025-07-11 02:12:55 +03:30
ensure(m_handle, "lWindow::lWindow: failed to create 'GLFWwindow'");
2025-07-05 13:28:41 +03:30
glfwSetWindowUserPointer(m_handle, &m_event_callback);
bind_glfw_events();
2025-07-05 13:28:41 +03:30
}
lWindow::~lWindow()
{
glfwDestroyWindow(m_handle);
2025-07-05 13:28:41 +03:30
}
void lWindow::poll_events()
2025-07-05 13:28:41 +03:30
{
glfwPollEvents();
}
void lWindow::on_event(const Event &event)
2025-07-05 13:28:41 +03:30
{
switch (event.get_event_type())
2025-07-05 13:28:41 +03:30
{
/* closed */
case EventType::WindowClosed: b_Closed = true; break;
/* resized */
case EventType::WindowResized:
on_window_resize(dynamic_cast<const WindowResizedEvent &>(event));
break;
2025-07-05 13:28:41 +03:30
}
}
void lWindow::on_window_resize(const WindowResizedEvent &event)
2025-07-05 13:28:41 +03:30
{
m_properties.size = event.get_size();
2025-07-05 13:28:41 +03:30
}
void lWindow::
set_properties(const WindowProperties &properties, bool overrideVisibility /* = false */)
2025-07-05 13:28:41 +03:30
{
// save the visibility status and re-assign if 'overrideVisibility' is false
2025-07-06 14:02:50 +03:30
auto visible = overrideVisibility ? properties.visible : m_properties.visible;
m_properties = properties;
m_properties.visible = visible;
2025-07-05 13:28:41 +03:30
// set properties
set_title(properties.title);
set_size(properties.size);
set_v_sync(properties.vsync);
set_visibility(visible);
2025-07-05 13:28:41 +03:30
}
void lWindow::set_title(const std::string &title)
2025-07-05 13:28:41 +03:30
{
m_properties.title = title;
2025-07-05 13:28:41 +03:30
glfwSetWindowTitle(m_handle, title.c_str());
2025-07-05 13:28:41 +03:30
}
void lWindow::set_size(const glm::uvec2 &size, bool additive /* = false */)
2025-07-05 13:28:41 +03:30
{
m_properties.size.x = size.x == 0u ? m_properties.size.x :
additive ? m_properties.size.x + size.x :
2025-07-05 13:28:41 +03:30
size.x;
m_properties.size.y = size.y == 0u ? m_properties.size.y :
additive ? m_properties.size.y + size.y :
2025-07-05 13:28:41 +03:30
size.y;
glfwSetWindowSize(m_handle, size.x, size.y);
2025-07-05 13:28:41 +03:30
}
void lWindow::set_v_sync(bool vsync, bool toggle /* = false */)
2025-07-05 13:28:41 +03:30
{
m_properties.vsync = toggle ? !m_properties.vsync : vsync;
2025-07-05 13:28:41 +03:30
glfwSwapInterval(m_properties.vsync);
2025-07-05 13:28:41 +03:30
}
void lWindow::set_visibility(bool visible, bool toggle)
2025-07-05 13:28:41 +03:30
{
m_properties.visible = toggle ? !m_properties.visible : visible;
2025-07-05 13:28:41 +03:30
if (m_properties.visible)
{
glfwShowWindow(m_handle);
}
else
{
glfwHideWindow(m_handle);
}
2025-07-06 16:52:50 +03:30
}
2025-07-05 13:28:41 +03:30
void lWindow::bind_glfw_events()
2025-07-05 13:28:41 +03:30
{
glfwSetCursorPosCallback(m_handle, [](GLFWwindow *window, double xpos, double ypos) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
2025-07-05 13:28:41 +03:30
2025-07-06 14:02:50 +03:30
auto event = MouseMovedEvent {
static_cast<float>(xpos),
static_cast<float>(ypos),
};
2025-07-05 13:28:41 +03:30
callback(event);
});
glfwSetMouseButtonCallback(
m_handle,
[](GLFWwindow *window, int button, int action, int /*mods*/) {
2025-07-11 14:05:59 +03:30
std::function<void(Event &)> const callback = *(
std::function<void(Event &)> *
)glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
auto event = ButtonPressedEvent { button };
callback(event);
}
else if (action == GLFW_RELEASE)
{
auto event = ButtonReleasedEvent { button };
callback(event);
}
}
);
2025-07-05 13:28:41 +03:30
glfwSetScrollCallback(m_handle, [](GLFWwindow *window, double /*xoffset*/, double yoffset) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
2025-07-05 13:28:41 +03:30
2025-07-06 14:02:50 +03:30
auto event = WheelScrolledEvent { static_cast<float>(yoffset) };
2025-07-05 13:28:41 +03:30
callback(event);
});
glfwSetKeyCallback(
m_handle,
[](GLFWwindow *window, int key, int /*scancode*/, int action, int /*mods*/) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
2025-07-05 13:28:41 +03:30
if (action == GLFW_PRESS)
{
2025-07-06 14:02:50 +03:30
auto event = KeyPressedEvent { key };
2025-07-05 13:28:41 +03:30
callback(event);
}
else if (action == GLFW_RELEASE)
{
2025-07-06 14:02:50 +03:30
auto event = KeyReleasedEvent { key };
2025-07-05 13:28:41 +03:30
callback(event);
}
}
);
2025-07-06 14:02:50 +03:30
glfwSetCharCallback(m_handle, [](GLFWwindow *window, unsigned int character) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
2025-07-05 13:28:41 +03:30
2025-07-06 14:02:50 +03:30
auto event = SetCharEvent { character };
2025-07-05 13:28:41 +03:30
callback(event);
});
glfwSetWindowPosCallback(m_handle, [](GLFWwindow *window, int xpos, int ypos) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
auto event = WindowMovedEvent { xpos, ypos };
2025-07-05 13:28:41 +03:30
callback(event);
});
glfwSetWindowSizeCallback(m_handle, [](GLFWwindow *window, int width, int height) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
auto event = WindowResizedEvent {
static_cast<unsigned int>(width),
static_cast<unsigned int>(height),
};
2025-07-05 13:28:41 +03:30
callback(event);
});
glfwSetWindowCloseCallback(m_handle, [](GLFWwindow *window) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
auto event = WindowClosedEvent {};
2025-07-05 13:28:41 +03:30
callback(event);
});
glfwSetWindowFocusCallback(m_handle, [](GLFWwindow *window, int focus) {
2025-07-06 14:02:50 +03:30
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
2025-07-05 13:28:41 +03:30
if (focus == GLFW_TRUE)
{
2025-07-06 14:02:50 +03:30
auto event = WindowGainFocusEvent {};
2025-07-05 13:28:41 +03:30
callback(event);
}
else
{
2025-07-06 14:02:50 +03:30
auto event = WindowLostFocusEvent {};
2025-07-05 13:28:41 +03:30
callback(event);
}
});
}
2025-07-11 00:05:48 +03:30
} // namespace lt