WIP(zephr): window icon. basic ui button

- zephr: added ability to assign an icon to a window
- zephr: added a basic ui button with hover and click states and cursor
  change
This commit is contained in:
2023-12-17 03:52:35 +02:00
parent 499591162e
commit 2fc8ac6456
9 changed files with 8202 additions and 27 deletions
+2
View File
@@ -0,0 +1,2 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
+7985
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,9 +1,9 @@
BIN=c2048 BIN=c2048
CC=gcc CC=gcc
CFLAGS=-Wall -Wextra -Werror -Wfloat-conversion -Wimplicit-fallthrough -pedantic -g `pkg-config --cflags freetype2` -I3rdparty/glad/include -I3rdparty/fmod/include CFLAGS=-Wall -Wextra -Werror -Wfloat-conversion -Wimplicit-fallthrough -pedantic -g `pkg-config --cflags freetype2` -I3rdparty/glad/include -I3rdparty/fmod/include -I3rdparty/stb/
OBJ=main.o game.o core.o shader.o text.o audio.o timer.o ui.o zephr.o zephr_math.o 3rdparty/glad/src/gl.o 3rdparty/glad/src/glx.o OBJ=main.o game.o core.o shader.o text.o audio.o timer.o ui.o zephr.o zephr_math.o 3rdparty/glad/src/gl.o 3rdparty/glad/src/glx.o 3rdparty/stb/stb.o
LDFLAGS=`pkg-config --libs x11 freetype2` -lm -L3rdparty/fmod/lib -Wl,-rpath=3rdparty/fmod/lib -lfmod LDFLAGS=`pkg-config --libs x11 freetype2` -lm -L3rdparty/fmod/lib -Wl,-rpath=3rdparty/fmod/lib -lfmod
DEPS=3rdparty/glad/include/glad/gl.h 3rdparty/glad/include/glad/glx.h 3rdparty/fmod/include/fmod.h DEPS=3rdparty/glad/include/glad/gl.h 3rdparty/glad/include/glad/glx.h 3rdparty/fmod/include/fmod.h 3rdparty/stb/stb_image.h
%.o: %.c $(DEPS) %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

