Compare commits

..

3 Commits

Author SHA1 Message Date
12dac2fc04 feat: event system 2026-02-25 12:19:59 +01:00
0dd2404881 feat: event sketch 2026-02-25 10:31:43 +01:00
73fda759c5 feat: input handler work 2026-02-25 10:08:29 +01:00
14 changed files with 317 additions and 29 deletions

View File

@@ -1,8 +1,8 @@
CFLAGS = -Wall -Wextra -I./include/ -g
LIBS = $(shell pkg-config --libs wayland-client wayland-egl egl glesv2 wayland-cursor)
build/main: src/main.cpp build/shader.o build/state.o build/renderer.o build/window.o build/window_wayland.o build/input_wayland.o build/xdg-shell-protocol.o
g++ -o build/main $(CFLAGS) src/main.cpp build/shader.o build/state.o build/renderer.o build/window.o build/window_wayland.o build/input_wayland.o build/xdg-shell-protocol.o $(LIBS)
build/main: src/main.cpp build/shader.o build/state.o build/renderer.o build/window.o build/window_wayland.o build/input.o build/input_wayland.o build/event.o build/event_input.o build/xdg-shell-protocol.o
g++ -o build/main $(CFLAGS) src/main.cpp build/shader.o build/state.o build/renderer.o build/window.o build/window_wayland.o build/input.o build/input_wayland.o build/event.o build/event_input.o build/xdg-shell-protocol.o $(LIBS)
build/shader.o: src/shader.cpp include/shader.h
g++ -o build/shader.o $(CFLAGS) -c src/shader.cpp
@@ -21,10 +21,19 @@ build/window.o: src/window.cpp include/window.h
build/window_wayland.o: include/window/wayland.h src/window/wayland.cpp
g++ -o build/window_wayland.o $(CFLAGS) -c src/window/wayland.cpp
build/input.o: src/input.cpp include/input.h
g++ -o build/input.o $(CFLAGS) -c src/input.cpp
# TODO: dynamic input impl selection depending on platform (wayland/x11)
build/input_wayland.o: include/input/wayland.h src/input/wayland.cpp
g++ -o build/input_wayland.o $(CFLAGS) -c src/input/wayland.cpp
build/event.o: src/event.cpp include/event.h
g++ -o build/event.o $(CFLAGS) -c src/event.cpp
build/event_input.o: src/event/input.cpp include/event/input.h
g++ -o build/event_input.o $(CFLAGS) -c src/event/input.cpp
build/xdg-shell-protocol.o: src/xdg-shell-protocol.c
gcc -o build/xdg-shell-protocol.o -c $(CFLAGS) $(LIBS) src/xdg-shell-protocol.c

59
include/event.h Normal file
View File

@@ -0,0 +1,59 @@
#pragma once
#ifndef EVENT_H_
#define EVENT_H_
#include <stdbool.h>
#include <stddef.h>
enum class EventType : unsigned int {
// ----- INPUT -----
INPUT = 1 << 0,
// Mouse
MOUSE = 1 << 1,
MOUSE_MOVED = 1 << 2,
};
constexpr EventType operator|(EventType a, EventType b) {
return static_cast<EventType>(
static_cast<unsigned int>(a) |
static_cast<unsigned int>(b)
);
}
constexpr EventType operator&(EventType a, EventType b) {
return static_cast<EventType>(
static_cast<unsigned int>(a) &
static_cast<unsigned int>(b)
);
}
constexpr EventType operator~(EventType a) {
return static_cast<EventType>(
~static_cast<unsigned int>(a)
);
}
struct Event {
public:
Event();
virtual ~Event() = default;
public:
virtual EventType GetType() const = 0;
public:
void Handle();
size_t Id() const;
public:
bool IsHandled() const;
private:
bool m_handled;
size_t m_id;
private:
static size_t s_id_counter;
};
#endif // EVENT_H_

