Hook up mouse callbacks

This commit is contained in:
Phireh 2024-11-24 21:01:34 +01:00
commit a3f8043afa
2 changed files with 128 additions and 10 deletions

View file

@ -1,9 +1,9 @@
INTERFACEDIR:=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
CFLAGS=-Wall -Wextra -Og -ggdb3 -Wno-unused-but-set-variable -Wno-unused-parameter
LIBS=-lwayland-client -lwayland-egl -lEGL -lOpenGL
LIBS=-lwayland-client -lwayland-egl -lEGL -lOpenGL -lxkbcommon
wayland: wayland.c xdg-shell-protocol.c xdg-shell-client-protocol.h
gcc $(CFLAGS) $(LIBS) wayland.c xdg-shell-protocol.c -o wayland
xdg-shell-protocol.c:
xdg-shell-protocol.c:
wayland-scanner private-code $(INTERFACEDIR)/stable/xdg-shell/xdg-shell.xml xdg-shell-protocol.c
xdg-shell-client-protocol.h:
wayland-scanner client-header $(INTERFACEDIR)/stable/xdg-shell/xdg-shell.xml xdg-shell-client-protocol.h
wayland-scanner client-header $(INTERFACEDIR)/stable/xdg-shell/xdg-shell.xml xdg-shell-client-protocol.h

132
wayland.c
View file

