37d868440da484f3de47ee093a5ef890db5207dc — Drew DeVault 8 months ago d82cdc8
Add wlr_keyboard module

This module transparently gobbles up godot input events and re-publishes
them from a wlr_keyboard, which you can attach to a seat.
5 files changed, 102 insertions(+), 0 deletions(-)

M SCsub
M godotston/Main.tscn
M register_types.cpp
A wlr_keyboard.cpp
A wlr_keyboard.h
M SCsub => SCsub +1 -0
@@ 13,6 13,7 @@ srcs = [
     "wlr_backend.cpp",
     "wlr_compositor.cpp",
     "wlr_data_device_manager.cpp",
+    "wlr_keyboard.cpp",
     "wlr_output.cpp",
     "wlr_seat.cpp",
     "wlr_surface.cpp",

M godotston/Main.tscn => godotston/Main.tscn +2 -0
@@ 33,6 33,8 @@ capabilities = 3
 
 [node name="WlrDataDeviceManager" type="WlrDataDeviceManager" parent="WaylandDisplay"]
 
+[node name="WlrKeyboard" type="WlrKeyboard" parent="WaylandDisplay"]
+
 [node name="ViewportBounds" type="StaticBody2D" parent="."]
 physics_material_override = SubResource( 1 )
 

M register_types.cpp => register_types.cpp +2 -0
@@ 4,6 4,7 @@
 #include "wlr_backend.h"
 #include "wlr_compositor.h"
 #include "wlr_data_device_manager.h"
+#include "wlr_keyboard.h"
 #include "wlr_output.h"
 #include "wlr_seat.h"
 #include "wlr_surface.h"


@@ 14,6 15,7 @@ void register_gdwlroots_types() {
 	ClassDB::register_class<WlrBackend>();
 	ClassDB::register_class<WlrCompositor>();
 	ClassDB::register_class<WlrDataDeviceManager>();
+	ClassDB::register_class<WlrKeyboard>();
 	ClassDB::register_class<WlrOutput>();
 	ClassDB::register_class<WlrSeat>();
 	ClassDB::register_class<WlrSurface>();

A wlr_keyboard.cpp => wlr_keyboard.cpp +69 -0
@@ 0,0 1,69 @@
+#include <time.h>
+#include "core/object.h"
+#include "core/os/input_event.h"
+#include "keycode_map.h"
+#include "scene/main/node.h"
+#include "wlr_keyboard.h"
+extern "C" {
+#include <wlr/interfaces/wlr_keyboard.h>
+#include <wlr/types/wlr_keyboard.h>
+
+static void keyboard_destroy(struct wlr_keyboard *kb) {
+	// This space deliberately left blank
+}
+
+static const struct wlr_keyboard_impl keyboard_impl = {
+	.destroy = keyboard_destroy,
+};
+
+}
+
+void WlrKeyboard::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("_input", "event"),
+			&WlrKeyboard::_input);
+}
+
+void WlrKeyboard::_notification(int p_what) {
+	switch (p_what) {
+	case NOTIFICATION_ENTER_TREE:
+		wlr_keyboard_init(&wlr_keyboard, &keyboard_impl);
+		keyboard_init = true;
+		set_process_input(true);
+		break;
+	case NOTIFICATION_EXIT_TREE:
+		if (keyboard_init) {
+			wlr_keyboard_destroy(&wlr_keyboard);
+		}
+		set_process_input(false);
+		break;
+	}
+}
+
+static inline int64_t timespec_to_msec(const struct timespec *a) {
+	return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
+}
+
+void WlrKeyboard::_input(const Ref<InputEvent> &p_event) {
+	struct timespec now;
+	clock_gettime(CLOCK_MONOTONIC, &now);
+	Ref<InputEventKey> k = p_event;
+	if (k.is_valid()) {
+		struct wlr_event_keyboard_key event = { 0 };
+		event.time_msec = timespec_to_msec(&now);
+		event.keycode = eudev_from_godot(k->get_scancode()) - 8;
+		event.state = k->is_pressed() ? WLR_KEY_PRESSED : WLR_KEY_RELEASED;
+		event.update_state = true;
+		wlr_keyboard_notify_key(&wlr_keyboard, &event);
+	}
+}
+
+WlrKeyboard::WlrKeyboard() {
+	keyboard_init = false;
+	wlr_keyboard = { 0 };
+}
+
+WlrKeyboard::~WlrKeyboard() {
+	if (keyboard_init) {
+		wlr_keyboard_destroy(&wlr_keyboard);
+	}
+}

A wlr_keyboard.h => wlr_keyboard.h +28 -0
@@ 0,0 1,28 @@
+#ifndef GDWLR_WLR_KEYBOARD_H
+#define GDWLR_WLR_KEYBOARD_H
+#include <stdint.h>
+#include "core/os/input_event.h"
+#include "scene/main/node.h"
+#include "wayland_display.h"
+extern "C" {
+#include <wayland-server.h>
+#include <wlr/types/wlr_keyboard.h>
+}
+
+class WlrKeyboard : public Node {
+	GDCLASS(WlrKeyboard, Node);
+
+	bool keyboard_init;
+	struct wlr_keyboard wlr_keyboard;
+
+protected:
+	static void _bind_methods();
+	virtual void _notification(int p_what);
+	virtual void _input(const Ref<InputEvent> &p_event);
+
+public:
+	WlrKeyboard();
+	~WlrKeyboard();
+};
+
+#endif