37
include/event/input.h Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#ifndef H_INPUT_EVENT_
#define H_INPUT_EVENT_
#include "event.h"
struct InputEvent : public Event {
public:
InputEvent() = default;
~InputEvent() = default;
public:
EventType GetType() const override;
};
struct MouseEvent : public InputEvent {
public:
MouseEvent(EventType type);
~MouseEvent() = default;
public:
EventType GetType() const override;
private:
EventType m_mouse_type;
};
struct MouseMoveEvent : public MouseEvent {
public:
MouseMoveEvent(size_t x, size_t y);
~MouseMoveEvent() = default;
public:
size_t x;
size_t y;
};
#endif // H_INPUT_EVENT_

33
include/input.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#ifndef H_INPUT_
#define H_INPUT_
#include <cstddef>
class InputHandlerImpl {
public:
InputHandlerImpl() = default;
virtual ~InputHandlerImpl() = default;
public:
virtual size_t GetMouseX() = 0;
virtual size_t GetMouseY() = 0;
};
class InputHandler {
public:
static InputHandler* GetInstance() {
if (!s_instance) s_instance = new InputHandler;
return s_instance;
}
private:
InputHandler();
public:
size_t GetMouseX();
size_t GetMouseY();
private:
static InputHandler* s_instance;
InputHandlerImpl* m_impl;
};
#endif // H_INPUT_

View File

