From 61cfdbccf3230b73d42eb90f6eec934dbe1ddfdb Mon Sep 17 00:00:00 2001 From: Roz K Date: Fri, 23 Dec 2022 10:18:26 +0100 Subject: [PATCH] Add support for key press and release events. --- Makefile | 22 ++++++++++++- __init__.py | 24 ++++++++++++++ cpp/events.hpp | 43 ++++++++++++++++++++++++ cpp/events/events_x11.cpp | 55 +++++++++++++++++++++++++++++++ cpp/opengl/render_context_glx.cpp | 7 ++-- 5 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 cpp/events.hpp create mode 100644 cpp/events/events_x11.cpp diff --git a/Makefile b/Makefile index c9826ef..d9323ba 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,24 @@ -SOURCES = cpp/opengl/render_context_glx.cpp cpp/opengl/render_opengles.cpp cpp/math.cpp +# Copyright (C) 2022 RozK +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +SOURCES = \ +cpp/opengl/render_context_glx.cpp \ +cpp/opengl/render_opengles.cpp \ +cpp/events/events_x11.cpp \ +cpp/math.cpp + OUTPUTFILE = engine.so CXXFLAGS = -fpic -Wall -Werror -O2 -flto -fomit-frame-pointer -ffast-math -funroll-loops -fno-rtti -fno-exceptions diff --git a/__init__.py b/__init__.py index e40b861..92e1d04 100644 --- a/__init__.py +++ b/__init__.py @@ -344,3 +344,27 @@ destroy_shader.argtypes = ( ctypes.c_void_p,) # shader terminate = _engine.rk_terminate + +EVENT_KEY_PRESS = 0 +EVENT_KEY_RELEASE = 1 + +class _EventKey(ctypes.Structure): + _fields_ = ( + ('keycode', ctypes.c_uint), + ) + +class _AllEvents(ctypes.Union): + _fields_ = ( + ('key', _EventKey), + ) + +class Event(ctypes.Structure): + _fields_ = ('type', ctypes.c_uint), ('data', _AllEvents) + +consume_events = _engine.rk_consume_events +consume_events.restype = ctypes.c_uint +consume_events.argtypes = ( + ctypes.POINTER(Event), # events + ctypes.c_uint) # max_events + +flush_events = _engine.rk_flush_events diff --git a/cpp/events.hpp b/cpp/events.hpp new file mode 100644 index 0000000..4431e5b --- /dev/null +++ b/cpp/events.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2022 RozK +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _RK_ENGINE_EVENTS_H +#define _RK_ENGINE_EVENTS_H + +#include "types.hpp" + +enum rk_event_type : rk_uint { + RK_EVENT_KEY_PRESS = 0, + RK_EVENT_KEY_RELEASE = 1 +}; + +struct rk_event_key { + rk_uint keycode; +}; + +struct rk_event { + rk_event_type type; + union { + rk_event_key key; + }; +}; + +RK_EXPORT rk_uint rk_consume_events( + rk_event * events, + rk_uint max_events); + +RK_EXPORT void rk_flush_events(); + +#endif // _RK_ENGINE_EVENTS_H diff --git a/cpp/events/events_x11.cpp b/cpp/events/events_x11.cpp new file mode 100644 index 0000000..b8c5375 --- /dev/null +++ b/cpp/events/events_x11.cpp @@ -0,0 +1,55 @@ +// Copyright (C) 2022 RozK +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "../events.hpp" +#include + +unsigned rk_events_mask = KeyPressMask | KeyReleaseMask; +extern Display * rk_display; +extern Window rk_window; + +rk_uint rk_consume_events( + rk_event * events, + rk_uint max_events) { + if (!events || !max_events) { + return 0; + } + XEvent x11_event; + unsigned nevents = 0; + for ( ; nevents < max_events ; ++nevents) { + if (XCheckWindowEvent(rk_display, rk_window, rk_events_mask, &x11_event)) { + rk_event & event = events[nevents]; + switch (x11_event.type) { + case KeyPress: + event.type = RK_EVENT_KEY_PRESS; + event.key.keycode = x11_event.xkey.keycode; + break; + case KeyRelease: + event.type = RK_EVENT_KEY_RELEASE; + event.key.keycode = x11_event.xkey.keycode; + break; + } + } else { + break; + } + } + return nevents; +} + +void rk_flush_events() { + XEvent x11_event; + while (XCheckWindowEvent(rk_display, rk_window, rk_events_mask, &x11_event)) { + } +} diff --git a/cpp/opengl/render_context_glx.cpp b/cpp/opengl/render_context_glx.cpp index dbf8f40..9ed7ed3 100644 --- a/cpp/opengl/render_context_glx.cpp +++ b/cpp/opengl/render_context_glx.cpp @@ -21,9 +21,10 @@ #include #include -static Display * rk_display = nullptr; +Display * rk_display = nullptr; +Window rk_window = 0; +extern unsigned rk_events_mask; static Colormap rk_colormap = 0; -static Window rk_window = 0; static GLXContext rk_context = nullptr; static bool rk_error_occured = false; @@ -146,7 +147,7 @@ rk_window_t rk_create_context( swa.colormap = rk_colormap; swa.background_pixmap = None; swa.border_pixel = 0; - swa.event_mask = StructureNotifyMask; + swa.event_mask = rk_events_mask; rk_window = XCreateWindow(rk_display, RootWindow(rk_display, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);