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);