wayland: pointer listener

This commit is contained in:
IoIxD 2025-12-07 17:25:16 -07:00
commit 6433322cda
3 changed files with 104 additions and 25 deletions

View file

@ -1,4 +1,3 @@
/* $Id$ */
/*!
* @file Mw/LowLevel/Wayland.h
* @brief Wayland Backend
@ -12,6 +11,7 @@
#include <Mw/TypeDefs.h>
#include <Mw/LowLevel.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GL/gl.h>
@ -44,7 +44,6 @@ struct _MwLLWaylandTopLevel {
struct xkb_context* xkb_context;
MwBool running;
MwBool compositor_created;
MwBool xdg_wm_base_created;
MwBool xdg_surface_created;
@ -79,14 +78,18 @@ struct _MwLLWayland {
struct wl_shm* shm;
struct wl_registry_listener registry_listener;
struct wl_pointer* pointer;
MwLL* subwidgets;
MwBool configured;
MwBool force_redraw;
MwBool egl_setup;
MwBool egl_do_resetup;
MwU32 x, y, ww, wh;
int z_index;
MwBool configured;
MwBool force_redraw;
MwBool egl_setup;
MwBool egl_do_resetup;
MwU32 x, y, ww, wh;
MwPoint cur_mouse_pos;
int last_serial;
MwLL parent;

View file

@ -1,12 +1,9 @@
/* $Id$ */
// #include <GL/gl.h>
#include <GL/gl.h>
#include <Mw/Milsko.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input-event-codes.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
@ -24,6 +21,9 @@
#include <wayland-egl-core.h>
#include <wayland-util.h>
/* TODO: find out what FreeBSD and such wants us to include */
#include <linux/input.h>
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
@ -32,6 +32,16 @@ PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus;
/*
callback todo:
void (*up)(MwLL handle, void* data);
void (*down)(MwLL handle, void* data);
void (*key)(MwLL handle, void* data);
void (*key_released)(MwLL handle, void* data);
void (*focus_in)(MwLL handle, void* data);
void (*focus_out)(MwLL handle, void* data);
*/
#define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name)
static void new_protocol(void* data, struct wl_registry* registry,
@ -54,9 +64,73 @@ static void protocol_removed(void* data,
};
static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {};
static void 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 pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial,
struct wl_surface* surface) {};
static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t time,
wl_fixed_t surface_x, wl_fixed_t surface_y) {
MwLL self = data;
MwLLMouse p;
self->wayland.cur_mouse_pos.x = wl_fixed_to_double(surface_x);
self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y);
p.point = self->wayland.cur_mouse_pos;
MwLLDispatch(self, move, &p);
};
static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
MwLL self = data;
MwLLMouse p;
p.point = self->wayland.cur_mouse_pos;
if(p.point.x > self->wayland.x && p.point.x < self->wayland.x + self->wayland.ww && p.point.y > self->wayland.y && p.point.y < self->wayland.y + self->wayland.wh) {
switch(button) {
case BTN_LEFT:
p.button = MwLLMouseLeft;
break;
case BTN_MIDDLE:
p.button = MwLLMouseMiddle;
break;
case BTN_RIGHT:
p.button = MwLLMouseRight;
break;
}
switch(state) {
case WL_POINTER_BUTTON_STATE_PRESSED:
MwLLDispatch(self, down, &p);
break;
case WL_POINTER_BUTTON_STATE_RELEASED:
MwLLDispatch(self, up, &p);
break;
}
}
};
static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time,
uint32_t axis, wl_fixed_t value) {};
struct wl_pointer_listener pointer_listener = {
.enter = pointer_enter,
.leave = pointer_leave,
.motion = pointer_motion,
.button = pointer_button,
.axis = pointer_axis,
};
static void
wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {};
static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
MwU32 capabilities) {};
MwU32 capabilities) {
MwLL self = data;
if(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
struct wl_keyboard* keyboard = wl_seat_get_keyboard(wl_seat);
// wl_keyboard_add_listener(keyboard, const struct wl_keyboard_listener* listener, data);
}
if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) {
self->wayland.pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data);
return;
}
};
void xdg_wm_base_ping(void* data,
struct xdg_wm_base* xdg_wm_base,
@ -66,15 +140,15 @@ void xdg_wm_base_ping(void* data,
xdg_wm_base_pong(xdg_wm_base, serial);
};
static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) {
static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) {
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
proto->listener = malloc(sizeof(struct wl_seat_listener));
((struct wl_seat_listener*)proto->listener)->name = wl_seat_name;
((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities;
proto->context = wl_registry_bind(wayland->registry, name, &wl_seat_interface, 1);
wl_seat_add_listener(proto->context, proto->listener, wayland);
proto->context = wl_registry_bind(ll->wayland.registry, name, &wl_seat_interface, 1);
wl_seat_add_listener(proto->context, proto->listener, ll);
return proto;
}
@ -347,9 +421,7 @@ static void decoration_configure(
static void xdg_toplevel_close(
void* data, struct xdg_toplevel* xdg_toplevel) {
MwLL self = data;
// Stop running if the user requests to close the toplevel
self->wayland.toplevel->running = MwFALSE;
MwLLDispatch(self, close, NULL);
};
static void xdg_surface_configure(
@ -397,7 +469,7 @@ static int event_loop(MwLL handle) {
if(errno != EINTR && errno != EAGAIN) {
wl_display_cancel_read(wayland->display);
wayland->toplevel->running = MwFALSE;
MwLLDispatch(handle, close, NULL);
return 0;
}
}
@ -446,8 +518,8 @@ static void setup_callbacks(struct _MwLLWayland* wayland) {
WL_INTERFACE(wl_compositor);
WL_INTERFACE(wl_subcompositor);
WL_INTERFACE(wl_seat);
if(wayland->type == MWLL_WAYLAND_TOPLEVEL) {
WL_INTERFACE(wl_seat);
WL_INTERFACE(xdg_wm_base);
WL_INTERFACE(zxdg_decoration_manager_v1);
WL_INTERFACE(wp_cursor_shape_manager_v1);
@ -627,7 +699,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
r->wayland.force_redraw = MwFALSE;
r->wayland.subwidgets = NULL;
r->wayland.pointer = NULL;
if(parent == NULL) {
setup_toplevel(r, x, y);
} else {
@ -766,6 +838,8 @@ static void MwLLEndDrawImpl(MwLL handle) {
h = parent->wayland.wh;
}
recursive_draw(handle);
glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture);
// glClear(GL_COLOR_BUFFER_BIT);
// glClearColor(1.0, 0, 0, 1);
@ -822,7 +896,6 @@ static void MwLLNextEventImpl(MwLL handle) {
MwBool render = handle->wayland.force_redraw;
if(render) {
recursive_draw(handle);
handle->wayland.force_redraw = MwFALSE;
}
}

View file

@ -14,6 +14,10 @@ static void lldrawhandler(MwLL handle, void* data) {
MwDispatch(h, draw);
if(h->draw_inject != NULL) h->draw_inject(h);
MwDispatchUserHandler(h, MwNdrawHandler, NULL);
if(handle->wayland.parent == NULL) {
MwLLEndDraw(handle);
}
}
static void lluphandler(MwLL handle, void* data) {
@ -332,7 +336,6 @@ void MwLoop(MwWidget handle) {
while(MwPending(handle)) {
if((v = MwStep(handle)) != 0) break;
}
MwLLEndDraw(handle->lowlevel);
if(v != 0) break;
for(i = 0; i < arrlen(handle->tick_list); i++) {