1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
#pragma once
#if !(defined(STELA_API_NULL) || defined(STELA_API_OPENGL) || \
defined(STELA_API_VULKAN) || defined(STELA_API_DX11))
#error "No graphics API defined."
#endif
#if defined(STELA_API_NULL) + defined(STELA_API_OPENGL) + \
defined(STELA_API_VULKAN) + defined(STELA_API_DX11) != 1
#error "Conflicting graphics APIs."
#endif
#if !(defined(STELA_POLL_FD) || defined(STELA_POLL_INLINE))
#error "No poll method defined."
#endif
#include <al/types.h>
#include <al/lib.h>
#include <al/str.h>
#ifdef STELA_EVENT_BUFFER
#include <al/ring_buffer.h>
#endif
#if defined STELA_API_VULKAN
#if defined STELA_WINDOW_WIN32
#define VK_USE_PLATFORM_WIN32_KHR
#elif defined STELA_WINDOW_WAYLAND
#define VK_USE_PLATFORM_WAYLAND_KHR
#elif defined STELA_WINDOW_X11
#define VK_USE_PLATFORM_XLIB_KHR
#endif
#include <vulkan/vulkan.h>
#elif defined STELA_API_DX11
#include <nnwt/windows.h>
#elif defined STELA_API_OPENGL && defined STELA_USE_EGL
#include "egl_common.h"
#endif
#ifndef STELA_MIN_WIDTH
#define STELA_MIN_WIDTH 16u
#endif
#ifndef STELA_MIN_HEIGHT
#define STELA_MIN_HEIGHT 16u
#endif
#ifdef STELA_WINDOW_WAYLAND
#define STELA_ICON_AT_RUNTIME
#endif
// Drag window by clicking anywhere with MOUSE2.
#define STELA_MOUSE2_DRAG
enum {
STELA_WINDOW_VSYNC = 1,
STELA_WINDOW_WALLPAPER = 1 << 1
};
enum {
STELA_CURSOR_NORMAL = 0,
STELA_CURSOR_MOVE,
STELA_CURSOR_CROSSHAIR,
STELA_CURSOR_HIDDEN
};
#define STELA_MAX_MONITOR_NAME 255u
struct stl_monitor {
u32 width;
u32 height;
u32 scale;
bool vertical;
char name[STELA_MAX_MONITOR_NAME];
};
#define STELA_EVENT_SIZE 24u
#ifndef STELA_EVENTS_SIZE
#define STELA_EVENTS_SIZE (STELA_EVENT_SIZE * 64u)
#endif
struct stl_window {
u32 width;
u32 height;
u32 scale;
bool fullscreen;
u32 flags;
// Methods.
bool (*create_window)(struct stl_window *, u32, u32, u32, const char *, const char *, const char *);
void (*resize_internal)(struct stl_window *, u32, u32);
void (*resize)(struct stl_window *, u32, u32);
void (*toggle_fullscreen)(struct stl_window *);
void (*set_cursor)(struct stl_window *window, u8);
void (*set_decorations)(struct stl_window *, bool);
#ifdef STELA_POLL_INLINE
void (*poll)(struct stl_window *, bool);
#ifdef STELA_PAUSE
void (*wake)(struct stl_window *);
#endif
#endif
void (*process_events)(struct stl_window *);
#ifdef STELA_PAUSE
bool (*should_refresh)(struct stl_window *);
#endif
void (*close)(struct stl_window *window);
void (*free)(struct stl_window **);
// Context specific.
#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *);
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *);
VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR);
const char *const *(*vk_get_extensions)(u32 *);
#elif defined STELA_API_DX11
HWND win32_window;
#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
EGLDisplay egl_display;
EGLContext egl_context;
#endif
void (*(*get_gl_proc_address)(const char *))(void);
bool (*gl_loader_load)(void *);
bool (*gl_make_current)(void *);
void (*gl_release_current)(void *);
void (*gl_swap_buffers)(void *);
#endif
// Callbacks.
void (*output_discovered_callback)(void *, struct stl_monitor *);
void (*render_callback)(void *);
void (*resize_callback)(void *, u32, u32);
bool (*pointer_pos_callback)(void *, f64, f64);
bool (*touch_callback)(void *, s32, u8, f64, f64);
bool (*scroll_callback)(void *, f64);
bool (*mouse_button_callback)(void *, u8, u8);
bool (*key_callback)(void *, u8, u16);
// Immediate:
// - Always runs on the thread that received the event.
// - Return value decides if the event should "pass through" or not.
// True = Consume, False = Passthrough.
bool (*key_immediate_callback)(void *, u8, u16);
void (*should_close_callback)(void *);
void *userdata;
bool closed;
u32 held_mouse_buttons;
u32 held_modifiers;
#ifdef STELA_PAUSE
bool pending_refresh;
#endif
#ifdef STELA_EVENT_BUFFER
bool pending_resize;
// Render thread events.
struct al_ring_buffer events;
u8 data[STELA_EVENTS_SIZE];
#endif
};
enum {
STELA_EVENT_RESIZE = 0,
STELA_EVENT_POINTER_POS,
STELA_EVENT_TOUCH,
STELA_EVENT_SCROLL,
STELA_EVENT_MOUSE_BUTTON,
STELA_EVENT_KEY,
STELA_EVENT_SHOULD_CLOSE,
STELA_EVENT_NONE = 255
};
enum {
STELA_BUTTON_PRESSED = 0,
STELA_BUTTON_RELEASED
};
enum {
STELA_MOUSE1 = 1,
STELA_MOUSE2 = 1 << 1,
STELA_MOUSE3 = 1 << 2
};
AL_IGNORE_WARNING("-Wunused-variable")
static u8 stl_all_mouse_buttons[] = {
STELA_MOUSE1,
STELA_MOUSE2,
STELA_MOUSE3
};
AL_IGNORE_WARNING_END
enum {
STELA_TOUCH_HOVER = 0,
STELA_TOUCH_BEGAN,
STELA_TOUCH_MOVED,
STELA_TOUCH_ENDED,
STELA_TOUCH_CANCELLED
};
extern s32 stl_platform_main(u32 argc, str *argv);
f64 stl_scale_scroll(f64 v, f64 factor);
void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata);
#ifdef STELA_ICON_AT_RUNTIME
void stl_set_icon_data(u8 *data, u32 size);
#endif
bool stl_global_init(bool skip_graphics);
s32 stl_global_get_poll_fd(void);
void stl_global_process_events(void);
s32 stl_swallow_main(u32 argc, str *argv, s32 (*main)(u32, str *, void *), void *extra);
void stl_global_close(void);
struct stl_window *stl_window_create(void);
void stl_window_send_render_event(struct stl_window *window);
void stl_window_send_resize_event(struct stl_window *window, u32 width, u32 height);
void stl_window_send_pointer_pos_event(struct stl_window *window, f64 x, f64 y);
void stl_window_send_touch_event(struct stl_window *window, s32 index, u8 phase, f64 x, f64 y);
void stl_window_send_scroll_event(struct stl_window *window, f64 y);
void stl_window_send_mouse_button_event(struct stl_window *window, u8 state, u8 button);
void stl_window_drop_mouse_buttons(struct stl_window *window);
void stl_window_send_key_event(struct stl_window *window, u8 state, u16 button);
bool stl_window_send_key_immediate_event(struct stl_window *window, u8 state, u16 button);
void stl_window_drop_modifiers(struct stl_window *window);
void stl_window_send_should_close_event(struct stl_window *window);
#ifdef STELA_EVENT_BUFFER
bool stl_window_read_events(struct stl_window *window);
#endif
|