Files
VEFontCache-Odin/thirdparty/sokol/app/app.odin
2025-07-12 22:47:19 -04:00

2041 lines
82 KiB
Odin

// machine generated, do not edit
package sokol_app
/*
sokol_app.h -- cross-platform application wrapper
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_APP_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
In the same place define one of the following to select the 3D-API
which should be initialized by sokol_app.h (this must also match
the backend selected for sokol_gfx.h if both are used in the same
project):
#define SOKOL_GLCORE
#define SOKOL_GLES3
#define SOKOL_D3D11
#define SOKOL_METAL
#define SOKOL_WGPU
#define SOKOL_NOAPI
Optionally provide the following defines with your own implementations:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
SOKOL_WIN32_FORCE_MAIN - define this on Win32 to add a main() entry point
SOKOL_WIN32_FORCE_WINMAIN - define this on Win32 to add a WinMain() entry point (enabled by default unless
SOKOL_WIN32_FORCE_MAIN or SOKOL_NO_ENTRY is defined)
SOKOL_NO_ENTRY - define this if sokol_app.h shouldn't "hijack" the main() function
SOKOL_APP_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_APP_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
Optionally define the following to force debug checks and validations
even in release mode:
SOKOL_DEBUG - by default this is defined if _DEBUG is defined
If sokol_app.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_APP_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
if SOKOL_WIN32_FORCE_MAIN and SOKOL_WIN32_FORCE_WINMAIN are both defined,
it is up to the developer to define the desired subsystem.
On Linux, SOKOL_GLCORE can use either GLX or EGL.
GLX is default, set SOKOL_FORCE_EGL to override.
For example code, see https://github.com/floooh/sokol-samples/tree/master/sapp
Portions of the Windows and Linux GL initialization, event-, icon- etc... code
have been taken from GLFW (http://www.glfw.org/).
iOS onscreen keyboard support 'inspired' by libgdx.
Link with the following system libraries:
- on macOS with Metal: Cocoa, QuartzCore, Metal, MetalKit
- on macOS with GL: Cocoa, QuartzCore, OpenGL
- on iOS with Metal: Foundation, UIKit, Metal, MetalKit
- on iOS with GL: Foundation, UIKit, OpenGLES, GLKit
- on Linux with EGL: X11, Xi, Xcursor, EGL, GL (or GLESv2), dl, pthread, m(?)
- on Linux with GLX: X11, Xi, Xcursor, GL, dl, pthread, m(?)
- on Android: GLESv3, EGL, log, android
- on Windows with the MSVC or Clang toolchains: no action needed, libs are defined in-source via pragma-comment-lib
- on Windows with MINGW/MSYS2 gcc: compile with '-mwin32' so that _WIN32 is defined
- link with the following libs: -lkernel32 -luser32 -lshell32
- additionally with the GL backend: -lgdi32
- additionally with the D3D11 backend: -ld3d11 -ldxgi
On Linux, you also need to use the -pthread compiler and linker option, otherwise weird
things will happen, see here for details: https://github.com/floooh/sokol/issues/376
On macOS and iOS, the implementation must be compiled as Objective-C.
On Emscripten:
- for WebGL2: add the linker option `-s USE_WEBGL2=1`
- for WebGPU: compile and link with `--use-port=emdawnwebgpu`
(for more exotic situations, read: https://dawn.googlesource.com/dawn/+/refs/heads/main/src/emdawnwebgpu/pkg/README.md)
FEATURE OVERVIEW
================
sokol_app.h provides a minimalistic cross-platform API which
implements the 'application-wrapper' parts of a 3D application:
- a common application entry function
- creates a window and 3D-API context/device with a 'default framebuffer'
- makes the rendered frame visible
- provides keyboard-, mouse- and low-level touch-events
- platforms: MacOS, iOS, HTML5, Win32, Linux/RaspberryPi, Android
- 3D-APIs: Metal, D3D11, GL4.1, GL4.3, GLES3, WebGL, WebGL2, NOAPI
FEATURE/PLATFORM MATRIX
=======================
| Windows | macOS | Linux | iOS | Android | HTML5
--------------------+---------+-------+-------+-------+---------+--------
gl 4.x | YES | YES | YES | --- | --- | ---
gles3/webgl2 | --- | --- | YES(2)| YES | YES | YES
metal | --- | YES | --- | YES | --- | ---
d3d11 | YES | --- | --- | --- | --- | ---
noapi | YES | TODO | TODO | --- | TODO | ---
KEY_DOWN | YES | YES | YES | SOME | TODO | YES
KEY_UP | YES | YES | YES | SOME | TODO | YES
CHAR | YES | YES | YES | YES | TODO | YES
MOUSE_DOWN | YES | YES | YES | --- | --- | YES
MOUSE_UP | YES | YES | YES | --- | --- | YES
MOUSE_SCROLL | YES | YES | YES | --- | --- | YES
MOUSE_MOVE | YES | YES | YES | --- | --- | YES
MOUSE_ENTER | YES | YES | YES | --- | --- | YES
MOUSE_LEAVE | YES | YES | YES | --- | --- | YES
TOUCHES_BEGAN | --- | --- | --- | YES | YES | YES
TOUCHES_MOVED | --- | --- | --- | YES | YES | YES
TOUCHES_ENDED | --- | --- | --- | YES | YES | YES
TOUCHES_CANCELLED | --- | --- | --- | YES | YES | YES
RESIZED | YES | YES | YES | YES | YES | YES
ICONIFIED | YES | YES | YES | --- | --- | ---
RESTORED | YES | YES | YES | --- | --- | ---
FOCUSED | YES | YES | YES | --- | --- | YES
UNFOCUSED | YES | YES | YES | --- | --- | YES
SUSPENDED | --- | --- | --- | YES | YES | TODO
RESUMED | --- | --- | --- | YES | YES | TODO
QUIT_REQUESTED | YES | YES | YES | --- | --- | YES
IME | TODO | TODO? | TODO | ??? | TODO | ???
key repeat flag | YES | YES | YES | --- | --- | YES
windowed | YES | YES | YES | --- | --- | YES
fullscreen | YES | YES | YES | YES | YES | ---
mouse hide | YES | YES | YES | --- | --- | YES
mouse lock | YES | YES | YES | --- | --- | YES
set cursor type | YES | YES | YES | --- | --- | YES
screen keyboard | --- | --- | --- | YES | TODO | YES
swap interval | YES | YES | YES | YES | TODO | YES
high-dpi | YES | YES | TODO | YES | YES | YES
clipboard | YES | YES | YES | --- | --- | YES
MSAA | YES | YES | YES | YES | YES | YES
drag'n'drop | YES | YES | YES | --- | --- | YES
window icon | YES | YES(1)| YES | --- | --- | YES
(1) macOS has no regular window icons, instead the dock icon is changed
(2) supported with EGL only (not GLX)
STEP BY STEP
============
--- Add a sokol_main() function to your code which returns a sapp_desc structure
with initialization parameters and callback function pointers. This
function is called very early, usually at the start of the
platform's entry function (e.g. main or WinMain). You should do as
little as possible here, since the rest of your code might be called
from another thread (this depends on the platform):
sapp_desc sokol_main(int argc, char* argv[]) {
return (sapp_desc) {
.width = 640,
.height = 480,
.init_cb = my_init_func,
.frame_cb = my_frame_func,
.cleanup_cb = my_cleanup_func,
.event_cb = my_event_func,
...
};
}
To get any logging output in case of errors you need to provide a log
callback. The easiest way is via sokol_log.h:
#include "sokol_log.h"
sapp_desc sokol_main(int argc, char* argv[]) {
return (sapp_desc) {
...
.logger.func = slog_func,
};
}
There are many more setup parameters, but these are the most important.
For a complete list search for the sapp_desc structure declaration
below.
DO NOT call any sokol-app function from inside sokol_main(), since
sokol-app will not be initialized at this point.
The .width and .height parameters are the preferred size of the 3D
rendering canvas. The actual size may differ from this depending on
platform and other circumstances. Also the canvas size may change at
any time (for instance when the user resizes the application window,
or rotates the mobile device). You can just keep .width and .height
zero-initialized to open a default-sized window (what "default-size"
exactly means is platform-specific, but usually it's a size that covers
most of, but not all, of the display).
All provided function callbacks will be called from the same thread,
but this may be different from the thread where sokol_main() was called.
.init_cb (void (*)(void))
This function is called once after the application window,
3D rendering context and swap chain have been created. The
function takes no arguments and has no return value.
.frame_cb (void (*)(void))
This is the per-frame callback, which is usually called 60
times per second. This is where your application would update
most of its state and perform all rendering.
.cleanup_cb (void (*)(void))
The cleanup callback is called once right before the application
quits.
.event_cb (void (*)(const sapp_event* event))
The event callback is mainly for input handling, but is also
used to communicate other types of events to the application. Keep the
event_cb struct member zero-initialized if your application doesn't require
event handling.
As you can see, those 'standard callbacks' don't have a user_data
argument, so any data that needs to be preserved between callbacks
must live in global variables. If keeping state in global variables
is not an option, there's an alternative set of callbacks with
an additional user_data pointer argument:
.user_data (void*)
The user-data argument for the callbacks below
.init_userdata_cb (void (*)(void* user_data))
.frame_userdata_cb (void (*)(void* user_data))
.cleanup_userdata_cb (void (*)(void* user_data))
.event_userdata_cb (void(*)(const sapp_event* event, void* user_data))
The function sapp_userdata() can be used to query the user_data
pointer provided in the sapp_desc struct.
You can also call sapp_query_desc() to get a copy of the
original sapp_desc structure.
NOTE that there's also an alternative compile mode where sokol_app.h
doesn't "hijack" the main() function. Search below for SOKOL_NO_ENTRY.
--- Implement the initialization callback function (init_cb), this is called
once after the rendering surface, 3D API and swap chain have been
initialized by sokol_app. All sokol-app functions can be called
from inside the initialization callback, the most useful functions
at this point are:
int sapp_width(void)
int sapp_height(void)
Returns the current width and height of the default framebuffer in pixels,
this may change from one frame to the next, and it may be different
from the initial size provided in the sapp_desc struct.
float sapp_widthf(void)
float sapp_heightf(void)
These are alternatives to sapp_width() and sapp_height() which return
the default framebuffer size as float values instead of integer. This
may help to prevent casting back and forth between int and float
in more strongly typed languages than C and C++.
double sapp_frame_duration(void)
Returns the frame duration in seconds averaged over a number of
frames to smooth out any jittering spikes.
int sapp_color_format(void)
int sapp_depth_format(void)
The color and depth-stencil pixelformats of the default framebuffer,
as integer values which are compatible with sokol-gfx's
sg_pixel_format enum (so that they can be plugged directly in places
where sg_pixel_format is expected). Possible values are:
23 == SG_PIXELFORMAT_RGBA8
28 == SG_PIXELFORMAT_BGRA8
42 == SG_PIXELFORMAT_DEPTH
43 == SG_PIXELFORMAT_DEPTH_STENCIL
int sapp_sample_count(void)
Return the MSAA sample count of the default framebuffer.
const void* sapp_metal_get_device(void)
const void* sapp_metal_get_current_drawable(void)
const void* sapp_metal_get_depth_stencil_texture(void)
const void* sapp_metal_get_msaa_color_texture(void)
If the Metal backend has been selected, these functions return pointers
to various Metal API objects required for rendering, otherwise
they return a null pointer. These void pointers are actually
Objective-C ids converted with a (ARC) __bridge cast so that
the ids can be tunneled through C code. Also note that the returned
pointers may change from one frame to the next, only the Metal device
object is guaranteed to stay the same.
const void* sapp_macos_get_window(void)
On macOS, get the NSWindow object pointer, otherwise a null pointer.
Before being used as Objective-C object, the void* must be converted
back with a (ARC) __bridge cast.
const void* sapp_ios_get_window(void)
On iOS, get the UIWindow object pointer, otherwise a null pointer.
Before being used as Objective-C object, the void* must be converted
back with a (ARC) __bridge cast.
const void* sapp_d3d11_get_device(void)
const void* sapp_d3d11_get_device_context(void)
const void* sapp_d3d11_get_render_view(void)
const void* sapp_d3d11_get_resolve_view(void);
const void* sapp_d3d11_get_depth_stencil_view(void)
Similar to the sapp_metal_* functions, the sapp_d3d11_* functions
return pointers to D3D11 API objects required for rendering,
only if the D3D11 backend has been selected. Otherwise they
return a null pointer. Note that the returned pointers to the
render-target-view and depth-stencil-view may change from one
frame to the next!
const void* sapp_win32_get_hwnd(void)
On Windows, get the window's HWND, otherwise a null pointer. The
HWND has been cast to a void pointer in order to be tunneled
through code which doesn't include Windows.h.
const void* sapp_x11_get_window(void)
On Linux, get the X11 Window, otherwise a null pointer. The
Window has been cast to a void pointer in order to be tunneled
through code which doesn't include X11/Xlib.h.
const void* sapp_x11_get_display(void)
On Linux, get the X11 Display, otherwise a null pointer. The
Display has been cast to a void pointer in order to be tunneled
through code which doesn't include X11/Xlib.h.
const void* sapp_wgpu_get_device(void)
const void* sapp_wgpu_get_render_view(void)
const void* sapp_wgpu_get_resolve_view(void)
const void* sapp_wgpu_get_depth_stencil_view(void)
These are the WebGPU-specific functions to get the WebGPU
objects and values required for rendering. If sokol_app.h
is not compiled with SOKOL_WGPU, these functions return null.
uint32_t sapp_gl_get_framebuffer(void)
This returns the 'default framebuffer' of the GL context.
Typically this will be zero.
int sapp_gl_get_major_version(void)
int sapp_gl_get_minor_version(void)
bool sapp_gl_is_gles(void)
Returns the major and minor version of the GL context and
whether the GL context is a GLES context
const void* sapp_android_get_native_activity(void);
On Android, get the native activity ANativeActivity pointer, otherwise
a null pointer.
--- Implement the frame-callback function, this function will be called
on the same thread as the init callback, but might be on a different
thread than the sokol_main() function. Note that the size of
the rendering framebuffer might have changed since the frame callback
was called last. Call the functions sapp_width() and sapp_height()
each frame to get the current size.
--- Optionally implement the event-callback to handle input events.
sokol-app provides the following type of input events:
- a 'virtual key' was pressed down or released
- a single text character was entered (provided as UTF-32 encoded
UNICODE code point)
- a mouse button was pressed down or released (left, right, middle)
- mouse-wheel or 2D scrolling events
- the mouse was moved
- the mouse has entered or left the application window boundaries
- low-level, portable multi-touch events (began, moved, ended, cancelled)
- the application window was resized, iconified or restored
- the application was suspended or restored (on mobile platforms)
- the user or application code has asked to quit the application
- a string was pasted to the system clipboard
- one or more files have been dropped onto the application window
To explicitly 'consume' an event and prevent that the event is
forwarded for further handling to the operating system, call
sapp_consume_event() from inside the event handler (NOTE that
this behaviour is currently only implemented for some HTML5
events, support for other platforms and event types will
be added as needed, please open a GitHub ticket and/or provide
a PR if needed).
NOTE: Do *not* call any 3D API rendering functions in the event
callback function, since the 3D API context may not be active when the
event callback is called (it may work on some platforms and 3D APIs,
but not others, and the exact behaviour may change between
sokol-app versions).
--- Implement the cleanup-callback function, this is called once
after the user quits the application (see the section
"APPLICATION QUIT" for detailed information on quitting
behaviour, and how to intercept a pending quit - for instance to show a
"Really Quit?" dialog box). Note that the cleanup-callback isn't
guaranteed to be called on the web and mobile platforms.
MOUSE CURSOR TYPE AND VISIBILITY
================================
You can show and hide the mouse cursor with
void sapp_show_mouse(bool show)
And to get the current shown status:
bool sapp_mouse_shown(void)
NOTE that hiding the mouse cursor is different and independent from
the MOUSE/POINTER LOCK feature which will also hide the mouse pointer when
active (MOUSE LOCK is described below).
To change the mouse cursor to one of several predefined types, call
the function:
void sapp_set_mouse_cursor(sapp_mouse_cursor cursor)
Setting the default mouse cursor SAPP_MOUSECURSOR_DEFAULT will restore
the standard look.
To get the currently active mouse cursor type, call:
sapp_mouse_cursor sapp_get_mouse_cursor(void)
MOUSE LOCK (AKA POINTER LOCK, AKA MOUSE CAPTURE)
================================================
In normal mouse mode, no mouse movement events are reported when the
mouse leaves the windows client area or hits the screen border (whether
it's one or the other depends on the platform), and the mouse move events
(SAPP_EVENTTYPE_MOUSE_MOVE) contain absolute mouse positions in
framebuffer pixels in the sapp_event items mouse_x and mouse_y, and
relative movement in framebuffer pixels in the sapp_event items mouse_dx
and mouse_dy.
To get continuous mouse movement (also when the mouse leaves the window
client area or hits the screen border), activate mouse-lock mode
by calling:
sapp_lock_mouse(true)
When mouse lock is activated, the mouse pointer is hidden, the
reported absolute mouse position (sapp_event.mouse_x/y) appears
frozen, and the relative mouse movement in sapp_event.mouse_dx/dy
no longer has a direct relation to framebuffer pixels but instead
uses "raw mouse input" (what "raw mouse input" exactly means also
differs by platform).
To deactivate mouse lock and return to normal mouse mode, call
sapp_lock_mouse(false)
And finally, to check if mouse lock is currently active, call
if (sapp_mouse_locked()) { ... }
Note that mouse-lock state may not change immediately after sapp_lock_mouse(true/false)
is called, instead on some platforms the actual state switch may be delayed
to the end of the current frame or even to a later frame.
The mouse may also be unlocked automatically without calling sapp_lock_mouse(false),
most notably when the application window becomes inactive.
On the web platform there are further restrictions to be aware of, caused
by the limitations of the HTML5 Pointer Lock API:
- sapp_lock_mouse(true) can be called at any time, but it will
only take effect in a 'short-lived input event handler of a specific
type', meaning when one of the following events happens:
- SAPP_EVENTTYPE_MOUSE_DOWN
- SAPP_EVENTTYPE_MOUSE_UP
- SAPP_EVENTTYPE_MOUSE_SCROLL
- SAPP_EVENTTYPE_KEY_UP
- SAPP_EVENTTYPE_KEY_DOWN
- The mouse lock/unlock action on the web platform is asynchronous,
this means that sapp_mouse_locked() won't immediately return
the new status after calling sapp_lock_mouse(), instead the
reported status will only change when the pointer lock has actually
been activated or deactivated in the browser.
- On the web, mouse lock can be deactivated by the user at any time
by pressing the Esc key. When this happens, sokol_app.h behaves
the same as if sapp_lock_mouse(false) is called.
For things like camera manipulation it's most straightforward to lock
and unlock the mouse right from the sokol_app.h event handler, for
instance the following code enters and leaves mouse lock when the
left mouse button is pressed and released, and then uses the relative
movement information to manipulate a camera (taken from the
cgltf-sapp.c sample in the sokol-samples repository
at https://github.com/floooh/sokol-samples):
static void input(const sapp_event* ev) {
switch (ev->type) {
case SAPP_EVENTTYPE_MOUSE_DOWN:
if (ev->mouse_button == SAPP_MOUSEBUTTON_LEFT) {
sapp_lock_mouse(true);
}
break;
case SAPP_EVENTTYPE_MOUSE_UP:
if (ev->mouse_button == SAPP_MOUSEBUTTON_LEFT) {
sapp_lock_mouse(false);
}
break;
case SAPP_EVENTTYPE_MOUSE_MOVE:
if (sapp_mouse_locked()) {
cam_orbit(&state.camera, ev->mouse_dx * 0.25f, ev->mouse_dy * 0.25f);
}
break;
default:
break;
}
}
For a 'first person shooter mouse' the following code inside the sokol-app event handler
is recommended somewhere in your frame callback:
if (!sapp_mouse_locked()) {
sapp_lock_mouse(true);
}
CLIPBOARD SUPPORT
=================
Applications can send and receive UTF-8 encoded text data from and to the
system clipboard. By default, clipboard support is disabled and
must be enabled at startup via the following sapp_desc struct
members:
sapp_desc.enable_clipboard - set to true to enable clipboard support
sapp_desc.clipboard_size - size of the internal clipboard buffer in bytes
Enabling the clipboard will dynamically allocate a clipboard buffer
for UTF-8 encoded text data of the requested size in bytes, the default
size is 8 KBytes. Strings that don't fit into the clipboard buffer
(including the terminating zero) will be silently clipped, so it's
important that you provide a big enough clipboard size for your
use case.
To send data to the clipboard, call sapp_set_clipboard_string() with
a pointer to an UTF-8 encoded, null-terminated C-string.
NOTE that on the HTML5 platform, sapp_set_clipboard_string() must be
called from inside a 'short-lived event handler', and there are a few
other HTML5-specific caveats to workaround. You'll basically have to
tinker until it works in all browsers :/ (maybe the situation will
improve when all browsers agree on and implement the new
HTML5 navigator.clipboard API).
To get data from the clipboard, check for the SAPP_EVENTTYPE_CLIPBOARD_PASTED
event in your event handler function, and then call sapp_get_clipboard_string()
to obtain the pasted UTF-8 encoded text.
NOTE that behaviour of sapp_get_clipboard_string() is slightly different
depending on platform:
- on the HTML5 platform, the internal clipboard buffer will only be updated
right before the SAPP_EVENTTYPE_CLIPBOARD_PASTED event is sent,
and sapp_get_clipboard_string() will simply return the current content
of the clipboard buffer
- on 'native' platforms, the call to sapp_get_clipboard_string() will
update the internal clipboard buffer with the most recent data
from the system clipboard
Portable code should check for the SAPP_EVENTTYPE_CLIPBOARD_PASTED event,
and then call sapp_get_clipboard_string() right in the event handler.
The SAPP_EVENTTYPE_CLIPBOARD_PASTED event will be generated by sokol-app
as follows:
- on macOS: when the Cmd+V key is pressed down
- on HTML5: when the browser sends a 'paste' event to the global 'window' object
- on all other platforms: when the Ctrl+V key is pressed down
DRAG AND DROP SUPPORT
=====================
PLEASE NOTE: the drag'n'drop feature works differently on WASM/HTML5
and on the native desktop platforms (Win32, Linux and macOS) because
of security-related restrictions in the HTML5 drag'n'drop API. The
WASM/HTML5 specifics are described at the end of this documentation
section:
Like clipboard support, drag'n'drop support must be explicitly enabled
at startup in the sapp_desc struct.
sapp_desc sokol_main(void) {
return (sapp_desc) {
.enable_dragndrop = true, // default is false
...
};
}
You can also adjust the maximum number of files that are accepted
in a drop operation, and the maximum path length in bytes if needed:
sapp_desc sokol_main(void) {
return (sapp_desc) {
.enable_dragndrop = true, // default is false
.max_dropped_files = 8, // default is 1
.max_dropped_file_path_length = 8192, // in bytes, default is 2048
...
};
}
When drag'n'drop is enabled, the event callback will be invoked with an
event of type SAPP_EVENTTYPE_FILES_DROPPED whenever the user drops files on
the application window.
After the SAPP_EVENTTYPE_FILES_DROPPED is received, you can query the
number of dropped files, and their absolute paths by calling separate
functions:
void on_event(const sapp_event* ev) {
if (ev->type == SAPP_EVENTTYPE_FILES_DROPPED) {
// the mouse position where the drop happened
float x = ev->mouse_x;
float y = ev->mouse_y;
// get the number of files and their paths like this:
const int num_dropped_files = sapp_get_num_dropped_files();
for (int i = 0; i < num_dropped_files; i++) {
const char* path = sapp_get_dropped_file_path(i);
...
}
}
}
The returned file paths are UTF-8 encoded strings.
You can call sapp_get_num_dropped_files() and sapp_get_dropped_file_path()
anywhere, also outside the event handler callback, but be aware that the
file path strings will be overwritten with the next drop operation.
In any case, sapp_get_dropped_file_path() will never return a null pointer,
instead an empty string "" will be returned if the drag'n'drop feature
hasn't been enabled, the last drop-operation failed, or the file path index
is out of range.
Drag'n'drop caveats:
- if more files are dropped in a single drop-action
than sapp_desc.max_dropped_files, the additional
files will be silently ignored
- if any of the file paths is longer than
sapp_desc.max_dropped_file_path_length (in number of bytes, after UTF-8
encoding) the entire drop operation will be silently ignored (this
needs some sort of error feedback in the future)
- no mouse positions are reported while the drag is in
process, this may change in the future
Drag'n'drop on HTML5/WASM:
The HTML5 drag'n'drop API doesn't return file paths, but instead
black-box 'file objects' which must be used to load the content
of dropped files. This is the reason why sokol_app.h adds two
HTML5-specific functions to the drag'n'drop API:
uint32_t sapp_html5_get_dropped_file_size(int index)
Returns the size in bytes of a dropped file.
void sapp_html5_fetch_dropped_file(const sapp_html5_fetch_request* request)
Asynchronously loads the content of a dropped file into a
provided memory buffer (which must be big enough to hold
the file content)
To start loading the first dropped file after an SAPP_EVENTTYPE_FILES_DROPPED
event is received:
sapp_html5_fetch_dropped_file(&(sapp_html5_fetch_request){
.dropped_file_index = 0,
.callback = fetch_cb
.buffer = {
.ptr = buf,
.size = sizeof(buf)
},
.user_data = ...
});
Make sure that the memory pointed to by 'buf' stays valid until the
callback function is called!
As result of the asynchronous loading operation (no matter if succeeded or
failed) the 'fetch_cb' function will be called:
void fetch_cb(const sapp_html5_fetch_response* response) {
// IMPORTANT: check if the loading operation actually succeeded:
if (response->succeeded) {
// the size of the loaded file:
const size_t num_bytes = response->data.size;
// and the pointer to the data (same as 'buf' in the fetch-call):
const void* ptr = response->data.ptr;
}
else {
// on error check the error code:
switch (response->error_code) {
case SAPP_HTML5_FETCH_ERROR_BUFFER_TOO_SMALL:
...
break;
case SAPP_HTML5_FETCH_ERROR_OTHER:
...
break;
}
}
}
Check the droptest-sapp example for a real-world example which works
both on native platforms and the web:
https://github.com/floooh/sokol-samples/blob/master/sapp/droptest-sapp.c
HIGH-DPI RENDERING
==================
You can set the sapp_desc.high_dpi flag during initialization to request
a full-resolution framebuffer on HighDPI displays. The default behaviour
is sapp_desc.high_dpi=false, this means that the application will
render to a lower-resolution framebuffer on HighDPI displays and the
rendered content will be upscaled by the window system composer.
In a HighDPI scenario, you still request the same window size during
sokol_main(), but the framebuffer sizes returned by sapp_width()
and sapp_height() will be scaled up according to the DPI scaling
ratio.
Note that on some platforms the DPI scaling factor may change at any
time (for instance when a window is moved from a high-dpi display
to a low-dpi display).
To query the current DPI scaling factor, call the function:
float sapp_dpi_scale(void);
For instance on a Retina Mac, returning the following sapp_desc
struct from sokol_main():
sapp_desc sokol_main(void) {
return (sapp_desc) {
.width = 640,
.height = 480,
.high_dpi = true,
...
};
}
...the functions the functions sapp_width(), sapp_height()
and sapp_dpi_scale() will return the following values:
sapp_width: 1280
sapp_height: 960
sapp_dpi_scale: 2.0
If the high_dpi flag is false, or you're not running on a Retina display,
the values would be:
sapp_width: 640
sapp_height: 480
sapp_dpi_scale: 1.0
If the window is moved from the Retina display to a low-dpi external display,
the values would change as follows:
sapp_width: 1280 => 640
sapp_height: 960 => 480
sapp_dpi_scale: 2.0 => 1.0
Currently there is no event associated with a DPI change, but an
SAPP_EVENTTYPE_RESIZED will be sent as a side effect of the
framebuffer size changing.
Per-monitor DPI is currently supported on macOS and Windows.
APPLICATION QUIT
================
Without special quit handling, a sokol_app.h application will quit
'gracefully' when the user clicks the window close-button unless a
platform's application model prevents this (e.g. on web or mobile).
'Graceful exit' means that the application-provided cleanup callback will
be called before the application quits.
On native desktop platforms sokol_app.h provides more control over the
application-quit-process. It's possible to initiate a 'programmatic quit'
from the application code, and a quit initiated by the application user can
be intercepted (for instance to show a custom dialog box).
This 'programmatic quit protocol' is implemented through 3 functions
and 1 event:
- sapp_quit(): This function simply quits the application without
giving the user a chance to intervene. Usually this might
be called when the user clicks the 'Ok' button in a 'Really Quit?'
dialog box
- sapp_request_quit(): Calling sapp_request_quit() will send the
event SAPP_EVENTTYPE_QUIT_REQUESTED to the applications event handler
callback, giving the user code a chance to intervene and cancel the
pending quit process (for instance to show a 'Really Quit?' dialog
box). If the event handler callback does nothing, the application
will be quit as usual. To prevent this, call the function
sapp_cancel_quit() from inside the event handler.
- sapp_cancel_quit(): Cancels a pending quit request, either initiated
by the user clicking the window close button, or programmatically
by calling sapp_request_quit(). The only place where calling this
function makes sense is from inside the event handler callback when
the SAPP_EVENTTYPE_QUIT_REQUESTED event has been received.
- SAPP_EVENTTYPE_QUIT_REQUESTED: this event is sent when the user
clicks the window's close button or application code calls the
sapp_request_quit() function. The event handler callback code can handle
this event by calling sapp_cancel_quit() to cancel the quit.
If the event is ignored, the application will quit as usual.
On the web platform, the quit behaviour differs from native platforms,
because of web-specific restrictions:
A `programmatic quit` initiated by calling sapp_quit() or
sapp_request_quit() will work as described above: the cleanup callback is
called, platform-specific cleanup is performed (on the web
this means that JS event handlers are unregistered), and then
the request-animation-loop will be exited. However that's all. The
web page itself will continue to exist (e.g. it's not possible to
programmatically close the browser tab).
On the web it's also not possible to run custom code when the user
closes a browser tab, so it's not possible to prevent this with a
fancy custom dialog box.
Instead the standard "Leave Site?" dialog box can be activated (or
deactivated) with the following function:
sapp_html5_ask_leave_site(bool ask);
The initial state of the associated internal flag can be provided
at startup via sapp_desc.html5_ask_leave_site.
This feature should only be used sparingly in critical situations - for
instance when the user would loose data - since popping up modal dialog
boxes is considered quite rude in the web world. Note that there's no way
to customize the content of this dialog box or run any code as a result
of the user's decision. Also note that the user must have interacted with
the site before the dialog box will appear. These are all security measures
to prevent fishing.
The Dear ImGui HighDPI sample contains example code of how to
implement a 'Really Quit?' dialog box with Dear ImGui (native desktop
platforms only), and for showing the hardwired "Leave Site?" dialog box
when running on the web platform:
https://floooh.github.io/sokol-html5/wasm/imgui-highdpi-sapp.html
FULLSCREEN
==========
If the sapp_desc.fullscreen flag is true, sokol-app will try to create
a fullscreen window on platforms with a 'proper' window system
(mobile devices will always use fullscreen). The implementation details
depend on the target platform, in general sokol-app will use a
'soft approach' which doesn't interfere too much with the platform's
window system (for instance borderless fullscreen window instead of
a 'real' fullscreen mode). Such details might change over time
as sokol-app is adapted for different needs.
The most important effect of fullscreen mode to keep in mind is that
the requested canvas width and height will be ignored for the initial
window size, calling sapp_width() and sapp_height() will instead return
the resolution of the fullscreen canvas (however the provided size
might still be used for the non-fullscreen window, in case the user can
switch back from fullscreen- to windowed-mode).
To toggle fullscreen mode programmatically, call sapp_toggle_fullscreen().
To check if the application window is currently in fullscreen mode,
call sapp_is_fullscreen().
WINDOW ICON SUPPORT
===================
Some sokol_app.h backends allow to change the window icon programmatically:
- on Win32: the small icon in the window's title bar, and the
bigger icon in the task bar
- on Linux: highly dependent on the used window manager, but usually
the window's title bar icon and/or the task bar icon
- on HTML5: the favicon shown in the page's browser tab
- on macOS: the application icon shown in the dock, but only
for currently running applications
NOTE that it is not possible to set the actual application icon which is
displayed by the operating system on the desktop or 'home screen'. Those
icons must be provided 'traditionally' through operating-system-specific
resources which are associated with the application (sokol_app.h might
later support setting the window icon from platform specific resource data
though).
There are two ways to set the window icon:
- at application start in the sokol_main() function by initializing
the sapp_desc.icon nested struct
- or later by calling the function sapp_set_icon()
As a convenient shortcut, sokol_app.h comes with a builtin default-icon
(a rainbow-colored 'S', which at least looks a bit better than the Windows
default icon for applications), which can be activated like this:
At startup in sokol_main():
sapp_desc sokol_main(...) {
return (sapp_desc){
...
icon.sokol_default = true
};
}
Or later by calling:
sapp_set_icon(&(sapp_icon_desc){ .sokol_default = true });
NOTE that a completely zero-initialized sapp_icon_desc struct will not
update the window icon in any way. This is an 'escape hatch' so that you
can handle the window icon update yourself (or if you do this already,
sokol_app.h won't get in your way, in this case just leave the
sapp_desc.icon struct zero-initialized).
Providing your own icon images works exactly like in GLFW (down to the
data format):
You provide one or more 'candidate images' in different sizes, and the
sokol_app.h platform backends pick the best match for the specific backend
and icon type.
For each candidate image, you need to provide:
- the width in pixels
- the height in pixels
- and the actual pixel data in RGBA8 pixel format (e.g. 0xFFCC8844
on a little-endian CPU means: alpha=0xFF, blue=0xCC, green=0x88, red=0x44)
For instance, if you have 3 candidate images (small, medium, big) of
sizes 16x16, 32x32 and 64x64 the corresponding sapp_icon_desc struct is setup
like this:
// the actual pixel data (RGBA8, origin top-left)
const uint32_t small[16][16] = { ... };
const uint32_t medium[32][32] = { ... };
const uint32_t big[64][64] = { ... };
const sapp_icon_desc icon_desc = {
.images = {
{ .width = 16, .height = 16, .pixels = SAPP_RANGE(small) },
{ .width = 32, .height = 32, .pixels = SAPP_RANGE(medium) },
// ...or without the SAPP_RANGE helper macro:
{ .width = 64, .height = 64, .pixels = { .ptr=big, .size=sizeof(big) } }
}
};
An sapp_icon_desc struct initialized like this can then either be applied
at application start in sokol_main:
sapp_desc sokol_main(...) {
return (sapp_desc){
...
icon = icon_desc
};
}
...or later by calling sapp_set_icon():
sapp_set_icon(&icon_desc);
Some window icon caveats:
- once the window icon has been updated, there's no way to go back to
the platform's default icon, this is because some platforms (Linux
and HTML5) don't switch the icon visual back to the default even if
the custom icon is deleted or removed
- on HTML5, if the sokol_app.h icon doesn't show up in the browser
tab, check that there's no traditional favicon 'link' element
is defined in the page's index.html, sokol_app.h will only
append a new favicon link element, but not delete any manually
defined favicon in the page
For an example and test of the window icon feature, check out the
'icon-sapp' sample on the sokol-samples git repository.
ONSCREEN KEYBOARD
=================
On some platforms which don't provide a physical keyboard, sokol-app
can display the platform's integrated onscreen keyboard for text
input. To request that the onscreen keyboard is shown, call
sapp_show_keyboard(true);
Likewise, to hide the keyboard call:
sapp_show_keyboard(false);
Note that onscreen keyboard functionality is no longer supported
on the browser platform (the previous hacks and workarounds to make browser
keyboards work for on web applications that don't use HTML UIs
never really worked across browsers).
INPUT EVENT BUBBLING ON THE WEB PLATFORM
========================================
By default, input event bubbling on the web platform is configured in
a way that makes the most sense for 'full-canvas' apps that cover the
entire browser client window area:
- mouse, touch and wheel events do not bubble up, this prevents various
ugly side events, like:
- HTML text overlays being selected on double- or triple-click into
the canvas
- 'scroll bumping' even when the canvas covers the entire client area
- key_up/down events for 'character keys' *do* bubble up (otherwise
the browser will not generate UNICODE character events)
- all other key events *do not* bubble up by default (this prevents side effects
like F1 opening help, or F7 starting 'caret browsing')
- character events do not bubble up (although I haven't noticed any side effects
otherwise)
Event bubbling can be enabled for input event categories during initialization
in the sapp_desc struct:
sapp_desc sokol_main(int argc, char* argv[]) {
return (sapp_desc){
//...
.html5_bubble_mouse_events = true,
.html5_bubble_touch_events = true,
.html5_bubble_wheel_events = true,
.html5_bubble_key_events = true,
.html5_bubble_char_events = true,
};
}
This basically opens the floodgates and lets *all* input events bubble up to the browser.
To prevent individual events from bubbling, call sapp_consume_event() from within
the sokol_app.h event callback when that specific event is reported.
SETTING THE CANVAS OBJECT ON THE WEB PLATFORM
=============================================
On the web, sokol_app.h and the Emscripten SDK functions need to find
the WebGL/WebGPU canvas intended for rendering and attaching event
handlers. This can happen in four ways:
1. do nothing and just set the id of the canvas object to 'canvas' (preferred)
2. via a CSS Selector string (preferred)
3. by setting the `Module.canvas` property to the canvas object
4. by adding the canvas object to the global variable `specialHTMLTargets[]`
(this is a special variable used by the Emscripten runtime to lookup
event target objects for which document.querySelector() cannot be used)
The easiest way is to just name your canvas object 'canvas':
<canvas id="canvas" ...></canvas>
This works because the default css selector string used by sokol_app.h
is '#canvas'.
If you name your canvas differently, you need to communicate that name to
sokol_app.h via `sapp_desc.html5_canvas_selector` as a regular css selector
string that's compatible with `document.querySelector()`. E.g. if your canvas
object looks like this:
<canvas id="bla" ...></canvas>
The `sapp_desc.html5_canvas_selector` string must be set to '#bla':
.html5_canvas_selector = "#bla"
If the canvas object cannot be looked up via `document.querySelector()` you
need to use one of the alternative methods, both involve the special
Emscripten runtime `Module` object which is usually setup in the index.html
like this before the WASM blob is loaded and instantiated:
<script type='text/javascript'>
var Module = {
// ...
};
</script>
The first option is to set the `Module.canvas` property to your canvas object:
<script type='text/javascript'>
var Module = {
canvas: my_canvas_object,
};
</script>
When sokol_app.h initializes, it will check the global Module object whether
a `Module.canvas` property exists and is an object. This method will add
a new entry to the `specialHTMLTargets[]` object
The other option is to add the canvas under a name chosen by you to the
special `specialHTMLTargets[]` map, which is used by the Emscripten runtime
to lookup 'event target objects' which are not visible to `document.querySelector()`.
Note that `specialHTMLTargets[]` must be updated after the Emscripten runtime
has started but before the WASM code is running. A good place for this is
the special `Module.preRun` array in index.html:
<script type='text/javascript'>
var Module = {
preRun: [
() => {
specialHTMLTargets['my_canvas'] = my_canvas_object;
}
],
};
</script>
In that case, pass the same string to sokol_app.h which is used as key
in the specialHTMLTargets[] map:
.html5_canvas_selector = "my_canvas"
If sokol_app.h can't find your canvas for some reason check for warning
messages on the browser console.
OPTIONAL: DON'T HIJACK main() (#define SOKOL_NO_ENTRY)
======================================================
NOTE: SOKOL_NO_ENTRY and sapp_run() is currently not supported on Android.
In its default configuration, sokol_app.h "hijacks" the platform's
standard main() function. This was done because different platforms
have different entry point conventions which are not compatible with
C's main() (for instance WinMain on Windows has completely different
arguments). However, this "main hijacking" posed a problem for
usage scenarios like integrating sokol_app.h with other languages than
C or C++, so an alternative SOKOL_NO_ENTRY mode has been added
in which the user code provides the platform's main function:
- define SOKOL_NO_ENTRY before including the sokol_app.h implementation
- do *not* provide a sokol_main() function
- instead provide the standard main() function of the platform
- from the main function, call the function ```sapp_run()``` which
takes a pointer to an ```sapp_desc``` structure.
- from here on```sapp_run()``` takes over control and calls the provided
init-, frame-, event- and cleanup-callbacks just like in the default model.
sapp_run() behaves differently across platforms:
- on some platforms, sapp_run() will return when the application quits
- on other platforms, sapp_run() will never return, even when the
application quits (the operating system is free to simply terminate
the application at any time)
- on Emscripten specifically, sapp_run() will return immediately while
the frame callback keeps being called
This different behaviour of sapp_run() essentially means that there shouldn't
be any code *after* sapp_run(), because that may either never be called, or in
case of Emscripten will be called at an unexpected time (at application start).
An application also should not depend on the cleanup-callback being called
when cross-platform compatibility is required.
Since sapp_run() returns immediately on Emscripten you shouldn't activate
the 'EXIT_RUNTIME' linker option (this is disabled by default when compiling
for the browser target), since the C/C++ exit runtime would be called immediately at
application start, causing any global objects to be destroyed and global
variables to be zeroed.
WINDOWS CONSOLE OUTPUT
======================
On Windows, regular windowed applications don't show any stdout/stderr text
output, which can be a bit of a hassle for printf() debugging or generally
logging text to the console. Also, console output by default uses a local
codepage setting and thus international UTF-8 encoded text is printed
as garbage.
To help with these issues, sokol_app.h can be configured at startup
via the following Windows-specific sapp_desc flags:
sapp_desc.win32_console_utf8 (default: false)
When set to true, the output console codepage will be switched
to UTF-8 (and restored to the original codepage on exit)
sapp_desc.win32_console_attach (default: false)
When set to true, stdout and stderr will be attached to the
console of the parent process (if the parent process actually
has a console). This means that if the application was started
in a command line window, stdout and stderr output will be printed
to the terminal, just like a regular command line program. But if
the application is started via double-click, it will behave like
a regular UI application, and stdout/stderr will not be visible.
sapp_desc.win32_console_create (default: false)
When set to true, a new console window will be created and
stdout/stderr will be redirected to that console window. It
doesn't matter if the application is started from the command
line or via double-click.
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
sapp_desc sokol_main(int argc, char* argv[]) {
return (sapp_desc){
// ...
.allocator = {
.alloc_fn = my_alloc,
.free_fn = my_free,
.user_data = ...,
}
};
}
If no overrides are provided, malloc and free will be used.
This only affects memory allocation calls done by sokol_app.h
itself though, not any allocations in OS libraries.
ERROR REPORTING AND LOGGING
===========================
To get any logging information at all you need to provide a logging callback in the setup call
the easiest way is to use sokol_log.h:
#include "sokol_log.h"
sapp_desc sokol_main(int argc, char* argv[]) {
return (sapp_desc) {
...
.logger.func = slog_func,
};
}
To override logging with your own callback, first write a logging function like this:
void my_log(const char* tag, // e.g. 'sapp'
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
uint32_t log_item_id, // SAPP_LOGITEM_*
const char* message_or_null, // a message string, may be nullptr in release mode
uint32_t line_nr, // line number in sokol_app.h
const char* filename_or_null, // source filename, may be nullptr in release mode
void* user_data)
{
...
}
...and then setup sokol-app like this:
sapp_desc sokol_main(int argc, char* argv[]) {
return (sapp_desc) {
...
.logger = {
.func = my_log,
.user_data = my_user_data,
}
};
}
The provided logging function must be reentrant (e.g. be callable from
different threads).
If you don't want to provide your own custom logger it is highly recommended to use
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
errors.
TEMP NOTE DUMP
==============
- sapp_desc needs a bool whether to initialize depth-stencil surface
- the Android implementation calls cleanup_cb() and destroys the egl context in onDestroy
at the latest but should do it earlier, in onStop, as an app is "killable" after onStop
on Android Honeycomb and later (it can't be done at the moment as the app may be started
again after onStop and the sokol lifecycle does not yet handle context teardown/bringup)
LICENSE
=======
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
import "core:c"
_ :: c
SOKOL_DEBUG :: #config(SOKOL_DEBUG, ODIN_DEBUG)
DEBUG :: #config(SOKOL_APP_DEBUG, SOKOL_DEBUG)
USE_GL :: #config(SOKOL_USE_GL, false)
USE_DLL :: #config(SOKOL_DLL, false)
when ODIN_OS == .Windows {
when USE_DLL {
when USE_GL {
when DEBUG { foreign import sokol_app_clib { "../sokol_dll_windows_x64_gl_debug.lib" } }
else { foreign import sokol_app_clib { "../sokol_dll_windows_x64_gl_release.lib" } }
} else {
when DEBUG { foreign import sokol_app_clib { "../sokol_dll_windows_x64_d3d11_debug.lib" } }
else { foreign import sokol_app_clib { "../sokol_dll_windows_x64_d3d11_release.lib" } }
}
} else {
when USE_GL {
when DEBUG { foreign import sokol_app_clib { "sokol_app_windows_x64_gl_debug.lib" } }
else { foreign import sokol_app_clib { "sokol_app_windows_x64_gl_release.lib" } }
} else {
when DEBUG { foreign import sokol_app_clib { "sokol_app_windows_x64_d3d11_debug.lib" } }
else { foreign import sokol_app_clib { "sokol_app_windows_x64_d3d11_release.lib" } }
}
}
} else when ODIN_OS == .Darwin {
when USE_DLL {
when USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib" } }
else when USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_arm64_gl_release.dylib" } }
else when USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_x64_gl_debug.dylib" } }
else when USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_x64_gl_release.dylib" } }
else when !USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib" } }
else when !USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_arm64_metal_release.dylib" } }
else when !USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_x64_metal_debug.dylib" } }
else when !USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_app_clib { "../dylib/sokol_dylib_macos_x64_metal_release.dylib" } }
} else {
when USE_GL {
when ODIN_ARCH == .arm64 {
when DEBUG { foreign import sokol_app_clib { "sokol_app_macos_arm64_gl_debug.a", "system:Cocoa.framework","system:QuartzCore.framework","system:OpenGL.framework" } }
else { foreign import sokol_app_clib { "sokol_app_macos_arm64_gl_release.a", "system:Cocoa.framework","system:QuartzCore.framework","system:OpenGL.framework" } }
} else {
when DEBUG { foreign import sokol_app_clib { "sokol_app_macos_x64_gl_debug.a", "system:Cocoa.framework","system:QuartzCore.framework","system:OpenGL.framework" } }
else { foreign import sokol_app_clib { "sokol_app_macos_x64_gl_release.a", "system:Cocoa.framework","system:QuartzCore.framework","system:OpenGL.framework" } }
}
} else {
when ODIN_ARCH == .arm64 {
when DEBUG { foreign import sokol_app_clib { "sokol_app_macos_arm64_metal_debug.a", "system:Cocoa.framework","system:QuartzCore.framework","system:Metal.framework","system:MetalKit.framework" } }
else { foreign import sokol_app_clib { "sokol_app_macos_arm64_metal_release.a", "system:Cocoa.framework","system:QuartzCore.framework","system:Metal.framework","system:MetalKit.framework" } }
} else {
when DEBUG { foreign import sokol_app_clib { "sokol_app_macos_x64_metal_debug.a", "system:Cocoa.framework","system:QuartzCore.framework","system:Metal.framework","system:MetalKit.framework" } }
else { foreign import sokol_app_clib { "sokol_app_macos_x64_metal_release.a", "system:Cocoa.framework","system:QuartzCore.framework","system:Metal.framework","system:MetalKit.framework" } }
}
}
}
} else when ODIN_OS == .Linux {
when USE_DLL {
when DEBUG { foreign import sokol_app_clib { "sokol_app_linux_x64_gl_debug.so", "system:X11", "system:Xi", "system:Xcursor", "system:GL", "system:dl", "system:pthread" } }
else { foreign import sokol_app_clib { "sokol_app_linux_x64_gl_release.so", "system:X11", "system:Xi", "system:Xcursor", "system:GL", "system:dl", "system:pthread" } }
} else {
when DEBUG { foreign import sokol_app_clib { "sokol_app_linux_x64_gl_debug.a", "system:X11", "system:Xi", "system:Xcursor", "system:GL", "system:dl", "system:pthread" } }
else { foreign import sokol_app_clib { "sokol_app_linux_x64_gl_release.a", "system:X11", "system:Xi", "system:Xcursor", "system:GL", "system:dl", "system:pthread" } }
}
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
// Feed sokol_app_wasm_gl_debug.a or sokol_app_wasm_gl_release.a into emscripten compiler.
foreign import sokol_app_clib { "env.o" }
} else {
#panic("This OS is currently not supported")
}
@(default_calling_convention="c", link_prefix="sapp_")
foreign sokol_app_clib {
// returns true after sokol-app has been initialized
isvalid :: proc() -> bool ---
// returns the current framebuffer width in pixels
width :: proc() -> c.int ---
// same as sapp_width(), but returns float
widthf :: proc() -> f32 ---
// returns the current framebuffer height in pixels
height :: proc() -> c.int ---
// same as sapp_height(), but returns float
heightf :: proc() -> f32 ---
// get default framebuffer color pixel format
color_format :: proc() -> c.int ---
// get default framebuffer depth pixel format
depth_format :: proc() -> c.int ---
// get default framebuffer sample count
sample_count :: proc() -> c.int ---
// returns true when high_dpi was requested and actually running in a high-dpi scenario
high_dpi :: proc() -> bool ---
// returns the dpi scaling factor (window pixels to framebuffer pixels)
dpi_scale :: proc() -> f32 ---
// show or hide the mobile device onscreen keyboard
show_keyboard :: proc(show: bool) ---
// return true if the mobile device onscreen keyboard is currently shown
keyboard_shown :: proc() -> bool ---
// query fullscreen mode
is_fullscreen :: proc() -> bool ---
// toggle fullscreen mode
toggle_fullscreen :: proc() ---
// show or hide the mouse cursor
show_mouse :: proc(show: bool) ---
// show or hide the mouse cursor
mouse_shown :: proc() -> bool ---
// enable/disable mouse-pointer-lock mode
lock_mouse :: proc(lock: bool) ---
// return true if in mouse-pointer-lock mode (this may toggle a few frames later)
mouse_locked :: proc() -> bool ---
// set mouse cursor type
set_mouse_cursor :: proc(cursor: Mouse_Cursor) ---
// get current mouse cursor type
get_mouse_cursor :: proc() -> Mouse_Cursor ---
// return the userdata pointer optionally provided in sapp_desc
userdata :: proc() -> rawptr ---
// return a copy of the sapp_desc structure
query_desc :: proc() -> Desc ---
// initiate a "soft quit" (sends SAPP_EVENTTYPE_QUIT_REQUESTED)
request_quit :: proc() ---
// cancel a pending quit (when SAPP_EVENTTYPE_QUIT_REQUESTED has been received)
cancel_quit :: proc() ---
// initiate a "hard quit" (quit application without sending SAPP_EVENTTYPE_QUIT_REQUESTED)
quit :: proc() ---
// call from inside event callback to consume the current event (don't forward to platform)
consume_event :: proc() ---
// get the current frame counter (for comparison with sapp_event.frame_count)
frame_count :: proc() -> u64 ---
// get an averaged/smoothed frame duration in seconds
frame_duration :: proc() -> f64 ---
// write string into clipboard
set_clipboard_string :: proc(str: cstring) ---
// read string from clipboard (usually during SAPP_EVENTTYPE_CLIPBOARD_PASTED)
get_clipboard_string :: proc() -> cstring ---
// set the window title (only on desktop platforms)
set_window_title :: proc(str: cstring) ---
// set the window icon (only on Windows and Linux)
set_icon :: proc(#by_ptr icon_desc: Icon_Desc) ---
// gets the total number of dropped files (after an SAPP_EVENTTYPE_FILES_DROPPED event)
get_num_dropped_files :: proc() -> c.int ---
// gets the dropped file paths
get_dropped_file_path :: proc(#any_int index: c.int) -> cstring ---
// special run-function for SOKOL_NO_ENTRY (in standard mode this is an empty stub)
run :: proc(#by_ptr desc: Desc) ---
// EGL: get EGLDisplay object
egl_get_display :: proc() -> rawptr ---
// EGL: get EGLContext object
egl_get_context :: proc() -> rawptr ---
// HTML5: enable or disable the hardwired "Leave Site?" dialog box
html5_ask_leave_site :: proc(ask: bool) ---
// HTML5: get byte size of a dropped file
html5_get_dropped_file_size :: proc(#any_int index: c.int) -> u32 ---
// HTML5: asynchronously load the content of a dropped file
html5_fetch_dropped_file :: proc(#by_ptr request: Html5_Fetch_Request) ---
// Metal: get bridged pointer to Metal device object
metal_get_device :: proc() -> rawptr ---
// Metal: get bridged pointer to MTKView's current drawable of type CAMetalDrawable
metal_get_current_drawable :: proc() -> rawptr ---
// Metal: get bridged pointer to MTKView's depth-stencil texture of type MTLTexture
metal_get_depth_stencil_texture :: proc() -> rawptr ---
// Metal: get bridged pointer to MTKView's msaa-color-texture of type MTLTexture (may be null)
metal_get_msaa_color_texture :: proc() -> rawptr ---
// macOS: get bridged pointer to macOS NSWindow
macos_get_window :: proc() -> rawptr ---
// iOS: get bridged pointer to iOS UIWindow
ios_get_window :: proc() -> rawptr ---
// D3D11: get pointer to ID3D11Device object
d3d11_get_device :: proc() -> rawptr ---
// D3D11: get pointer to ID3D11DeviceContext object
d3d11_get_device_context :: proc() -> rawptr ---
// D3D11: get pointer to IDXGISwapChain object
d3d11_get_swap_chain :: proc() -> rawptr ---
// D3D11: get pointer to ID3D11RenderTargetView object for rendering
d3d11_get_render_view :: proc() -> rawptr ---
// D3D11: get pointer ID3D11RenderTargetView object for msaa-resolve (may return null)
d3d11_get_resolve_view :: proc() -> rawptr ---
// D3D11: get pointer ID3D11DepthStencilView
d3d11_get_depth_stencil_view :: proc() -> rawptr ---
// Win32: get the HWND window handle
win32_get_hwnd :: proc() -> rawptr ---
// WebGPU: get WGPUDevice handle
wgpu_get_device :: proc() -> rawptr ---
// WebGPU: get swapchain's WGPUTextureView handle for rendering
wgpu_get_render_view :: proc() -> rawptr ---
// WebGPU: get swapchain's MSAA-resolve WGPUTextureView (may return null)
wgpu_get_resolve_view :: proc() -> rawptr ---
// WebGPU: get swapchain's WGPUTextureView for the depth-stencil surface
wgpu_get_depth_stencil_view :: proc() -> rawptr ---
// GL: get framebuffer object
gl_get_framebuffer :: proc() -> u32 ---
// GL: get major version
gl_get_major_version :: proc() -> c.int ---
// GL: get minor version
gl_get_minor_version :: proc() -> c.int ---
// GL: return true if the context is GLES
gl_is_gles :: proc() -> bool ---
// X11: get Window
x11_get_window :: proc() -> rawptr ---
// X11: get Display
x11_get_display :: proc() -> rawptr ---
// Android: get native activity handle
android_get_native_activity :: proc() -> rawptr ---
}
// misc constants
MAX_TOUCHPOINTS :: 8
MAX_MOUSEBUTTONS :: 3
MAX_KEYCODES :: 512
MAX_ICONIMAGES :: 8
/*
sapp_event_type
The type of event that's passed to the event handler callback
in the sapp_event.type field. These are not just "traditional"
input events, but also notify the application about state changes
or other user-invoked actions.
*/
Event_Type :: enum i32 {
INVALID,
KEY_DOWN,
KEY_UP,
CHAR,
MOUSE_DOWN,
MOUSE_UP,
MOUSE_SCROLL,
MOUSE_MOVE,
MOUSE_ENTER,
MOUSE_LEAVE,
TOUCHES_BEGAN,
TOUCHES_MOVED,
TOUCHES_ENDED,
TOUCHES_CANCELLED,
RESIZED,
ICONIFIED,
RESTORED,
FOCUSED,
UNFOCUSED,
SUSPENDED,
RESUMED,
QUIT_REQUESTED,
CLIPBOARD_PASTED,
FILES_DROPPED,
}
/*
sapp_keycode
The 'virtual keycode' of a KEY_DOWN or KEY_UP event in the
struct field sapp_event.key_code.
Note that the keycode values are identical with GLFW.
*/
Keycode :: enum i32 {
INVALID = 0,
SPACE = 32,
APOSTROPHE = 39,
COMMA = 44,
MINUS = 45,
PERIOD = 46,
SLASH = 47,
_0 = 48,
_1 = 49,
_2 = 50,
_3 = 51,
_4 = 52,
_5 = 53,
_6 = 54,
_7 = 55,
_8 = 56,
_9 = 57,
SEMICOLON = 59,
EQUAL = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LEFT_BRACKET = 91,
BACKSLASH = 92,
RIGHT_BRACKET = 93,
GRAVE_ACCENT = 96,
WORLD_1 = 161,
WORLD_2 = 162,
ESCAPE = 256,
ENTER = 257,
TAB = 258,
BACKSPACE = 259,
INSERT = 260,
DELETE = 261,
RIGHT = 262,
LEFT = 263,
DOWN = 264,
UP = 265,
PAGE_UP = 266,
PAGE_DOWN = 267,
HOME = 268,
END = 269,
CAPS_LOCK = 280,
SCROLL_LOCK = 281,
NUM_LOCK = 282,
PRINT_SCREEN = 283,
PAUSE = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
F13 = 302,
F14 = 303,
F15 = 304,
F16 = 305,
F17 = 306,
F18 = 307,
F19 = 308,
F20 = 309,
F21 = 310,
F22 = 311,
F23 = 312,
F24 = 313,
F25 = 314,
KP_0 = 320,
KP_1 = 321,
KP_2 = 322,
KP_3 = 323,
KP_4 = 324,
KP_5 = 325,
KP_6 = 326,
KP_7 = 327,
KP_8 = 328,
KP_9 = 329,
KP_DECIMAL = 330,
KP_DIVIDE = 331,
KP_MULTIPLY = 332,
KP_SUBTRACT = 333,
KP_ADD = 334,
KP_ENTER = 335,
KP_EQUAL = 336,
LEFT_SHIFT = 340,
LEFT_CONTROL = 341,
LEFT_ALT = 342,
LEFT_SUPER = 343,
RIGHT_SHIFT = 344,
RIGHT_CONTROL = 345,
RIGHT_ALT = 346,
RIGHT_SUPER = 347,
MENU = 348,
}
/*
Android specific 'tool type' enum for touch events. This lets the
application check what type of input device was used for
touch events.
NOTE: the values must remain in sync with the corresponding
Android SDK type, so don't change those.
See https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_UNKNOWN
*/
Android_Tooltype :: enum i32 {
UNKNOWN = 0,
FINGER = 1,
STYLUS = 2,
MOUSE = 3,
}
/*
sapp_touchpoint
Describes a single touchpoint in a multitouch event (TOUCHES_BEGAN,
TOUCHES_MOVED, TOUCHES_ENDED).
Touch points are stored in the nested array sapp_event.touches[],
and the number of touches is stored in sapp_event.num_touches.
*/
Touchpoint :: struct {
identifier : c.uintptr_t,
pos_x : f32,
pos_y : f32,
android_tooltype : Android_Tooltype,
changed : bool,
}
/*
sapp_mousebutton
The currently pressed mouse button in the events MOUSE_DOWN
and MOUSE_UP, stored in the struct field sapp_event.mouse_button.
*/
Mousebutton :: enum i32 {
LEFT = 0,
RIGHT = 1,
MIDDLE = 2,
INVALID = 256,
}
/*
These are currently pressed modifier keys (and mouse buttons) which are
passed in the event struct field sapp_event.modifiers.
*/
MODIFIER_SHIFT :: 1
MODIFIER_CTRL :: 2
MODIFIER_ALT :: 4
MODIFIER_SUPER :: 8
MODIFIER_LMB :: 256
MODIFIER_RMB :: 512
MODIFIER_MMB :: 1024
/*
sapp_event
This is an all-in-one event struct passed to the event handler
user callback function. Note that it depends on the event
type what struct fields actually contain useful values, so you
should first check the event type before reading other struct
fields.
*/
Event :: struct {
frame_count : u64,
type : Event_Type,
key_code : Keycode,
char_code : u32,
key_repeat : bool,
modifiers : u32,
mouse_button : Mousebutton,
mouse_x : f32,
mouse_y : f32,
mouse_dx : f32,
mouse_dy : f32,
scroll_x : f32,
scroll_y : f32,
num_touches : c.int,
touches : [8]Touchpoint,
window_width : c.int,
window_height : c.int,
framebuffer_width : c.int,
framebuffer_height : c.int,
}
/*
sg_range
A general pointer/size-pair struct and constructor macros for passing binary blobs
into sokol_app.h.
*/
Range :: struct {
ptr : rawptr,
size : c.size_t,
}
/*
sapp_image_desc
This is used to describe image data to sokol_app.h (at first, window
icons, later maybe cursor images).
Note that the actual image pixel format depends on the use case:
- window icon pixels are RGBA8
*/
Image_Desc :: struct {
width : c.int,
height : c.int,
pixels : Range,
}
/*
sapp_icon_desc
An icon description structure for use in sapp_desc.icon and
sapp_set_icon().
When setting a custom image, the application can provide a number of
candidates differing in size, and sokol_app.h will pick the image(s)
closest to the size expected by the platform's window system.
To set sokol-app's default icon, set .sokol_default to true.
Otherwise provide candidate images of different sizes in the
images[] array.
If both the sokol_default flag is set to true, any image candidates
will be ignored and the sokol_app.h default icon will be set.
*/
Icon_Desc :: struct {
sokol_default : bool,
images : [8]Image_Desc,
}
/*
sapp_allocator
Used in sapp_desc to provide custom memory-alloc and -free functions
to sokol_app.h. If memory management should be overridden, both the
alloc_fn and free_fn function must be provided (e.g. it's not valid to
override one function but not the other).
*/
Allocator :: struct {
alloc_fn : proc "c" (a0: c.size_t, a1: rawptr) -> rawptr,
free_fn : proc "c" (a0: rawptr, a1: rawptr),
user_data : rawptr,
}
Log_Item :: enum i32 {
OK,
MALLOC_FAILED,
MACOS_INVALID_NSOPENGL_PROFILE,
WIN32_LOAD_OPENGL32_DLL_FAILED,
WIN32_CREATE_HELPER_WINDOW_FAILED,
WIN32_HELPER_WINDOW_GETDC_FAILED,
WIN32_DUMMY_CONTEXT_SET_PIXELFORMAT_FAILED,
WIN32_CREATE_DUMMY_CONTEXT_FAILED,
WIN32_DUMMY_CONTEXT_MAKE_CURRENT_FAILED,
WIN32_GET_PIXELFORMAT_ATTRIB_FAILED,
WIN32_WGL_FIND_PIXELFORMAT_FAILED,
WIN32_WGL_DESCRIBE_PIXELFORMAT_FAILED,
WIN32_WGL_SET_PIXELFORMAT_FAILED,
WIN32_WGL_ARB_CREATE_CONTEXT_REQUIRED,
WIN32_WGL_ARB_CREATE_CONTEXT_PROFILE_REQUIRED,
WIN32_WGL_OPENGL_VERSION_NOT_SUPPORTED,
WIN32_WGL_OPENGL_PROFILE_NOT_SUPPORTED,
WIN32_WGL_INCOMPATIBLE_DEVICE_CONTEXT,
WIN32_WGL_CREATE_CONTEXT_ATTRIBS_FAILED_OTHER,
WIN32_D3D11_CREATE_DEVICE_AND_SWAPCHAIN_WITH_DEBUG_FAILED,
WIN32_D3D11_GET_IDXGIFACTORY_FAILED,
WIN32_D3D11_GET_IDXGIADAPTER_FAILED,
WIN32_D3D11_QUERY_INTERFACE_IDXGIDEVICE1_FAILED,
WIN32_REGISTER_RAW_INPUT_DEVICES_FAILED_MOUSE_LOCK,
WIN32_REGISTER_RAW_INPUT_DEVICES_FAILED_MOUSE_UNLOCK,
WIN32_GET_RAW_INPUT_DATA_FAILED,
LINUX_GLX_LOAD_LIBGL_FAILED,
LINUX_GLX_LOAD_ENTRY_POINTS_FAILED,
LINUX_GLX_EXTENSION_NOT_FOUND,
LINUX_GLX_QUERY_VERSION_FAILED,
LINUX_GLX_VERSION_TOO_LOW,
LINUX_GLX_NO_GLXFBCONFIGS,
LINUX_GLX_NO_SUITABLE_GLXFBCONFIG,
LINUX_GLX_GET_VISUAL_FROM_FBCONFIG_FAILED,
LINUX_GLX_REQUIRED_EXTENSIONS_MISSING,
LINUX_GLX_CREATE_CONTEXT_FAILED,
LINUX_GLX_CREATE_WINDOW_FAILED,
LINUX_X11_CREATE_WINDOW_FAILED,
LINUX_EGL_BIND_OPENGL_API_FAILED,
LINUX_EGL_BIND_OPENGL_ES_API_FAILED,
LINUX_EGL_GET_DISPLAY_FAILED,
LINUX_EGL_INITIALIZE_FAILED,
LINUX_EGL_NO_CONFIGS,
LINUX_EGL_NO_NATIVE_VISUAL,
LINUX_EGL_GET_VISUAL_INFO_FAILED,
LINUX_EGL_CREATE_WINDOW_SURFACE_FAILED,
LINUX_EGL_CREATE_CONTEXT_FAILED,
LINUX_EGL_MAKE_CURRENT_FAILED,
LINUX_X11_OPEN_DISPLAY_FAILED,
LINUX_X11_QUERY_SYSTEM_DPI_FAILED,
LINUX_X11_DROPPED_FILE_URI_WRONG_SCHEME,
LINUX_X11_FAILED_TO_BECOME_OWNER_OF_CLIPBOARD,
ANDROID_UNSUPPORTED_INPUT_EVENT_INPUT_CB,
ANDROID_UNSUPPORTED_INPUT_EVENT_MAIN_CB,
ANDROID_READ_MSG_FAILED,
ANDROID_WRITE_MSG_FAILED,
ANDROID_MSG_CREATE,
ANDROID_MSG_RESUME,
ANDROID_MSG_PAUSE,
ANDROID_MSG_FOCUS,
ANDROID_MSG_NO_FOCUS,
ANDROID_MSG_SET_NATIVE_WINDOW,
ANDROID_MSG_SET_INPUT_QUEUE,
ANDROID_MSG_DESTROY,
ANDROID_UNKNOWN_MSG,
ANDROID_LOOP_THREAD_STARTED,
ANDROID_LOOP_THREAD_DONE,
ANDROID_NATIVE_ACTIVITY_ONSTART,
ANDROID_NATIVE_ACTIVITY_ONRESUME,
ANDROID_NATIVE_ACTIVITY_ONSAVEINSTANCESTATE,
ANDROID_NATIVE_ACTIVITY_ONWINDOWFOCUSCHANGED,
ANDROID_NATIVE_ACTIVITY_ONPAUSE,
ANDROID_NATIVE_ACTIVITY_ONSTOP,
ANDROID_NATIVE_ACTIVITY_ONNATIVEWINDOWCREATED,
ANDROID_NATIVE_ACTIVITY_ONNATIVEWINDOWDESTROYED,
ANDROID_NATIVE_ACTIVITY_ONINPUTQUEUECREATED,
ANDROID_NATIVE_ACTIVITY_ONINPUTQUEUEDESTROYED,
ANDROID_NATIVE_ACTIVITY_ONCONFIGURATIONCHANGED,
ANDROID_NATIVE_ACTIVITY_ONLOWMEMORY,
ANDROID_NATIVE_ACTIVITY_ONDESTROY,
ANDROID_NATIVE_ACTIVITY_DONE,
ANDROID_NATIVE_ACTIVITY_ONCREATE,
ANDROID_CREATE_THREAD_PIPE_FAILED,
ANDROID_NATIVE_ACTIVITY_CREATE_SUCCESS,
WGPU_SWAPCHAIN_CREATE_SURFACE_FAILED,
WGPU_SWAPCHAIN_SURFACE_GET_CAPABILITIES_FAILED,
WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_TEXTURE_FAILED,
WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_VIEW_FAILED,
WGPU_SWAPCHAIN_CREATE_MSAA_TEXTURE_FAILED,
WGPU_SWAPCHAIN_CREATE_MSAA_VIEW_FAILED,
WGPU_SWAPCHAIN_GETCURRENTTEXTURE_FAILED,
WGPU_REQUEST_DEVICE_STATUS_ERROR,
WGPU_REQUEST_DEVICE_STATUS_UNKNOWN,
WGPU_REQUEST_ADAPTER_STATUS_UNAVAILABLE,
WGPU_REQUEST_ADAPTER_STATUS_ERROR,
WGPU_REQUEST_ADAPTER_STATUS_UNKNOWN,
WGPU_CREATE_INSTANCE_FAILED,
IMAGE_DATA_SIZE_MISMATCH,
DROPPED_FILE_PATH_TOO_LONG,
CLIPBOARD_STRING_TOO_BIG,
}
/*
sapp_logger
Used in sapp_desc to provide a logging function. Please be aware that
without logging function, sokol-app will be completely silent, e.g. it will
not report errors or warnings. For maximum error verbosity, compile in
debug mode (e.g. NDEBUG *not* defined) and install a logger (for instance
the standard logging function from sokol_log.h).
*/
Logger :: struct {
func : proc "c" (a0: cstring, a1: u32, a2: u32, a3: cstring, a4: u32, a5: cstring, a6: rawptr),
user_data : rawptr,
}
/*
sokol-app initialization options, used as return value of sokol_main()
or sapp_run() argument.
*/
Desc :: struct {
init_cb : proc "c" (),
frame_cb : proc "c" (),
cleanup_cb : proc "c" (),
event_cb : proc "c" (a0: ^Event),
user_data : rawptr,
init_userdata_cb : proc "c" (a0: rawptr),
frame_userdata_cb : proc "c" (a0: rawptr),
cleanup_userdata_cb : proc "c" (a0: rawptr),
event_userdata_cb : proc "c" (a0: ^Event, a1: rawptr),
width : c.int,
height : c.int,
sample_count : c.int,
swap_interval : c.int,
high_dpi : bool,
fullscreen : bool,
alpha : bool,
window_title : cstring,
enable_clipboard : bool,
clipboard_size : c.int,
enable_dragndrop : bool,
max_dropped_files : c.int,
max_dropped_file_path_length : c.int,
icon : Icon_Desc,
allocator : Allocator,
logger : Logger,
gl_major_version : c.int,
gl_minor_version : c.int,
win32_console_utf8 : bool,
win32_console_create : bool,
win32_console_attach : bool,
html5_canvas_selector : cstring,
html5_canvas_resize : bool,
html5_preserve_drawing_buffer : bool,
html5_premultiplied_alpha : bool,
html5_ask_leave_site : bool,
html5_update_document_title : bool,
html5_bubble_mouse_events : bool,
html5_bubble_touch_events : bool,
html5_bubble_wheel_events : bool,
html5_bubble_key_events : bool,
html5_bubble_char_events : bool,
html5_use_emsc_set_main_loop : bool,
html5_emsc_set_main_loop_simulate_infinite_loop : bool,
ios_keyboard_resizes_canvas : bool,
}
/*
HTML5 specific: request and response structs for
asynchronously loading dropped-file content.
*/
Html5_Fetch_Error :: enum i32 {
FETCH_ERROR_NO_ERROR,
FETCH_ERROR_BUFFER_TOO_SMALL,
FETCH_ERROR_OTHER,
}
Html5_Fetch_Response :: struct {
succeeded : bool,
error_code : Html5_Fetch_Error,
file_index : c.int,
data : Range,
buffer : Range,
user_data : rawptr,
}
Html5_Fetch_Request :: struct {
dropped_file_index : c.int,
callback : proc "c" (a0: ^Html5_Fetch_Response),
buffer : Range,
user_data : rawptr,
}
/*
sapp_mouse_cursor
Predefined cursor image definitions, set with sapp_set_mouse_cursor(sapp_mouse_cursor cursor)
*/
Mouse_Cursor :: enum i32 {
DEFAULT = 0,
ARROW,
IBEAM,
CROSSHAIR,
POINTING_HAND,
RESIZE_EW,
RESIZE_NS,
RESIZE_NWSE,
RESIZE_NESW,
RESIZE_ALL,
NOT_ALLOWED,
}