@ -3,9 +3,12 @@
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GL/gl.h>
#include <xkbcommon/xkbcommon.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <unistd.h>
// Generated header using wayland-scanner
#include "xdg-shell-client-protocol.h"
@ -16,13 +19,19 @@ struct xdg_wm_base *wm_base = NULL;
struct xdg_surface *xdg_surface = NULL;
struct xdg_toplevel *xdg_toplevel = NULL;
struct wl_egl_window *window = NULL;
/* Input API */
struct wl_seat *wl_seat = NULL;
struct wl_keyboard *wl_keyboard = NULL;
struct wl_pointer *wl_pointer = NULL;
EGLBoolean errcode = 0;
/* XKB library */
struct xkb_context *xkb_context = NULL;
struct xkb_state *xkb_state = NULL;
struct xkb_keymap *xkb_keymap = NULL;
/* Misc. global state */
EGLBoolean errcode = 0;
bool running = true;
char *egl_s(int code)
@ -60,14 +69,15 @@ void registry_handle_global( void *data, struct wl_registry *registry,
fprintf(stdout, "Registering XDG WM base interface...\n");
wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
}
/* NOTE: Since wl_seat v5, pointer events are grouped into "frames", which do not appear to be useful for non-touch applications and
also create more events which are more complicated to dispatch. */
if (!strcmp(interface, wl_seat_interface.name))
{
fprintf(stdout, "Registering WL seat interface...\n");
wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 9);
}
}
void registry_handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name)
{
@ -103,10 +113,24 @@ void wayland_ping(void *data, struct xdg_wm_base *base, uint32_t serial)
xdg_wm_base_pong(base, serial);
}
void wl_seat_capabilities_callback(void *data, struct wl_seat *wl_seat, uint capabilities)
{
fprintf(stdout, "Capabilities changed for WL seat\n");
}
void keymap_callback(void *data, struct wl_keyboard *kb, uint format, int fd, uint size)
{
// TODO: Check for XKB compatibility and use xkbcommon to extract
fprintf(stdout, "KBMAP of size %d detected\n", size);
char *mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
fprintf(stdout, "XKBMAP desc:\n\t%s\n", mem);
xkb_keymap = xkb_keymap_new_from_string(xkb_context, mem, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(mem, size);
close(fd);
if (!(xkb_state = xkb_state_new(xkb_keymap)))
fprintf(stderr, "Could not initialize XKB state machine\n");
}
void enter_callback(void *data, struct wl_keyboard* kb, uint serial, struct wl_surface* surface, struct wl_array *keys)
@ -121,12 +145,27 @@ void leave_callback(void *data, struct wl_keyboard* kb, uint serial, struct wl_s
void key_callback(void *data, struct wl_keyboard *kb, uint serial, uint time, uint key, uint state)
{
fprintf(stdout, "Pressed key %d\n", key);
/* TODO: This does *not* respect the system's language defaults. At least not in KDE.
* Wayland's own (terrible) documentation does not go into detail about languages:
* https://wayland-book.com/seat/xkb.html
*/
key += 8;
uint32_t layout = xkb_state_key_get_layout(xkb_state, key);
if (layout >= xkb_keymap_num_layouts_for_key(xkb_keymap, key))
fprintf(stderr, "Layout %d exceeds number of available key layouts\n", layout);
xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, key);
char keyname[128];
xkb_keysym_get_name(sym, keyname, sizeof(keyname));
char keyutf8[128];
xkb_state_key_get_utf8(xkb_state, key, keyutf8, sizeof(keyutf8));
fprintf(stdout, "%s key %d layout %d (KEYSYM %s) (UTF8 %s)\n", (state == WL_KEYBOARD_KEY_STATE_PRESSED ? "Pressed" : "Released"), key, layout, keyname, keyutf8);
}
void modifier_callback(void *data, struct wl_keyboard *kb, uint serial, uint mods_depressed, uint mods_latched, uint mods_locked, uint group)
{
fprintf(stdout, "Keyboard modifier keys changed\n");
xkb_state_update_mask(xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
}
void repeat_info_callback(void *data, struct wl_keyboard *kb, int rate, int delay)
@ -134,6 +173,56 @@ void repeat_info_callback(void *data, struct wl_keyboard *kb, int rate, int dela
fprintf(stdout, "Keyboard repeat/delay rate changed\n");
}
void pointer_enter_callback(void *data, struct wl_pointer *pointer, uint serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
{
fprintf(stdout, "Pointer entered WL surface on coordinates %d %d\n", x, y);
}
void pointer_leave_callback(void *data, struct wl_pointer *pointer, uint serial, struct wl_surface *surface)
{
fprintf(stdout, "Pointer left WL surface\n");
}
void pointer_motion_callback(void *data, struct wl_pointer *pointer, uint time, wl_fixed_t x, wl_fixed_t y)
{
fprintf(stdout, "Pointer moved to %d %d\n", x, y);
}
void pointer_button_callback(void *data, struct wl_pointer *pointer, uint serial, uint time, uint button, uint state)
{
fprintf(stdout, "Pointer button %d changed state\n", button);
}
void pointer_axis_callback(void *data, struct wl_pointer *pointer, uint time, uint axis, wl_fixed_t value)
{
fprintf(stdout, "Pointer scroll on axis %d value %d\n", axis, value);
}
/* NOTE: *some* events are logically grouped together. The frame event marks the boundary between groups of them. More info: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_pointer */
void pointer_frame_callback(void *data, struct wl_pointer *frame)
{
fprintf(stdout, "Pointer frame ended\n");
}
/* NOTE: This event is also used to group pointer events together. It specifies info about all events in its frame */
void pointer_axis_source_callback(void *data, struct wl_pointer *pointer, uint axis_source)
{
fprintf(stdout, "Pointer axis source: %d\n", axis_source);
}
/* Optional event to implement kinetic scrolling */
void pointer_axis_stop_callback(void *data, struct wl_pointer *pointer, uint time, uint axis)
{
fprintf(stdout, "Pointer axis stopped: %d\n", axis);
}
/* Optional event. Carries discrete scroll info after an 'axis' event */
void pointer_axis_discrete_callback(void *data, struct wl_pointer *pointer, uint axis, int discrete)
{
fprintf(stdout, "Pointer axis discrete step: %d\n", discrete);
}
int main()
{
fprintf(stdout, "Starting platform layer...\n");
@ -165,13 +254,19 @@ int main()
xdg_toplevel = xdg_surface_get_toplevel(xdg_surface);
xdg_toplevel_set_title(xdg_toplevel, "Hi");
/* XKB library initialization */
xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
const struct xdg_toplevel_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure,
.close = xdg_toplevel_close
};
const struct xdg_wm_base_listener xdg_wm_base_listener = {
.ping = wayland_ping
};
if (xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL))
fprintf(stderr, "Could not set XDG toplevel listener\n");
if (xdg_wm_base_add_listener(wm_base, &xdg_wm_base_listener, NULL))
@ -181,6 +276,13 @@ int main()
if (!(wl_pointer = wl_seat_get_pointer(wl_seat)))
fprintf(stderr, "Could not get WL pointer\n");
const struct wl_seat_listener wl_seat_listener = {
.capabilities = wl_seat_capabilities_callback
};
if (wl_seat_add_listener(wl_seat, &wl_seat_listener, NULL))
fprintf(stderr, "Could not set WL seat listener\n");
/* NOTE: We have to define all available callbacks for the keyboard listener even if we are not interested in them:
https://gitlab.freedesktop.org/wayland/wayland/-/issues/160 */
const struct wl_keyboard_listener wl_keyboard_listener = {
@ -191,8 +293,24 @@ int main()
.modifiers = modifier_callback,
.repeat_info = repeat_info_callback,
};
wl_keyboard_add_listener(wl_keyboard, &wl_keyboard_listener, NULL);
if (wl_keyboard_add_listener(wl_keyboard, &wl_keyboard_listener, NULL))
fprintf(stderr, "Could not set XKB keyboard listener\n");
// TODO: Apparently we are not setting opcode 10's callback?
const struct wl_pointer_listener wl_pointer_listener = {
.enter = pointer_enter_callback,
.leave = pointer_leave_callback,
.motion = pointer_motion_callback,
.button = pointer_button_callback,
.axis = pointer_axis_callback,
.frame = pointer_frame_callback,
.axis_source = pointer_axis_source_callback,
.axis_stop = pointer_axis_stop_callback,
.axis_discrete = pointer_axis_discrete_callback
};
if (wl_pointer_add_listener(wl_pointer, &wl_pointer_listener, NULL))
fprintf(stderr, "Could not set WL pointer listener\n");
/* WL EGL initialization */
window = wl_egl_window_create(surface, 480, 460);
@ -339,7 +457,7 @@ int main()
// necessary before our first eglSwapBuffers
wl_surface_commit(surface);
// Main event loop
int framecount = 0;
while (running)