diff --git a/Makefile b/Makefile index 67a4947..fe97df9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ INTERFACEDIR:=$(shell pkg-config --variable=pkgdatadir wayland-protocols) -CFLAGS=-Wall -Wextra -Og -ggdb3 +CFLAGS=-Wall -Wextra -Og -ggdb3 -Wno-unused-but-set-variable -Wno-unused-parameter LIBS=-lwayland-client -lwayland-egl -lEGL -lOpenGL wayland: wayland.c xdg-shell-protocol.c xdg-shell-client-protocol.h gcc $(CFLAGS) $(LIBS) wayland.c xdg-shell-protocol.c -o wayland diff --git a/wayland.c b/wayland.c index 1d34b56..88505e8 100644 --- a/wayland.c +++ b/wayland.c @@ -5,6 +5,7 @@ #include #include #include +#include // Generated header using wayland-scanner #include "xdg-shell-client-protocol.h" @@ -15,8 +16,15 @@ 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; +/* Misc. global state */ +bool running = true; + char *egl_s(int code) { switch (code) @@ -37,7 +45,7 @@ char *egl_s(int code) } } -void registry_handle_global([[maybe_unused]] void *data, struct wl_registry *registry, +void registry_handle_global( void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { fprintf(stdout, "Wayland interface: '%s', version: %d, name: %d\n", @@ -52,11 +60,16 @@ void registry_handle_global([[maybe_unused]] void *data, struct wl_registry *reg fprintf(stdout, "Registering XDG WM base interface...\n"); wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1); } + 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); + } } -void registry_handle_global_remove([[maybe_unused]]void *data, [[maybe_unused]]struct wl_registry *registry, - [[maybe_unused]]uint32_t name) +void registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { // This space deliberately left blank } @@ -68,7 +81,7 @@ registry_listener = { }; /* Window size change callbacks */ -static void xdg_toplevel_configure([[maybe_unused]] void *data, [[maybe_unused]] struct xdg_toplevel *t, int32_t width, int32_t height, [[maybe_unused]] struct wl_array *states) +void xdg_toplevel_configure(void *data, struct xdg_toplevel *t, int32_t width, int32_t height, struct wl_array *states) { if (!width || !height) return; // compositor is deferring to us @@ -78,6 +91,49 @@ static void xdg_toplevel_configure([[maybe_unused]] void *data, [[maybe_unused]] glViewport(0, 0, width, height); } +/* Window close callback */ +void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) +{ + running = false; +} + +/* Basic wayland method to check if our program is responsive still */ +void wayland_ping(void *data, struct xdg_wm_base *base, uint32_t serial) +{ + xdg_wm_base_pong(base, serial); +} + +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); +} + +void enter_callback(void *data, struct wl_keyboard* kb, uint serial, struct wl_surface* surface, struct wl_array *keys) +{ + fprintf(stdout, "KBMAP with serial %d entered surface\n", serial); +} + +void leave_callback(void *data, struct wl_keyboard* kb, uint serial, struct wl_surface* surface) +{ + fprintf(stdout, "KBMAP with serial %d left surface\n", serial); +} + +void key_callback(void *data, struct wl_keyboard *kb, uint serial, uint time, uint key, uint state) +{ + fprintf(stdout, "Pressed key %d\n", key); +} + +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"); +} + +void repeat_info_callback(void *data, struct wl_keyboard *kb, int rate, int delay) +{ + fprintf(stdout, "Keyboard repeat/delay rate changed\n"); +} + int main() { fprintf(stdout, "Starting platform layer...\n"); @@ -110,10 +166,33 @@ int main() xdg_toplevel_set_title(xdg_toplevel, "Hi"); const struct xdg_toplevel_listener xdg_toplevel_listener = { - .configure = xdg_toplevel_configure + .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)) + fprintf(stderr, "Could not set XDG WM base listener\n"); + if (!(wl_keyboard = wl_seat_get_keyboard(wl_seat))) + fprintf(stderr, "Could not get XKB keyboard\n"); + if (!(wl_pointer = wl_seat_get_pointer(wl_seat))) + fprintf(stderr, "Could not get WL pointer\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 = { + .keymap = keymap_callback, + .enter = enter_callback, + .leave = leave_callback, + .key = key_callback, + .modifiers = modifier_callback, + .repeat_info = repeat_info_callback, + }; + wl_keyboard_add_listener(wl_keyboard, &wl_keyboard_listener, NULL); + /* WL EGL initialization */ window = wl_egl_window_create(surface, 480, 460); @@ -159,7 +238,7 @@ int main() int attr; #define PRINT_ATTR(attr_name) \ errcode = eglGetConfigAttrib(egl_display, configs[i], attr_name, &attr); \ - [[maybe_unused]] int attr_##attr_name = -1; \ + int attr_##attr_name = -1; \ do { \ if (errcode == EGL_TRUE) { \ fprintf(stdout, "\t\t" #attr_name ": %d (%#0x)\n", attr, attr); \ @@ -263,7 +342,7 @@ int main() // Main event loop int framecount = 0; - while (1) + while (running) { wl_display_dispatch_pending(display); //fprintf(stdout, "Frame %d\n", framecount);