Compare commits

...

4 Commits

Author SHA1 Message Date
dde47e7fac feat: build input_wayland.o 2026-02-15 12:50:32 +01:00
f4dd85ddc2 test: check if WaylandInputHandler works 2026-02-15 12:50:16 +01:00
f4c646a7e0 feat: handle wl_seat global 2026-02-15 12:49:46 +01:00
4ddd2423b9 feat: input handler class init 2026-02-15 12:49:29 +01:00
6 changed files with 240 additions and 3 deletions

View File

@@ -1,8 +1,8 @@
CFLAGS = -Wall -Wextra -I./include/ -g CFLAGS = -Wall -Wextra -I./include/ -g
LIBS = $(shell pkg-config --libs wayland-client wayland-egl egl glesv2) 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/xdg-shell-protocol.o 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/xdg-shell-protocol.o $(LIBS) 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/shader.o: src/shader.cpp include/shader.h build/shader.o: src/shader.cpp include/shader.h
g++ -o build/shader.o $(CFLAGS) -c src/shader.cpp g++ -o build/shader.o $(CFLAGS) -c src/shader.cpp
@@ -21,6 +21,10 @@ build/window.o: src/window.cpp include/window.h
build/window_wayland.o: include/window/wayland.h src/window/wayland.cpp build/window_wayland.o: include/window/wayland.h src/window/wayland.cpp
g++ -o build/window_wayland.o $(CFLAGS) -c src/window/wayland.cpp g++ -o build/window_wayland.o $(CFLAGS) -c src/window/wayland.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/xdg-shell-protocol.o: src/xdg-shell-protocol.c 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 gcc -o build/xdg-shell-protocol.o -c $(CFLAGS) $(LIBS) src/xdg-shell-protocol.c

67
include/input/wayland.h Normal file
View File

@@ -0,0 +1,67 @@
#pragma once
#ifndef H_WAYLAND_INPUT_
#define H_WAYLAND_INPUT_
#include <wayland-client-protocol.h>
class WaylandInputHandler {
public:
static WaylandInputHandler* GetInstance();
private:
static void handle_pointer_enter(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
struct wl_surface *surface,
wl_fixed_t surface_x,
wl_fixed_t surface_y);
static void handle_pointer_leave(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
struct wl_surface *surface);
static void handle_pointer_motion(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
wl_fixed_t surface_x,
wl_fixed_t surface_y);
static void handle_pointer_button(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
uint32_t time,
uint32_t button,
uint32_t state);
static void handle_pointer_axis(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
uint32_t axis,
wl_fixed_t value);
static void handle_pointer_frame(void *data,
struct wl_pointer *wl_pointer);
static void handle_pointer_axis_source(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis_source);
static void handle_pointer_axis_stop(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
uint32_t axis);
static void handle_pointer_axis_discrete(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis,
int32_t discrete);
static void handle_pointer_axis_value120(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis,
int32_t value120);
static void handle_pointer_axis_relative_direction(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis,
uint32_t direction);
private:
WaylandInputHandler();
~WaylandInputHandler() = default;
private:
static WaylandInputHandler* s_instance;
private:
struct wl_pointer_listener m_pointer_listener;
};
#endif // H_WAYLAND_INPUT_

View File

@@ -19,6 +19,12 @@ private:
static void registry_handle_global_remove(void *data, static void registry_handle_global_remove(void *data,
struct wl_registry *registry, struct wl_registry *registry,
uint32_t name); uint32_t name);
static void seat_handle_capabilities(void *data,
struct wl_seat *seat,
uint32_t capabilities);
static void seat_handle_name(void *data,
struct wl_seat *seat,
const char *name);
private: private:
WaylandState(); WaylandState();
~WaylandState(); ~WaylandState();
@@ -33,8 +39,15 @@ private:
struct xdg_wm_base_listener m_wm_base_listener; struct xdg_wm_base_listener m_wm_base_listener;
struct wl_registry_listener m_reg_listener; struct wl_registry_listener m_reg_listener;
struct wl_shm *m_shm;
struct wl_seat *m_seat;
struct wl_seat_listener m_seat_listener;
struct wl_pointer* m_pointer;
friend class WaylandWindowImpl; friend class WaylandWindowImpl;
friend class Renderer; friend class Renderer;
friend class WaylandInputHandler;
}; };
#endif // H_WAYLAND_STATE_ #endif // H_WAYLAND_STATE_