+2 -1
View File
@@ -5,13 +5,14 @@
const char *font_path = "assets/fonts/Rubik/Rubik-VariableFont_wght.ttf"; const char *font_path = "assets/fonts/Rubik/Rubik-VariableFont_wght.ttf";
/* const char *font_path = "assets/fonts/Roboto/Roboto-Bold.ttf"; */ /* const char *font_path = "assets/fonts/Roboto/Roboto-Bold.ttf"; */
const char *game_icon_path = "assets/icon-128x128.png";
const char *title = "C2048"; const char *title = "C2048";
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
CORE_UNUSED(argc); CORE_UNUSED(argc);
CORE_UNUSED(argv); CORE_UNUSED(argv);
zephr_init(font_path, title, (Size){1200, 800}); zephr_init(font_path, game_icon_path, title, (Size){1200, 800});
zephr_make_window_non_resizable(); zephr_make_window_non_resizable();
/* zephr_toggle_fullscreen(); */ /* zephr_toggle_fullscreen(); */
+57 -4
View File
@@ -9,10 +9,7 @@ Shader ui_shader;
unsigned int ui_vao; unsigned int ui_vao;
unsigned int ui_vbo; unsigned int ui_vbo;
int init_ui(const char* font_path, Size window_size) { int init_ui(const char* font_path) {
zephr_ctx->window.size = window_size;
zephr_ctx->projection = orthographic_projection_2d(0.f, window_size.width, window_size.height, 0.f);
int res = init_fonts(font_path); int res = init_fonts(font_path);
if (res == -1) { if (res == -1) {
printf("[ERROR]: could not initialize freetype library\n"); printf("[ERROR]: could not initialize freetype library\n");
@@ -122,6 +119,11 @@ void apply_constraints(UIConstraints *constraints, Vec2f *pos, Sizef *size) {
*size = (Sizef){constraints->width, constraints->height}; *size = (Sizef){constraints->width, constraints->height};
} }
void apply_constraints_rect(UIConstraints *constraints, Rect *rect) {
rect->pos = (Vec2f){constraints->x, constraints->y};
rect->size = (Sizef){constraints->width, constraints->height};
}
void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Sizef size) { void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Sizef size) {
// if we don't have a parent then we're a top level element and we should align against the window // if we don't have a parent then we're a top level element and we should align against the window
Sizef parent_size = (Sizef){zephr_ctx->window.size.width, zephr_ctx->window.size.height}; Sizef parent_size = (Sizef){zephr_ctx->window.size.width, zephr_ctx->window.size.height};
@@ -269,6 +271,57 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig
glBindVertexArray(0); glBindVertexArray(0);
} }
bool inside_rect(Rect *rect, Vec2 *point) {
if (point->x >= rect->pos.x && point->x <= rect->pos.x + rect->size.width &&
point->y >= rect->pos.y && point->y <= rect->pos.y + rect->size.height) {
return true;
}
return false;
}
bool draw_button(UIConstraints *constraints, const Color color, const char *text, f32 radius, Alignment align) {
Rect rect = {0};
apply_constraints(constraints, &rect.pos, &rect.size);
apply_alignment(align, constraints, &rect.pos, rect.size);
if (inside_rect(&rect, &zephr_ctx->mouse.pos)) {
zephr_set_cursor(ZEPHR_CURSOR_HAND);
if (zephr_ctx->mouse.pressed) {
Color new_color = mult_color(color, 0.8f);
draw_quad(constraints, new_color, radius, align);
} else {
Color new_color = mult_color(color, 0.9f);
draw_quad(constraints, new_color, radius, align);
}
} else {
zephr_set_cursor(ZEPHR_CURSOR_ARROW);
draw_quad(constraints, color, radius, align);
}
if (text) {
UIConstraints text_constraints = {0};
set_parent_constraint(&text_constraints, constraints);
set_x_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&text_constraints, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
u8 font_size = (u8)(constraints->width * 0.2 / text_constraints.width * 0.2 * 100.f);
// TODO: need to adjust the font size based on the text height
draw_text(text, font_size, text_constraints, COLOR_BLACK, ALIGN_CENTER);
}
if (inside_rect(&rect, &zephr_ctx->mouse.pos) && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
return true;
}
return false;
}
/* enum Element { */ /* enum Element { */
/* Rect, */ /* Rect, */
/* Circle, */ /* Circle, */
+7 -1
View File
@@ -2,6 +2,11 @@
#include "zephr_math.h" #include "zephr_math.h"
typedef struct Rect {
Vec2f pos;
Sizef size;
} Rect;
typedef enum Alignment { typedef enum Alignment {
ALIGN_TOP_LEFT, ALIGN_TOP_LEFT,
ALIGN_TOP_CENTER, ALIGN_TOP_CENTER,
@@ -30,7 +35,7 @@ typedef struct UIConstraints {
struct UIConstraints *parent; struct UIConstraints *parent;
} UIConstraints; } UIConstraints;
int init_ui(const char* font_path, Size window_size); int init_ui(const char* font_path);
void set_parent_constraint(UIConstraints *constraints, UIConstraints *parent_constraints); void set_parent_constraint(UIConstraints *constraints, UIConstraints *parent_constraints);
void set_x_constraint(UIConstraints *constraints, float value, UIConstraint type); void set_x_constraint(UIConstraints *constraints, float value, UIConstraint type);
void set_y_constraint(UIConstraints *constraints, float value, UIConstraint type); void set_y_constraint(UIConstraints *constraints, float value, UIConstraint type);
@@ -42,3 +47,4 @@ void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Si
void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align); void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align);
void draw_circle(UIConstraints *constraints, const Color color, Alignment align); void draw_circle(UIConstraints *constraints, const Color color, Alignment align);
void draw_triangle(UIConstraints *constraints, const Color color, Alignment align); void draw_triangle(UIConstraints *constraints, const Color color, Alignment align);
bool draw_button(UIConstraints *constraints, const Color color, const char *text, f32 radius, Alignment align);
+121 -16
View File
@@ -3,7 +3,10 @@
#include <string.h> #include <string.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include <glad/glx.h> #include <glad/glx.h>
#include <stb_image.h>
#include "audio.h" #include "audio.h"
#include "core.h" #include "core.h"
@@ -484,6 +487,8 @@ void x11_resize_window(void) {
glViewport(0, 0, win_attrs.width, win_attrs.height); glViewport(0, 0, win_attrs.width, win_attrs.height);
} }
// BUG: fullscreen doesn't work on gnome. may or may not be related to the window being
// opened as a dialog window
void x11_go_fullscreen(void) { void x11_go_fullscreen(void) {
XEvent xev; XEvent xev;
Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
@@ -524,25 +529,60 @@ void x11_toggle_fullscreen(bool fullscreen) {
} }
} }
int x11_create_window(const char* title, int window_width, int window_height) { void x11_assign_window_icon(const char *icon_path) {
int icon_width, icon_height;
unsigned char *icon_data = stbi_load(icon_path, &icon_width, &icon_height, NULL, STBI_rgb_alpha);
CORE_ASSERT(icon_data, "Failed to load icon image\n");
u32 target_size = 2 + icon_width * icon_height;
u64 *data = malloc(target_size * sizeof(u64));
u64 *target = data;
// first two elements are width and height
*target++ = icon_width;
*target++ = icon_height;
for (int i = 0; i < icon_width * icon_height; i++) {
*target++ = (icon_data[i * 4] << 16) | (icon_data[i * 4 + 1] << 8) | (icon_data[i * 4 + 2] << 0) | (icon_data[i * 4 + 3] << 24);
}
Atom net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False);
XChangeProperty(x11_display, x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)data, target_size);
free(data);
stbi_image_free(icon_data);
}
int x11_create_window(const char* title, int window_width, int window_height, const char *icon_path) {
x11_display = XOpenDisplay(NULL); x11_display = XOpenDisplay(NULL);
CORE_ASSERT(x11_display, "Cannot open x11 display connection\n"); CORE_ASSERT(x11_display, "Cannot open x11 display connection\n");
int screen = DefaultScreen(x11_display); int screen_num = DefaultScreen(x11_display);
Window root = RootWindow(x11_display, screen); Window root = RootWindow(x11_display, screen_num);
Visual *visual = DefaultVisual(x11_display, screen); Visual *visual = DefaultVisual(x11_display, screen_num);
x11_colormap = XCreateColormap(x11_display, root, visual, AllocNone); x11_colormap = XCreateColormap(x11_display, root, visual, AllocNone);
XSetWindowAttributes attributes; XSetWindowAttributes attributes;
attributes.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | attributes.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
StructureNotifyMask | ButtonPressMask | ButtonReleaseMask; StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
attributes.colormap = x11_colormap; attributes.colormap = x11_colormap;
x11_window = XCreateWindow(x11_display, root, 0, 0, window_width, window_height, 0, Screen *screen = DefaultScreenOfDisplay(x11_display);
DefaultDepth(x11_display, screen), InputOutput, visual,
int window_start_x = screen->width / 2 - window_width / 2;
int window_start_y = screen->height / 2 - window_height / 2;
x11_window = XCreateWindow(x11_display, root, window_start_x, window_start_y, window_width, window_height, 0,
DefaultDepth(x11_display, screen_num), InputOutput, visual,
CWColormap | CWEventMask, &attributes); CWColormap | CWEventMask, &attributes);
if (icon_path) {
x11_assign_window_icon(icon_path);
}
// Hints to the WM that the window is a dialog window which makes it a floating // Hints to the WM that the window is a dialog window which makes it a floating
// window in tiling WMs (only tested on DWM though) // window in tiling WMs (only tested on DWM though)
// Of course this is only a hint and the WM can ignore it // Of course this is only a hint and the WM can ignore it
@@ -554,12 +594,21 @@ int x11_create_window(const char* title, int window_width, int window_height) {
XSetWMProtocols(x11_display, x11_window, &wm_delete_window, 1); XSetWMProtocols(x11_display, x11_window, &wm_delete_window, 1);
zephr_ctx->window_delete_atom = wm_delete_window; zephr_ctx->window_delete_atom = wm_delete_window;
XMapWindow(x11_display, x11_window); // BUG: window title is broken on gnome's sidebar but works on the window itself.
// sidebar shows "Unknown"
XStoreName(x11_display, x11_window, title); XStoreName(x11_display, x11_window, title);
XTextProperty text_property;
text_property.value = (unsigned char *)title;
text_property.format = 8;
text_property.encoding = XA_STRING;
text_property.nitems = strlen(title);
XSetWMName(x11_display, x11_window, &text_property);
XMapWindow(x11_display, x11_window);
CORE_ASSERT(x11_window, "Failed to create window\n"); CORE_ASSERT(x11_window, "Failed to create window\n");
int glx_version = gladLoaderLoadGLX(x11_display, screen); int glx_version = gladLoaderLoadGLX(x11_display, screen_num);
if (!glx_version) { if (!glx_version) {
printf("[FATAL] Failed to load GLX\n"); printf("[FATAL] Failed to load GLX\n");
@@ -579,7 +628,7 @@ int x11_create_window(const char* title, int window_width, int window_height) {
int num_fbc = 0; int num_fbc = 0;
GLXFBConfig *fbc = GLXFBConfig *fbc =
glXChooseFBConfig(x11_display, screen, visual_attributes, &num_fbc); glXChooseFBConfig(x11_display, screen_num, visual_attributes, &num_fbc);
GLint context_attributes[] = { GLint context_attributes[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
@@ -623,8 +672,8 @@ int x11_create_window(const char* title, int window_width, int window_height) {
return 0; return 0;
} }
int x11_init(const char* title, int window_width, int window_height) { int x11_init(const char* title, int window_width, int window_height, const char *icon_path) {
int res = x11_create_window(title, window_width, window_height); int res = x11_create_window(title, window_width, window_height, icon_path);
/* // loads the XMODIFIERS environment variable to see what IME to use */ /* // loads the XMODIFIERS environment variable to see what IME to use */
/* XSetLocaleModifiers(""); */ /* XSetLocaleModifiers(""); */
@@ -704,19 +753,28 @@ void x11_make_window_non_resizable(int width, int height) {
/////////////////////////// ///////////////////////////
void zephr_init(const char* font_path, const char* window_title, Size window_size) { void zephr_init(const char* font_path, const char* icon_path, const char* window_title, Size window_size) {
zephr_ctx = malloc(sizeof(ZephrContext)); zephr_ctx = malloc(sizeof(ZephrContext));
// TODO: should I initalize the audio here or let the game handle that?? // TODO: should I initalize the audio here or let the game handle that??
int res = audio_init(); int res = audio_init();
CORE_ASSERT(res == 0, "Failed to initialize audio"); CORE_ASSERT(res == 0, "Failed to initialize audio");
res = x11_init(window_title, window_size.width, window_size.height); res = x11_init(window_title, window_size.width, window_size.height, icon_path);
CORE_ASSERT(res == 0, "Failed to initialize X11"); CORE_ASSERT(res == 0, "Failed to initialize X11");
res = init_ui(font_path, (Size){ .width = window_size.width, .height = window_size.height }); res = init_ui(font_path);
CORE_ASSERT(res == 0, "Failed to initialize UI"); CORE_ASSERT(res == 0, "Failed to initialize UI");
zephr_ctx->window.size = window_size;
zephr_ctx->projection = orthographic_projection_2d(0.f, window_size.width, window_size.height, 0.f);
zephr_ctx->cursors[ZEPHR_CURSOR_ARROW] = XCreateFontCursor(x11_display, XC_left_ptr);
zephr_ctx->cursors[ZEPHR_CURSOR_IBEAM] = XCreateFontCursor(x11_display, XC_xterm);
zephr_ctx->cursors[ZEPHR_CURSOR_CROSSHAIR] = XCreateFontCursor(x11_display, XC_crosshair);
zephr_ctx->cursors[ZEPHR_CURSOR_HAND] = XCreateFontCursor(x11_display, XC_hand1);
zephr_ctx->cursors[ZEPHR_CURSOR_HRESIZE] = XCreateFontCursor(x11_display, XC_sb_h_double_arrow);
zephr_ctx->cursors[ZEPHR_CURSOR_VRESIZE] = XCreateFontCursor(x11_display, XC_sb_v_double_arrow);
x11_get_screen_size(&zephr_ctx->screen_size.width, &zephr_ctx->screen_size.height); x11_get_screen_size(&zephr_ctx->screen_size.width, &zephr_ctx->screen_size.height);
start_internal_timer(); start_internal_timer();
} }
@@ -741,6 +799,8 @@ bool zephr_should_quit(void) {
void zephr_swap_buffers(void) { void zephr_swap_buffers(void) {
CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized"); CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized");
zephr_ctx->mouse.released = false;
glXSwapBuffers(x11_display, x11_window); glXSwapBuffers(x11_display, x11_window);
} }
@@ -748,7 +808,7 @@ Size zephr_get_window_size(void) {
return zephr_ctx->window.size; return zephr_ctx->window.size;
} }
// This MUST be called after calling init_zephr() // This MUST be called after calling zephr_init()
void zephr_make_window_non_resizable(void) { void zephr_make_window_non_resizable(void) {
CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized"); CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized");
@@ -901,16 +961,20 @@ bool zephr_iter_events(ZephrEvent *event_out) {
} else if (xev.type == ButtonPress) { } else if (xev.type == ButtonPress) {
event_out->type = ZEPHR_EVENT_MOUSE_BUTTON_PRESSED; event_out->type = ZEPHR_EVENT_MOUSE_BUTTON_PRESSED;
event_out->mouse.position = (Vec2){ .x = xev.xbutton.x, .y = xev.xbutton.y }; event_out->mouse.position = (Vec2){ .x = xev.xbutton.x, .y = xev.xbutton.y };
zephr_ctx->mouse.pressed = true;
switch (xev.xbutton.button) { switch (xev.xbutton.button) {
case Button1: case Button1:
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_LEFT; event_out->mouse.button = ZEPHR_MOUSE_BUTTON_LEFT;
zephr_ctx->mouse.button = ZEPHR_MOUSE_BUTTON_LEFT;
break; break;
case Button2: case Button2:
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_MIDDLE; event_out->mouse.button = ZEPHR_MOUSE_BUTTON_MIDDLE;
zephr_ctx->mouse.button = ZEPHR_MOUSE_BUTTON_MIDDLE;
break; break;
case Button3: case Button3:
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_RIGHT; event_out->mouse.button = ZEPHR_MOUSE_BUTTON_RIGHT;
zephr_ctx->mouse.button = ZEPHR_MOUSE_BUTTON_RIGHT;
break; break;
case Button4: case Button4:
event_out->type = ZEPHR_EVENT_MOUSE_SCROLL; event_out->type = ZEPHR_EVENT_MOUSE_SCROLL;
@@ -922,9 +986,11 @@ bool zephr_iter_events(ZephrEvent *event_out) {
break; break;
case 8: // Back case 8: // Back
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_BACK; event_out->mouse.button = ZEPHR_MOUSE_BUTTON_BACK;
zephr_ctx->mouse.button = ZEPHR_MOUSE_BUTTON_BACK;
break; break;
case 9: // Forward case 9: // Forward
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_FORWARD; event_out->mouse.button = ZEPHR_MOUSE_BUTTON_FORWARD;
zephr_ctx->mouse.button = ZEPHR_MOUSE_BUTTON_FORWARD;
break; break;
default: default:
printf("[WARN] Unknown mouse button pressed: %d\n", xev.xbutton.button); printf("[WARN] Unknown mouse button pressed: %d\n", xev.xbutton.button);
@@ -935,6 +1001,8 @@ bool zephr_iter_events(ZephrEvent *event_out) {
} else if (xev.type == ButtonRelease) { } else if (xev.type == ButtonRelease) {
event_out->type = ZEPHR_EVENT_MOUSE_BUTTON_RELEASED; event_out->type = ZEPHR_EVENT_MOUSE_BUTTON_RELEASED;
event_out->mouse.position = (Vec2){ .x = xev.xbutton.x, .y = xev.xbutton.y }; event_out->mouse.position = (Vec2){ .x = xev.xbutton.x, .y = xev.xbutton.y };
zephr_ctx->mouse.released = true;
zephr_ctx->mouse.pressed = false;
switch (xev.xbutton.button) { switch (xev.xbutton.button) {
case Button1: case Button1:
@@ -957,12 +1025,49 @@ bool zephr_iter_events(ZephrEvent *event_out) {
XRefreshKeyboardMapping(&xev.xmapping); XRefreshKeyboardMapping(&xev.xmapping);
/* x11_keyboard_map_update(); */ /* x11_keyboard_map_update(); */
break; break;
} else if (xev.type == MotionNotify) {
event_out->type = ZEPHR_EVENT_MOUSE_MOVED;
event_out->mouse.position = (Vec2){ .x = xev.xmotion.x, .y = xev.xmotion.y };
zephr_ctx->mouse.pos = event_out->mouse.position;
return true;
} }
} }
return false; return false;
} }
void zephr_set_cursor(ZephrCursor cursor) {
if (zephr_ctx->cursor == cursor) {
return;
}
zephr_ctx->cursor = cursor;
switch (cursor) {
case ZEPHR_CURSOR_ARROW:
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_ARROW]);
break;
case ZEPHR_CURSOR_IBEAM:
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_IBEAM]);
break;
case ZEPHR_CURSOR_CROSSHAIR:
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_CROSSHAIR]);
break;
case ZEPHR_CURSOR_HAND:
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_HAND]);
break;
case ZEPHR_CURSOR_HRESIZE:
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_HRESIZE]);
break;
case ZEPHR_CURSOR_VRESIZE:
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_VRESIZE]);
break;
default :
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_ARROW]);
break;
}
}
/* bool zephr_keyboard_scancode_is_pressed(ZephrScancode scancode) { */ /* bool zephr_keyboard_scancode_is_pressed(ZephrScancode scancode) { */
/* return core_bitset_is_set(zephr_ctx.keyboard.scancode_is_pressed_bitset, scancode); */ /* return core_bitset_is_set(zephr_ctx.keyboard.scancode_is_pressed_bitset, scancode); */
/* } */ /* } */
+25 -2
View File
@@ -32,7 +32,8 @@ typedef enum ZephrEventType {
ZEPHR_EVENT_MOUSE_BUTTON_RELEASED, ZEPHR_EVENT_MOUSE_BUTTON_RELEASED,
ZEPHR_EVENT_MOUSE_SCROLL, ZEPHR_EVENT_MOUSE_SCROLL,
ZEPHR_EVENT_WINDOW_RESIZED, ZEPHR_EVENT_WINDOW_RESIZED,
ZEPHR_EVENT_WINDOW_CLOSED ZEPHR_EVENT_WINDOW_CLOSED,
ZEPHR_EVENT_MOUSE_MOVED,
} ZephrEventType; } ZephrEventType;
typedef enum ZephrMouseScrollDirection { typedef enum ZephrMouseScrollDirection {
@@ -53,6 +54,17 @@ typedef enum ZephrMouseButton {
ZEPHR_MOUSE_BUTTON_7, ZEPHR_MOUSE_BUTTON_7,
} ZephrMouseButton; } ZephrMouseButton;
typedef enum ZephrCursor {
ZEPHR_CURSOR_ARROW,
ZEPHR_CURSOR_IBEAM,
ZEPHR_CURSOR_CROSSHAIR,
ZEPHR_CURSOR_HAND,
ZEPHR_CURSOR_HRESIZE,
ZEPHR_CURSOR_VRESIZE,
ZEPHR_CURSOR_COUNT,
} ZephrCursor;
typedef u16 ZephrScancode; typedef u16 ZephrScancode;
typedef u16 ZephrKeycode; typedef u16 ZephrKeycode;
@@ -351,12 +363,22 @@ typedef struct ZephrEvent {
} ZephrEvent; } ZephrEvent;
/* CORE_DEFINE_STACK(ZephrEvent); */ /* CORE_DEFINE_STACK(ZephrEvent); */
typedef struct ZephrMouse {
Vec2 pos;
bool pressed;
bool released;
ZephrMouseButton button;
} ZephrMouse;
typedef struct ZephrContext { typedef struct ZephrContext {
Atom window_delete_atom; Atom window_delete_atom;
bool should_quit; bool should_quit;
Size screen_size; Size screen_size;
ZephrWindow window; ZephrWindow window;
ZephrFont font; ZephrFont font;
ZephrMouse mouse;
ZephrCursor cursor;
ZephrCursor cursors[ZEPHR_CURSOR_COUNT];
/* ZephrKeyboard keyboard; */ /* ZephrKeyboard keyboard; */
/* XkbDescPtr xkb; */ /* XkbDescPtr xkb; */
/* XIM xim; */ /* XIM xim; */
@@ -366,7 +388,7 @@ typedef struct ZephrContext {
Matrix4x4 projection; Matrix4x4 projection;
} ZephrContext; } ZephrContext;
void zephr_init(const char* font_path, const char* window_title, Size window_size); void zephr_init(const char* font_path, const char* icon_path, const char* window_title, Size window_size);
void zephr_deinit(void); void zephr_deinit(void);
bool zephr_should_quit(void); bool zephr_should_quit(void);
void zephr_swap_buffers(void); void zephr_swap_buffers(void);
@@ -376,6 +398,7 @@ void zephr_toggle_fullscreen(void);
void zephr_quit(void); void zephr_quit(void);
Color ColorRGBA(u8 r, u8 g, u8 b, u8 a); Color ColorRGBA(u8 r, u8 g, u8 b, u8 a);
bool zephr_iter_events(ZephrEvent *event_out); bool zephr_iter_events(ZephrEvent *event_out);
void zephr_set_cursor(ZephrCursor cursor);
/* bool zephr_keyboard_keycode_is_pressed(ZephrKeycode keycode); */ /* bool zephr_keyboard_keycode_is_pressed(ZephrKeycode keycode); */
/* bool zephr_keyboard_keycode_has_been_pressed(ZephrKeycode keycode); */ /* bool zephr_keyboard_keycode_has_been_pressed(ZephrKeycode keycode); */