@@ -2,11 +2,14 @@
#ifndef H_WAYLAND_INPUT_
#define H_WAYLAND_INPUT_
#include "input.h"
#include <vector>
#include <wayland-client-protocol.h>
class WaylandInputHandler {
public:
static WaylandInputHandler* GetInstance();
#include "event.h"
class WaylandInputHandler : public InputHandlerImpl {
private:
static void handle_pointer_enter(void *data,
struct wl_pointer *wl_pointer,
@@ -58,10 +61,18 @@ private:
private:
WaylandInputHandler();
~WaylandInputHandler() = default;
private:
static WaylandInputHandler* s_instance;
friend class InputHandler;
public:
size_t GetMouseX() override;
size_t GetMouseY() override;
private:
struct wl_pointer_listener m_pointer_listener;
wl_fixed_t m_surface_x;
wl_fixed_t m_surface_y;
private:
std::vector<Event*> m_event_queue;
};
#endif // H_WAYLAND_INPUT_

View File

@@ -35,6 +35,8 @@ public:
Window(size_t width, size_t height);
virtual ~Window();
static void Init();
Window(const Window &) = delete;
Window(Window &&) = delete;

View File

@@ -8,6 +8,8 @@ public:
WaylandWindowImpl(size_t width, size_t height);
~WaylandWindowImpl() override;
static void Init();
public:
bool Dispatch() override;
void OnFrame(IFrameListener fn) override;

18
src/event.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include "event.h"
size_t Event::s_id_counter = 0;
Event::Event() : m_id(s_id_counter++) {}
void Event::Handle() {
m_handled = true;
}
bool Event::IsHandled() const {
return m_handled;
}
size_t Event::Id() const {
return m_id;
}

15
src/event/input.cpp Normal file
View File

@@ -0,0 +1,15 @@
#include "event/input.h"
#include "event.h"
EventType InputEvent::GetType() const {
return EventType::INPUT;
}
MouseEvent::MouseEvent(EventType type) : InputEvent(), m_mouse_type(type) {}
EventType MouseEvent::GetType() const {
return InputEvent::GetType() | EventType::MOUSE | m_mouse_type;
}
MouseMoveEvent::MouseMoveEvent() : MouseEvent(EventType::MOUSE_MOVED) {}

25
src/input.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include "input.h"
#include <assert.h>
#include "input/wayland.h"
InputHandler* InputHandler::s_instance = nullptr;
// TODO: dynamically load input handling implementation depending on platform
#define WAYLAND 1
InputHandler::InputHandler() {
#ifdef WAYLAND
m_impl = new WaylandInputHandler();
#endif
assert(m_impl && "no implementation found for this platform");
}
size_t InputHandler::GetMouseX() {
return m_impl->GetMouseX();
}
size_t InputHandler::GetMouseY() {
return m_impl->GetMouseY();
}

View File

@@ -2,6 +2,7 @@
#include <stdio.h>
#include "input/wayland.h"
#include "event/input.h"
#include "state/wayland.h"
#include <wayland-client-core.h>
#include <wayland-client-protocol.h>
@@ -10,10 +11,9 @@
#define UNUSED(x) (void)(x)
WaylandInputHandler *WaylandInputHandler::s_instance = nullptr;
WaylandInputHandler::WaylandInputHandler() {
auto pointer = WaylandState::GetInstance()->m_pointer;
assert(pointer && "wayland seat_pointer not initialized");
m_pointer_listener.enter = handle_pointer_enter;
m_pointer_listener.leave = handle_pointer_leave;
m_pointer_listener.motion = handle_pointer_motion;
@@ -28,10 +28,12 @@ WaylandInputHandler::WaylandInputHandler() {
wl_pointer_add_listener(pointer, &m_pointer_listener, this);
}
WaylandInputHandler *WaylandInputHandler::GetInstance() {
if (!WaylandInputHandler::s_instance)
WaylandInputHandler::s_instance = new WaylandInputHandler();
return s_instance;
size_t WaylandInputHandler::GetMouseX() {
return wl_fixed_to_double(m_surface_x);
}
size_t WaylandInputHandler::GetMouseY() {
return wl_fixed_to_double(m_surface_y);
}
void WaylandInputHandler::handle_pointer_enter(
@@ -41,8 +43,9 @@ void WaylandInputHandler::handle_pointer_enter(
UNUSED(surface);
auto handler = reinterpret_cast<WaylandInputHandler*>(data);
// auto state = WaylandState::GetInstance();
UNUSED(handler);
printf("[DEBUG] INPUT.POINTER: pointer enter event:\n\tserial = %d, surface_x = %f, surface_y = %f\n", serial, wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
handler->m_surface_x = surface_x;
handler->m_surface_y = surface_y;
// const char* cursor_theme = "XCursor-Pro-Dark";
// auto theme = wl_cursor_theme_load(cursor_theme, 22, state->m_shm);
// printf("[DEBUG] CURSOR: theme '%s' loaded: %p\n", cursor_theme, theme);
@@ -59,45 +62,96 @@ void WaylandInputHandler::handle_pointer_enter(
void WaylandInputHandler::handle_pointer_leave(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
struct wl_surface *surface) {}
struct wl_surface *surface) {
UNUSED(data);
UNUSED(wl_pointer);
UNUSED(serial);
UNUSED(surface);
}
void WaylandInputHandler::handle_pointer_motion(void *data,
struct wl_pointer *wl_pointer,
struct wl_pointer *pointer,
uint32_t time,
wl_fixed_t surface_x,
wl_fixed_t surface_y) {}
wl_fixed_t surface_y) {
UNUSED(pointer);
UNUSED(time);
auto handler = reinterpret_cast<WaylandInputHandler*>(data);
handler->m_surface_x = surface_x;
handler->m_surface_y = surface_y;
handler->m_event_queue.push_back(new MouseMoveEvent(surface_x, surface_y));
}
void WaylandInputHandler::handle_pointer_button(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time,
uint32_t button,
uint32_t state) {}
uint32_t state) {
UNUSED(data);
UNUSED(wl_pointer);
UNUSED(serial);
UNUSED(button);
UNUSED(state);
UNUSED(time);
}
void WaylandInputHandler::handle_pointer_axis(void *data,
struct wl_pointer *wl_pointer,
uint32_t time, uint32_t axis,
wl_fixed_t value) {}
wl_fixed_t value) {
UNUSED(data);
UNUSED(wl_pointer);
UNUSED(axis);
UNUSED(value);
UNUSED(time);
}
void WaylandInputHandler::handle_pointer_frame(void *data,
struct wl_pointer *wl_pointer) {
printf("[DEBUG] INPUT.POINTER: received pointer frame event\n");
UNUSED(data);
UNUSED(wl_pointer);
}
void WaylandInputHandler::handle_pointer_axis_source(
void *data, struct wl_pointer *wl_pointer, uint32_t axis_source) {}
void *data, struct wl_pointer *wl_pointer, uint32_t axis_source) {
UNUSED(data);
UNUSED(wl_pointer);
UNUSED(axis_source);
}
void WaylandInputHandler::handle_pointer_axis_stop(
void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) {}
void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) {
UNUSED(data);
UNUSED(wl_pointer);
UNUSED(time);
UNUSED(axis);
}
void WaylandInputHandler::handle_pointer_axis_discrete(
void *data, struct wl_pointer *wl_pointer, uint32_t axis,
int32_t discrete) {}
int32_t discrete) {
UNUSED(data);
UNUSED(wl_pointer);
UNUSED(axis);
UNUSED(discrete);
}
void WaylandInputHandler::handle_pointer_axis_value120(
void *data, struct wl_pointer *wl_pointer, uint32_t axis,
int32_t value120) {}
int32_t value120) {
UNUSED(data);
UNUSED(value120);
UNUSED(axis);
UNUSED(wl_pointer);
}
void WaylandInputHandler::handle_pointer_axis_relative_direction(
void *data, struct wl_pointer *wl_pointer, uint32_t axis,
uint32_t direction) {}
uint32_t direction) {
UNUSED(data);
UNUSED(direction);
UNUSED(axis);
UNUSED(wl_pointer);
}

