~sircmpwn/gdwlroots

37d868440da484f3de47ee093a5ef890db5207dc — Drew DeVault 1 year, 4 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