wayland input

This commit is contained in:
Matteo De Carlo
2025-04-24 02:31:54 +02:00
parent 1179fa532d
commit ed223c3121
10 changed files with 984 additions and 31 deletions
+10
View File
@@ -98,6 +98,16 @@ void wayland_loop(wi::wayland::Backend &wwbackend, Tests &tests)
{
bool quit = false;
wwbackend.window.on_close = [&quit](wi::wayland::Window*w) { quit = true; };
wwbackend.window.on_focus_on = [&tests](wi::wayland::Window*w)
{
tests.is_window_active = true;
std::clog << "window on enter" << std::endl;
};
wwbackend.window.on_focus_off = [&tests](wi::wayland::Window*w)
{
tests.is_window_active = false;
std::clog << "window on leave" << std::endl;
};
while(!quit)
{
+3
View File
@@ -54,6 +54,7 @@ else ()
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
pkg_check_modules(WAYLAND_SCANNER REQUIRED wayland-scanner)
pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols)
pkg_check_modules(XKBCOMMON REQUIRED xkbcommon)
# Get variables
pkg_get_variable(WAYLAND_SCANNER_BIN wayland-scanner wayland_scanner)
pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir)
@@ -194,12 +195,14 @@ else ()
target_include_directories(${TARGET_NAME}
PUBLIC ${WAYLAND_CLIENT_INCLUDE_DIRS}
# PRIVATE ${WAYLAND_CURSOR_INCLUDE_DIRS}
PUBLIC ${XKBCOMMON_INCLUDE_DIRS}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
# PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/WickedEngine>
)
target_link_libraries(${TARGET_NAME}
PUBLIC ${WAYLAND_CLIENT_LIBRARIES}
PUBLIC ${XKBCOMMON_LIBRARIES}
# PRIVATE ${WAYLAND_CURSOR_LIBRARIES}
)
endif()
+209 -1
View File
@@ -5,6 +5,7 @@
#include <wayland-client.h>
#include <iostream>
#include "wiWaylandInput.h"
#include "xdg-shell.h"
#include "xdg-decoration-unstable-v1.h"
@@ -30,6 +31,159 @@ extern "C" void window_manager_pong(void *data, struct xdg_wm_base *xdg_wm_base,
backend->window_manager_pong(serial);
}
extern "C" void _static_on_keyboard_keymap(void* data, wl_keyboard* keyboard,
uint32_t format,
int32_t fd, uint32_t size)
{
Backend *backend = static_cast<Backend*>(data);
wi::input::wayland::SetKeyMap(format, fd, size);
}
extern "C" void _static_on_keyboard_focuson(void* data, wl_keyboard* keyboard,
uint32_t serial,
wl_surface* surface,
wl_array* keys)
{
Backend *backend = static_cast<Backend*>(data);
backend->keyboard_focuson(serial, surface, keys);
}
extern "C" void _static_on_keyboard_focusoff(void* data, wl_keyboard* keyboard,
uint32_t serial,
wl_surface* surface)
{
Backend *backend = static_cast<Backend*>(data);
backend->keyboard_focusoff(serial, surface);
}
extern "C" void _static_on_keyboard_key(void* data, wl_keyboard* keyboard,
uint32_t serial,
uint32_t time,
uint32_t key,
uint32_t state)
{
Backend *backend = static_cast<Backend*>(data);
// fprintf(stderr, "Key is %d state is %d\n", key, state);
// backend->keyboard_key(serial, time, key, state);
wi::input::wayland::ProcessKeyboardEvent(time, key, state);
}
extern "C" void _static_on_keyboard_modifiers(void* data, wl_keyboard* keyboard,
uint32_t serial,
uint32_t mods_depressed,
uint32_t mods_latched,
uint32_t mods_locked,
uint32_t group)
{
Backend *backend = static_cast<Backend*>(data);
// backend->keyboard_focusoff(serial, surface);
fprintf(stderr, "Modifiers depressed %d, latched %d, locked %d, group %d\n",
mods_depressed, mods_latched, mods_locked, group);
}
extern "C" void _static_on_keyboard_repeat_info(void* data, wl_keyboard* keyboard,
int32_t rate,
int32_t delay)
{
Backend *backend = static_cast<Backend*>(data);
// backend->keyboard_focusoff(serial, surface);
}
extern "C" void _static_on_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)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_leave(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
struct wl_surface *surface)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_motion(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
wl_fixed_t surface_x,
wl_fixed_t surface_y)
{
double x = wl_fixed_to_double(surface_x), y = wl_fixed_to_double(surface_y);
Backend *backend = static_cast<Backend*>(data);
fprintf(stderr, "Mouse movement %f,%f\n", x, y);
wi::input::wayland::ProcessPointerMotion(time, x, y);
}
extern "C" void _static_on_pointer_button(void *data,
struct wl_pointer *wl_pointer,
uint32_t serial,
uint32_t time,
uint32_t button,
uint32_t state)
{
Backend *backend = static_cast<Backend*>(data);
wi::input::wayland::ProcessPointerButton(time, button, state);
fprintf(stderr, "Mouse key is %d state is %d\n", button, state);
}
extern "C" void _static_on_pointer_axis(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
uint32_t axis,
wl_fixed_t value)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_frame(void *data, struct wl_pointer *wl_pointer)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_axis_source(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis_source)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_axis_stop(void *data,
struct wl_pointer *wl_pointer,
uint32_t time,
uint32_t axis)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_axis_discrete(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis,
int32_t discrete)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_axis_value120(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis,
int32_t value120)
{
Backend *backend = static_cast<Backend*>(data);
}
extern "C" void _static_on_pointer_axis_relative_direction(void *data,
struct wl_pointer *wl_pointer,
uint32_t axis,
uint32_t direction)
{
Backend *backend = static_cast<Backend*>(data);
}
/// functions callbacks - END
bool Backend::Init()
@@ -45,8 +199,38 @@ bool Backend::Init()
if (!registry_has("xdg_wm_base")) {std::cerr<<"XDG WM BASE not found"<<std::endl; return false;}
if (!bind_xdg_wm_base()) {std::cerr<<"bind xdg_wm_base failed"<<std::endl; return false;}
if (!init_window_manager()) {std::cerr<<"xdg_wm_base init failed"<<std::endl; return false;}
if (!bind_decoration_manager()) {std::cerr<<"bind decoration_manager failed"<<std::endl;} //optional, being "unstable" API (GNOME does not implement this)
//optional, being "unstable" API (GNOME does not implement this)
if (!bind_decoration_manager()) {std::cerr<<"bind decoration_manager failed"<<std::endl;}
// mouse and keyboard focus and inputs
if (!bind_wl_seat()) {std::cerr<<"bind wl seat failed"<<std::endl; return false;}
keyboard = wl_seat_get_keyboard(seat);
if (keyboard == nullptr) {std::cerr<<"wl_keyboard not found"<<std::endl; return false;}
pointer = wl_seat_get_pointer(seat);
if (pointer == nullptr) {std::cerr<<"wl_pointer not found"<<std::endl; return false;}
keyboard_listener.keymap = &_static_on_keyboard_keymap;
keyboard_listener.enter = &_static_on_keyboard_focuson;
keyboard_listener.leave = &_static_on_keyboard_focusoff;
keyboard_listener.key = &_static_on_keyboard_key;
keyboard_listener.modifiers = &_static_on_keyboard_modifiers;
keyboard_listener.repeat_info = &_static_on_keyboard_repeat_info;
wl_keyboard_add_listener(keyboard, &keyboard_listener, this);
//TODO add pointer image every time the pointer enters! see https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Input
pointer_listener.enter = &_static_on_pointer_enter;
pointer_listener.leave = _static_on_pointer_leave;
pointer_listener.motion = _static_on_pointer_motion;
pointer_listener.button = _static_on_pointer_button;
pointer_listener.axis = _static_on_pointer_axis;
pointer_listener.frame = _static_on_pointer_frame;
pointer_listener.axis_source = _static_on_pointer_axis_source;
pointer_listener.axis_stop = _static_on_pointer_axis_stop;
pointer_listener.axis_discrete = _static_on_pointer_axis_discrete;
pointer_listener.axis_value120 = _static_on_pointer_axis_value120;
pointer_listener.axis_relative_direction = _static_on_pointer_axis_relative_direction;
wl_pointer_add_listener(pointer, &pointer_listener, this);
wi::input::wayland::Initialize();
return true;
}
@@ -86,6 +270,12 @@ bool Backend::bind_decoration_manager()
return decoration_manager != nullptr;
}
bool Backend::bind_wl_seat()
{
seat = this->bind<wl_seat>("wl_seat", &wl_seat_interface);
return seat != nullptr;
}
bool Backend::init_window_manager()
{
window_manager_listener.ping = &::window_manager_pong;
@@ -95,6 +285,10 @@ bool Backend::init_window_manager()
void Backend::DeInit()
{
wi::input::wayland::Deinit();
safe_delete(pointer, wl_pointer_release);
safe_delete(keyboard, wl_keyboard_release);
safe_delete(seat, wl_seat_destroy);
safe_delete(decoration_manager, zxdg_decoration_manager_v1_destroy);
safe_delete(window_manager, xdg_wm_base_destroy);
safe_delete(compositor, wl_compositor_destroy);
@@ -139,3 +333,17 @@ void Backend::window_manager_pong(uint32_t serial)
{
xdg_wm_base_pong(window_manager, serial);
}
void Backend::keyboard_focuson(uint32_t serial, wl_surface* surface, wl_array* keys)
{
if (surface != window.WLsurface)
return;
if (window.on_focus_on) window.on_focus_on(&window);
}
void Backend::keyboard_focusoff(uint32_t serial, wl_surface* surface)
{
if (surface != window.WLsurface)
return;
if (window.on_focus_off) window.on_focus_off(&window);
}
+10
View File
@@ -1,4 +1,5 @@
#pragma once
#include "wayland-client-protocol.h"
#include "wiWaylandWindow.h"
#include <wayland-client.h>
#include <map>
@@ -30,6 +31,12 @@ private:
xdg_wm_base_listener window_manager_listener;
zxdg_decoration_manager_v1 *decoration_manager = nullptr;
wl_seat* seat = nullptr;
wl_keyboard* keyboard = nullptr;
wl_pointer* pointer = nullptr;
wl_keyboard_listener keyboard_listener {};
wl_pointer_listener pointer_listener {};
public:
Window window;
@@ -48,6 +55,8 @@ public:
void registry_event_add(uint32_t id, const char* interface, uint32_t version);
void registry_event_remove(uint32_t id);
void window_manager_pong(uint32_t serial);
void keyboard_focuson(uint32_t serial, wl_surface* surface, wl_array* keys);
void keyboard_focusoff(uint32_t serial, wl_surface* surface);
private:
bool init_registry();
@@ -74,6 +83,7 @@ private:
bool bind_compositor();
bool bind_xdg_wm_base();
bool bind_decoration_manager();
bool bind_wl_seat();
bool init_window_manager();
File diff suppressed because it is too large Load Diff
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
#include "wiInput.h"
typedef int Event;
namespace wi::input::wayland {
struct Event {
enum EventType {
None = 0,
Keyboard,
Mouse,
} type;
struct KeyboardEvent {
uint32_t time, key, state;
} keyboard_event;
};
void Initialize();
void Deinit();
void SetKeyMap(uint32_t format, int32_t fd, uint32_t size);
void ProcessKeyboardEvent(uint32_t time, uint32_t key, uint32_t state);
void ProcessPointerButton(uint32_t time, uint32_t uint32, uint32_t state);
void ProcessPointerMotion(uint32_t time, double x, double y);
void Update();
void GetKeyboardState(wi::input::KeyboardState* state);
void GetMouseState(wi::input::MouseState* state);
}
+19 -18
View File
@@ -17,31 +17,31 @@ extern "C" void _static_on_redraw(void *data,
wl_callback *wl_callback,
uint32_t time)
{
static_cast<Window*>(data)->on_redraw(wl_callback, time);
static_cast<Window*>(data)->_on_redraw(wl_callback, time);
}
extern "C" void _static_on_enter(void *data,
extern "C" void _static_on_enter_monitor(void *data,
wl_surface *wl_surface,
wl_output *output)
{
static_cast<Window*>(data)->on_enter(output);
static_cast<Window*>(data)->_on_enter_monitor(output);
}
extern "C" void _static_on_leave(void *data,
extern "C" void _static_on_leave_monitor(void *data,
wl_surface *wl_surface,
wl_output *output)
{
static_cast<Window*>(data)->on_leave(output);
static_cast<Window*>(data)->_on_leave_monitor(output);
}
extern "C" void _static_xdg_surface_configure(void* data, xdg_surface* raw, uint32_t serial)
{
static_cast<Window*>(data)->on_xdg_surface_ack_configure(serial);
static_cast<Window*>(data)->_on_xdg_surface_ack_configure(serial);
}
extern "C" void _static_toplevel_close(void *data, xdg_toplevel *xdg_toplevel)
{
static_cast<Window*>(data)->on_toplevel_close();
static_cast<Window*>(data)->_on_toplevel_close();
}
extern "C" void _static_toplevel_configure(void *data,
@@ -50,7 +50,7 @@ extern "C" void _static_toplevel_configure(void *data,
int32_t height,
wl_array *states)
{
static_cast<Window*>(data)->on_toplevel_configure(width, height, states);
static_cast<Window*>(data)->_on_toplevel_configure(width, height, states);
}
extern "C" void _static_toplevel_configure_bounds(void *data,
@@ -58,16 +58,16 @@ extern "C" void _static_toplevel_configure_bounds(void *data,
int32_t width,
int32_t height)
{
static_cast<Window*>(data)->on_toplevel_configure_bounds(width, height);
static_cast<Window*>(data)->_on_toplevel_configure_bounds(width, height);
}
void Window::on_enter(wl_output *output)
void Window::_on_enter_monitor(wl_output *output)
{}
void Window::on_leave(wl_output *output)
void Window::_on_leave_monitor(wl_output *output)
{}
void Window::on_redraw(wl_callback *wl_callback, uint32_t time)
void Window::_on_redraw(wl_callback *wl_callback, uint32_t time)
{
if(frame_callback != nullptr) {
wl_callback_destroy(frame_callback);
@@ -77,23 +77,23 @@ void Window::on_redraw(wl_callback *wl_callback, uint32_t time)
on_redraw_callback(this);
}
void Window::on_xdg_surface_ack_configure(uint32_t serial)
void Window::_on_xdg_surface_ack_configure(uint32_t serial)
{
xdg_surface_ack_configure(XDGsurface, serial);
}
void Window::on_toplevel_close()
void Window::_on_toplevel_close()
{
if (on_close) on_close(this);
}
void Window::on_toplevel_configure(int32_t width, int32_t height, wl_array* states)
void Window::_on_toplevel_configure(int32_t width, int32_t height, wl_array* states)
{
desired_width = width;
desired_height = height;
}
void Window::on_toplevel_configure_bounds(int32_t width, int32_t height)
void Window::_on_toplevel_configure_bounds(int32_t width, int32_t height)
{}
@@ -104,8 +104,8 @@ bool Window::Init(Backend* backend, const char* title)
// Surface
WLsurface = wl_compositor_create_surface(backend->compositor);
if (WLsurface == nullptr) {std::cerr << "Could not create surface from compositor" << std::endl; return false;}
WLsurface_listener.enter = &_static_on_enter;
WLsurface_listener.leave = &_static_on_leave;
WLsurface_listener.enter = &_static_on_enter_monitor;
WLsurface_listener.leave = &_static_on_leave_monitor;
frame_listener.done = &_static_on_redraw;
wl_surface_add_listener(WLsurface, &WLsurface_listener, this);
@@ -133,6 +133,7 @@ bool Window::Init(Backend* backend, const char* title)
}
}
xdg_toplevel_set_app_id(toplevel, "WickedEngine");
SetTitle(title);
return true;
}
+11 -7
View File
@@ -43,6 +43,8 @@ private:
public:
std::function<void(Window* window)> on_redraw_callback;
std::function<void(Window* window)> on_close;
std::function<void(Window* window)> on_focus_on;
std::function<void(Window* window)> on_focus_off;
public:
~Window() { Deinit(); }
@@ -59,13 +61,15 @@ public:
VkResult CreateVulkanSurface(VkInstance instance, VkSurfaceKHR* VKSurface);
// callbacks
void on_enter(wl_output *output);
void on_leave(wl_output *output);
void on_redraw(wl_callback *wl_callback, uint32_t time);
void on_xdg_surface_ack_configure(uint32_t serial);
void on_toplevel_close();
void on_toplevel_configure(int32_t width, int32_t height, wl_array *states);
void on_toplevel_configure_bounds(int32_t width, int32_t height);
void _on_enter_monitor(wl_output *output);
void _on_leave_monitor(wl_output *output);
void _on_redraw(wl_callback *wl_callback, uint32_t time);
void _on_xdg_surface_ack_configure(uint32_t serial);
void _on_toplevel_close();
void _on_toplevel_configure(int32_t width, int32_t height, wl_array *states);
void _on_toplevel_configure_bounds(int32_t width, int32_t height);
friend class Backend;
};
}
+12 -5
View File
@@ -3,6 +3,7 @@
#include "wiXInput.h"
#include "wiRawInput.h"
#include "wiSDLInput.h"
#include "Wayland/wiWaylandInput.h"
#include "wiHelper.h"
#include "wiBacklog.h"
#include "wiProfiler.h"
@@ -148,6 +149,7 @@ namespace wi::input
wi::input::xinput::Update();
wi::input::rawinput::Update();
wi::input::sdlinput::Update();
wi::input::wayland::Update();
#ifdef PLATFORM_PS5
wi::input::ps5::Update();
@@ -170,12 +172,17 @@ namespace wi::input
mouse.position.y = (float)p.y;
mouse.position.x /= canvas.GetDPIScaling();
mouse.position.y /= canvas.GetDPIScaling();
#elif SDL2
wi::input::sdlinput::GetMouseState(&mouse);
mouse.position.x /= canvas.GetDPIScaling();
mouse.position.y /= canvas.GetDPIScaling();
wi::input::sdlinput::GetKeyboardState(&keyboard);
if (window.type == platform::LinuxWindow::eSDLWindow) {
wi::input::sdlinput::GetMouseState(&mouse);
mouse.position.x /= canvas.GetDPIScaling();
mouse.position.y /= canvas.GetDPIScaling();
wi::input::sdlinput::GetKeyboardState(&keyboard);
}
else if (window.type == platform::LinuxWindow::eWaylandWindow) {
wi::input::wayland::GetMouseState(&mouse);
wi::input::wayland::GetKeyboardState(&keyboard);
}
//TODO controllers
//TODO touch
#endif
+3
View File
@@ -36,4 +36,7 @@ namespace wi::input::sdlinput
// Call this within the main.cpp program loop for the engine to be able handle the input
void ProcessEvent(const SDL_Event &event);
#endif
// Helper function to convert into Wicked Key "space"
int to_wicked(const SDL_Scancode &key, const SDL_Keycode &keyk);
}