View File

@@ -1,6 +1,6 @@
#include <stdio.h>
#include "input/wayland.h"
#include "input.h"
#include "window.h"
#include "renderer.h"
@@ -10,7 +10,13 @@ static Window window(720, 480);
void HandleFrame() {
printf("[APP]: width = %zu, height = %zu\n", window.GetWidth(), window.GetHeight());
WaylandInputHandler::GetInstance();
auto x = InputHandler::GetInstance()->GetMouseX();
auto y = InputHandler::GetInstance()->GetMouseY();
printf("[APP]: mouse position: x = %zu, y = %zu\n", x, y);
}
void HandleMouseMove() {
printf("[APP]: mouse moved");
}
int main(int argc, char **argv) {
@@ -18,6 +24,7 @@ int main(int argc, char **argv) {
UNUSED(argv);
Renderer::GetInstance();
Window::Init();
window.OnFrame(HandleFrame);

View File

@@ -1,6 +1,7 @@
#include <stdio.h>
#include "window.h"
#include "state/wayland.h"
#define WINDOW_WAYLAND 1
@@ -13,7 +14,15 @@ Window::Window(size_t width, size_t height)
#ifdef WINDOW_WAYLAND
m_impl = new WaylandWindowImpl(width, height);
#endif
}
}
void Window::Init() {
#ifdef WINDOW_WAYLAND
printf("[DEBUG] Window::Init() called\n");
WaylandState::GetInstance();
WaylandWindowImpl::Init();
#endif
}
Window::~Window() {}

View File

@@ -1,4 +1,5 @@
#include <stdio.h>
#include <assert.h>
#include <wayland-client-core.h>
#include <wayland-client-protocol.h>
@@ -100,6 +101,12 @@ WaylandWindowImpl::~WaylandWindowImpl() { m_running = false; }
void WaylandWindowImpl::OnFrame(IFrameListener fn) { m_on_frame = fn; }
void WaylandWindowImpl::Init() {
auto display = WaylandState::GetInstance()->m_display;
assert(display && "wayland display is not initialized");
wl_display_dispatch_pending(display);
}
bool WaylandWindowImpl::Dispatch() {
if (!m_running) return false;