Added logging and X11 Keymap translation. Also various bugfixes.

This commit is contained in:
Patrick 2025-10-04 16:38:45 +02:00
commit 54a0f5eb4e
16 changed files with 181 additions and 57 deletions

View file

@ -1,6 +1,4 @@
#include <pgpl.h>
#include <stdio.h>
#include <stdlib.h>
static bool pgpl_gui_internal_event_loop(PGPL_Window *window,
@ -37,7 +35,8 @@ static bool pgpl_gui_internal_event_loop(PGPL_Window *window,
pgpl_gui_destroy(gui, true);
return false;
} else if (event_type == PGPL_WINDOW_EVENT_ERROR) {
printf("PGPL_Window has experienced an unexpected error!\nExiting...");
pgpl_log_message(PGPL_LOG_LEVEL_ERROR,
"PGPL_Window has experienced an unexpected error!");
} else {
uint32_t width, height;
uint32_t length = pgpl_vector_get_length(gui->widgets);

View file

@ -45,24 +45,21 @@ static void event(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme, PGPL_Gui *gui,
if (event_type == PGPL_WINDOW_EVENT_MOUSE_PRESS &&
event_data->input_event.key == PGPL_WINDOW_MOUSE_BUTTON_LEFT) {
widget->gui_color = PGPL_GUI_STATUS_COLOR_ACTIVE;
return;
} else if (event_type == PGPL_WINDOW_EVENT_MOUSE_RELEASE &&
event_data->input_event.key == PGPL_WINDOW_MOUSE_BUTTON_LEFT) {
if (widget->gui_color == PGPL_GUI_STATUS_COLOR_ACTIVE) {
button_widget->click_callback(gui->app_data);
}
widget->gui_color = PGPL_GUI_STATUS_COLOR_HOVER;
return;
} else {
if (widget->gui_color != PGPL_GUI_STATUS_COLOR_ACTIVE) {
widget->gui_color = PGPL_GUI_STATUS_COLOR_HOVER;
}
return;
}
} else {
widget->gui_color = PGPL_GUI_STATUS_COLOR_NORMAL;
}
}
widget->gui_color = PGPL_GUI_STATUS_COLOR_NORMAL;
}
static void destroy(PGPL_GuiWidget *widget) {

46
src/log.c Normal file
View file

@ -0,0 +1,46 @@
#include <pgpl.h>
#include <stdarg.h>
#include <stdio.h>
extern PGPL_Mutex *pgpl_internal_log_lock;
extern FILE *pgpl_internal_log_file;
static PGPL_LogLevel pgpl_log_internal_minimum_level = PGPL_LOG_LEVEL_ERROR;
void pgpl_log_set_minimum_level(PGPL_LogLevel level) {
pgpl_log_internal_minimum_level = level;
}
void pgpl_log_output_file(FILE *file) { pgpl_internal_log_file = file; }
void pgpl_log_message(PGPL_LogLevel level, const char *format, ...) {
va_list args;
va_start(args, format);
pgpl_mutex_lock(pgpl_internal_log_lock);
if (level >= pgpl_log_internal_minimum_level) {
switch (level) {
case PGPL_LOG_LEVEL_DEBUG:
fprintf(pgpl_internal_log_file, "[DEBUG] ");
break;
case PGPL_LOG_LEVEL_INFO:
fprintf(pgpl_internal_log_file, "[INFO] ");
break;
case PGPL_LOG_LEVEL_WARN:
fprintf(pgpl_internal_log_file, "[WARN] ");
break;
case PGPL_LOG_LEVEL_ERROR:
fprintf(pgpl_internal_log_file, "[ERROR] ");
break;
}
vfprintf(pgpl_internal_log_file, format, args);
fputc('\n', pgpl_internal_log_file);
}
va_end(args);
pgpl_mutex_unlock(pgpl_internal_log_lock);
}

View file

@ -1,7 +1,16 @@
#include <pgpl.h>
PGPL_Mutex *render_lock;
PGPL_Mutex *pgpl_internal_render_lock;
PGPL_Mutex *pgpl_internal_log_lock;
FILE *pgpl_internal_log_file;
void pgpl_init(void) { render_lock = pgpl_mutex_create(); }
void pgpl_init(void) {
pgpl_internal_render_lock = pgpl_mutex_create();
pgpl_internal_log_lock = pgpl_mutex_create();
pgpl_internal_log_file = stderr;
}
void pgpl_deinit(void) { pgpl_mutex_destroy(render_lock); }
void pgpl_deinit(void) {
pgpl_mutex_destroy(pgpl_internal_render_lock);
pgpl_mutex_destroy(pgpl_internal_log_lock);
}

View file

@ -9,10 +9,6 @@
#define STBTT_STATIC
#include <stb/stb_truetype.h>
#ifdef __WIN32__
#include <windows.h>
#endif
#define CHAR_AMOUNT 256
#define BANK_AMOUNT 256
@ -30,26 +26,6 @@ struct PGPL_Font {
uint8_t *data;
};
/* Converts a string to a wide string, don't forget to call free() on the
* returned pointer. */
static wchar_t *str_to_wstr(const char *str) {
size_t length = strlen(str);
wchar_t *wstr = malloc((length + 1) * sizeof(*wstr));
setlocale(LC_ALL, "en_US.UTF-8");
/* mbstowcs works just fine with UTF-8 strings on most platforms, except on
* Windows, where we have to use MultiByteToWideChar to do the exact same
* thing. */
#if defined(__WIN32__)
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, str, -1, wstr, length + 1);
#else
mbstowcs(wstr, str, length + 1);
#endif
return wstr;
}
PGPL_Font *pgpl_font_create_from_file(const char *filename,
uint32_t glyph_size) {
PGPL_Font *font;
@ -58,7 +34,7 @@ PGPL_Font *pgpl_font_create_from_file(const char *filename,
uint8_t *font_data;
if (font_file == NULL) {
perror("Failed to open font");
pgpl_log_message(PGPL_LOG_LEVEL_ERROR, "Failed to open font!");
return NULL;
}
@ -158,7 +134,7 @@ void pgpl_font_render_glyph(PGPL_Renderer *renderer, PGPL_Font *font, wchar_t c,
void pgpl_font_render_string(PGPL_Renderer *renderer, PGPL_Font *font,
const char *str, PGPL_Color color, double x,
double y, double size) {
wchar_t *wstr = str_to_wstr(str);
wchar_t *wstr = pgpl_string_to_wide_string(str);
pgpl_font_render_wstring(renderer, font, wstr, color, x, y, size);
@ -213,11 +189,10 @@ void pgpl_font_glyph_dimensions(PGPL_Font *font, wchar_t c, double size,
}
/* Calculates the coordinates of an entire string. Also returns them in the
* passed pointers.
*/
* passed pointers. */
void pgpl_font_string_dimensions(PGPL_Font *font, const char *str, double size,
PGPL_Rectangle *rectangle) {
wchar_t *wstr = str_to_wstr(str);
wchar_t *wstr = pgpl_string_to_wide_string(str);
pgpl_font_wstring_dimensions(font, wstr, size, rectangle);

View file

@ -19,7 +19,8 @@ pgpl_render_create_texture_file_memory(PGPL_Renderer *renderer,
texture = pgpl_render_create_texture(renderer, data, x, y, filter,
PGPL_TEXTURE_FORMAT_RGBA);
} else {
fprintf(stderr, "Failed to open image: %s\n", stbi_failure_reason());
pgpl_log_message(PGPL_LOG_LEVEL_ERROR, "Failed to open image: %s\n",
stbi_failure_reason());
return NULL;
}
@ -38,7 +39,8 @@ PGPL_Texture *pgpl_render_create_texture_file(PGPL_Renderer *renderer,
texture = pgpl_render_create_texture(renderer, data, x, y, filter,
PGPL_TEXTURE_FORMAT_RGBA);
} else {
fprintf(stderr, "Failed to open image: %s\n", stbi_failure_reason());
pgpl_log_message(PGPL_LOG_LEVEL_ERROR, "Failed to open image: %s\n",
stbi_failure_reason());
return NULL;
}

26
src/string.c Normal file
View file

@ -0,0 +1,26 @@
#include <locale.h>
#include <pgpl.h>
#include <stdlib.h>
#include <string.h>
#ifdef __WIN32__
#include <windows.h>
#endif
wchar_t *pgpl_string_to_wide_string(const char *str) {
size_t length = strlen(str);
wchar_t *wstr = malloc((length + 1) * sizeof(*wstr));
setlocale(LC_ALL, "en_US.UTF-8");
/* mbstowcs works just fine with UTF-8 strings on most platforms, except on
* Windows, where we have to use MultiByteToWideChar to do the exact same
* thing. */
#if defined(__WIN32__)
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, str, -1, wstr, length + 1);
#else
mbstowcs(wstr, str, length + 1);
#endif
return wstr;
}

View file

@ -5,7 +5,7 @@
/* This is needed if there are multiple windows open. Created by pgpl_init,
* destroyed by pgpl_deinit. */
extern PGPL_Mutex *render_lock;
extern PGPL_Mutex *pgpl_internal_render_lock;
typedef struct PGPL_WindowShared {
double scale;

View file

@ -319,13 +319,13 @@ void pgpl_window_reparent_to(PGPL_Window *window, void *parent) {
void *pgpl_window_get_raw_window(PGPL_Window *window) { return window->hwnd; }
void pgpl_window_internal_start_render(PGPL_Window *window) {
pgpl_mutex_lock(render_lock);
pgpl_mutex_lock(pgpl_internal_render_lock);
wglMakeCurrent(window->hdc, window->wgl_context);
}
void pgpl_window_internal_finish_render(PGPL_Window *window) {
wglSwapLayerBuffers(window->hdc, WGL_SWAP_MAIN_PLANE);
pgpl_mutex_unlock(render_lock);
pgpl_mutex_unlock(pgpl_internal_render_lock);
}
#endif

View file

@ -2,6 +2,7 @@
#include "internal.h"
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
struct PGPL_Window {
@ -144,10 +145,29 @@ void pgpl_window_set_position(PGPL_Window *window, int32_t x, int32_t y) {
XFlush(window->display);
}
static int32_t pgpl_window_internal_get_key(XKeyEvent *key_event) {
KeySym key_sym;
char buffer[32];
wchar_t *wbuffer;
int32_t character = 0;
int length =
XLookupString(key_event, buffer, sizeof(buffer) - 1, &key_sym, NULL);
buffer[length] = '\0';
if (length != 0) {
wbuffer = pgpl_string_to_wide_string(buffer);
character = wbuffer[0];
} else {
/* TODO: Handle control characters. */
}
return character;
}
/* This fetches the event from X11 and translates it to our own format, returns
* an Error if the Event was unknown.
*
* TODO: Translate the keymaps */
* an Error if the Event was unknown. */
PGPL_WindowEventType
pgpl_window_internal_fetch_window_event(PGPL_Window *window,
PGPL_WindowEventData *event_data) {
@ -159,7 +179,7 @@ pgpl_window_internal_fetch_window_event(PGPL_Window *window,
if (event_data != NULL) {
event_data->input_event.x = event.xkey.x;
event_data->input_event.y = event.xkey.y;
event_data->input_event.key = event.xkey.keycode;
event_data->input_event.key = pgpl_window_internal_get_key(&event.xkey);
}
return PGPL_WINDOW_EVENT_KEY_PRESS;
break;
@ -167,7 +187,7 @@ pgpl_window_internal_fetch_window_event(PGPL_Window *window,
if (event_data != NULL) {
event_data->input_event.x = event.xkey.x;
event_data->input_event.y = event.xkey.y;
event_data->input_event.key = event.xkey.keycode;
event_data->input_event.key = pgpl_window_internal_get_key(&event.xkey);
}
return PGPL_WINDOW_EVENT_KEY_RELEASE;
break;
@ -221,12 +241,12 @@ void *pgpl_window_get_raw_window(PGPL_Window *window) {
}
void pgpl_window_internal_start_render(PGPL_Window *window) {
pgpl_mutex_lock(render_lock);
pgpl_mutex_lock(pgpl_internal_render_lock);
glXMakeCurrent(window->display, window->window, window->glx_context);
}
void pgpl_window_internal_finish_render(PGPL_Window *window) {
glXSwapBuffers(window->display, window->window);
pgpl_mutex_unlock(render_lock);
pgpl_mutex_unlock(pgpl_internal_render_lock);
}
#endif