103
src/input/wayland.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include <cassert>
#include <stdio.h>
#include "input/wayland.h"
#include "state/wayland.h"
#include <wayland-client-core.h>
#include <wayland-client-protocol.h>
#include <wayland-util.h>
#include <wayland-cursor.h>
#define UNUSED(x) (void)(x)
WaylandInputHandler *WaylandInputHandler::s_instance = nullptr;
WaylandInputHandler::WaylandInputHandler() {
auto pointer = WaylandState::GetInstance()->m_pointer;
m_pointer_listener.enter = handle_pointer_enter;
m_pointer_listener.leave = handle_pointer_leave;
m_pointer_listener.motion = handle_pointer_motion;
m_pointer_listener.button = handle_pointer_button;
m_pointer_listener.axis = handle_pointer_axis;
m_pointer_listener.frame = handle_pointer_frame;
m_pointer_listener.axis_source = handle_pointer_axis_source;
m_pointer_listener.axis_stop = handle_pointer_axis_stop;
m_pointer_listener.axis_discrete = handle_pointer_axis_discrete;
m_pointer_listener.axis_value120 = handle_pointer_axis_value120;
m_pointer_listener.axis_relative_direction = handle_pointer_axis_relative_direction;
wl_pointer_add_listener(pointer, &m_pointer_listener, this);
}
WaylandInputHandler *WaylandInputHandler::GetInstance() {
if (!WaylandInputHandler::s_instance)
WaylandInputHandler::s_instance = new WaylandInputHandler();
return s_instance;
}
void WaylandInputHandler::handle_pointer_enter(
void *data, struct wl_pointer *wl_pointer, uint32_t serial,
struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
UNUSED(wl_pointer);
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));
// 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);
// auto cursor = wl_cursor_theme_get_cursor(theme, "hand2");
// printf("[DEBUG] CURSOR: cursor found (%p) with %u images\n", cursor, cursor->image_count);
// auto buffer = wl_cursor_image_get_buffer(*cursor->images);
// printf("[DEBUG] CURSOR: buffer for cursor '%s' loaded (%p)\n", cursor->name, buffer);
// auto pointer_surface = wl_compositor_create_surface(state->m_compositor);
// wl_pointer_set_cursor(state->m_pointer, serial, pointer_surface, cursor->images[0]->hotspot_x, cursor->images[0]->hotspot_y);
// wl_surface_attach(pointer_surface, buffer, 0, 0);
// wl_surface_commit(pointer_surface);
}
void WaylandInputHandler::handle_pointer_leave(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
struct wl_surface *surface) {}
void WaylandInputHandler::handle_pointer_motion(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
wl_fixed_t surface_x,
wl_fixed_t 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) {}
void WaylandInputHandler::handle_pointer_axis(void *data,
struct wl_pointer *wl_pointer,
uint32_t time, uint32_t axis,
wl_fixed_t value) {}
void WaylandInputHandler::handle_pointer_frame(void *data,
struct wl_pointer *wl_pointer) {
printf("[DEBUG] INPUT.POINTER: received pointer frame event\n");
}
void WaylandInputHandler::handle_pointer_axis_source(
void *data, struct wl_pointer *wl_pointer, uint32_t axis_source) {}
void WaylandInputHandler::handle_pointer_axis_stop(
void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) {}
void WaylandInputHandler::handle_pointer_axis_discrete(
void *data, struct wl_pointer *wl_pointer, uint32_t axis,
int32_t discrete) {}
void WaylandInputHandler::handle_pointer_axis_value120(
void *data, struct wl_pointer *wl_pointer, uint32_t axis,
int32_t value120) {}
void WaylandInputHandler::handle_pointer_axis_relative_direction(
void *data, struct wl_pointer *wl_pointer, uint32_t axis,
uint32_t direction) {}

View File

@@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include "input/wayland.h"
#include "window.h" #include "window.h"
#include "renderer.h" #include "renderer.h"
@@ -9,6 +10,7 @@ static Window window(720, 480);
void HandleFrame() { void HandleFrame() {
printf("[APP]: width = %zu, height = %zu\n", window.GetWidth(), window.GetHeight()); printf("[APP]: width = %zu, height = %zu\n", window.GetWidth(), window.GetHeight());
WaylandInputHandler::GetInstance();
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {

View File

@@ -48,6 +48,54 @@ void WaylandState::registry_handle_global(void *data, struct wl_registry *regist
xdg_wm_base_add_listener(state->m_wm_base, &state->m_wm_base_listener, xdg_wm_base_add_listener(state->m_wm_base, &state->m_wm_base_listener,
NULL); NULL);
} }
if (interface_name == "wl_seat") {
state->m_seat = reinterpret_cast<struct wl_seat *>(
wl_registry_bind(registry, name, &wl_seat_interface, version));
printf("[DEBUG] global_binding(%s): wl_seat %p\n", interface,
state->m_seat);
if (state->m_seat == NULL) {
fprintf(stderr, "ERROR: could not bind to wl_seat\n");
}
state->m_seat_listener.capabilities = seat_handle_capabilities;
state->m_seat_listener.name = seat_handle_name;
wl_seat_add_listener(state->m_seat, &state->m_seat_listener, state);
}
if (interface_name == "wl_shm") {
state->m_shm = reinterpret_cast<struct wl_shm *>(
wl_registry_bind(registry, name, &wl_shm_interface, version));
printf("[DEBUG] global_binding(%s): wl_shm %p\n", interface,
state->m_shm);
if (state->m_shm == NULL) {
fprintf(stderr, "ERROR: could not bind to wl_shm\n");
}
}
}
void WaylandState::seat_handle_name(void *data,
struct wl_seat *seat,
const char *name) {
UNUSED(seat);
UNUSED(data);
printf("[DEBUG] SEAT: name of the seat = %s\n", name);
}
void WaylandState::seat_handle_capabilities(void *data,
struct wl_seat *seat,
uint32_t capabilities) {
auto state = reinterpret_cast<WaylandState *>(data);
UNUSED(state);
UNUSED(seat);
if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) > 0) {
printf("[DEBUG] SEAT: keyboard is available\n");
}
if ((capabilities & WL_SEAT_CAPABILITY_POINTER) > 0) {
printf("[DEBUG] SEAT: pointer is available\n");
state->m_pointer = wl_seat_get_pointer(seat);
printf("[DEBUG] SEAT: pointer is bound under %p address\n", state->m_pointer);
}
if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) > 0) {
printf("[DEBUG] SEAT: touch is available\n");
}
} }
void WaylandState::registry_handle_global_remove(void *data, void WaylandState::registry_handle_global_remove(void *data,