From f834644db4a4f35ceebb626d43b70b00cfafceeb Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 10 Jul 2019 13:27:35 +0200 Subject: [PATCH] make gg work on Windows; prebuild glad and cJSON; new ft module --- compiler/cgen.v | 22 + compiler/fn.v | 4 +- compiler/main.v | 4 +- compiler/parser.v | 22 +- thirdparty/glad/glad.c | 1 + thirdparty/glfw/GLFW/glfw3.h | 5637 ++++++++++++++++++++++++++++ thirdparty/glfw/GLFW/glfw3native.h | 525 +++ thirdparty/glfw/glfw3.dll | Bin 0 -> 249856 bytes vlib/ft/ft.v | 358 ++ vlib/gg/gg.v | 335 +- vlib/gl/1shader.v | 2 +- vlib/gl/gl.v | 7 +- vlib/glfw/glfw.v | 4 + vlib/glm/glm.v | 4 +- vlib/json/json_primitives.v | 3 +- vlib/os/os.v | 2 +- vlib/stbi/stbi.v | 3 +- 17 files changed, 6593 insertions(+), 340 deletions(-) create mode 100644 thirdparty/glfw/GLFW/glfw3.h create mode 100644 thirdparty/glfw/GLFW/glfw3native.h create mode 100644 thirdparty/glfw/glfw3.dll create mode 100644 vlib/ft/ft.v diff --git a/compiler/cgen.v b/compiler/cgen.v index d02530f570..a946a4c843 100644 --- a/compiler/cgen.v +++ b/compiler/cgen.v @@ -40,6 +40,7 @@ fn new_cgen(out_name_c string) *CGen { gen := &CGen { out_path: path out: out + lines: _make(0, 1000, sizeof(string)) } return gen } @@ -220,3 +221,24 @@ fn (g mut CGen) add_to_main(s string) { g.fn_main = g.fn_main + s } + +fn build_thirdparty_obj_file(flag string) { + obj_path := flag.all_after(' ') + if os.file_exists(obj_path) { + return + } + println('$obj_path not found, building it...') + parent := obj_path.all_before_last('/').trim_space() + files := os.ls(parent) + //files := os.ls(parent).filter(_.ends_with('.c')) TODO + mut cfiles := '' + for file in files { + if file.ends_with('.c') { + cfiles += parent + '/' + file + ' ' + } + } + cc := if os.user_os() == 'windows' { 'gcc' } else { 'cc' } // TODO clang support on Windows + res := os.exec('$cc -c -o $obj_path $cfiles') + println(res) +} + diff --git a/compiler/fn.v b/compiler/fn.v index e662d9dcd6..2134094d2b 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -244,11 +244,9 @@ fn (p mut Parser) fn_decl() { typ = p.get_type() } // Translated C code can have empty functions (just definitions) - is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && - (p.tok != .lcbr)// || (p.tok == .name && p.peek() != .lcbr)) + is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr if is_fn_header { f.is_decl = true - // println('.key_goT fn header $f.name') } // { required only in normal function declarations if !is_c && !is_sig && !is_fn_header { diff --git a/compiler/main.v b/compiler/main.v index 0ab80ff056..214a4fb67b 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -247,7 +247,7 @@ void init_consts();') // Embed cjson either in embedvlib or in json.o if imports_json && v.pref.build_mode == .embed_vlib || (v.pref.build_mode == .build && v.out_name.contains('json.o')) { - cgen.genln('#include "cJSON.c" ') + //cgen.genln('#include "cJSON.c" ') } // We need the cjson header for all the json decoding user will do in default mode if v.pref.build_mode == .default_mode { @@ -522,7 +522,7 @@ fn (v mut V) cc() { } linux_host := os.user_os() == 'linux' v.log('cc() isprod=$v.pref.is_prod outname=$v.out_name') - mut a := ['-w', '-march=native']// arguments for the C compiler + mut a := ['-w'] // arguments for the C compiler flags := v.table.flags.join(' ') //mut shared := '' if v.pref.is_so { diff --git a/compiler/parser.v b/compiler/parser.v index ee6c870d30..619d003068 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -356,7 +356,7 @@ fn (p mut Parser) const_decl() { // cur_line has const's value right now. if it's just a number, then optimize generation: // output a #define so that we don't pollute the binary with unnecessary global vars if is_compile_time_const(p.cgen.cur_line) { - p.cgen.consts << '#define $name $p.cgen.cur_line' + p.cgen.consts << '#define $name $p.cgen.cur_line' p.cgen.cur_line = '' p.fgenln('') continue @@ -464,7 +464,7 @@ fn (p mut Parser) struct_decl() { if !is_c { kind := if is_union{'union'} else { 'struct'} p.gen_typedef('typedef $kind $name $name;') - p.gen_type('$kind /*kind*/ $name {') + p.gen_type('$kind $name {') } } // V used to have 'type Foo struct', many Go users might use this syntax @@ -591,7 +591,7 @@ fn (p mut Parser) enum_decl(_enum_name string) { } // Skip empty enums if enum_name != 'int' { - p.cgen.typedefs << 'typedef int $enum_name ;\n' + p.cgen.typedefs << 'typedef int $enum_name;' } p.check(.lcbr) mut val := 0 @@ -602,7 +602,7 @@ fn (p mut Parser) enum_decl(_enum_name string) { name := '${p.mod}__${enum_name}_$field' p.fgenln('') if p.run == .main { - p.cgen.consts << '#define $name $val \n' + p.cgen.consts << '#define $name $val' } if p.tok == .comma { p.next() @@ -2046,7 +2046,8 @@ fn (p mut Parser) factor() string { p.next() return 'T' case Token.lpar: - p.gen('(/*lpar*/') + //p.gen('(/*lpar*/') + p.gen('(') p.check(.lpar) typ = p.bool_expression() // Hack. If this `)` referes to a ptr cast `(*int__)__`, it was already checked @@ -2686,13 +2687,17 @@ fn (p mut Parser) chash() { pos := flag.index(' ') flag = flag.right(pos) } + has_vroot := flag.contains('@VROOT') flag = flag.trim_space().replace('@VROOT', p.vroot) if p.table.flags.contains(flag) { return } p.log('adding flag "$flag"') - p.table.flags << flag// .all_after(' ')) - // } + // `@VROOT/thirdparty/glad/glad.o`, make sure it exists, otherwise build it + if has_vroot && flag.contains('.o') { + build_thirdparty_obj_file(flag) + } + p.table.flags << flag return } if hash.starts_with('include') { @@ -2745,7 +2750,6 @@ fn (p mut Parser) if_st(is_expr bool) string { } else { p.genln(') {') - p.genln('/*if*/') } p.fgen(' ') p.check(.lcbr) @@ -2775,7 +2779,6 @@ fn (p mut Parser) if_st(is_expr bool) string { } else { p.genln(' else { ') - p.genln('/*else if*/') } p.check(.lcbr) // statements() returns the type of the last statement @@ -2957,6 +2960,7 @@ fn (p mut Parser) for_st() { } p.fspace() p.check(.lcbr) + p.genln('') p.statements() p.cur_fn.close_scope() p.for_expr_cnt-- diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c index 43041f386b..c410a0994b 100644 --- a/thirdparty/glad/glad.c +++ b/thirdparty/glad/glad.c @@ -21,6 +21,7 @@ #include #include #include +#include "glad.h" //#include static void* get_proc(const char *namez); diff --git a/thirdparty/glfw/GLFW/glfw3.h b/thirdparty/glfw/GLFW/glfw3.h new file mode 100644 index 0000000000..0521d19801 --- /dev/null +++ b/thirdparty/glfw/GLFW/glfw3.h @@ -0,0 +1,5637 @@ +/************************************************************************* + * GLFW 3.3 - www.glfw.org + * A library for OpenGL, window and input + *------------------------------------------------------------------------ + * Copyright (c) 2002-2006 Marcus Geelnard + * Copyright (c) 2006-2019 Camilla Löwy + * + * 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. + * + *************************************************************************/ + +#ifndef _glfw3_h_ +#define _glfw3_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************* + * Doxygen documentation + *************************************************************************/ + +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. + * + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. + */ +/*! @defgroup context Context reference + * @brief Functions and types related to OpenGL and OpenGL ES contexts. + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * @brief Functions and types related to Vulkan. + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference + * @brief Functions and types related to initialization and error handling. + * + * This is the reference documentation for initialization and termination of + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. + */ +/*! @defgroup input Input reference + * @brief Functions and types related to input handling. + * + * This is the reference documentation for input related functions and types. + * For more task-oriented information, see the @ref input_guide. + */ +/*! @defgroup monitor Monitor reference + * @brief Functions and types related to monitors. + * + * This is the reference documentation for monitor related functions and types. + * For more task-oriented information, see the @ref monitor_guide. + */ +/*! @defgroup window Window reference + * @brief Functions and types related to windows. + * + * This is the reference documentation for window related functions and types, + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. + */ + + +/************************************************************************* + * Compiler- and platform-specific preprocessor work + *************************************************************************/ + +/* If we are we on Windows, we want a single define for it. + */ +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) + #define _WIN32 +#endif /* _WIN32 */ + +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. + */ +#ifndef APIENTRY + #ifdef _WIN32 + #define APIENTRY __stdcall + #else + #define APIENTRY + #endif + #define GLFW_APIENTRY_DEFINED +#endif /* APIENTRY */ + +/* Some Windows OpenGL headers need this. + */ +#if !defined(WINGDIAPI) && defined(_WIN32) + #define WINGDIAPI __declspec(dllimport) + #define GLFW_WINGDIAPI_DEFINED +#endif /* WINGDIAPI */ + +/* Some Windows GLU headers need this. + */ +#if !defined(CALLBACK) && defined(_WIN32) + #define CALLBACK __stdcall + #define GLFW_CALLBACK_DEFINED +#endif /* CALLBACK */ + +/* Include because most Windows GLU headers need wchar_t and + * the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include + +/* Include because it is needed by Vulkan and related functions. + * Include it unconditionally to avoid surprising side-effects. + */ +#include + +/* Include the chosen OpenGL or OpenGL ES headers. + */ +#if defined(GLFW_INCLUDE_ES1) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES2) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES3) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES31) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES32) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_GLCOREARB) + + #if defined(__APPLE__) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif /*GLFW_INCLUDE_GLEXT*/ + + #else /*__APPLE__*/ + + #include + + #endif /*__APPLE__*/ + +#elif !defined(GLFW_INCLUDE_NONE) + + #if defined(__APPLE__) + + #if !defined(GLFW_INCLUDE_GLEXT) + #define GL_GLEXT_LEGACY + #endif + #include + #if defined(GLFW_INCLUDE_GLU) + #include + #endif + + #else /*__APPLE__*/ + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + #if defined(GLFW_INCLUDE_GLU) + #include + #endif + + #endif /*__APPLE__*/ + +#endif /* OpenGL and OpenGL ES headers */ + +#if defined(GLFW_INCLUDE_VULKAN) + #include +#endif /* Vulkan header */ + +#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) + /* GLFW_DLL must be defined by applications that are linking against the DLL + * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW + * configuration header when compiling the DLL version of the library. + */ + #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined" +#endif + +/* GLFWAPI is used to declare public API functions for export + * from the DLL / shared library / dynamic library. + */ +#if defined(_WIN32) && defined(_GLFW_BUILD_DLL) + /* We are building GLFW as a Win32 DLL */ + #define GLFWAPI __declspec(dllexport) +#elif defined(_WIN32) && defined(GLFW_DLL) + /* We are calling GLFW as a Win32 DLL */ + #define GLFWAPI __declspec(dllimport) +#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) + /* We are building GLFW as a shared / dynamic library */ + #define GLFWAPI __attribute__((visibility("default"))) +#else + /* We are building or calling GLFW as a static library */ + #define GLFWAPI +#endif + + +/************************************************************************* + * GLFW API tokens + *************************************************************************/ + +/*! @name GLFW version macros + * @{ */ +/*! @brief The major version number of the GLFW library. + * + * This is incremented when the API is changed in non-compatible ways. + * @ingroup init + */ +#define GLFW_VERSION_MAJOR 3 +/*! @brief The minor version number of the GLFW library. + * + * This is incremented when features are added to the API but it remains + * backward-compatible. + * @ingroup init + */ +#define GLFW_VERSION_MINOR 3 +/*! @brief The revision number of the GLFW library. + * + * This is incremented when a bug fix release is made that does not contain any + * API changes. + * @ingroup init + */ +#define GLFW_VERSION_REVISION 0 +/*! @} */ + +/*! @brief One. + * + * This is only semantic sugar for the number 1. You can instead use `1` or + * `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal + * to one. + * + * @ingroup init + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * This is only semantic sugar for the number 0. You can instead use `0` or + * `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is + * equal to zero. + * + * @ingroup init + */ +#define GLFW_FALSE 0 + +/*! @name Key and button actions + * @{ */ +/*! @brief The key or mouse button was released. + * + * The key or mouse button was released. + * + * @ingroup input + */ +#define GLFW_RELEASE 0 +/*! @brief The key or mouse button was pressed. + * + * The key or mouse button was pressed. + * + * @ingroup input + */ +#define GLFW_PRESS 1 +/*! @brief The key was held down until it repeated. + * + * The key was held down until it repeated. + * + * @ingroup input + */ +#define GLFW_REPEAT 2 +/*! @} */ + +/*! @defgroup hat_state Joystick hat states + * @brief Joystick hat states. + * + * See [joystick hat input](@ref joystick_hat) for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_HAT_CENTERED 0 +#define GLFW_HAT_UP 1 +#define GLFW_HAT_RIGHT 2 +#define GLFW_HAT_DOWN 4 +#define GLFW_HAT_LEFT 8 +#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP) +#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) +#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP) +#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN) +/*! @} */ + +/*! @defgroup keys Keyboard keys + * @brief Keyboard key IDs. + * + * See [key input](@ref input_key) for how these are used. + * + * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60), + * but re-arranged to map to 7-bit ASCII for printable keys (function keys are + * put in the 256+ range). + * + * The naming of the key codes follow these rules: + * - The US keyboard layout is used + * - Names of printable alpha-numeric characters are used (e.g. "A", "R", + * "3", etc.) + * - For non-alphanumeric characters, Unicode:ish names are used (e.g. + * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not + * correspond to the Unicode standard (usually for brevity) + * - Keys that lack a clear US mapping are named "WORLD_x" + * - For non-printable keys, custom names are used (e.g. "F4", + * "BACKSPACE", etc.) + * + * @ingroup input + * @{ + */ + +/* The unknown key */ +#define GLFW_KEY_UNKNOWN -1 + +/* Printable keys */ +#define GLFW_KEY_SPACE 32 +#define GLFW_KEY_APOSTROPHE 39 /* ' */ +#define GLFW_KEY_COMMA 44 /* , */ +#define GLFW_KEY_MINUS 45 /* - */ +#define GLFW_KEY_PERIOD 46 /* . */ +#define GLFW_KEY_SLASH 47 /* / */ +#define GLFW_KEY_0 48 +#define GLFW_KEY_1 49 +#define GLFW_KEY_2 50 +#define GLFW_KEY_3 51 +#define GLFW_KEY_4 52 +#define GLFW_KEY_5 53 +#define GLFW_KEY_6 54 +#define GLFW_KEY_7 55 +#define GLFW_KEY_8 56 +#define GLFW_KEY_9 57 +#define GLFW_KEY_SEMICOLON 59 /* ; */ +#define GLFW_KEY_EQUAL 61 /* = */ +#define GLFW_KEY_A 65 +#define GLFW_KEY_B 66 +#define GLFW_KEY_C 67 +#define GLFW_KEY_D 68 +#define GLFW_KEY_E 69 +#define GLFW_KEY_F 70 +#define GLFW_KEY_G 71 +#define GLFW_KEY_H 72 +#define GLFW_KEY_I 73 +#define GLFW_KEY_J 74 +#define GLFW_KEY_K 75 +#define GLFW_KEY_L 76 +#define GLFW_KEY_M 77 +#define GLFW_KEY_N 78 +#define GLFW_KEY_O 79 +#define GLFW_KEY_P 80 +#define GLFW_KEY_Q 81 +#define GLFW_KEY_R 82 +#define GLFW_KEY_S 83 +#define GLFW_KEY_T 84 +#define GLFW_KEY_U 85 +#define GLFW_KEY_V 86 +#define GLFW_KEY_W 87 +#define GLFW_KEY_X 88 +#define GLFW_KEY_Y 89 +#define GLFW_KEY_Z 90 +#define GLFW_KEY_LEFT_BRACKET 91 /* [ */ +#define GLFW_KEY_BACKSLASH 92 /* \ */ +#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */ +#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */ +#define GLFW_KEY_WORLD_1 161 /* non-US #1 */ +#define GLFW_KEY_WORLD_2 162 /* non-US #2 */ + +/* Function keys */ +#define GLFW_KEY_ESCAPE 256 +#define GLFW_KEY_ENTER 257 +#define GLFW_KEY_TAB 258 +#define GLFW_KEY_BACKSPACE 259 +#define GLFW_KEY_INSERT 260 +#define GLFW_KEY_DELETE 261 +#define GLFW_KEY_RIGHT 262 +#define GLFW_KEY_LEFT 263 +#define GLFW_KEY_DOWN 264 +#define GLFW_KEY_UP 265 +#define GLFW_KEY_PAGE_UP 266 +#define GLFW_KEY_PAGE_DOWN 267 +#define GLFW_KEY_HOME 268 +#define GLFW_KEY_END 269 +#define GLFW_KEY_CAPS_LOCK 280 +#define GLFW_KEY_SCROLL_LOCK 281 +#define GLFW_KEY_NUM_LOCK 282 +#define GLFW_KEY_PRINT_SCREEN 283 +#define GLFW_KEY_PAUSE 284 +#define GLFW_KEY_F1 290 +#define GLFW_KEY_F2 291 +#define GLFW_KEY_F3 292 +#define GLFW_KEY_F4 293 +#define GLFW_KEY_F5 294 +#define GLFW_KEY_F6 295 +#define GLFW_KEY_F7 296 +#define GLFW_KEY_F8 297 +#define GLFW_KEY_F9 298 +#define GLFW_KEY_F10 299 +#define GLFW_KEY_F11 300 +#define GLFW_KEY_F12 301 +#define GLFW_KEY_F13 302 +#define GLFW_KEY_F14 303 +#define GLFW_KEY_F15 304 +#define GLFW_KEY_F16 305 +#define GLFW_KEY_F17 306 +#define GLFW_KEY_F18 307 +#define GLFW_KEY_F19 308 +#define GLFW_KEY_F20 309 +#define GLFW_KEY_F21 310 +#define GLFW_KEY_F22 311 +#define GLFW_KEY_F23 312 +#define GLFW_KEY_F24 313 +#define GLFW_KEY_F25 314 +#define GLFW_KEY_KP_0 320 +#define GLFW_KEY_KP_1 321 +#define GLFW_KEY_KP_2 322 +#define GLFW_KEY_KP_3 323 +#define GLFW_KEY_KP_4 324 +#define GLFW_KEY_KP_5 325 +#define GLFW_KEY_KP_6 326 +#define GLFW_KEY_KP_7 327 +#define GLFW_KEY_KP_8 328 +#define GLFW_KEY_KP_9 329 +#define GLFW_KEY_KP_DECIMAL 330 +#define GLFW_KEY_KP_DIVIDE 331 +#define GLFW_KEY_KP_MULTIPLY 332 +#define GLFW_KEY_KP_SUBTRACT 333 +#define GLFW_KEY_KP_ADD 334 +#define GLFW_KEY_KP_ENTER 335 +#define GLFW_KEY_KP_EQUAL 336 +#define GLFW_KEY_LEFT_SHIFT 340 +#define GLFW_KEY_LEFT_CONTROL 341 +#define GLFW_KEY_LEFT_ALT 342 +#define GLFW_KEY_LEFT_SUPER 343 +#define GLFW_KEY_RIGHT_SHIFT 344 +#define GLFW_KEY_RIGHT_CONTROL 345 +#define GLFW_KEY_RIGHT_ALT 346 +#define GLFW_KEY_RIGHT_SUPER 347 +#define GLFW_KEY_MENU 348 + +#define GLFW_KEY_LAST GLFW_KEY_MENU + +/*! @} */ + +/*! @defgroup mods Modifier key flags + * @brief Modifier key flags. + * + * See [key input](@ref input_key) for how these are used. + * + * @ingroup input + * @{ */ + +/*! @brief If this bit is set one or more Shift keys were held down. + * + * If this bit is set one or more Shift keys were held down. + */ +#define GLFW_MOD_SHIFT 0x0001 +/*! @brief If this bit is set one or more Control keys were held down. + * + * If this bit is set one or more Control keys were held down. + */ +#define GLFW_MOD_CONTROL 0x0002 +/*! @brief If this bit is set one or more Alt keys were held down. + * + * If this bit is set one or more Alt keys were held down. + */ +#define GLFW_MOD_ALT 0x0004 +/*! @brief If this bit is set one or more Super keys were held down. + * + * If this bit is set one or more Super keys were held down. + */ +#define GLFW_MOD_SUPER 0x0008 +/*! @brief If this bit is set the Caps Lock key is enabled. + * + * If this bit is set the Caps Lock key is enabled and the @ref + * GLFW_LOCK_KEY_MODS input mode is set. + */ +#define GLFW_MOD_CAPS_LOCK 0x0010 +/*! @brief If this bit is set the Num Lock key is enabled. + * + * If this bit is set the Num Lock key is enabled and the @ref + * GLFW_LOCK_KEY_MODS input mode is set. + */ +#define GLFW_MOD_NUM_LOCK 0x0020 + +/*! @} */ + +/*! @defgroup buttons Mouse buttons + * @brief Mouse button IDs. + * + * See [mouse button input](@ref input_mouse_button) for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_MOUSE_BUTTON_1 0 +#define GLFW_MOUSE_BUTTON_2 1 +#define GLFW_MOUSE_BUTTON_3 2 +#define GLFW_MOUSE_BUTTON_4 3 +#define GLFW_MOUSE_BUTTON_5 4 +#define GLFW_MOUSE_BUTTON_6 5 +#define GLFW_MOUSE_BUTTON_7 6 +#define GLFW_MOUSE_BUTTON_8 7 +#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8 +#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1 +#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2 +#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3 +/*! @} */ + +/*! @defgroup joysticks Joysticks + * @brief Joystick IDs. + * + * See [joystick input](@ref joystick) for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_JOYSTICK_1 0 +#define GLFW_JOYSTICK_2 1 +#define GLFW_JOYSTICK_3 2 +#define GLFW_JOYSTICK_4 3 +#define GLFW_JOYSTICK_5 4 +#define GLFW_JOYSTICK_6 5 +#define GLFW_JOYSTICK_7 6 +#define GLFW_JOYSTICK_8 7 +#define GLFW_JOYSTICK_9 8 +#define GLFW_JOYSTICK_10 9 +#define GLFW_JOYSTICK_11 10 +#define GLFW_JOYSTICK_12 11 +#define GLFW_JOYSTICK_13 12 +#define GLFW_JOYSTICK_14 13 +#define GLFW_JOYSTICK_15 14 +#define GLFW_JOYSTICK_16 15 +#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16 +/*! @} */ + +/*! @defgroup gamepad_buttons Gamepad buttons + * @brief Gamepad buttons. + * + * See @ref gamepad for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_GAMEPAD_BUTTON_A 0 +#define GLFW_GAMEPAD_BUTTON_B 1 +#define GLFW_GAMEPAD_BUTTON_X 2 +#define GLFW_GAMEPAD_BUTTON_Y 3 +#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4 +#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5 +#define GLFW_GAMEPAD_BUTTON_BACK 6 +#define GLFW_GAMEPAD_BUTTON_START 7 +#define GLFW_GAMEPAD_BUTTON_GUIDE 8 +#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9 +#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10 +#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11 +#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12 +#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13 +#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14 +#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT + +#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A +#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B +#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X +#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y +/*! @} */ + +/*! @defgroup gamepad_axes Gamepad axes + * @brief Gamepad axes. + * + * See @ref gamepad for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_GAMEPAD_AXIS_LEFT_X 0 +#define GLFW_GAMEPAD_AXIS_LEFT_Y 1 +#define GLFW_GAMEPAD_AXIS_RIGHT_X 2 +#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3 +#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4 +#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5 +#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER +/*! @} */ + +/*! @defgroup errors Error codes + * @brief Error codes. + * + * See [error handling](@ref error_handling) for how these are used. + * + * @ingroup init + * @{ */ +/*! @brief No error has occurred. + * + * No error has occurred. + * + * @analysis Yay. + */ +#define GLFW_NO_ERROR 0 +/*! @brief GLFW has not been initialized. + * + * This occurs if a GLFW function was called that must not be called unless the + * library is [initialized](@ref intro_init). + * + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. + */ +#define GLFW_NOT_INITIALIZED 0x00010001 +/*! @brief No context is current for this thread. + * + * This occurs if a GLFW function was called that needs and operates on the + * current OpenGL or OpenGL ES context but no context is current on the calling + * thread. One such function is @ref glfwSwapInterval. + * + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. + */ +#define GLFW_NO_CURRENT_CONTEXT 0x00010002 +/*! @brief One of the arguments to the function was an invalid enum value. + * + * One of the arguments to the function was an invalid enum value, for example + * requesting @ref GLFW_RED_BITS with @ref glfwGetWindowAttrib. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_INVALID_ENUM 0x00010003 +/*! @brief One of the arguments to the function was an invalid value. + * + * One of the arguments to the function was an invalid value, for example + * requesting a non-existent OpenGL or OpenGL ES version like 2.7. + * + * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead + * result in a @ref GLFW_VERSION_UNAVAILABLE error. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_INVALID_VALUE 0x00010004 +/*! @brief A memory allocation failed. + * + * A memory allocation failed. + * + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). + */ +#define GLFW_OUT_OF_MEMORY 0x00010005 +/*! @brief GLFW could not find support for the requested API on the system. + * + * GLFW could not find support for the requested API on the system. + * + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. + * + * @par + * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via + * a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa + * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary + * driver. Older graphics drivers do not support Vulkan. + */ +#define GLFW_API_UNAVAILABLE 0x00010006 +/*! @brief The requested OpenGL or OpenGL ES version is not available. + * + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. + * + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your + * requirements. + * + * @par + * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0 + * comes out before the 4.x series gets that far, also fail with this error and + * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions + * will exist. + */ +#define GLFW_VERSION_UNAVAILABLE 0x00010007 +/*! @brief A platform-specific error occurred that does not match any of the + * more specific categories. + * + * A platform-specific error occurred that does not match any of the more + * specific categories. + * + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). + */ +#define GLFW_PLATFORM_ERROR 0x00010008 +/*! @brief The requested format is not supported or available. + * + * If emitted during window creation, the requested pixel format is not + * supported. + * + * If emitted when querying the clipboard, the contents of the clipboard could + * not be converted to the requested format. + * + * @analysis If emitted during window creation, one or more + * [hard constraints](@ref window_hints_hard) did not match any of the + * available pixel formats. If your application is sufficiently flexible, + * downgrade your requirements and try again. Otherwise, inform the user that + * their machine does not match your requirements. + * + * @par + * If emitted when querying the clipboard, ignore the error or report it to + * the user, as appropriate. + */ +#define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A +/*! @} */ + +/*! @addtogroup window + * @{ */ +/*! @brief Input focus window hint and attribute + * + * Input focus [window hint](@ref GLFW_FOCUSED_hint) or + * [window attribute](@ref GLFW_FOCUSED_attrib). + */ +#define GLFW_FOCUSED 0x00020001 +/*! @brief Window iconification window attribute + * + * Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib). + */ +#define GLFW_ICONIFIED 0x00020002 +/*! @brief Window resize-ability window hint and attribute + * + * Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and + * [window attribute](@ref GLFW_RESIZABLE_attrib). + */ +#define GLFW_RESIZABLE 0x00020003 +/*! @brief Window visibility window hint and attribute + * + * Window visibility [window hint](@ref GLFW_VISIBLE_hint) and + * [window attribute](@ref GLFW_VISIBLE_attrib). + */ +#define GLFW_VISIBLE 0x00020004 +/*! @brief Window decoration window hint and attribute + * + * Window decoration [window hint](@ref GLFW_DECORATED_hint) and + * [window attribute](@ref GLFW_DECORATED_attrib). + */ +#define GLFW_DECORATED 0x00020005 +/*! @brief Window auto-iconification window hint and attribute + * + * Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and + * [window attribute](@ref GLFW_AUTO_ICONIFY_attrib). + */ +#define GLFW_AUTO_ICONIFY 0x00020006 +/*! @brief Window decoration window hint and attribute + * + * Window decoration [window hint](@ref GLFW_FLOATING_hint) and + * [window attribute](@ref GLFW_FLOATING_attrib). + */ +#define GLFW_FLOATING 0x00020007 +/*! @brief Window maximization window hint and attribute + * + * Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and + * [window attribute](@ref GLFW_MAXIMIZED_attrib). + */ +#define GLFW_MAXIMIZED 0x00020008 +/*! @brief Cursor centering window hint + * + * Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint). + */ +#define GLFW_CENTER_CURSOR 0x00020009 +/*! @brief Window framebuffer transparency hint and attribute + * + * Window framebuffer transparency + * [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and + * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). + */ +#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A +/*! @brief Mouse cursor hover window attribute. + * + * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). + */ +#define GLFW_HOVERED 0x0002000B +/*! @brief Input focus on calling show window hint and attribute + * + * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or + * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). + */ +#define GLFW_FOCUS_ON_SHOW 0x0002000C + +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). + */ +#define GLFW_RED_BITS 0x00021001 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS). + */ +#define GLFW_GREEN_BITS 0x00021002 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS). + */ +#define GLFW_BLUE_BITS 0x00021003 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS). + */ +#define GLFW_ALPHA_BITS 0x00021004 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS). + */ +#define GLFW_DEPTH_BITS 0x00021005 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS). + */ +#define GLFW_STENCIL_BITS 0x00021006 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS). + */ +#define GLFW_ACCUM_RED_BITS 0x00021007 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS). + */ +#define GLFW_ACCUM_GREEN_BITS 0x00021008 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS). + */ +#define GLFW_ACCUM_BLUE_BITS 0x00021009 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS). + */ +#define GLFW_ACCUM_ALPHA_BITS 0x0002100A +/*! @brief Framebuffer auxiliary buffer hint. + * + * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS). + */ +#define GLFW_AUX_BUFFERS 0x0002100B +/*! @brief OpenGL stereoscopic rendering hint. + * + * OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO). + */ +#define GLFW_STEREO 0x0002100C +/*! @brief Framebuffer MSAA samples hint. + * + * Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES). + */ +#define GLFW_SAMPLES 0x0002100D +/*! @brief Framebuffer sRGB hint. + * + * Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE). + */ +#define GLFW_SRGB_CAPABLE 0x0002100E +/*! @brief Monitor refresh rate hint. + * + * Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE). + */ +#define GLFW_REFRESH_RATE 0x0002100F +/*! @brief Framebuffer double buffering hint. + * + * Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER). + */ +#define GLFW_DOUBLEBUFFER 0x00021010 + +/*! @brief Context client API hint and attribute. + * + * Context client API [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CLIENT_API 0x00022001 +/*! @brief Context client API major version hint and attribute. + * + * Context client API major version [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 +/*! @brief Context client API minor version hint and attribute. + * + * Context client API minor version [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 +/*! @brief Context client API revision number hint and attribute. + * + * Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_REVISION 0x00022004 +/*! @brief Context robustness hint and attribute. + * + * Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_ROBUSTNESS 0x00022005 +/*! @brief OpenGL forward-compatibility hint and attribute. + * + * OpenGL forward-compatibility [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006 +/*! @brief OpenGL debug context hint and attribute. + * + * OpenGL debug context [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 +/*! @brief OpenGL profile hint and attribute. + * + * OpenGL profile [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_OPENGL_PROFILE 0x00022008 +/*! @brief Context flush-on-release hint and attribute. + * + * Context flush-on-release [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +/*! @brief Context error suppression hint and attribute. + * + * Context error suppression [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +/*! @brief Context creation API hint and attribute. + * + * Context creation API [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CONTEXT_CREATION_API 0x0002200B +/*! @brief Window content area scaling window + * [window hint](@ref GLFW_SCALE_TO_MONITOR). + */ +#define GLFW_SCALE_TO_MONITOR 0x0002200C +/*! @brief macOS specific + * [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint). + */ +#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 +/*! @brief macOS specific + * [window hint](@ref GLFW_COCOA_FRAME_NAME_hint). + */ +#define GLFW_COCOA_FRAME_NAME 0x00023002 +/*! @brief macOS specific + * [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint). + */ +#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003 +/*! @brief X11 specific + * [window hint](@ref GLFW_X11_CLASS_NAME_hint). + */ +#define GLFW_X11_CLASS_NAME 0x00024001 +/*! @brief X11 specific + * [window hint](@ref GLFW_X11_CLASS_NAME_hint). + */ +#define GLFW_X11_INSTANCE_NAME 0x00024002 +/*! @} */ + +#define GLFW_NO_API 0 +#define GLFW_OPENGL_API 0x00030001 +#define GLFW_OPENGL_ES_API 0x00030002 + +#define GLFW_NO_ROBUSTNESS 0 +#define GLFW_NO_RESET_NOTIFICATION 0x00031001 +#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002 + +#define GLFW_OPENGL_ANY_PROFILE 0 +#define GLFW_OPENGL_CORE_PROFILE 0x00032001 +#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002 + +#define GLFW_CURSOR 0x00033001 +#define GLFW_STICKY_KEYS 0x00033002 +#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 +#define GLFW_LOCK_KEY_MODS 0x00033004 +#define GLFW_RAW_MOUSE_MOTION 0x00033005 + +#define GLFW_CURSOR_NORMAL 0x00034001 +#define GLFW_CURSOR_HIDDEN 0x00034002 +#define GLFW_CURSOR_DISABLED 0x00034003 + +#define GLFW_ANY_RELEASE_BEHAVIOR 0 +#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 +#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 + +#define GLFW_NATIVE_CONTEXT_API 0x00036001 +#define GLFW_EGL_CONTEXT_API 0x00036002 +#define GLFW_OSMESA_CONTEXT_API 0x00036003 + +/*! @defgroup shapes Standard cursor shapes + * @brief Standard system cursor shapes. + * + * See [standard cursor creation](@ref cursor_standard) for how these are used. + * + * @ingroup input + * @{ */ + +/*! @brief The regular arrow cursor shape. + * + * The regular arrow cursor. + */ +#define GLFW_ARROW_CURSOR 0x00036001 +/*! @brief The text input I-beam cursor shape. + * + * The text input I-beam cursor shape. + */ +#define GLFW_IBEAM_CURSOR 0x00036002 +/*! @brief The crosshair shape. + * + * The crosshair shape. + */ +#define GLFW_CROSSHAIR_CURSOR 0x00036003 +/*! @brief The hand shape. + * + * The hand shape. + */ +#define GLFW_HAND_CURSOR 0x00036004 +/*! @brief The horizontal resize arrow shape. + * + * The horizontal resize arrow shape. + */ +#define GLFW_HRESIZE_CURSOR 0x00036005 +/*! @brief The vertical resize arrow shape. + * + * The vertical resize arrow shape. + */ +#define GLFW_VRESIZE_CURSOR 0x00036006 +/*! @} */ + +#define GLFW_CONNECTED 0x00040001 +#define GLFW_DISCONNECTED 0x00040002 + +/*! @addtogroup init + * @{ */ +/*! @brief Joystick hat buttons init hint. + * + * Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS). + */ +#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001 +/*! @brief macOS specific init hint. + * + * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). + */ +#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001 +/*! @brief macOS specific init hint. + * + * macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint). + */ +#define GLFW_COCOA_MENUBAR 0x00051002 +/*! @} */ + +#define GLFW_DONT_CARE -1 + + +/************************************************************************* + * GLFW API types + *************************************************************************/ + +/*! @brief Client API function pointer type. + * + * Generic function pointer used for returning client API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref context_glext + * @sa @ref glfwGetProcAddress + * + * @since Added in version 3.0. + * + * @ingroup context + */ +typedef void (*GLFWglproc)(void); + +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa @ref glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + +/*! @brief Opaque monitor object. + * + * Opaque monitor object. + * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +typedef struct GLFWmonitor GLFWmonitor; + +/*! @brief Opaque window object. + * + * Opaque window object. + * + * @see @ref window_object + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef struct GLFWwindow GLFWwindow; + +/*! @brief Opaque cursor object. + * + * Opaque cursor object. + * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * + * @ingroup input + */ +typedef struct GLFWcursor GLFWcursor; + +/*! @brief The function signature for error callbacks. + * + * This is the function signature for error callback functions. + * + * @param[in] error An [error code](@ref errors). + * @param[in] description A UTF-8 encoded string describing the error. + * + * @sa @ref error_handling + * @sa @ref glfwSetErrorCallback + * + * @since Added in version 3.0. + * + * @ingroup init + */ +typedef void (* GLFWerrorfun)(int,const char*); + +/*! @brief The function signature for window position callbacks. + * + * This is the function signature for window position callback functions. + * + * @param[in] window The window that was moved. + * @param[in] xpos The new x-coordinate, in screen coordinates, of the + * upper-left corner of the content area of the window. + * @param[in] ypos The new y-coordinate, in screen coordinates, of the + * upper-left corner of the content area of the window. + * + * @sa @ref window_pos + * @sa @ref glfwSetWindowPosCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); + +/*! @brief The function signature for window resize callbacks. + * + * This is the function signature for window size callback functions. + * + * @param[in] window The window that was resized. + * @param[in] width The new width, in screen coordinates, of the window. + * @param[in] height The new height, in screen coordinates, of the window. + * + * @sa @ref window_size + * @sa @ref glfwSetWindowSizeCallback + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); + +/*! @brief The function signature for window close callbacks. + * + * This is the function signature for window close callback functions. + * + * @param[in] window The window that the user attempted to close. + * + * @sa @ref window_close + * @sa @ref glfwSetWindowCloseCallback + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +typedef void (* GLFWwindowclosefun)(GLFWwindow*); + +/*! @brief The function signature for window content refresh callbacks. + * + * This is the function signature for window refresh callback functions. + * + * @param[in] window The window whose content needs to be refreshed. + * + * @sa @ref window_refresh + * @sa @ref glfwSetWindowRefreshCallback + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); + +/*! @brief The function signature for window focus/defocus callbacks. + * + * This is the function signature for window focus callback functions. + * + * @param[in] window The window that gained or lost input focus. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. + * + * @sa @ref window_focus + * @sa @ref glfwSetWindowFocusCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); + +/*! @brief The function signature for window iconify/restore callbacks. + * + * This is the function signature for window iconify/restore callback + * functions. + * + * @param[in] window The window that was iconified or restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. + * + * @sa @ref window_iconify + * @sa @ref glfwSetWindowIconifyCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); + +/*! @brief The function signature for window maximize/restore callbacks. + * + * This is the function signature for window maximize/restore callback + * functions. + * + * @param[in] window The window that was maximized or restored. + * @param[in] iconified `GLFW_TRUE` if the window was maximized, or + * `GLFW_FALSE` if it was restored. + * + * @sa @ref window_maximize + * @sa glfwSetWindowMaximizeCallback + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int); + +/*! @brief The function signature for framebuffer resize callbacks. + * + * This is the function signature for framebuffer resize callback + * functions. + * + * @param[in] window The window whose framebuffer was resized. + * @param[in] width The new width, in pixels, of the framebuffer. + * @param[in] height The new height, in pixels, of the framebuffer. + * + * @sa @ref window_fbsize + * @sa @ref glfwSetFramebufferSizeCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); + +/*! @brief The function signature for window content scale callbacks. + * + * This is the function signature for window content scale callback + * functions. + * + * @param[in] window The window whose content scale changed. + * @param[in] xscale The new x-axis content scale of the window. + * @param[in] yscale The new y-axis content scale of the window. + * + * @sa @ref window_scale + * @sa @ref glfwSetWindowContentScaleCallback + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float); + +/*! @brief The function signature for mouse button callbacks. + * + * This is the function signature for mouse button callback functions. + * + * @param[in] window The window that received the event. + * @param[in] button The [mouse button](@ref buttons) that was pressed or + * released. + * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa @ref input_mouse_button + * @sa @ref glfwSetMouseButtonCallback + * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * + * @ingroup input + */ +typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); + +/*! @brief The function signature for cursor position callbacks. + * + * This is the function signature for cursor position callback functions. + * + * @param[in] window The window that received the event. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the content area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * content area. + * + * @sa @ref cursor_pos + * @sa @ref glfwSetCursorPosCallback + * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * + * @ingroup input + */ +typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); + +/*! @brief The function signature for cursor enter/leave callbacks. + * + * This is the function signature for cursor enter/leave callback functions. + * + * @param[in] window The window that received the event. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's content + * area, or `GLFW_FALSE` if it left it. + * + * @sa @ref cursor_enter + * @sa @ref glfwSetCursorEnterCallback + * + * @since Added in version 3.0. + * + * @ingroup input + */ +typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); + +/*! @brief The function signature for scroll callbacks. + * + * This is the function signature for scroll callback functions. + * + * @param[in] window The window that received the event. + * @param[in] xoffset The scroll offset along the x-axis. + * @param[in] yoffset The scroll offset along the y-axis. + * + * @sa @ref scrolling + * @sa @ref glfwSetScrollCallback + * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * + * @ingroup input + */ +typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); + +/*! @brief The function signature for keyboard key callbacks. + * + * This is the function signature for keyboard key callback functions. + * + * @param[in] window The window that received the event. + * @param[in] key The [keyboard key](@ref keys) that was pressed or released. + * @param[in] scancode The system-specific scancode of the key. + * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa @ref input_key + * @sa @ref glfwSetKeyCallback + * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * + * @ingroup input + */ +typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); + +/*! @brief The function signature for Unicode character callbacks. + * + * This is the function signature for Unicode character callback functions. + * + * @param[in] window The window that received the event. + * @param[in] codepoint The Unicode code point of the character. + * + * @sa @ref input_char + * @sa @ref glfwSetCharCallback + * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); + +/*! @brief The function signature for Unicode character with modifiers + * callbacks. + * + * This is the function signature for Unicode character with modifiers callback + * functions. It is called for each input character, regardless of what + * modifier keys are held down. + * + * @param[in] window The window that received the event. + * @param[in] codepoint The Unicode code point of the character. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa @ref input_char + * @sa @ref glfwSetCharModsCallback + * + * @deprecated Scheduled for removal in version 4.0. + * + * @since Added in version 3.1. + * + * @ingroup input + */ +typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); + +/*! @brief The function signature for file drop callbacks. + * + * This is the function signature for file drop callbacks. + * + * @param[in] window The window that received the event. + * @param[in] count The number of dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. + * + * @sa @ref path_drop + * @sa @ref glfwSetDropCallback + * + * @since Added in version 3.1. + * + * @ingroup input + */ +typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); + +/*! @brief The function signature for monitor configuration callbacks. + * + * This is the function signature for monitor configuration callback functions. + * + * @param[in] monitor The monitor that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining + * values reserved for future use. + * + * @sa @ref monitor_event + * @sa @ref glfwSetMonitorCallback + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); + +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] jid The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining + * values reserved for future use. + * + * @sa @ref joystick_event + * @sa @ref glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + +/*! @brief Video mode type. + * + * This describes a single video mode. + * + * @sa @ref monitor_modes + * @sa @ref glfwGetVideoMode + * @sa @ref glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * + * @ingroup monitor + */ +typedef struct GLFWvidmode +{ + /*! The width, in screen coordinates, of the video mode. + */ + int width; + /*! The height, in screen coordinates, of the video mode. + */ + int height; + /*! The bit depth of the red channel of the video mode. + */ + int redBits; + /*! The bit depth of the green channel of the video mode. + */ + int greenBits; + /*! The bit depth of the blue channel of the video mode. + */ + int blueBits; + /*! The refresh rate, in Hz, of the video mode. + */ + int refreshRate; +} GLFWvidmode; + +/*! @brief Gamma ramp. + * + * This describes the gamma ramp for a monitor. + * + * @sa @ref monitor_gamma + * @sa @ref glfwGetGammaRamp + * @sa @ref glfwSetGammaRamp + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +typedef struct GLFWgammaramp +{ + /*! An array of value describing the response of the red channel. + */ + unsigned short* red; + /*! An array of value describing the response of the green channel. + */ + unsigned short* green; + /*! An array of value describing the response of the blue channel. + */ + unsigned short* blue; + /*! The number of elements in each array. + */ + unsigned int size; +} GLFWgammaramp; + +/*! @brief Image data. + * + * This describes a single 2D image. See the documentation for each related + * function what the expected pixel format is. + * + * @sa @ref cursor_custom + * @sa @ref window_icon + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. + * + * @ingroup window + */ +typedef struct GLFWimage +{ + /*! The width, in pixels, of this image. + */ + int width; + /*! The height, in pixels, of this image. + */ + int height; + /*! The pixel data of this image, arranged left-to-right, top-to-bottom. + */ + unsigned char* pixels; +} GLFWimage; + +/*! @brief Gamepad input state + * + * This describes the input state of a gamepad. + * + * @sa @ref gamepad + * @sa @ref glfwGetGamepadState + * + * @since Added in version 3.3. + * + * @ingroup input + */ +typedef struct GLFWgamepadstate +{ + /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS` + * or `GLFW_RELEASE`. + */ + unsigned char buttons[15]; + /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0 + * to 1.0 inclusive. + */ + float axes[6]; +} GLFWgamepadstate; + + +/************************************************************************* + * GLFW API functions + *************************************************************************/ + +/*! @brief Initializes the GLFW library. + * + * This function initializes the GLFW library. Before most GLFW functions can + * be used, GLFW must be initialized, and before an application terminates GLFW + * should be terminated in order to free any resources allocated during or + * after initialization. + * + * If this function fails, it calls @ref glfwTerminate before returning. If it + * succeeds, you should call @ref glfwTerminate before the application exits. + * + * Additional calls to this function after successful initialization but before + * termination will return `GLFW_TRUE` immediately. + * + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @macos This function will change the current directory of the + * application to the `Contents/Resources` subdirectory of the application's + * bundle, if present. This can be disabled with the @ref + * GLFW_COCOA_CHDIR_RESOURCES init hint. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref intro_init + * @sa @ref glfwTerminate + * + * @since Added in version 1.0. + * + * @ingroup init + */ +GLFWAPI int glfwInit(void); + +/*! @brief Terminates the GLFW library. + * + * This function destroys all remaining windows and cursors, restores any + * modified gamma ramps and frees any other allocated resources. Once this + * function is called, you must again call @ref glfwInit successfully before + * you will be able to use most GLFW functions. + * + * If GLFW has been successfully initialized, this function should be called + * before the application exits. If initialization fails, there is no need to + * call this function, as it is called by @ref glfwInit before it returns + * failure. + * + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark This function may be called before @ref glfwInit. + * + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref intro_init + * @sa @ref glfwInit + * + * @since Added in version 1.0. + * + * @ingroup init + */ +GLFWAPI void glfwTerminate(void); + +/*! @brief Sets the specified init hint to the desired value. + * + * This function sets hints for the next initialization of GLFW. + * + * The values you set hints to are never reset by GLFW, but they only take + * effect during initialization. Once GLFW has been initialized, any values + * you set will be ignored until the library is terminated and initialized + * again. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. + * + * @param[in] hint The [init hint](@ref init_hints) to set. + * @param[in] value The new value of the init hint. + * + * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref + * GLFW_INVALID_VALUE. + * + * @remarks This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa init_hints + * @sa glfwInit + * + * @since Added in version 3.3. + * + * @ingroup init + */ +GLFWAPI void glfwInitHint(int hint, int value); + +/*! @brief Retrieves the version of the GLFW library. + * + * This function retrieves the major, minor and revision numbers of the GLFW + * library. It is intended for when you are using GLFW as a shared library and + * want to ensure that you are using the minimum required version. + * + * Any or all of the version arguments may be `NULL`. + * + * @param[out] major Where to store the major version number, or `NULL`. + * @param[out] minor Where to store the minor version number, or `NULL`. + * @param[out] rev Where to store the revision number, or `NULL`. + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref intro_version + * @sa @ref glfwGetVersionString + * + * @since Added in version 1.0. + * + * @ingroup init + */ +GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); + +/*! @brief Returns a string describing the compile-time configuration. + * + * This function returns the compile-time generated + * [version string](@ref intro_version_string) of the GLFW library binary. It + * describes the version, platform, compiler and any platform-specific + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. + * + * __Do not use the version string__ to parse the GLFW library version. The + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. + * + * @return The ASCII encoded GLFW version string. + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @pointer_lifetime The returned string is static and compile-time generated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref intro_version + * @sa @ref glfwGetVersion + * + * @since Added in version 3.0. + * + * @ingroup init + */ +GLFWAPI const char* glfwGetVersionString(void); + +/*! @brief Returns and clears the last error for the calling thread. + * + * This function returns and clears the [error code](@ref errors) of the last + * error that occurred on the calling thread, and optionally a UTF-8 encoded + * human-readable description of it. If no error has occurred since the last + * call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is + * set to `NULL`. + * + * @param[in] description Where to store the error description pointer, or `NULL`. + * @return The last error code for the calling thread, or @ref GLFW_NO_ERROR + * (zero). + * + * @errors None. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * next error occurs or the library is terminated. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref error_handling + * @sa @ref glfwSetErrorCallback + * + * @since Added in version 3.3. + * + * @ingroup init + */ +GLFWAPI int glfwGetError(const char** description); + +/*! @brief Sets the error callback. + * + * This function sets the error callback, which is called with an error code + * and a human-readable description each time a GLFW error occurs. + * + * The error code is set before the callback is called. Calling @ref + * glfwGetError from the error callback will return the same value as the error + * code argument. + * + * The error callback is called on the thread where the error occurred. If you + * are using GLFW from multiple threads, your error callback needs to be + * written accordingly. + * + * Because the description string may have been generated specifically for that + * error, it is not guaranteed to be valid after the callback has returned. If + * you wish to use it after the callback returns, you need to make a copy. + * + * Once set, the error callback remains set even after the library has been + * terminated. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set. + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref error_handling + * @sa @ref glfwGetError + * + * @since Added in version 3.0. + * + * @ingroup init + */ +GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun); + +/*! @brief Returns the currently connected monitors. + * + * This function returns an array of handles for all currently connected + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. + * + * @param[out] count Where to store the number of monitors in the returned + * array. This is set to zero if an error occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_monitors + * @sa @ref monitor_event + * @sa @ref glfwGetPrimaryMonitor + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitor** glfwGetMonitors(int* count); + +/*! @brief Returns the primary monitor. + * + * This function returns the primary monitor. This is usually the monitor + * where elements like the task bar or global menu bar are located. + * + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. + * + * @sa @ref monitor_monitors + * @sa @ref glfwGetMonitors + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); + +/*! @brief Returns the position of the monitor's viewport on the virtual screen. + * + * This function returns the position, in screen coordinates, of the upper-left + * corner of the specified monitor. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. + * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); + +/*! @brief Retrives the work area of the monitor. + * + * This function returns the position, in screen coordinates, of the upper-left + * corner of the work area of the specified monitor along with the work area + * size in screen coordinates. The work area is defined as the area of the + * monitor not occluded by the operating system task bar where present. If no + * task bar exists then the work area is the monitor resolution in screen + * coordinates. + * + * Any or all of the position and size arguments may be `NULL`. If an error + * occurs, all non-`NULL` position and size arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. + * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. + * @param[out] width Where to store the monitor width, or `NULL`. + * @param[out] height Where to store the monitor height, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_workarea + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); + +/*! @brief Returns the physical size of the monitor. + * + * This function returns the size, in millimetres, of the display area of the + * specified monitor. + * + * Some systems do not provide accurate monitor size information, either + * because the monitor + * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data) + * data is incorrect or because the driver does not report it accurately. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] widthMM Where to store the width, in millimetres, of the + * monitor's display area, or `NULL`. + * @param[out] heightMM Where to store the height, in millimetres, of the + * monitor's display area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the + * current resolution and system DPI instead of querying the monitor EDID data. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM); + +/*! @brief Retrieves the content scale for the specified monitor. + * + * This function retrieves the content scale for the specified monitor. The + * content scale is the ratio between the current DPI and the platform's + * default DPI. This is especially important for text and any UI elements. If + * the pixel dimensions of your UI scaled by this look appropriate on your + * machine then it should appear at a reasonable size on other machines + * regardless of their DPI and scaling settings. This relies on the system DPI + * and scaling settings being somewhat correct. + * + * The content scale may depend on both the monitor resolution and pixel + * density and on user settings. It may be very different from the raw DPI + * calculated from the physical size and current resolution. + * + * @param[in] monitor The monitor to query. + * @param[out] xscale Where to store the x-axis content scale, or `NULL`. + * @param[out] yscale Where to store the y-axis content scale, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_scale + * @sa @ref glfwGetWindowContentScale + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale); + +/*! @brief Returns the name of the specified monitor. + * + * This function returns a human-readable name, encoded as UTF-8, of the + * specified monitor. The name typically reflects the make and model of the + * monitor and is not guaranteed to be unique among the connected monitors. + * + * @param[in] monitor The monitor to query. + * @return The UTF-8 encoded name of the monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor); + +/*! @brief Sets the user pointer of the specified monitor. + * + * This function sets the user-defined pointer of the specified monitor. The + * current value is retained until the monitor is disconnected. The initial + * value is `NULL`. + * + * This function may be called from the monitor callback, even for a monitor + * that is being disconnected. + * + * @param[in] monitor The monitor whose pointer to set. + * @param[in] pointer The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref monitor_userptr + * @sa @ref glfwGetMonitorUserPointer + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer); + +/*! @brief Returns the user pointer of the specified monitor. + * + * This function returns the current value of the user-defined pointer of the + * specified monitor. The initial value is `NULL`. + * + * This function may be called from the monitor callback, even for a monitor + * that is being disconnected. + * + * @param[in] monitor The monitor whose pointer to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref monitor_userptr + * @sa @ref glfwSetMonitorUserPointer + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor); + +/*! @brief Sets the monitor configuration callback. + * + * This function sets the monitor configuration callback, or removes the + * currently set callback. This is called when a monitor is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_event + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun); + +/*! @brief Returns the available video modes for the specified monitor. + * + * This function returns an array of all video modes supported by the specified + * monitor. The returned array is sorted in ascending order, first by color + * bit depth (the sum of all channel depths) and then by resolution area (the + * product of width and height). + * + * @param[in] monitor The monitor to query. + * @param[out] count Where to store the number of video modes in the returned + * array. This is set to zero if an error occurred. + * @return An array of video modes, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_modes + * @sa @ref glfwGetVideoMode + * + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. + * + * @ingroup monitor + */ +GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); + +/*! @brief Returns the current mode of the specified monitor. + * + * This function returns the current video mode of the specified monitor. If + * you have created a full screen window for that monitor, the return value + * will depend on whether that window is iconified. + * + * @param[in] monitor The monitor to query. + * @return The current mode of the monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_modes + * @sa @ref glfwGetVideoModes + * + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. + * + * @ingroup monitor + */ +GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); + +/*! @brief Generates a gamma ramp and sets it for the specified monitor. + * + * This function generates an appropriately sized gamma ramp from the specified + * exponent and then calls @ref glfwSetGammaRamp with it. The value must be + * a finite number greater than zero. + * + * The software controlled gamma ramp is applied _in addition_ to the hardware + * gamma correction, which today is usually an approximation of sRGB gamma. + * This means that setting a perfectly linear ramp, or gamma 1.0, will produce + * the default (usually sRGB-like) behavior. + * + * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref + * GLFW_SRGB_CAPABLE hint. + * + * @param[in] monitor The monitor whose gamma ramp to set. + * @param[in] gamma The desired exponent. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark @wayland Gamma handling is a priviledged protocol, this function + * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); + +/*! @brief Returns the current gamma ramp for the specified monitor. + * + * This function returns the current gamma ramp of the specified monitor. + * + * @param[in] monitor The monitor to query. + * @return The current gamma ramp, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland Gamma handling is a priviledged protocol, this function + * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while + * returning `NULL`. + * + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); + +/*! @brief Sets the current gamma ramp for the specified monitor. + * + * This function sets the current gamma ramp for the specified monitor. The + * original gamma ramp for that monitor is saved by GLFW the first time this + * function is called and is restored by @ref glfwTerminate. + * + * The software controlled gamma ramp is applied _in addition_ to the hardware + * gamma correction, which today is usually an approximation of sRGB gamma. + * This means that setting a perfectly linear ramp, or gamma 1.0, will produce + * the default (usually sRGB-like) behavior. + * + * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref + * GLFW_SRGB_CAPABLE hint. + * + * @param[in] monitor The monitor whose gamma ramp to set. + * @param[in] ramp The gamma ramp to use. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark The size of the specified gamma ramp should match the size of the + * current ramp for that monitor. + * + * @remark @win32 The gamma ramp size must be 256. + * + * @remark @wayland Gamma handling is a priviledged protocol, this function + * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); + +/*! @brief Resets all window hints to their default values. + * + * This function resets all window hints to their + * [default values](@ref window_hints_values). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hints + * @sa @ref glfwWindowHint + * @sa @ref glfwWindowHintString + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwDefaultWindowHints(void); + +/*! @brief Sets the specified window hint to the desired value. + * + * This function sets hints for the next call to @ref glfwCreateWindow. The + * hints, once set, retain their values until changed by a call to this + * function or @ref glfwDefaultWindowHints, or until the library is terminated. + * + * Only integer value hints can be set with this function. String value hints + * are set with @ref glfwWindowHintString. + * + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. + * + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hints + * @sa @ref glfwWindowHintString + * @sa @ref glfwDefaultWindowHints + * + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. + * + * @ingroup window + */ +GLFWAPI void glfwWindowHint(int hint, int value); + +/*! @brief Sets the specified window hint to the desired value. + * + * This function sets hints for the next call to @ref glfwCreateWindow. The + * hints, once set, retain their values until changed by a call to this + * function or @ref glfwDefaultWindowHints, or until the library is terminated. + * + * Only string type hints can be set with this function. Integer value hints + * are set with @ref glfwWindowHint. + * + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. + * + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hints + * @sa @ref glfwWindowHint + * @sa @ref glfwDefaultWindowHints + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwWindowHintString(int hint, const char* value); + +/*! @brief Creates a window and its associated context. + * + * This function creates a window and its associated OpenGL or OpenGL ES + * context. Most of the options controlling how the window and its context + * should be created are specified with [window hints](@ref window_hints). + * + * Successful creation does not change which context is current. Before you + * can use the newly created context, you need to + * [make it current](@ref context_current). For information about the `share` + * parameter, see @ref context_sharing. + * + * The created window, framebuffer and context may differ from what you + * requested, as not all parameters and hints are + * [hard constraints](@ref window_hints_hard). This includes the size of the + * window, especially for full screen windows. To query the actual attributes + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. + * + * To create a full screen window, you need to specify the monitor the window + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. + * + * For full screen windows, the specified size becomes the resolution of the + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. + * + * Once you have created the window, you can switch it between windowed and + * full screen mode with @ref glfwSetWindowMonitor. This will not affect its + * OpenGL or OpenGL ES context. + * + * By default, newly created windows use the placement recommended by the + * window system. To create the window at a specific position, make it + * initially invisible using the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window + * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) + * it. + * + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. + * + * Window systems put limits on window sizes. Very large or very small window + * dimensions may be overridden by the window system on creation. Check the + * actual [size](@ref window_size) after creation. + * + * The [swap interval](@ref buffer_swap) is not set during window creation and + * the initial value may vary depending on driver settings and defaults. + * + * @param[in] width The desired width, in screen coordinates, of the window. + * This must be greater than zero. + * @param[in] height The desired height, in screen coordinates, of the window. + * This must be greater than zero. + * @param[in] title The initial, UTF-8 encoded window title. + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for + * windowed mode. + * @param[in] share The window whose context to share resources with, or `NULL` + * to not share resources. + * @return The handle of the created window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. + * + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it + * will be set as the initial icon for the window. If no such icon is present, + * the `IDI_APPLICATION` icon will be used instead. To set a different icon, + * see @ref glfwSetWindowIcon. + * + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @macos The OS only supports forward-compatible core profile contexts + * for OpenGL versions 3.2 and later. Before creating an OpenGL context of + * version 3.2 or later you must set the + * [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and + * [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly. + * OpenGL 3.0 and 3.1 contexts are not supported at all on macOS. + * + * @remark @macos The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @remark @macos The first time a window is created the menu bar is created. + * If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu + * bar. Otherwise a minimal menu bar is created manually with common commands + * like Hide, Quit and About. The About entry opens a minimal about dialog + * with information from the application's bundle. Menu bar creation can be + * disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint. + * + * @remark @macos On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the + * [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint) + * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the + * application bundle's `Info.plist`. For more information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. + * + * @remark @macos When activating frame autosaving with + * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified + * window size and position may be overriden by previously saved values. + * + * @remark @x11 Some window managers will not respect the placement of + * initially hidden windows. + * + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. + * + * @remark @x11 The class part of the `WM_CLASS` window property will by + * default be set to the window title passed to this function. The instance + * part will use the contents of the `RESOURCE_NAME` environment variable, if + * present and not empty, or fall back to the window title. Set the + * [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and + * [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to + * override this. + * + * @remark @wayland Compositors should implement the xdg-decoration protocol + * for GLFW to decorate the window properly. If this protocol isn't + * supported, or if the compositor prefers client-side decorations, a very + * simple fallback frame will be drawn using the wp_viewporter protocol. A + * compositor can still emit close, maximize or fullscreen events, using for + * instance a keybind mechanism. If neither of these protocols is supported, + * the window won't be decorated. + * + * @remark @wayland A full screen window will not attempt to change the mode, + * no matter what the requested size or refresh rate. + * + * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol + * to be implemented in the user's compositor. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_creation + * @sa @ref glfwDestroyWindow + * + * @since Added in version 3.0. Replaces `glfwOpenWindow`. + * + * @ingroup window + */ +GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share); + +/*! @brief Destroys the specified window and its context. + * + * This function destroys the specified window and its context. On calling + * this function, no further callbacks will be called for that window. + * + * If the context of the specified window is current on the main thread, it is + * detached before being destroyed. + * + * @param[in] window The window to destroy. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @note The context of the specified window must not be current on any other + * thread when this function is called. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_creation + * @sa @ref glfwCreateWindow + * + * @since Added in version 3.0. Replaces `glfwCloseWindow`. + * + * @ingroup window + */ +GLFWAPI void glfwDestroyWindow(GLFWwindow* window); + +/*! @brief Checks the close flag of the specified window. + * + * This function returns the value of the close flag of the specified window. + * + * @param[in] window The window to query. + * @return The value of the close flag. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_close + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI int glfwWindowShouldClose(GLFWwindow* window); + +/*! @brief Sets the close flag of the specified window. + * + * This function sets the value of the close flag of the specified window. + * This can be used to override the user's attempt to close the window, or + * to signal that it should be closed. + * + * @param[in] window The window whose flag to change. + * @param[in] value The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_close + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value); + +/*! @brief Sets the title of the specified window. + * + * This function sets the window title, encoded as UTF-8, of the specified + * window. + * + * @param[in] window The window whose title to change. + * @param[in] title The UTF-8 encoded window title. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @macos The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_title + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); + +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel with the red channel first. They are arranged canonically + * as packed sequential rows, starting from the top-left corner. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @macos The GLFW window has no icon, as it is not a document + * window, so this function does nothing. The dock icon will be the same as + * the application bundle's icon. For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @remark @wayland There is no existing protocol to change an icon, the + * window will thus inherit the one defined in the application's desktop file. + * This function always emits @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + +/*! @brief Retrieves the position of the content area of the specified window. + * + * This function retrieves the position, in screen coordinates, of the + * upper-left corner of the content area of the specified window. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] window The window to query. + * @param[out] xpos Where to store the x-coordinate of the upper-left corner of + * the content area, or `NULL`. + * @param[out] ypos Where to store the y-coordinate of the upper-left corner of + * the content area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland There is no way for an application to retrieve the global + * position of its windows, this function will always emit @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_pos + * @sa @ref glfwSetWindowPos + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); + +/*! @brief Sets the position of the content area of the specified window. + * + * This function sets the position, in screen coordinates, of the upper-left + * corner of the content area of the specified windowed mode window. If the + * window is a full screen window, this function does nothing. + * + * __Do not use this function__ to move an already visible window unless you + * have very good reasons for doing so, as it will confuse and annoy the user. + * + * The window manager may put limits on what positions are allowed. GLFW + * cannot and should not override these limits. + * + * @param[in] window The window to query. + * @param[in] xpos The x-coordinate of the upper-left corner of the content area. + * @param[in] ypos The y-coordinate of the upper-left corner of the content area. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland There is no way for an application to set the global + * position of its windows, this function will always emit @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_pos + * @sa @ref glfwGetWindowPos + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); + +/*! @brief Retrieves the size of the content area of the specified window. + * + * This function retrieves the size, in screen coordinates, of the content area + * of the specified window. If you wish to retrieve the size of the + * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose size to retrieve. + * @param[out] width Where to store the width, in screen coordinates, of the + * content area, or `NULL`. + * @param[out] height Where to store the height, in screen coordinates, of the + * content area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * @sa @ref glfwSetWindowSize + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); + +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the content area of the specified + * window. If the window is full screen, the size limits only take effect + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * The maximum dimensions must be greater than or equal to the minimum + * dimensions and all must be greater than or equal to zero. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the content + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * content area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the content + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * content area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @remark @wayland The size limits will not be applied until the window is + * actually resized, either by the user or by the compositor. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa @ref glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the content area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @remark @wayland The aspect ratio will not be applied until the window is + * actually resized, either by the user or by the compositor. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa @ref glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + +/*! @brief Sets the size of the content area of the specified window. + * + * This function sets the size, in screen coordinates, of the content area of + * the specified window. + * + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. + * + * The window manager may put limits on what sizes are allowed. GLFW cannot + * and should not override these limits. + * + * @param[in] window The window to resize. + * @param[in] width The desired width, in screen coordinates, of the window + * content area. + * @param[in] height The desired height, in screen coordinates, of the window + * content area. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland A full screen window will not attempt to change the mode, + * no matter what the requested size. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * @sa @ref glfwGetWindowSize + * @sa @ref glfwSetWindowMonitor + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); + +/*! @brief Retrieves the size of the framebuffer of the specified window. + * + * This function retrieves the size, in pixels, of the framebuffer of the + * specified window. If you wish to retrieve the size of the window in screen + * coordinates, see @ref glfwGetWindowSize. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose framebuffer to query. + * @param[out] width Where to store the width, in pixels, of the framebuffer, + * or `NULL`. + * @param[out] height Where to store the height, in pixels, of the framebuffer, + * or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_fbsize + * @sa @ref glfwSetFramebufferSizeCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height); + +/*! @brief Retrieves the size of the frame of the window. + * + * This function retrieves the size, in screen coordinates, of each edge of the + * frame of the specified window. This size includes the title bar, if the + * window has one. The size of the frame may vary depending on the + * [window-related hints](@ref window_hints_wnd) used to create it. + * + * Because this function retrieves the size of each window frame edge and not + * the offset along a particular coordinate axis, the retrieved values will + * always be zero or positive. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose frame size to query. + * @param[out] left Where to store the size, in screen coordinates, of the left + * edge of the window frame, or `NULL`. + * @param[out] top Where to store the size, in screen coordinates, of the top + * edge of the window frame, or `NULL`. + * @param[out] right Where to store the size, in screen coordinates, of the + * right edge of the window frame, or `NULL`. + * @param[out] bottom Where to store the size, in screen coordinates, of the + * bottom edge of the window frame, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * + * @since Added in version 3.1. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom); + +/*! @brief Retrieves the content scale for the specified window. + * + * This function retrieves the content scale for the specified window. The + * content scale is the ratio between the current DPI and the platform's + * default DPI. This is especially important for text and any UI elements. If + * the pixel dimensions of your UI scaled by this look appropriate on your + * machine then it should appear at a reasonable size on other machines + * regardless of their DPI and scaling settings. This relies on the system DPI + * and scaling settings being somewhat correct. + * + * On systems where each monitors can have its own content scale, the window + * content scale will depend on which monitor the system considers the window + * to be on. + * + * @param[in] window The window to query. + * @param[out] xscale Where to store the x-axis content scale, or `NULL`. + * @param[out] yscale Where to store the y-axis content scale, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_scale + * @sa @ref glfwSetWindowContentScaleCallback + * @sa @ref glfwGetMonitorContentScale + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale); + +/*! @brief Returns the opacity of the whole window. + * + * This function returns the opacity of the window, including any decorations. + * + * The opacity (or alpha) value is a positive finite number between zero and + * one, where zero is fully transparent and one is fully opaque. If the system + * does not support whole window transparency, this function always returns one. + * + * The initial opacity value for newly created windows is one. + * + * @param[in] window The window to query. + * @return The opacity value of the specified window. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_transparency + * @sa @ref glfwSetWindowOpacity + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window); + +/*! @brief Sets the opacity of the whole window. + * + * This function sets the opacity of the window, including any decorations. + * + * The opacity (or alpha) value is a positive finite number between zero and + * one, where zero is fully transparent and one is fully opaque. + * + * The initial opacity value for newly created windows is one. + * + * A window created with framebuffer transparency may not use whole window + * transparency. The results of doing this are undefined. + * + * @param[in] window The window to set the opacity for. + * @param[in] opacity The desired opacity of the specified window. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_transparency + * @sa @ref glfwGetWindowOpacity + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); + +/*! @brief Iconifies the specified window. + * + * This function iconifies (minimizes) the specified window if it was + * previously restored. If the window is already iconified, this function does + * nothing. + * + * If the specified window is a full screen window, the original monitor + * resolution is restored until the window is restored. + * + * @param[in] window The window to iconify. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland There is no concept of iconification in wl_shell, this + * function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated + * protocol. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa @ref glfwRestoreWindow + * @sa @ref glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwIconifyWindow(GLFWwindow* window); + +/*! @brief Restores the specified window. + * + * This function restores the specified window if it was previously iconified + * (minimized) or maximized. If the window is already restored, this function + * does nothing. + * + * If the specified window is a full screen window, the resolution chosen for + * the window is restored on the selected monitor. + * + * @param[in] window The window to restore. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa @ref glfwIconifyWindow + * @sa @ref glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_iconify + * @sa @ref glfwIconifyWindow + * @sa @ref glfwRestoreWindow + * + * @since Added in GLFW 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); + +/*! @brief Makes the specified window visible. + * + * This function makes the specified window visible if it was previously + * hidden. If the window is already visible or is in full screen mode, this + * function does nothing. + * + * By default, windowed mode windows are focused when shown + * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint + * to change this behavior for all newly created windows, or change the + * behavior for an existing window with @ref glfwSetWindowAttrib. + * + * @param[in] window The window to make visible. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hide + * @sa @ref glfwHideWindow + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwShowWindow(GLFWwindow* window); + +/*! @brief Hides the specified window. + * + * This function hides the specified window if it was previously visible. If + * the window is already hidden or is in full screen mode, this function does + * nothing. + * + * @param[in] window The window to hide. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hide + * @sa @ref glfwShowWindow + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwHideWindow(GLFWwindow* window); + +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to + * disable this behavior. + * + * Also by default, windowed mode windows are focused when shown + * with @ref glfwShowWindow. Set the + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * For a less disruptive way of getting the user's attention, see + * [attention requests](@ref window_attention). + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland It is not possible for an application to bring its windows + * to front, this function will always emit @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * @sa @ref window_attention + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + +/*! @brief Requests user attention to the specified window. + * + * This function requests user attention to the specified window. On + * platforms where this is not supported, attention is requested to the + * application as a whole. + * + * Once the user has given attention, usually by focusing the window or + * application, the system will end the request automatically. + * + * @param[in] window The window to request attention to. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @macos Attention is requested to the application as a whole, not the + * specific window. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_attention + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); + +/*! @brief Returns the monitor that the window uses for full screen mode. + * + * This function returns the handle of the monitor that the specified window is + * in full screen on. + * + * @param[in] window The window to query. + * @return The monitor, or `NULL` if the window is in windowed mode or an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref glfwSetWindowMonitor + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); + +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window content area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * content area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * content area. + * @param[in] width The desired with, in screen coordinates, of the content + * area or video mode. + * @param[in] height The desired height, in screen coordinates, of the content + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode, + * or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise + * affected by any resizing or mode switching, although you may need to update + * your viewport if the framebuffer size has changed. + * + * @remark @wayland The desired window position is ignored, as there is no way + * for an application to set this property. + * + * @remark @wayland Setting the window to full screen will not attempt to + * change the mode, no matter what the requested size or refresh rate. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa @ref glfwGetWindowMonitor + * @sa @ref glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + +/*! @brief Returns an attribute of the specified window. + * + * This function returns the value of an attribute of the specified window or + * its OpenGL or OpenGL ES context. + * + * @param[in] window The window to query. + * @param[in] attrib The [window attribute](@ref window_attribs) whose value to + * return. + * @return The value of the attribute, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_attribs + * @sa @ref glfwSetWindowAttrib + * + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and + * `glfwGetGLVersion`. + * + * @ingroup window + */ +GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); + +/*! @brief Sets an attribute of the specified window. + * + * This function sets the value of an attribute of the specified window. + * + * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), + * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), + * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), + * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). + * + * Some of these attributes are ignored for full screen windows. The new + * value will take effect if the window is later made windowed. + * + * Some of these attributes are ignored for windowed mode windows. The new + * value will take effect if the window is later made full screen. + * + * @param[in] window The window to set the attribute for. + * @param[in] attrib A supported window attribute. + * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark Calling @ref glfwGetWindowAttrib will always return the latest + * value, even if that value is ignored by the current mode of the window. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_attribs + * @sa @ref glfwGetWindowAttrib + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value); + +/*! @brief Sets the user pointer of the specified window. + * + * This function sets the user-defined pointer of the specified window. The + * current value is retained until the window is destroyed. The initial value + * is `NULL`. + * + * @param[in] window The window whose pointer to set. + * @param[in] pointer The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_userptr + * @sa @ref glfwGetWindowUserPointer + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer); + +/*! @brief Returns the user pointer of the specified window. + * + * This function returns the current value of the user-defined pointer of the + * specified window. The initial value is `NULL`. + * + * @param[in] window The window whose pointer to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_userptr + * @sa @ref glfwSetWindowUserPointer + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window); + +/*! @brief Sets the position callback for the specified window. + * + * This function sets the position callback of the specified window, which is + * called when the window is moved. The callback is provided with the + * position, in screen coordinates, of the upper-left corner of the content + * area of the window. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @wayland This callback will never be called, as there is no way for + * an application to know its global position. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_pos + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun cbfun); + +/*! @brief Sets the size callback for the specified window. + * + * This function sets the size callback of the specified window, which is + * called when the window is resized. The callback is provided with the size, + * in screen coordinates, of the content area of the window. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup window + */ +GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbfun); + +/*! @brief Sets the close callback for the specified window. + * + * This function sets the close callback of the specified window, which is + * called when the user attempts to close the window, for example by clicking + * the close widget in the title bar. + * + * The close flag is set before this callback is called, but you can modify it + * at any time with @ref glfwSetWindowShouldClose. + * + * The close callback is not triggered by @ref glfwDestroyWindow. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @macos Selecting Quit from the application menu will trigger the + * close callback for all windows. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_close + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup window + */ +GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun); + +/*! @brief Sets the refresh callback for the specified window. + * + * This function sets the refresh callback of the specified window, which is + * called when the content area of the window needs to be redrawn, for example + * if the window has been exposed after having been covered by another window. + * + * On compositing window systems such as Aero, Compiz, Aqua or Wayland, where + * the window contents are saved off-screen, this callback may be called only + * very infrequently or never at all. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_refresh + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup window + */ +GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun cbfun); + +/*! @brief Sets the focus callback for the specified window. + * + * This function sets the focus callback of the specified window, which is + * called when the window gains or loses input focus. + * + * After the focus callback is called for a window that lost input focus, + * synthetic key and mouse button release events will be generated for all such + * that had been pressed. For more information, see @ref glfwSetKeyCallback + * and @ref glfwSetMouseButtonCallback. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun); + +/*! @brief Sets the iconify callback for the specified window. + * + * This function sets the iconification callback of the specified window, which + * is called when the window is iconified or restored. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @wayland The wl_shell protocol has no concept of iconification, + * this callback will never be called when using this deprecated protocol. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun); + +/*! @brief Sets the maximize callback for the specified window. + * + * This function sets the maximization callback of the specified window, which + * is called when the window is maximized or restored. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_maximize + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun cbfun); + +/*! @brief Sets the framebuffer resize callback for the specified window. + * + * This function sets the framebuffer resize callback of the specified window, + * which is called when the framebuffer of the specified window is resized. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_fbsize + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun); + +/*! @brief Sets the window content scale callback for the specified window. + * + * This function sets the window content scale callback of the specified window, + * which is called when the content scale of the specified window changes. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_scale + * @sa @ref glfwGetWindowContentScale + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun); + +/*! @brief Processes all pending events. + * + * This function processes only those events that are already in the event + * queue and then returns immediately. Processing events will cause the window + * and input callbacks associated with those events to be called. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * Do not assume that callbacks you set will _only_ be called in response to + * event processing functions like this one. While it is necessary to poll for + * events, window systems that require GLFW to register callbacks of its own + * can pass events to GLFW in response to many window system function calls. + * GLFW will pass those events on to the application callbacks before + * returning. + * + * Event processing is not required for joystick input to work. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa @ref glfwWaitEvents + * @sa @ref glfwWaitEventsTimeout + * + * @since Added in version 1.0. + * + * @ingroup window + */ +GLFWAPI void glfwPollEvents(void); + +/*! @brief Waits until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue. Once one or more events are available, + * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue + * are processed and the function then returns immediately. Processing events + * will cause the window and input callbacks associated with those events to be + * called. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * Do not assume that callbacks you set will _only_ be called in response to + * event processing functions like this one. While it is necessary to poll for + * events, window systems that require GLFW to register callbacks of its own + * can pass events to GLFW in response to many window system function calls. + * GLFW will pass those events on to the application callbacks before + * returning. + * + * Event processing is not required for joystick input to work. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa @ref glfwPollEvents + * @sa @ref glfwWaitEventsTimeout + * + * @since Added in version 2.5. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEvents(void); + +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * Do not assume that callbacks you set will _only_ be called in response to + * event processing functions like this one. While it is necessary to poll for + * events, window systems that require GLFW to register callbacks of its own + * can pass events to GLFW in response to many window system function calls. + * GLFW will pass those events on to the application callbacks before + * returning. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa @ref glfwPollEvents + * @sa @ref glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + +/*! @brief Posts an empty event to the event queue. + * + * This function posts an empty event from the current thread to the event + * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref events + * @sa @ref glfwWaitEvents + * @sa @ref glfwWaitEventsTimeout + * + * @since Added in version 3.1. + * + * @ingroup window + */ +GLFWAPI void glfwPostEmptyEvent(void); + +/*! @brief Returns the value of an input option for the specified window. + * + * This function returns the value of an input option for the specified window. + * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or + * @ref GLFW_RAW_MOUSE_MOTION. + * + * @param[in] window The window to query. + * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or + * `GLFW_RAW_MOUSE_MOTION`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref glfwSetInputMode + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); + +/*! @brief Sets an input option for the specified window. + * + * This function sets an input mode option for the specified window. The mode + * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or + * @ref GLFW_RAW_MOUSE_MOTION. + * + * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor + * modes: + * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally. + * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the + * content area of the window but does not restrict the cursor from leaving. + * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual + * and unlimited cursor movement. This is useful for implementing for + * example 3D camera controls. + * + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are + * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` + * the next time it is called even if the key had been released before the + * call. This is useful when you are only interested in whether keys have been + * pressed but not when or in which order. + * + * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. + * + * If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to + * enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled, + * callbacks that receive modifier bits will also have the @ref + * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on, + * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on. + * + * If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE` + * to enable raw (unscaled and unaccelerated) mouse motion when the cursor is + * disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported, + * attempting to set this will emit @ref GLFW_PLATFORM_ERROR. Call @ref + * glfwRawMouseMotionSupported to check for support. + * + * @param[in] window The window whose input mode to set. + * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or + * `GLFW_RAW_MOUSE_MOTION`. + * @param[in] value The new value of the specified input mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref glfwGetInputMode + * + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. + * + * @ingroup input + */ +GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); + +/*! @brief Returns whether raw mouse motion is supported. + * + * This function returns whether raw mouse motion is supported on the current + * system. This status does not change after GLFW has been initialized so you + * only need to check this once. If you attempt to enable raw motion on + * a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted. + * + * Raw mouse motion is closer to the actual motion of the mouse across + * a surface. It is not affected by the scaling and acceleration applied to + * the motion of the desktop cursor. That processing is suitable for a cursor + * while raw motion is better for controlling for example a 3D camera. Because + * of this, raw mouse motion is only provided when the cursor is disabled. + * + * @return `GLFW_TRUE` if raw mouse motion is supported on the current machine, + * or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref raw_mouse_motion + * @sa @ref glfwSetInputMode + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwRawMouseMotionSupported(void); + +/*! @brief Returns the layout-specific name of the specified printable key. + * + * This function returns the name of the specified printable key, encoded as + * UTF-8. This is typically the character that key would produce without any + * modifier keys, intended for displaying key bindings to the user. For dead + * keys, it is typically the diacritic it would add to a character. + * + * __Do not use this function__ for [text input](@ref input_char). You will + * break text input for many languages even if it happens to work for yours. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key, + * otherwise the scancode is ignored. If you specify a non-printable key, or + * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this + * function returns `NULL` but does not emit an error. + * + * This behavior allows you to always pass in the arguments in the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * Names for printable keys depend on keyboard layout, while names for + * non-printable keys are the same across layouts but depend on the application + * language and should be localized along with other user interface text. + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + +/*! @brief Returns the platform-specific scancode of the specified key. + * + * This function returns the platform-specific scancode of the specified key. + * + * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this + * method will return `-1`. + * + * @param[in] key Any [named key](@ref keys). + * @return The platform-specific scancode for the key, or `-1` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref input_key + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwGetKeyScancode(int key); + +/*! @brief Returns the last reported state of a keyboard key for the specified + * window. + * + * This function returns the last state reported for the specified key to the + * specified window. The returned state is one of `GLFW_PRESS` or + * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to + * the key callback. + * + * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns + * `GLFW_PRESS` the first time you call it for a key that was pressed, even if + * that key has already been released. + * + * The key functions deal with physical keys, with [key tokens](@ref keys) + * named after their use on the standard US keyboard layout. If you want to + * input text, use the Unicode character callback instead. + * + * The [modifier key bit masks](@ref mods) are not key tokens and cannot be + * used with this function. + * + * __Do not use this function__ to implement [text input](@ref input_char). + * + * @param[in] window The desired window. + * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is + * not a valid key for this function. + * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +GLFWAPI int glfwGetKey(GLFWwindow* window, int key); + +/*! @brief Returns the last reported state of a mouse button for the specified + * window. + * + * This function returns the last state reported for the specified mouse button + * to the specified window. The returned state is one of `GLFW_PRESS` or + * `GLFW_RELEASE`. + * + * If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function + * returns `GLFW_PRESS` the first time you call it for a mouse button that was + * pressed, even if that mouse button has already been released. + * + * @param[in] window The desired window. + * @param[in] button The desired [mouse button](@ref buttons). + * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_mouse_button + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button); + +/*! @brief Retrieves the position of the cursor relative to the content area of + * the window. + * + * This function returns the position of the cursor, in screen coordinates, + * relative to the upper-left corner of the content area of the specified + * window. + * + * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor + * position is unbounded and limited only by the minimum and maximum values of + * a `double`. + * + * The coordinate can be converted to their integer equivalents with the + * `floor` function. Casting directly to an integer type works for positive + * coordinates, but fails for negative ones. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] window The desired window. + * @param[out] xpos Where to store the cursor x-coordinate, relative to the + * left edge of the content area, or `NULL`. + * @param[out] ypos Where to store the cursor y-coordinate, relative to the to + * top edge of the content area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_pos + * @sa @ref glfwSetCursorPos + * + * @since Added in version 3.0. Replaces `glfwGetMousePos`. + * + * @ingroup input + */ +GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); + +/*! @brief Sets the position of the cursor, relative to the content area of the + * window. + * + * This function sets the position, in screen coordinates, of the cursor + * relative to the upper-left corner of the content area of the specified + * window. The window must have input focus. If the window does not have + * input focus when this function is called, it fails silently. + * + * __Do not use this function__ to implement things like camera controls. GLFW + * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the + * cursor, transparently re-centers it and provides unconstrained cursor + * motion. See @ref glfwSetInputMode for more information. + * + * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is + * unconstrained and limited only by the minimum and maximum values of + * a `double`. + * + * @param[in] window The desired window. + * @param[in] xpos The desired x-coordinate, relative to the left edge of the + * content area. + * @param[in] ypos The desired y-coordinate, relative to the top edge of the + * content area. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland This function will only work when the cursor mode is + * `GLFW_CURSOR_DISABLED`, otherwise it will do nothing. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_pos + * @sa @ref glfwGetCursorPos + * + * @since Added in version 3.0. Replaces `glfwSetMousePos`. + * + * @ingroup input + */ +GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); + +/*! @brief Creates a custom cursor. + * + * Creates a new custom cursor image that can be set for a window with @ref + * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. + * Any remaining cursors are destroyed by @ref glfwTerminate. + * + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel with the red channel first. They are arranged canonically + * as packed sequential rows, starting from the top-left corner. + * + * The cursor hotspot is specified in pixels, relative to the upper-left corner + * of the cursor image. Like all other coordinate systems in GLFW, the X-axis + * points to the right and the Y-axis points down. + * + * @param[in] image The desired cursor image. + * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. + * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. + * @return The handle of the created cursor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * @sa @ref glfwDestroyCursor + * @sa @ref glfwCreateStandardCursor + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot); + +/*! @brief Creates a cursor with a standard shape. + * + * Returns a cursor with a [standard shape](@ref shapes), that can be set for + * a window with @ref glfwSetCursor. + * + * @param[in] shape One of the [standard shapes](@ref shapes). + * @return A new cursor ready to use or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * @sa @ref glfwCreateCursor + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape); + +/*! @brief Destroys a cursor. + * + * This function destroys a cursor previously created with @ref + * glfwCreateCursor. Any remaining cursors will be destroyed by @ref + * glfwTerminate. + * + * If the specified cursor is current for any window, that window will be + * reverted to the default cursor. This does not affect the cursor mode. + * + * @param[in] cursor The cursor object to destroy. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * @sa @ref glfwCreateCursor + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor); + +/*! @brief Sets the cursor for the window. + * + * This function sets the cursor image to be used when the cursor is over the + * content area of the specified window. The set cursor will only be visible + * when the [cursor mode](@ref cursor_mode) of the window is + * `GLFW_CURSOR_NORMAL`. + * + * On some platforms, the set cursor may not be visible unless the window also + * has input focus. + * + * @param[in] window The window to set the cursor for. + * @param[in] cursor The cursor to set, or `NULL` to switch back to the default + * arrow cursor. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); + +/*! @brief Sets the key callback. + * + * This function sets the key callback of the specified window, which is called + * when a key is pressed, repeated or released. + * + * The key functions deal with physical keys, with layout independent + * [key tokens](@ref keys) named after their values in the standard US keyboard + * layout. If you want to input text, use the + * [character callback](@ref glfwSetCharCallback) instead. + * + * When a window loses input focus, it will generate synthetic key release + * events for all pressed keys. You can tell these events from user-generated + * events by the fact that the synthetic ones are generated after the focus + * loss event has been processed, i.e. after the + * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * + * The scancode of a key is specific to that platform or sometimes even to that + * machine. Scancodes are intended to allow users to bind keys that don't have + * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their + * state is not saved and so it cannot be queried with @ref glfwGetKey. + * + * Sometimes GLFW needs to generate synthetic key events, in which case the + * scancode may be zero. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new key callback, or `NULL` to remove the currently + * set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup input + */ +GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun); + +/*! @brief Sets the Unicode character callback. + * + * This function sets the character callback of the specified window, which is + * called when a Unicode character is input. + * + * The character callback is intended for Unicode text input. As it deals with + * characters, it is keyboard layout dependent, whereas the + * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1 + * to physical keys, as a key may produce zero, one or more characters. If you + * want to know whether a specific physical key was pressed or released, see + * the key callback instead. + * + * The character callback behaves as system text input normally does and will + * not be called if modifier keys are held down that would prevent normal text + * input on that platform, for example a Super (Command) key on macOS or Alt key + * on Windows. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_char + * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup input + */ +GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun); + +/*! @brief Sets the Unicode character with modifiers callback. + * + * This function sets the character with modifiers callback of the specified + * window, which is called when a Unicode character is input regardless of what + * modifier keys are used. + * + * The character with modifiers callback is intended for implementing custom + * Unicode character input. For regular Unicode text input, see the + * [character callback](@ref glfwSetCharCallback). Like the character + * callback, the character with modifiers callback deals with characters and is + * keyboard layout dependent. Characters do not map 1:1 to physical keys, as + * a key may produce zero, one or more characters. If you want to know whether + * a specific physical key was pressed or released, see the + * [key callback](@ref glfwSetKeyCallback) instead. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or an + * [error](@ref error_handling) occurred. + * + * @deprecated Scheduled for removal in version 4.0. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_char + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun); + +/*! @brief Sets the mouse button callback. + * + * This function sets the mouse button callback of the specified window, which + * is called when a mouse button is pressed or released. + * + * When a window loses input focus, it will generate synthetic mouse button + * release events for all pressed mouse buttons. You can tell these events + * from user-generated events by the fact that the synthetic ones are generated + * after the focus loss event has been processed, i.e. after the + * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_mouse_button + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup input + */ +GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun); + +/*! @brief Sets the cursor position callback. + * + * This function sets the cursor position callback of the specified window, + * which is called when the cursor is moved. The callback is provided with the + * position, in screen coordinates, relative to the upper-left corner of the + * content area of the window. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_pos + * + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. + * + * @ingroup input + */ +GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun); + +/*! @brief Sets the cursor enter/exit callback. + * + * This function sets the cursor boundary crossing callback of the specified + * window, which is called when the cursor enters or leaves the content area of + * the window. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_enter + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun); + +/*! @brief Sets the scroll callback. + * + * This function sets the scroll callback of the specified window, which is + * called when a scrolling device is used, such as a mouse wheel or scrolling + * area of a touchpad. + * + * The scroll callback receives all scrolling input, like that from a mouse + * wheel or a touchpad scrolling area. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently + * set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref scrolling + * + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. + * + * @ingroup input + */ +GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun); + +/*! @brief Sets the file drop callback. + * + * This function sets the file drop callback of the specified window, which is + * called when one or more dragged files are dropped on the window. + * + * Because the path array and its strings may have been generated specifically + * for that event, they are not guaranteed to be valid after the callback has + * returned. If you wish to use them after the callback returns, you need to + * make a deep copy. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new file drop callback, or `NULL` to remove the + * currently set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @wayland File drop is currently unimplemented. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref path_drop + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun); + +/*! @brief Returns whether the specified joystick is present. + * + * This function returns whether the specified joystick is present. + * + * There is no need to call this function before other functions that accept + * a joystick ID, as they all check for presence before performing any other + * work. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick + * + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. + * + * @ingroup input + */ +GLFWAPI int glfwJoystickPresent(int jid); + +/*! @brief Returns the values of all axes of the specified joystick. + * + * This function returns the values of all axes of the specified joystick. + * Each element in the array is a value between -1.0 and 1.0. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of axis values in the returned + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of axis values, or `NULL` if the joystick is not present or + * an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_axis + * + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. + * + * @ingroup input + */ +GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count); + +/*! @brief Returns the state of all buttons of the specified joystick. + * + * This function returns the state of all buttons of the specified joystick. + * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. + * + * For backward compatibility with earlier versions that did not have @ref + * glfwGetJoystickHats, the button array also includes all hats, each + * represented as four buttons. The hats are in the same order as returned by + * __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and + * _left_. To disable these extra buttons, set the @ref + * GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of button states in the returned + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of button states, or `NULL` if the joystick is not present + * or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_button + * + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. + * + * @ingroup input + */ +GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count); + +/*! @brief Returns the state of all hats of the specified joystick. + * + * This function returns the state of all hats of the specified joystick. + * Each element in the array is one of the following values: + * + * Name | Value + * ---- | ----- + * `GLFW_HAT_CENTERED` | 0 + * `GLFW_HAT_UP` | 1 + * `GLFW_HAT_RIGHT` | 2 + * `GLFW_HAT_DOWN` | 4 + * `GLFW_HAT_LEFT` | 8 + * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP` + * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN` + * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP` + * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN` + * + * The diagonal directions are bitwise combinations of the primary (up, right, + * down and left) directions and you can test for these individually by ANDing + * it with the corresponding direction. + * + * @code + * if (hats[2] & GLFW_HAT_RIGHT) + * { + * // State of hat 2 could be right-up, right or right-down + * } + * @endcode + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of hat states in the returned + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of hat states, or `NULL` if the joystick is not present + * or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_hat + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count); + +/*! @brief Returns the name of the specified joystick. + * + * This function returns the name, encoded as UTF-8, of the specified joystick. + * The returned string is allocated and freed by GLFW. You should not free it + * yourself. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick + * is not present or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_name + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetJoystickName(int jid); + +/*! @brief Returns the SDL comaptible GUID of the specified joystick. + * + * This function returns the SDL compatible GUID, as a UTF-8 encoded + * hexadecimal string, of the specified joystick. The returned string is + * allocated and freed by GLFW. You should not free it yourself. + * + * The GUID is what connects a joystick to a gamepad mapping. A connected + * joystick will always have a GUID even if there is no gamepad mapping + * assigned to it. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * The GUID uses the format introduced in SDL 2.0.5. This GUID tries to + * uniquely identify the make and model of a joystick but does not identify + * a specific unit, e.g. all wired Xbox 360 controllers will have the same + * GUID on that platform. The GUID for a unit may vary between platforms + * depending on what hardware information the platform specific APIs provide. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return The UTF-8 encoded GUID of the joystick, or `NULL` if the joystick + * is not present or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetJoystickGUID(int jid); + +/*! @brief Sets the user pointer of the specified joystick. + * + * This function sets the user-defined pointer of the specified joystick. The + * current value is retained until the joystick is disconnected. The initial + * value is `NULL`. + * + * This function may be called from the joystick callback, even for a joystick + * that is being disconnected. + * + * @param[in] jid The joystick whose pointer to set. + * @param[in] pointer The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref joystick_userptr + * @sa @ref glfwGetJoystickUserPointer + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer); + +/*! @brief Returns the user pointer of the specified joystick. + * + * This function returns the current value of the user-defined pointer of the + * specified joystick. The initial value is `NULL`. + * + * This function may be called from the joystick callback, even for a joystick + * that is being disconnected. + * + * @param[in] jid The joystick whose pointer to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref joystick_userptr + * @sa @ref glfwSetJoystickUserPointer + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI void* glfwGetJoystickUserPointer(int jid); + +/*! @brief Returns whether the specified joystick has a gamepad mapping. + * + * This function returns whether the specified joystick is both present and has + * a gamepad mapping. + * + * If the specified joystick is present but does not have a gamepad mapping + * this function will return `GLFW_FALSE` but will not generate an error. Call + * @ref glfwJoystickPresent to check if a joystick is present regardless of + * whether it has a mapping. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping, + * or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwGetGamepadState + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwJoystickIsGamepad(int jid); + +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * For joystick connection and disconnection events to be delivered on all + * platforms, you need to call one of the [event processing](@ref events) + * functions. Joystick disconnection may also be detected and the callback + * called by joystick functions. The function will then return whatever it + * returns if the joystick is not present. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + +/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings. + * + * This function parses the specified ASCII encoded string and updates the + * internal list with any gamepad mappings it finds. This string may + * contain either a single gamepad mapping or many mappings separated by + * newlines. The parser supports the full format of the `gamecontrollerdb.txt` + * source file including empty lines and comments. + * + * See @ref gamepad_mapping for a description of the format. + * + * If there is already a gamepad mapping for a given GUID in the internal list, + * it will be replaced by the one passed to this function. If the library is + * terminated and re-initialized the internal list will revert to the built-in + * default. + * + * @param[in] string The string containing the gamepad mappings. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwJoystickIsGamepad + * @sa @ref glfwGetGamepadName + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwUpdateGamepadMappings(const char* string); + +/*! @brief Returns the human-readable gamepad name for the specified joystick. + * + * This function returns the human-readable name of the gamepad from the + * gamepad mapping assigned to the specified joystick. + * + * If the specified joystick is not present or does not have a gamepad mapping + * this function will return `NULL` but will not generate an error. Call + * @ref glfwJoystickPresent to check whether it is present regardless of + * whether it has a mapping. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return The UTF-8 encoded name of the gamepad, or `NULL` if the + * joystick is not present, does not have a mapping or an + * [error](@ref error_handling) occurred. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, the gamepad mappings are updated or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwJoystickIsGamepad + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetGamepadName(int jid); + +/*! @brief Retrieves the state of the specified joystick remapped as a gamepad. + * + * This function retrives the state of the specified joystick remapped to + * an Xbox-like gamepad. + * + * If the specified joystick is not present or does not have a gamepad mapping + * this function will return `GLFW_FALSE` but will not generate an error. Call + * @ref glfwJoystickPresent to check whether it is present regardless of + * whether it has a mapping. + * + * The Guide button may not be available for input as it is often hooked by the + * system or the Steam client. + * + * Not all devices have all the buttons or axes provided by @ref + * GLFWgamepadstate. Unavailable buttons and axes will always report + * `GLFW_RELEASE` and 0.0 respectively. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] state The gamepad input state of the joystick. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is + * connected, it has no gamepad mapping or an [error](@ref error_handling) + * occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwUpdateGamepadMappings + * @sa @ref glfwJoystickIsGamepad + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state); + +/*! @brief Sets the clipboard to the specified string. + * + * This function sets the system clipboard to the specified, UTF-8 encoded + * string. + * + * @param[in] window Deprecated. Any valid window or `NULL`. + * @param[in] string A UTF-8 encoded string. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa @ref glfwGetClipboardString + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); + +/*! @brief Returns the contents of the clipboard as a string. + * + * This function returns the contents of the system clipboard, if it contains + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. + * + * @param[in] window Deprecated. Any valid window or `NULL`. + * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` + * if an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa @ref glfwSetClipboardString + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); + +/*! @brief Returns the value of the GLFW timer. + * + * This function returns the value of the GLFW timer. Unless the timer has + * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW + * was initialized. + * + * The resolution of the timer is system dependent, but is usually on the order + * of a few micro- or nanoseconds. It uses the highest-resolution monotonic + * time source on each supported platform. + * + * @return The current value, in seconds, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading and + * writing of the internal timer offset is not atomic, so it needs to be + * externally synchronized with calls to @ref glfwSetTime. + * + * @sa @ref time + * + * @since Added in version 1.0. + * + * @ingroup input + */ +GLFWAPI double glfwGetTime(void); + +/*! @brief Sets the GLFW timer. + * + * This function sets the value of the GLFW timer. It then continues to count + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. + * + * @param[in] time The new value, in seconds. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Reading and + * writing of the internal timer offset is not atomic, so it needs to be + * externally synchronized with calls to @ref glfwGetTime. + * + * @sa @ref time + * + * @since Added in version 2.2. + * + * @ingroup input + */ +GLFWAPI void glfwSetTime(double time); + +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa @ref glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa @ref glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + +/*! @brief Makes the context of the specified window current for the calling + * thread. + * + * This function makes the OpenGL or OpenGL ES context of the specified window + * current on the calling thread. A context must only be made current on + * a single thread at a time and each thread can have only a single current + * context at a time. + * + * When moving a context between threads, you must make it non-current on the + * old thread before making it current on the new one. + * + * By default, making a context non-current implicitly forces a pipeline flush. + * On machines that support `GL_KHR_context_flush_control`, you can control + * whether a context performs this flush by setting the + * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) + * hint. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * @param[in] window The window whose context to make current, or `NULL` to + * detach the current context. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_current + * @sa @ref glfwGetCurrentContext + * + * @since Added in version 3.0. + * + * @ingroup context + */ +GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window); + +/*! @brief Returns the window whose context is current on the calling thread. + * + * This function returns the window whose OpenGL or OpenGL ES context is + * current on the calling thread. + * + * @return The window whose context is current, or `NULL` if no window's + * context is current. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_current + * @sa @ref glfwMakeContextCurrent + * + * @since Added in version 3.0. + * + * @ingroup context + */ +GLFWAPI GLFWwindow* glfwGetCurrentContext(void); + +/*! @brief Swaps the front and back buffers of the specified window. + * + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. + * + * @param[in] window The window whose buffers to swap. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref buffer_swap + * @sa @ref glfwSwapInterval + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSwapBuffers(GLFWwindow* window); + +/*! @brief Sets the swap interval for the current context. + * + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. + * + * A context that supports either of the `WGL_EXT_swap_control_tear` and + * `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap + * intervals, which allows the driver to swap immediately even if a frame + * arrives a little bit late. You can check for these extensions with @ref + * glfwExtensionSupported. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * + * @param[in] interval The minimum number of screen updates to wait for + * until the buffers are swapped by @ref glfwSwapBuffers. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done + * because some swap interval extensions used by GLFW do not allow the swap + * interval to be reset to zero once it has been set to a non-zero value. + * + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref buffer_swap + * @sa @ref glfwSwapBuffers + * + * @since Added in version 1.0. + * + * @ingroup context + */ +GLFWAPI void glfwSwapInterval(int interval); + +/*! @brief Returns whether the specified extension is available. + * + * This function returns whether the specified + * [API extension](@ref context_glext) is supported by the current OpenGL or + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * As this functions retrieves and searches one or more extension strings each + * call, it is recommended that you cache its results if it is going to be used + * frequently. The extension strings will not change during the lifetime of + * a context, so there is no danger in doing this. + * + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. + * + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_glext + * @sa @ref glfwGetProcAddress + * + * @since Added in version 1.0. + * + * @ingroup context + */ +GLFWAPI int glfwExtensionSupported(const char* extension); + +/*! @brief Returns the address of the specified function for the current + * context. + * + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported + * by the current context. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. + * + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same + * between contexts. + * + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. + * + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_glext + * @sa @ref glfwExtensionSupported + * + * @since Added in version 1.0. + * + * @ingroup context + */ +GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); + +/*! @brief Returns whether the Vulkan loader and an ICD have been found. + * + * This function returns whether the Vulkan loader and any minimally functional + * ICD have been found. + * + * The availability of a Vulkan loader and even an ICD does not by itself + * guarantee that surface creation or even instance creation is possible. + * For example, on Fermi systems Nvidia will install an ICD that provides no + * actual Vulkan support. Call @ref glfwGetRequiredInstanceExtensions to check + * whether the extensions necessary for Vulkan surface creation are available + * and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue + * family of a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is at least minimally available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remark Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @remark @macos This function currently only supports the + * `VK_MVK_macos_surface` extension from MoltenVK. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa @ref glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is at least minimally available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is at least minimally available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remark @macos This function currently always returns `GLFW_TRUE`, as the + * `VK_MVK_macos_surface` extension does not provide + * a `vkGetPhysicalDevice*PresentationSupport` type function. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader or at least one minimally functional ICD were not found, + * this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref + * GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported to check whether + * Vulkan is at least minimally available. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface cannot be shared with another API so the window must + * have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib) + * set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error + * and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE + * + * @remark If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @remark @macos This function currently only supports the + * `VK_MVK_macos_surface` extension from MoltenVK. + * + * @remark @macos This function creates and sets a `CAMetalLayer` instance for + * the window content view, which is required for MoltenVK to function. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa @ref glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + + +/************************************************************************* + * Global definition cleanup + *************************************************************************/ + +/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ + +#ifdef GLFW_WINGDIAPI_DEFINED + #undef WINGDIAPI + #undef GLFW_WINGDIAPI_DEFINED +#endif + +#ifdef GLFW_CALLBACK_DEFINED + #undef CALLBACK + #undef GLFW_CALLBACK_DEFINED +#endif + +/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally + * defined by some gl.h variants (OpenBSD) so define it after if needed. + */ +#ifndef GLAPIENTRY + #define GLAPIENTRY APIENTRY +#endif + +/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _glfw3_h_ */ + diff --git a/thirdparty/glfw/GLFW/glfw3native.h b/thirdparty/glfw/GLFW/glfw3native.h new file mode 100644 index 0000000000..267e75ca9e --- /dev/null +++ b/thirdparty/glfw/GLFW/glfw3native.h @@ -0,0 +1,525 @@ +/************************************************************************* + * GLFW 3.3 - www.glfw.org + * A library for OpenGL, window and input + *------------------------------------------------------------------------ + * Copyright (c) 2002-2006 Marcus Geelnard + * Copyright (c) 2006-2018 Camilla Löwy + * + * 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. + * + *************************************************************************/ + +#ifndef _glfw3_native_h_ +#define _glfw3_native_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************* + * Doxygen documentation + *************************************************************************/ + +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ +/*! @defgroup native Native access + * @brief Functions related to accessing native handles. + * + * **By using the native access functions you assert that you know what you're + * doing and how to fix problems caused by using them. If you don't, you + * shouldn't be using them.** + * + * Before the inclusion of @ref glfw3native.h, you may define zero or more + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. + * + * The available window API macros are: + * * `GLFW_EXPOSE_NATIVE_WIN32` + * * `GLFW_EXPOSE_NATIVE_COCOA` + * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * + * The available context API macros are: + * * `GLFW_EXPOSE_NATIVE_WGL` + * * `GLFW_EXPOSE_NATIVE_NSGL` + * * `GLFW_EXPOSE_NATIVE_GLX` + * * `GLFW_EXPOSE_NATIVE_EGL` + * * `GLFW_EXPOSE_NATIVE_OSMESA` + * + * These macros select which of the native access functions that are declared + * and which platform-specific headers to include. It is then up your (by + * definition platform-specific) code to handle which of these should be + * defined. + */ + + +/************************************************************************* + * System headers and types + *************************************************************************/ + +#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) + // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for + // example to allow applications to correctly declare a GL_ARB_debug_output + // callback) but windows.h assumes no one will define APIENTRY before it does + #if defined(GLFW_APIENTRY_DEFINED) + #undef APIENTRY + #undef GLFW_APIENTRY_DEFINED + #endif + #include +#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL) + #if defined(__OBJC__) + #import + #else + #include + typedef void* id; + #endif +#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) + #include + #include +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WGL) + /* WGL is declared by windows.h */ +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) + /* NSGL is declared by Cocoa.h */ +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) + #include +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) + #include +#endif +#if defined(GLFW_EXPOSE_NATIVE_OSMESA) + #include +#endif + + +/************************************************************************* + * Functions + *************************************************************************/ + +#if defined(GLFW_EXPOSE_NATIVE_WIN32) +/*! @brief Returns the adapter device name of the specified monitor. + * + * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) + * of the specified monitor, or `NULL` if an [error](@ref error_handling) + * occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor); + +/*! @brief Returns the display device name of the specified monitor. + * + * @return The UTF-8 encoded display device name (for example + * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor); + +/*! @brief Returns the `HWND` of the specified window. + * + * @return The `HWND` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WGL) +/*! @brief Returns the `HGLRC` of the specified window. + * + * @return The `HGLRC` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_COCOA) +/*! @brief Returns the `CGDirectDisplayID` of the specified monitor. + * + * @return The `CGDirectDisplayID` of the specified monitor, or + * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `NSWindow` of the specified window. + * + * @return The `NSWindow` of the specified window, or `nil` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_NSGL) +/*! @brief Returns the `NSOpenGLContext` of the specified window. + * + * @return The `NSOpenGLContext` of the specified window, or `nil` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_X11) +/*! @brief Returns the `Display` used by GLFW. + * + * @return The `Display` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI Display* glfwGetX11Display(void); + +/*! @brief Returns the `RRCrtc` of the specified monitor. + * + * @return The `RRCrtc` of the specified monitor, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); + +/*! @brief Returns the `RROutput` of the specified monitor. + * + * @return The `RROutput` of the specified monitor, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor); + +/*! @brief Returns the `Window` of the specified window. + * + * @return The `Window` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI Window glfwGetX11Window(GLFWwindow* window); + +/*! @brief Sets the current primary selection to the specified string. + * + * @param[in] string A UTF-8 encoded string. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa glfwGetX11SelectionString + * @sa glfwSetClipboardString + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI void glfwSetX11SelectionString(const char* string); + +/*! @brief Returns the contents of the current primary selection as a string. + * + * If the selection is empty or if its contents cannot be converted, `NULL` + * is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated. + * + * @return The contents of the selection as a UTF-8 encoded string, or `NULL` + * if an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the + * library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa glfwSetX11SelectionString + * @sa glfwGetClipboardString + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetX11SelectionString(void); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_GLX) +/*! @brief Returns the `GLXContext` of the specified window. + * + * @return The `GLXContext` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_EGL) +/*! @brief Returns the `EGLDisplay` used by GLFW. + * + * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI EGLDisplay glfwGetEGLDisplay(void); + +/*! @brief Returns the `EGLContext` of the specified window. + * + * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window); + +/*! @brief Returns the `EGLSurface` of the specified window. + * + * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_OSMESA) +/*! @brief Retrieves the color buffer associated with the specified window. + * + * @param[in] window The window whose color buffer to retrieve. + * @param[out] width Where to store the width of the color buffer, or `NULL`. + * @param[out] height Where to store the height of the color buffer, or `NULL`. + * @param[out] format Where to store the OSMesa pixel format of the color + * buffer, or `NULL`. + * @param[out] buffer Where to store the address of the color buffer, or + * `NULL`. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer); + +/*! @brief Retrieves the depth buffer associated with the specified window. + * + * @param[in] window The window whose depth buffer to retrieve. + * @param[out] width Where to store the width of the depth buffer, or `NULL`. + * @param[out] height Where to store the height of the depth buffer, or `NULL`. + * @param[out] bytesPerValue Where to store the number of bytes per depth + * buffer element, or `NULL`. + * @param[out] buffer Where to store the address of the depth buffer, or + * `NULL`. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer); + +/*! @brief Returns the `OSMesaContext` of the specified window. + * + * @return The `OSMesaContext` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _glfw3_native_h_ */ + diff --git a/thirdparty/glfw/glfw3.dll b/thirdparty/glfw/glfw3.dll new file mode 100644 index 0000000000000000000000000000000000000000..1ed6f46c8df70835f70bd75ef97ab09dbf7dafbe GIT binary patch literal 249856 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%0DE0JD>^fIKEBmEkZ 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 literal 0 HcmV?d00001 diff --git a/vlib/ft/ft.v b/vlib/ft/ft.v new file mode 100644 index 0000000000..764bdfc8ff --- /dev/null +++ b/vlib/ft/ft.v @@ -0,0 +1,358 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module ft + +import stbi +import glm +import gl + +#flag -I @VROOT/thirdparty/freetype + +#flag @VROOT/thirdparty/freetype/libfreetype.a +#flag darwin -lpng -lbz2 -lz + + +#flag linux -I/usr/include/freetype2 +#flag linux -I. + + +#include "ft2build.h" +#include FT_FREETYPE_H + +struct GG { + shader gl.Shader + // use_ortho bool + width int + height int + VAO u32 + rect_vao u32 + rect_vbo u32 + line_vao u32 + line_vbo u32 + VBO u32 + chars []gg.Character + utf_runes []string + utf_chars []gg.Character + text_ctx *GG + face Face + scale int // retina = 2 , normal = 1 +} + +struct Character { + texture_id u32 + size Vec2 + bearing Vec2 + advance u32 +} + +// jfn ft_load_char(face FT_Face, code FT_ULong) Character { +// fn ft_load_char(_face voidptr, _code voidptr) Character { +fn ft_load_char(_face Face, code i64) Character { + // #FT_Face face = *(FT_Face*)(_face); FT_ULong code = *(FT_ULong*)(code); + # FT_Face face = *((FT_Face*)_face.cobj); + # if (FT_Load_Char(face, code, FT_LOAD_RENDER)) + { + println('freetype: Failed to load Glyph') + exit(1) + } + // Generate texture + # GLuint texture; + # glGenTextures(1, &texture); + # glBindTexture(GL_TEXTURE_2D, texture); + # glTexImage2D( + # GL_TEXTURE_2D, + # 0, + # GL_RED, + # face->glyph->bitmap.width, + # face->glyph->bitmap.rows, + # 0, + # GL_RED, + # GL_UNSIGNED_BYTE, + # face->glyph->bitmap.buffer + # ); + // Set texture options + # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // Now store character for later use + ch := Character{} + # ch.texture_id=texture ; + # ch.size = gg__vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows); + # ch.bearing = gg__vec2(face->glyph->bitmap_left, face->glyph->bitmap_top), + # ch.advance = face->glyph->advance.x; + return ch +} + +pub fn new_context_text(cfg Cfg, scale int) *GG { + // Can only have text in ortho mode + if !cfg.use_ortho { + return &GG{text_ctx: 0} + } + mut width := cfg.width * scale + mut height := cfg.height * scale + font_size := cfg.font_size * scale + // exit('fs=$font_size') + // if false { + // retina + // width = width * 2// scale// 2 + // height = height * 2// scale// 2 + // font_size *= scale// 2 + // } + /* + gl.viewport(0, 0, width, height) +*/ + // gl.enable(GL_CULL_FACE) // TODO NEED CULL? + gl.enable(GL_BLEND) +return &GG{} + // return &GG{} + # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + shader := gl.new_shader('text') + shader.use() + projection := glm.ortho(0, width, 0, height)// 0 at BOT + // projection_new := ortho(0, width, 0, height)// 0 at BOT + // projection := gl.ortho(0, width,height,0) // 0 at TOP + shader.set_mat4('projection', projection) + // FREETYPE + # FT_Library ft; + // All functions return a value different than 0 whenever an error occurred + # if (FT_Init_FreeType(&ft)) + println('ERROR::FREETYPE: Could not init FreeType Library') + // Load font as face + // face := FT_Face{} + mut font_path := 'RobotoMono-Regular.ttf' + if !os.file_exists(font_path) { + exePath := os.getexepath() + exeDir := os.basedir(exePath) + println('Trying to load from $exeDir') + font_path = '${exeDir}/RobotoMono-Regular.ttf' + } + if !os.file_exists(font_path) { + println('failed to load RobotoMono-Regular.ttf') + exit(1) + } + # FT_Face face; + # if (FT_New_Face(ft, font_path.str, 0, &face)) + // # if (FT_New_Face(ft, "/Library/Fonts/Courier New.ttf", 0, &face)) + // # if (FT_New_Face(ft, "/System/Library/Fonts/Apple Color Emoji.ttc", 0, &face)) + { + println('freetyp: Failed to load font') + exit(1) + } + // Set size to load glyphs as + # FT_Set_Pixel_Sizes(face, 0, font_size) ; + // Disable byte-alignment restriction + # glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + // Gen texture + // Load first 128 characters of ASCII set + mut chars := []gg.Character{} + f := Face { + cobj: 0 + } + # f.cobj = &face; + // # for (GLubyte c = 0; c < 128; c++) + for c := 0; c < 128; c++ { + // ch := Character{} + // ch:=ft_load_char(face, c) + // # ch =gg__ft_load_char(&face, &c); + // //////////////////////////////// + mut ch := ft_load_char(f, i64(c)) + // s := utf32_to_str(uint(0x043f)) + // s := 'п' + // ch = ft_load_char(f, s.utf32_code()) + // # ch = gg__ft_load_char(f, 0x043f); // RUS P + // # unsigned long c = FT_Get_Char_Index(face, 0x043f ); + // # printf("!!!!!!!!! %lu\n", c); + // # c = FT_Get_Char_Index(face, 0xd0bf ); + // # printf("!!!!!!!!! %lu\n", c); + // # ch = gg__ft_load_char(f, 0xd0bf) ; // UTF 8 + chars << ch + } + ch := Character{} + // # ch = gg__ft_load_char(f, 0x0000043f); + // # ch = gg__ft_load_char(f, 128169); + // chars.push(ch) + // Configure VAO + VAO := gl.gen_vertex_array() + println('new gg text context VAO=$VAO') + VBO := gl.gen_buffer() + gl.bind_vao(VAO) + gl.bind_buffer(GL_ARRAY_BUFFER, VBO) + // # glBufferData(GL_ARRAY_BUFFER, sizeof(GLf32) * 6 * 4, NULL, GL_DYNAMIC_DRAW); + gl.enable_vertex_attrib_array(0) + gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0) + // # glVertexAttribPointer(0, 4, GL_FLOAT,false, 4 * sizeof(GLf32), 0); + // gl.bind_buffer(GL_ARRAY_BUFFER, uint(0)) + // # glBindVertexArray(0); + mut ctx := &GG { + shader: shader, + width: width, + height: height, + scale: scale + VAO: VAO, + VBO: VBO, + chars: chars, + face: f + text_ctx: 0 + } + ctx.init_utf8_runes() + return ctx +} + +// A dirty hack to implement rendering of cyrillic letters. +// All UTF-8 must be supported. +fn (ctx mut GG) init_utf8_runes() { + s := '≈йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ' + println(s) + us := s.ustring() + for i := 0; i < us.len; i++ { + _rune := us.at(i) + ch := ft_load_char(ctx.face, _rune.utf32_code()) + // ctx.utf_rune_map.set(rune, ch) + ctx.utf_runes << _rune + ctx.utf_chars << ch + } +} + +// fn (ctx &GG) render_text(text string, x, y, scale f32, color gx.Color) { +pub fn (ctx &GG) draw_text(_x, _y int, text string, cfg gx.TextCfg) { + // dont draw non ascii for now + /* + for i := 0; i < text.len; i++ { + c := text[i] + if int(c) > 128 { + // ctx.text_ctx._draw_text(_x, _y, '[NON ASCII]', cfg) + // return + } + } +*/ + // # glScissor(0,0,300,300); + utext := text.ustring_tmp() + // utext := text.ustring() + ctx.text_ctx._draw_text(_x, _y, utext, cfg) + // utext.free() + // # glScissor(0,0,ctx->width*2,ctx->height*2); + // gl.disable(GL_SCISSOR_TEST)// TODO + // #free(text.str); +} + +fn (ctx &GG) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) { + ctx.text_ctx._draw_text(_x, _y, text, cfg) +} + +// TODO HACK with second text context +// fn (ctx &GG) _draw_text(_x, _y int, text string, cfg gx.TextCfg) { +fn (ctx &GG) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) { + /* + if utext.s.contains('on_seg') { + println('\nat(0)') + println(utext.runes) + firstc := utext.at(0) + println('drawtext "$utext.s" len=$utext.s.len ulen=$utext.len x=$_x firstc=$firstc') + if firstc != ' ' { + exit(1) + } + } +*/ + // println('scale=$ctx.scale size=$cfg.size') + if cfg.align == gx.ALIGN_RIGHT { + width := utext.len * 7 + _x -= width + 10 + } + x := f32(_x) * ctx.scale// f32(2) + // println('y=$_y height=$ctx.height') + // _y = _y * int(ctx.scale) //+ 26 + _y = _y * int(ctx.scale) + ((cfg.size * ctx.scale) / 2) + 5 * ctx.scale + y := f32(ctx.height - _y) + color := cfg.color + // Activate corresponding render state + ctx.shader.use() + ctx.shader.set_color('textColor', color) + # glActiveTexture(GL_TEXTURE0); + gl.bind_vao(ctx.VAO) + // Iterate through all characters + // utext := text.ustring() + for i := 0; i < utext.len; i++ { + _rune := utext.at(i) + // println('$i => $_rune') + mut ch := Character{} + if _rune.len == 1 { + idx := _rune[0] + if idx < 0 || idx >= ctx.chars.len { + println('BADE RUNE $_rune') + continue + } + ch = ctx.chars[_rune[0]] + } + else if _rune.len > 1 { + // TODO O(1) use map + for j := 0; j < ctx.utf_runes.len; j++ { + rune_j := ctx.utf_runes[j] + // if string_eq(ctx.utf_runes[j], rune) { + if rune_j==_rune { + ch = ctx.utf_chars[j] + break + } + } + } + if ch.size.x == 0 { + // continue + } + // mut c := int(text[i]) + // c = 128 + // s := 'A' + // c := int(s[0]) + // ch := ctx.chars[c] + xpos := x + f32(ch.bearing.x) * 1 + ypos := y - f32(ch.size.y - ch.bearing.y) * 1 + w := f32(ch.size.x) * 1 + h := f32(ch.size.y) * 1 + // Update VBO for each character + # GLfloat vertices[6][4] = { + # { xpos, ypos + h, 0.0, 0.0 }, + # { xpos, ypos, 0.0, 1.0 }, + # { xpos + w, ypos, 1.0, 1.0 }, + # { xpos, ypos + h, 0.0, 0.0 }, + # { xpos + w, ypos, 1.0, 1.0 }, + # { xpos + w, ypos + h, 1.0, 0.0 } + # }; + // t := glfw.get_time() + // Render glyph texture over quad + // t1 := glfw.get_time() + # glBindTexture(GL_TEXTURE_2D, ch.texture_id); + // Update content of VBO memory + gl.bind_buffer(GL_ARRAY_BUFFER, ctx.VBO) + // t2 := glfw.get_time() + // # glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData + # glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); + // t3 := glfw.get_time() + // gl.bind_buffer(GL_ARRAY_BUFFER, uint(0)) + // t4 := glfw.get_time() + // Render quad + gl.draw_arrays(GL_TRIANGLES, 0, 6) + // t5 := glfw.get_time() + // # if (glfw__get_time() - t > 0.001) + // { + // # printf("do_text = %f '%s' \n", glfw__get_time() - t, text.str); + // # printf("t1=%f, t2=%f, t3=%f, t4=%f, t5=%f\n\n\n", t1-t, t2-t1, t3-t2, t4-t3, t5-t4); + // } + // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) + // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + # x += (ch.advance >> 6) * 1; + } + gl.bind_vao(u32(0)) + # glBindTexture(GL_TEXTURE_2D, 0); + // runes.free() + // #free(runes.data); +} + +pub fn (ctx &GG) draw_text_def(x, y int, text string) { + cfg := gx.TextCfg { + color: gx.Black, + size: DEFAULT_FONT_SIZE, + align: gx.ALIGN_LEFT, + } + ctx.draw_text(x, y, text, cfg) +} diff --git a/vlib/gg/gg.v b/vlib/gg/gg.v index c07b677715..f0c2c1a64b 100644 --- a/vlib/gg/gg.v +++ b/vlib/gg/gg.v @@ -8,13 +8,6 @@ import stbi import glm import gl -#flag darwin -I/usr/local/Cellar/freetype/2.10.0/include/freetype2 -#flag -lfreetype -#flag linux -I/usr/include/freetype2 -#flag linux -I. -#include "ft2build.h" -#include FT_FREETYPE_H -#include "glad.h" struct Vec2 { x int y int @@ -40,13 +33,6 @@ pub fn vec2(x, y int) Vec2 { return res } -struct Character { - texture_id u32 - size Vec2 - bearing Vec2 - advance u32 -} - pub fn init() { println(gl.TEXT_VERT) gl.init_glad() @@ -75,11 +61,6 @@ struct GG { line_vao u32 line_vbo u32 VBO u32 - chars []gg.Character - utf_runes []string - utf_chars []gg.Character - text_ctx *GG - face Face scale int // retina = 2 , normal = 1 } @@ -112,11 +93,11 @@ pub fn new_context(cfg Cfg) *GG { */ // projection_new := ortho(0, width, height, 0) // println('\nORTHO OLD=') - # for (int i=0;i<16;i++) printf("%d=%f ",i, projection.data[i]); + //# for (int i=0;i<16;i++) printf("%d=%f ",i, projection.data[i]); // println('\n\n!ORTHO NEW=') // # for (int i=0;i<16;i++) printf("%d=%f ",i, projection_new[i]); // println('\n\n') - println('setting o') + //println('setting o') shader.set_mat4('projection', projection) } else { @@ -125,21 +106,29 @@ pub fn new_context(cfg Cfg) *GG { shader.set_mat4('projection', glm.identity()) } VAO := gl.gen_vertex_array() - println('new gg context VAO=$VAO') + //println('new gg context VAO=$VAO') VBO := gl.gen_buffer() mut scale := 1 if cfg.retina { scale = 2 } + gl.enable(GL_BLEND) + # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //println('new gg text context VAO=$VAO') + gl.bind_vao(VAO) + gl.bind_buffer(GL_ARRAY_BUFFER, VBO) + gl.enable_vertex_attrib_array(0) + gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0) + todo_remove_me(cfg, scale) mut ctx := &GG { - shader: shader, - width: cfg.width, - height: cfg.height, - VAO: VAO, - VBO: VBO, + shader: shader + width: cfg.width + height: cfg.height + VAO: VAO + VBO: VBO // /line_vao: gl.gen_vertex_array() // /line_vbo: gl.gen_buffer() - text_ctx: new_context_text(cfg, scale), + //text_ctx: new_context_text(cfg, scale), scale: scale // use_ortho: use_ortho } @@ -265,66 +254,15 @@ pub fn (ctx &GG) draw_rect2(x, y, w, h f32, c gx.Color) { C.glDeleteBuffers(1, &ebo) } -// jfn ft_load_char(face FT_Face, code FT_ULong) Character { -// fn ft_load_char(_face voidptr, _code voidptr) Character { -fn ft_load_char(_face Face, code i64) Character { - // #FT_Face face = *(FT_Face*)(_face); FT_ULong code = *(FT_ULong*)(code); - # FT_Face face = *((FT_Face*)_face.cobj); - # if (FT_Load_Char(face, code, FT_LOAD_RENDER)) - { - println('freetype: Failed to load Glyph') - exit(1) - } - // Generate texture - # GLuint texture; - # glGenTextures(1, &texture); - # glBindTexture(GL_TEXTURE_2D, texture); - # glTexImage2D( - # GL_TEXTURE_2D, - # 0, - # GL_RED, - # face->glyph->bitmap.width, - # face->glyph->bitmap.rows, - # 0, - # GL_RED, - # GL_UNSIGNED_BYTE, - # face->glyph->bitmap.buffer - # ); - // Set texture options - # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // Now store character for later use - ch := Character{} - # ch.texture_id=texture ; - # ch.size = gg__vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows); - # ch.bearing = gg__vec2(face->glyph->bitmap_left, face->glyph->bitmap_top), - # ch.advance = face->glyph->advance.x; - return ch -} - -pub fn new_context_text(cfg Cfg, scale int) *GG { +fn todo_remove_me(cfg Cfg, scale int) { // Can only have text in ortho mode if !cfg.use_ortho { - return &GG{text_ctx: 0} + return &GG{} } mut width := cfg.width * scale mut height := cfg.height * scale font_size := cfg.font_size * scale - // exit('fs=$font_size') - // if false { - // retina - // width = width * 2// scale// 2 - // height = height * 2// scale// 2 - // font_size *= scale// 2 - // } - /* - gl.viewport(0, 0, width, height) -*/ - // gl.enable(GL_CULL_FACE) // TODO NEED CULL? MEANS SHIT IS BROKEN? gl.enable(GL_BLEND) - // return &GG{} # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); shader := gl.new_shader('text') shader.use() @@ -332,246 +270,13 @@ pub fn new_context_text(cfg Cfg, scale int) *GG { // projection_new := ortho(0, width, 0, height)// 0 at BOT // projection := gl.ortho(0, width,height,0) // 0 at TOP shader.set_mat4('projection', projection) - // FREETYPE - # FT_Library ft; - // All functions return a value different than 0 whenever an error occurred - # if (FT_Init_FreeType(&ft)) - println('ERROR::FREETYPE: Could not init FreeType Library') - // Load font as face - // face := FT_Face{} - mut font_path := 'RobotoMono-Regular.ttf' - if !os.file_exists(font_path) { - exePath := os.getexepath() - exeDir := os.basedir(exePath) - println('Trying to load from $exeDir') - font_path = '${exeDir}/RobotoMono-Regular.ttf' - } - if !os.file_exists(font_path) { - println('failed to load RobotoMono-Regular.ttf') - exit(1) - } - # FT_Face face; - # if (FT_New_Face(ft, font_path.str, 0, &face)) - // # if (FT_New_Face(ft, "/Library/Fonts/Courier New.ttf", 0, &face)) - // # if (FT_New_Face(ft, "/System/Library/Fonts/Apple Color Emoji.ttc", 0, &face)) - { - println('freetyp: Failed to load font') - exit(1) - } - // Set size to load glyphs as - # FT_Set_Pixel_Sizes(face, 0, font_size) ; - // Disable byte-alignment restriction - # glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // Gen texture - // Load first 128 characters of ASCII set - mut chars := []gg.Character{} - f := Face { - cobj: 0 - } - # f.cobj = &face; - // # for (GLubyte c = 0; c < 128; c++) - for c := 0; c < 128; c++ { - // ch := Character{} - // ch:=ft_load_char(face, c) - // # ch =gg__ft_load_char(&face, &c); - // //////////////////////////////// - mut ch := ft_load_char(f, i64(c)) - // s := utf32_to_str(uint(0x043f)) - // s := 'п' - // ch = ft_load_char(f, s.utf32_code()) - // # ch = gg__ft_load_char(f, 0x043f); // RUS P - // # unsigned long c = FT_Get_Char_Index(face, 0x043f ); - // # printf("!!!!!!!!! %lu\n", c); - // # c = FT_Get_Char_Index(face, 0xd0bf ); - // # printf("!!!!!!!!! %lu\n", c); - // # ch = gg__ft_load_char(f, 0xd0bf) ; // UTF 8 - chars << ch - } - ch := Character{} - // # ch = gg__ft_load_char(f, 0x0000043f); - // # ch = gg__ft_load_char(f, 128169); - // chars.push(ch) - // Configure VAO VAO := gl.gen_vertex_array() - println('new gg text context VAO=$VAO') + //println('new gg text context VAO=$VAO') VBO := gl.gen_buffer() gl.bind_vao(VAO) gl.bind_buffer(GL_ARRAY_BUFFER, VBO) - // # glBufferData(GL_ARRAY_BUFFER, sizeof(GLf32) * 6 * 4, NULL, GL_DYNAMIC_DRAW); gl.enable_vertex_attrib_array(0) gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0) - // # glVertexAttribPointer(0, 4, GL_FLOAT,false, 4 * sizeof(GLf32), 0); - // gl.bind_buffer(GL_ARRAY_BUFFER, uint(0)) - // # glBindVertexArray(0); - mut ctx := &GG { - shader: shader, - width: width, - height: height, - scale: scale - VAO: VAO, - VBO: VBO, - chars: chars, - face: f - text_ctx: 0 - } - ctx.init_utf8_runes() - return ctx -} - -// A dirty hack to implement rendering of cyrillic letters. -// All UTF-8 must be supported. -fn (ctx mut GG) init_utf8_runes() { - s := '≈йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ' - println(s) - us := s.ustring() - for i := 0; i < us.len; i++ { - _rune := us.at(i) - ch := ft_load_char(ctx.face, _rune.utf32_code()) - // ctx.utf_rune_map.set(rune, ch) - ctx.utf_runes << _rune - ctx.utf_chars << ch - } -} - -// fn (ctx &GG) render_text(text string, x, y, scale f32, color gx.Color) { -pub fn (ctx &GG) draw_text(_x, _y int, text string, cfg gx.TextCfg) { - // dont draw non ascii for now - /* - for i := 0; i < text.len; i++ { - c := text[i] - if int(c) > 128 { - // ctx.text_ctx._draw_text(_x, _y, '[NON ASCII]', cfg) - // return - } - } -*/ - // # glScissor(0,0,300,300); - utext := text.ustring_tmp() - // utext := text.ustring() - ctx.text_ctx._draw_text(_x, _y, utext, cfg) - // utext.free() - // # glScissor(0,0,ctx->width*2,ctx->height*2); - // gl.disable(GL_SCISSOR_TEST)// TODO - // #free(text.str); -} - -fn (ctx &GG) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) { - ctx.text_ctx._draw_text(_x, _y, text, cfg) -} - -// TODO HACK with second text context -// fn (ctx &GG) _draw_text(_x, _y int, text string, cfg gx.TextCfg) { -fn (ctx &GG) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) { - /* - if utext.s.contains('on_seg') { - println('\nat(0)') - println(utext.runes) - firstc := utext.at(0) - println('drawtext "$utext.s" len=$utext.s.len ulen=$utext.len x=$_x firstc=$firstc') - if firstc != ' ' { - exit(1) - } - } -*/ - // println('scale=$ctx.scale size=$cfg.size') - if cfg.align == gx.ALIGN_RIGHT { - width := utext.len * 7 - _x -= width + 10 - } - x := f32(_x) * ctx.scale// f32(2) - // println('y=$_y height=$ctx.height') - // _y = _y * int(ctx.scale) //+ 26 - _y = _y * int(ctx.scale) + ((cfg.size * ctx.scale) / 2) + 5 * ctx.scale - y := f32(ctx.height - _y) - color := cfg.color - // Activate corresponding render state - ctx.shader.use() - ctx.shader.set_color('textColor', color) - # glActiveTexture(GL_TEXTURE0); - gl.bind_vao(ctx.VAO) - // Iterate through all characters - // utext := text.ustring() - for i := 0; i < utext.len; i++ { - _rune := utext.at(i) - // println('$i => $_rune') - mut ch := Character{} - if _rune.len == 1 { - idx := _rune[0] - if idx < 0 || idx >= ctx.chars.len { - println('BADE RUNE $_rune') - continue - } - ch = ctx.chars[_rune[0]] - } - else if _rune.len > 1 { - // TODO O(1) use map - for j := 0; j < ctx.utf_runes.len; j++ { - rune_j := ctx.utf_runes[j] - // if string_eq(ctx.utf_runes[j], rune) { - if rune_j==_rune { - ch = ctx.utf_chars[j] - break - } - } - } - if ch.size.x == 0 { - // continue - } - // mut c := int(text[i]) - // c = 128 - // s := 'A' - // c := int(s[0]) - // ch := ctx.chars[c] - xpos := x + f32(ch.bearing.x) * 1 - ypos := y - f32(ch.size.y - ch.bearing.y) * 1 - w := f32(ch.size.x) * 1 - h := f32(ch.size.y) * 1 - // Update VBO for each character - # GLfloat vertices[6][4] = { - # { xpos, ypos + h, 0.0, 0.0 }, - # { xpos, ypos, 0.0, 1.0 }, - # { xpos + w, ypos, 1.0, 1.0 }, - # { xpos, ypos + h, 0.0, 0.0 }, - # { xpos + w, ypos, 1.0, 1.0 }, - # { xpos + w, ypos + h, 1.0, 0.0 } - # }; - // t := glfw.get_time() - // Render glyph texture over quad - // t1 := glfw.get_time() - # glBindTexture(GL_TEXTURE_2D, ch.texture_id); - // Update content of VBO memory - gl.bind_buffer(GL_ARRAY_BUFFER, ctx.VBO) - // t2 := glfw.get_time() - // # glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData - # glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); - // t3 := glfw.get_time() - // gl.bind_buffer(GL_ARRAY_BUFFER, uint(0)) - // t4 := glfw.get_time() - // Render quad - gl.draw_arrays(GL_TRIANGLES, 0, 6) - // t5 := glfw.get_time() - // # if (glfw__get_time() - t > 0.001) - // { - // # printf("do_text = %f '%s' \n", glfw__get_time() - t, text.str); - // # printf("t1=%f, t2=%f, t3=%f, t4=%f, t5=%f\n\n\n", t1-t, t2-t1, t3-t2, t4-t3, t5-t4); - // } - // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) - // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) - # x += (ch.advance >> 6) * 1; - } - gl.bind_vao(u32(0)) - # glBindTexture(GL_TEXTURE_2D, 0); - // runes.free() - // #free(runes.data); -} - -pub fn (ctx &GG) draw_text_def(x, y int, text string) { - cfg := gx.TextCfg { - color: gx.Black, - size: DEFAULT_FONT_SIZE, - align: gx.ALIGN_LEFT, - } - ctx.draw_text(x, y, text, cfg) } fn update() { diff --git a/vlib/gl/1shader.v b/vlib/gl/1shader.v index 5ec7f42002..a84b62060a 100644 --- a/vlib/gl/1shader.v +++ b/vlib/gl/1shader.v @@ -103,7 +103,7 @@ pub fn new_shader(name string) Shader { } vertex_path := '${dir}${name}.vert' fragment_path := '${dir}${name}.frag' - println('shader path=$vertex_path,\n fpath="$fragment_path"') + //println('shader path=$vertex_path,\n fpath="$fragment_path"') // vertex_src := os.read_file(vertex_path.trim_space()) mut vertex_src := '' mut fragment_src := '' diff --git a/vlib/gl/gl.v b/vlib/gl/gl.v index f31f897c9d..cab940d122 100644 --- a/vlib/gl/gl.v +++ b/vlib/gl/gl.v @@ -19,12 +19,11 @@ import const ( GL_ARRAY_BUFFER ) -// TODO: windows support -#flag linux -I @VROOT/thirdparty/glad -#flag darwin -I @VROOT/thirdparty/glad +#flag -I @VROOT/thirdparty/glad #include "glad.h" -#include "glad.c" +#flag @VROOT/thirdparty/glad/glad.o +//#include "glad.c" pub fn init_glad() { ok := C.gladLoadGL() diff --git a/vlib/glfw/glfw.v b/vlib/glfw/glfw.v index 0e71e7403c..b6f63e530d 100644 --- a/vlib/glfw/glfw.v +++ b/vlib/glfw/glfw.v @@ -4,6 +4,10 @@ module glfw +#flag -I @VROOT/thirdparty/glfw + +#flag windows @VROOT/thirdparty/glfw/libglfw3.a + // Debugging a custom build #flag darwin -L/var/tmp/glfw/src/ #flag darwin -lglfw diff --git a/vlib/glm/glm.v b/vlib/glm/glm.v index b3f8ebe74f..3b3de63df7 100644 --- a/vlib/glm/glm.v +++ b/vlib/glm/glm.v @@ -117,7 +117,7 @@ fn (a Vec3) print() { x := a.x y := a.y z := a.z - # printf("vec3{%f,%f,%f}\n",x,y,z); + C.printf('vec3{%f,%f,%f}\n',x,y,z) // println('vec3{$x,$y,$z}') } @@ -162,7 +162,7 @@ fn normalize(vec Vec3) Vec3 { */ // https://github.com/g-truc/glm/blob/0ceb2b755fb155d593854aefe3e45d416ce153a4/glm/ext/matrix_clip_space.inl pub fn ortho(left, right, bottom, top f32) Mat4 { - println('glm ortho($left, $right, $bottom, $top)') + //println('glm ortho($left, $right, $bottom, $top)') // mat<4, 4, T, defaultp> Result(static_cast(1)); n := 16 mut res := f32_calloc(n) diff --git a/vlib/json/json_primitives.v b/vlib/json/json_primitives.v index b892444d10..810895a18e 100644 --- a/vlib/json/json_primitives.v +++ b/vlib/json/json_primitives.v @@ -9,7 +9,8 @@ module json #flag linux -I @VROOT/thirdparty/cJSON #flag darwin -I @VROOT/thirdparty/cJSON -// #include "cJSON.c" +#flag @VROOT/thirdparty/cJSON/cJSON.o + #include "cJSON.h" struct C.cJSON { valueint int diff --git a/vlib/os/os.v b/vlib/os/os.v index 3206808402..973822e9c8 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -615,7 +615,7 @@ pub fn ls(path string) []string { } $else { mut res := []string - dir := C.opendir(path.str) + dir := C.opendir(path.cstr()) if isnil(dir) { println('ls() couldnt open dir "$path"') print_c_errno() diff --git a/vlib/stbi/stbi.v b/vlib/stbi/stbi.v index 4f6e63f9fa..9e82ef8862 100644 --- a/vlib/stbi/stbi.v +++ b/vlib/stbi/stbi.v @@ -6,8 +6,7 @@ module stbi import gl -#flag linux -I @VROOT/thirdparty/stb_image -#flag darwin -I @VROOT/thirdparty/stb_image +#flag -I @VROOT/thirdparty/stb_image #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"