summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLevent Kaya <levent.kaya@codefirst.io>2024-11-26 18:54:55 +0300
committerLevent Kaya <levent.kaya@codefirst.io>2024-11-26 18:54:55 +0300
commit51b1a6304a7bc832ac2998e2e123c63894cb9ac4 (patch)
treeaf08e338e346ef6c6e79e658e0cb05b68f07a69a
parentc3252d07e4b03227b50a0564c2036be2dae61b7f (diff)
[feature] added keyboard events
-rw-r--r--CMakeLists.txt1
-rw-r--r--examples/keyboard.c91
-rw-r--r--fbgl.h91
3 files changed, 182 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e47cc2c..69efb9d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,3 +31,4 @@ add_example(raw_mode)
add_example(framebuf_info)
add_example(text)
add_example(texture_show_fps)
+add_example(keyboard)
diff --git a/examples/keyboard.c b/examples/keyboard.c
new file mode 100644
index 0000000..51a488e
--- /dev/null
+++ b/examples/keyboard.c
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <stdbool.h>
+#define FBGL_IMPLEMENTATION
+#include "fbgl.h"
+
+#define RECT_WIDTH 50
+#define RECT_HEIGHT 30
+#define MOVE_STEP 10
+#define BG_COLOR 0x000000 // Black
+#define RECT_COLOR 0xFFFFFF // White
+
+int main(void)
+{
+ // Initialize framebuffer
+ fbgl_t framebuffer;
+ if (fbgl_init(NULL, &framebuffer) != 0) {
+ fprintf(stderr, "Failed to initialize framebuffer\n");
+ return EXIT_FAILURE;
+ }
+
+ // Initialize keyboard
+ if (fbgl_keyboard_init() != 0) {
+ fprintf(stderr, "Failed to initialize keyboard\n");
+ fbgl_destroy(&framebuffer);
+ return EXIT_FAILURE;
+ }
+
+ atexit(fbgl_keyboard_clean); // Cleanup on exit
+ atexit((void (*)(void))fbgl_destroy, &framebuffer);
+
+ // Initial rectangle position
+ fbgl_point_t top_left = {framebuffer.width / 2 - RECT_WIDTH / 2, framebuffer.height / 2 - RECT_HEIGHT / 2};
+ fbgl_point_t bottom_right = {top_left.x + RECT_WIDTH, top_left.y + RECT_HEIGHT};
+
+ // Main loop
+ while (!fbgl_check_esc_key()) {
+ // Update keyboard state
+ fbgl_keyboard_update();
+
+ // Clear screen
+ fbgl_set_bg(&framebuffer, BG_COLOR);
+
+ // Move rectangle based on key input
+ if (fbgl_key_down('w')) {
+ top_left.y -= MOVE_STEP;
+ bottom_right.y -= MOVE_STEP;
+ }
+ if (fbgl_key_down('s')) {
+ top_left.y += MOVE_STEP;
+ bottom_right.y += MOVE_STEP;
+ }
+ if (fbgl_key_down('a')) {
+ top_left.x -= MOVE_STEP;
+ bottom_right.x -= MOVE_STEP;
+ }
+ if (fbgl_key_down('d')) {
+ top_left.x += MOVE_STEP;
+ bottom_right.x += MOVE_STEP;
+ }
+
+ // Ensure rectangle stays within screen bounds
+ if (top_left.x < 0) {
+ top_left.x = 0;
+ bottom_right.x = RECT_WIDTH;
+ }
+ if (top_left.y < 0) {
+ top_left.y = 0;
+ bottom_right.y = RECT_HEIGHT;
+ }
+ if (bottom_right.x > framebuffer.width) {
+ bottom_right.x = framebuffer.width;
+ top_left.x = framebuffer.width - RECT_WIDTH;
+ }
+ if (bottom_right.y > framebuffer.height) {
+ bottom_right.y = framebuffer.height;
+ top_left.y = framebuffer.height - RECT_HEIGHT;
+ }
+
+ // Draw the rectangle
+ fbgl_draw_rectangle_filled(top_left, bottom_right, RECT_COLOR, &framebuffer);
+
+ // Refresh frame (add a delay if needed)
+ usleep(16000); // ~60 FPS
+ }
+
+ // Cleanup
+ fbgl_keyboard_clean();
+ fbgl_destroy(&framebuffer);
+
+ return EXIT_SUCCESS;
+}
diff --git a/fbgl.h b/fbgl.h
index f34bca0..c511ad2 100644
--- a/fbgl.h
+++ b/fbgl.h
@@ -190,9 +190,9 @@ void fbgl_render_psf1_text(fbgl_t *fb, fbgl_psf1_font_t *font, const char *text,
int fbgl_keyboard_init(void);
void fbgl_keyboard_clean(void);
void fbgl_keyboard_update(void);
+bool fbgl_key_down(unsigned char key);
bool fbgl_key_pressed(unsigned char key);
bool fbgl_key_released(unsigned char key);
-bool fbgl_key_down(unsigned char key);
#ifdef FBGL_IMPLEMENTATION
@@ -732,6 +732,95 @@ void fbgl_render_psf1_text(fbgl_t *fb, fbgl_psf1_font_t *font, const char *text,
}
}
+int fbgl_keyboard_init(void)
+{
+ if (keyboard.is_initialized) {
+ return 0; // Already initialized
+ }
+
+ struct termios raw;
+
+ if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) {
+ perror("tcgetattr");
+ return -1;
+ }
+
+ raw = orig_termios;
+ raw.c_lflag &= ~(ECHO | ICANON); // Disable echo and canonical mode
+ raw.c_cc[VMIN] = 0; // Non-blocking read
+ raw.c_cc[VTIME] = 0; // No timeout
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
+ perror("tcsetattr");
+ return -1;
+ }
+
+ memset(&keyboard, 0, sizeof(fbgl_keyboard_t));
+ keyboard.is_initialized = true;
+ return 0;
+}
+
+void fbgl_keyboard_clean(void)
+{
+ if (!keyboard.is_initialized) {
+ return;
+ }
+
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) {
+ perror("tcsetattr");
+ }
+
+ keyboard.is_initialized = false;
+}
+
+void fbgl_keyboard_update(void)
+{
+ if (!keyboard.is_initialized) {
+ return;
+ }
+
+ // Copy current state to previous state
+ memcpy(keyboard.prev_keys, keyboard.keys, sizeof(keyboard.keys));
+
+ char c;
+ while (read(STDIN_FILENO, &c, 1) > 0) {
+ if (c >= 0 && c < FBGL_MAX_KEYS) {
+ keyboard.keys[(unsigned char)c] = true;
+ }
+ }
+
+ // Reset keys that are not pressed
+ for (int i = 0; i < FBGL_MAX_KEYS; i++) {
+ if (!keyboard.keys[i]) {
+ keyboard.keys[i] = false;
+ }
+ }
+}
+
+
+bool fbgl_key_down(unsigned char key)
+{
+ if (key >= FBGL_MAX_KEYS) {
+ return false;
+ }
+ return keyboard.keys[key];
+}
+
+bool fbgl_key_pressed(unsigned char key)
+{
+ if (key >= FBGL_MAX_KEYS) {
+ return false;
+ }
+ return keyboard.keys[key] && !keyboard.prev_keys[key];
+}
+
+bool fbgl_key_released(unsigned char key)
+{
+ if (key >= FBGL_MAX_KEYS) {
+ return false;
+ }
+ return !keyboard.keys[key] && keyboard.prev_keys[key];
+}
+
#endif // FBGL_IMPLEMENTATION
#ifdef __cplusplus