| 1 | #pragma once |
| 2 | /* |
| 3 | sokol_app.h -- cross-platform application wrapper |
| 4 | |
| 5 | Do this: |
| 6 | #define SOKOL_IMPL |
| 7 | before you include this file in *one* C or C++ file to create the |
| 8 | implementation. |
| 9 | |
| 10 | Optionally provide the following defines with your own implementations: |
| 11 | |
| 12 | SOKOL_ASSERT(c) - your own assert macro (default: assert(c)) |
| 13 | SOKOL_LOG(msg) - your own logging function (default: puts(msg)) |
| 14 | SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false)) |
| 15 | SOKOL_ABORT() - called after an unrecoverable error (default: abort()) |
| 16 | SOKOL_WIN32_FORCE_MAIN - define this on Win32 to use a main() entry point instead of WinMain |
| 17 | SOKOL_API_DECL - public function declaration prefix (default: extern) |
| 18 | SOKOL_API_IMPL - public function implementation prefix (default: -) |
| 19 | |
| 20 | Optionally define the following to force debug checks and validations |
| 21 | even in release mode: |
| 22 | |
| 23 | SOKOL_DEBUG - by default this is defined if _DEBUG is defined |
| 24 | |
| 25 | Portions of the Windows and Linux GL initialization and event code have been |
| 26 | taken from GLFW (http://www.glfw.org/) |
| 27 | |
| 28 | iOS onscreen keyboard support 'inspired' by libgdx. |
| 29 | |
| 30 | If you use sokol_app.h together with sokol_gfx.h, include both headers |
| 31 | in the implementation source file, and include sokol_app.h before |
| 32 | sokol_gfx.h since sokol_app.h will also include the required 3D-API |
| 33 | headers. |
| 34 | |
| 35 | On Windows, a minimal 'GL header' and function loader is integrated which |
| 36 | contains just enough of GL for sokol_gfx.h. If you want to use your own |
| 37 | GL header-generator/loader instead, define SOKOL_WIN32_NO_GL_LOADER |
| 38 | before including the implementation part of sokol_app.h. |
| 39 | |
| 40 | TEMP NOTE DUMP |
| 41 | ============== |
| 42 | - need a way to quit application programmatically (sapp_request_quit()) |
| 43 | - need a way to intercept a pending quit via UI close button (could be |
| 44 | done via frame_cb return value, and a sapp_quit_requested() function) |
| 45 | - onscreen keyboard support on Android requires Java :(, should we even bother? |
| 46 | - sapp_desc needs a bool whether to initialize depth-stencil surface |
| 47 | - GL context initialization needs more control (at least what GL version to initialize) |
| 48 | - application icon |
| 49 | - mouse pointer visibility(?) |
| 50 | - the UPDATE_CURSOR event currently behaves differently between Win32 and OSX |
| 51 | (Win32 sends the event each frame when the mouse moves and is inside the window |
| 52 | client area, OSX sends it only once when the mouse enters the client area) |
| 53 | |
| 54 | FIXME: ERROR HANDLING (this will need an error callback function) |
| 55 | |
| 56 | FEATURE OVERVIEW |
| 57 | ================ |
| 58 | sokol_app.h provides a minimalistic cross-platform API which |
| 59 | implements the 'application-wrapper' parts of a 3D application: |
| 60 | |
| 61 | - a common application entry function |
| 62 | - creates a window and 3D-API context/device with a 'default framebuffer' |
| 63 | - makes the rendered frame visible |
| 64 | - provides keyboard-, mouse- and low-level touch-events |
| 65 | - platforms: MacOS, iOS, HTML5, Win32, Linux (planned: Android, RaspberryPi) |
| 66 | - 3D-APIs: Metal, D3D11, GL3.2, GLES2, GLES3, WebGL, WebGL2 |
| 67 | |
| 68 | FEATURE/PLATFORM MATRIX |
| 69 | ======================= |
| 70 | | Windows | macOS | Linux | iOS | Android | Raspi | HTML5 |
| 71 | --------------------+---------+-------+-------+-------+---------+-------+------- |
| 72 | gl 3.x | YES | --- | YES | --- | --- | --- | --- |
| 73 | gles2/webgl | --- | --- | --- | YES | TODO | TODO | YES |
| 74 | gles3/webgl2 | --- | --- | --- | YES | TODO | --- | YES |
| 75 | metal | --- | YES | --- | YES | --- | --- | --- |
| 76 | d3d11 | YES | --- | --- | --- | --- | --- | --- |
| 77 | KEY_DOWN | YES | YES | YES | SOME | TODO | TODO | YES |
| 78 | KEY_UP | YES | YES | YES | SOME | TODO | TODO | YES |
| 79 | CHAR | YES | YES | YES | YES | TODO | TODO | YES |
| 80 | MOUSE_DOWN | YES | YES | YES | --- | --- | TODO | YES |
| 81 | MOUSE_UP | YES | YES | YES | --- | --- | TODO | YES |
| 82 | MOUSE_SCROLL | YES | YES | YES | --- | --- | TODO | YES |
| 83 | MOUSE_MOVE | YES | YES | YES | --- | --- | TODO | YES |
| 84 | MOUSE_ENTER | YES | YES | YES | --- | --- | TODO | YES |
| 85 | MOUSE_LEAVE | YES | YES | YES | --- | --- | TODO | YES |
| 86 | TOUCHES_BEGAN | --- | --- | --- | YES | TODO | --- | YES |
| 87 | TOUCHES_MOVED | --- | --- | --- | YES | TODO | --- | YES |
| 88 | TOUCHES_ENDED | --- | --- | --- | YES | TODO | --- | YES |
| 89 | TOUCHES_CANCELLED | --- | --- | --- | YES | TODO | --- | YES |
| 90 | RESIZED | YES | YES | YES | YES | TODO | --- | YES |
| 91 | ICONIFIED | YES | YES | YES | --- | --- | --- | --- |
| 92 | RESTORED | YES | YES | YES | --- | --- | --- | --- |
| 93 | SUSPENDED | --- | --- | --- | YES | TODO | --- | TODO |
| 94 | RESUMED | --- | --- | --- | YES | TODO | --- | TODO |
| 95 | UPDATE_CURSOR | YES | YES | TODO | --- | --- | --- | TODO |
| 96 | IME | TODO | TODO? | TODO | ??? | TODO | ??? | ??? |
| 97 | windowed | YES | YES | YES | --- | --- | TODO | YES |
| 98 | fullscreen | YES | YES | TODO | YES | TODO | TODO | --- |
| 99 | pointer lock | TODO | TODO | TODO | --- | --- | TODO | TODO |
| 100 | screen keyboard | --- | --- | --- | YES | TODO | --- | YES |
| 101 | swap interval | YES | YES | YES | YES | TODO | TODO | YES |
| 102 | high-dpi | YES | YES | TODO | YES | TODO | TODO | YES |
| 103 | |
| 104 | - what about bluetooth keyboard / mouse on mobile platforms? |
| 105 | |
| 106 | STEP BY STEP |
| 107 | ============ |
| 108 | --- Add a sokol_main() to your code which returns a sapp_desc structure |
| 109 | with initialization parameters and callback function pointers. This |
| 110 | function is called very early, usually at the start of the |
| 111 | platform's entry function (e.g. main or WinMain). You should do as |
| 112 | little as possible here, since the rest of your code might be called |
| 113 | from another thread (this depends on the platform): |
| 114 | |
| 115 | sapp_desc sokol_main(int argc, char* argv[]) { |
| 116 | return (sapp_desc) { |
| 117 | .width = 640, |
| 118 | .height = 480, |
| 119 | .init_cb = my_init_func, |
| 120 | .frame_cb = my_frame_func, |
| 121 | .cleanup_cb = my_cleanup_func, |
| 122 | .event_cb = my_event_func, |
| 123 | ... |
| 124 | }; |
| 125 | } |
| 126 | |
| 127 | There are many more setup parameters, but these are the most important. |
| 128 | For a complete list search for the sapp_desc structure declaration |
| 129 | below. |
| 130 | |
| 131 | DO NOT call any sokol-app function from inside sokol_main(), since |
| 132 | sokol-app will not be initialized at this point. |
| 133 | |
| 134 | The .width and .height parameters are the preferred size of the 3D |
| 135 | rendering canvas. The actual size may differ from this depending on |
| 136 | platform and other circumstances. Also the canvas size may change at |
| 137 | any time (for instance when the user resizes the application window, |
| 138 | or rotates the mobile device). |
| 139 | |
| 140 | All provided function callbacks will be called from the same thread, |
| 141 | but this may be different from the thread where sokol_main() was called. |
| 142 | |
| 143 | .init_cb (void (init_cb*)(void)) |
| 144 | This function is called once after the application window, |
| 145 | 3D rendering context and swap chain have been created. The |
| 146 | function takes no arguments and has no return value. |
| 147 | .frame_cb (void (frame_cb*)(void)) |
| 148 | This is the per-frame callback, which is usually called 60 |
| 149 | times per second. This is where your application would update |
| 150 | most of its state and perform all rendering. |
| 151 | .cleanup_cb (void (cleanup_cb*)(void)) |
| 152 | The cleanup callback is called once right before the application |
| 153 | quits. |
| 154 | .event_cb (void (event-cb*)(const sapp_event* event)) |
| 155 | The event callback is mainly for input handling, but in the |
| 156 | future may also be used to communicate other types of events |
| 157 | to the application. Keep the event_cb struct member zero-initialized |
| 158 | if your application doesn't require event handling. |
| 159 | |
| 160 | --- Implement the initialization callback function, this is called once |
| 161 | after the rendering surface, 3D API and swap chain have been |
| 162 | initialized by sokol_app. All sokol-app functions can be called |
| 163 | from inside the initialization callback, the most useful functions |
| 164 | at this point are: |
| 165 | |
| 166 | int sapp_width(void) |
| 167 | Returns the current width of the default framebuffer, this may change |
| 168 | from one frame to the next. |
| 169 | int sapp_height(void) |
| 170 | Likewise, returns the current height of the default framebuffer. |
| 171 | |
| 172 | bool sapp_gles2(void) |
| 173 | Returns true if as GLES2 or WebGL2 context had been created (for |
| 174 | instance because GLES3/WebGL2 isn't available on the device) |
| 175 | |
| 176 | const void* sapp_metal_get_device(void) |
| 177 | const void* sapp_metal_get_renderpass_descriptor(void) |
| 178 | const void* sapp_metal_get_drawable(void) |
| 179 | If the Metal backend has been selected, these functions return pointers |
| 180 | to various Metal API objects required for rendering, otherwise |
| 181 | they return a null pointer. Note that the returned pointers |
| 182 | to the renderpass-descriptor and drawable may change from one |
| 183 | frame to the next! |
| 184 | |
| 185 | const void* sapp_macos_get_window(void) |
| 186 | On macOS, get the NSWindow object pointer, otherwise a null pointer. |
| 187 | |
| 188 | const void* sapp_ios_get_window(void) |
| 189 | On iOS, get the UIWindow object pointer, otherwise a null pointer. |
| 190 | |
| 191 | const void* sapp_win32_get_hwnd(void) |
| 192 | On Windows, get the window's HWND, otherwise a null pointer. |
| 193 | |
| 194 | const void* sapp_d3d11_get_device(void); |
| 195 | const void* sapp_d3d11_get_device_context(void); |
| 196 | const void* sapp_d3d11_get_render_target_view(void); |
| 197 | const void* sapp_d3d11_get_depth_stencil_view(void); |
| 198 | Similar to the sapp_metal_* functions, the sapp_d3d11_* functions |
| 199 | return pointers to D3D11 API objects required for rendering, |
| 200 | only if the D3D11 backend has been selected. Otherwise they |
| 201 | return a null pointer. Note that the returned pointers to the |
| 202 | render-target-view and depth-stencil-view may change from one |
| 203 | frame to the next! |
| 204 | |
| 205 | --- Implement the frame-callback function, this function will be called |
| 206 | on the same thread as the init callback, but might be on a different |
| 207 | thread than the sokol_main() function. Note that the size of |
| 208 | the rendering framebuffer might have change since the frame callback |
| 209 | was called last. Call the functions sapp_width() and sapp_height() |
| 210 | to get the current size. |
| 211 | |
| 212 | --- Optionally implement the event-callback to handle input events. |
| 213 | sokol-app provides the following type of input events: |
| 214 | - a 'virtual key' was pressed down or released |
| 215 | - a single text character was entered (provided as UTF-32 code point) |
| 216 | - a mouse button was pressed down or released (left, right, middle) |
| 217 | - mouse-wheel or 2D scrolling events |
| 218 | - the mouse was moved |
| 219 | - the mouse has entered or left the application window boundaries |
| 220 | - low-level, portable multi-touch events (began, moved, ended, cancelled) |
| 221 | More types of events will be added in the future (like window |
| 222 | minimized, maximized, application life cycle events, etc...) |
| 223 | |
| 224 | --- Implement the cleanup-callback function, this is called once |
| 225 | after the user quits the application (currently there's now way |
| 226 | to quite the application programmatically) |
| 227 | |
| 228 | |
| 229 | HIGH-DPI RENDERING |
| 230 | ================== |
| 231 | You can set the sapp_desc.high_dpi flag during initialization to request |
| 232 | a full-resolution framebuffer on HighDPI displays. The default behaviour |
| 233 | is sapp_desc.high_dpi=false, this means that the application will |
| 234 | render to a lower-resolution framebuffer on HighDPI displays and the |
| 235 | rendered content will be upscaled by the window system composer. |
| 236 | |
| 237 | In a HighDPI scenario, you still request the same window size during |
| 238 | sokol_main(), but the framebuffer sizes returned by sapp_width() |
| 239 | and sapp_height() will be scaled up according to the DPI scaling |
| 240 | ratio. You can also get a DPI scaling factor with the function |
| 241 | sapp_dpi_scale(). |
| 242 | |
| 243 | Here's an example on a Mac with Retina display: |
| 244 | |
| 245 | sapp_desc sokol_main() { |
| 246 | return (sapp_desc) { |
| 247 | .width = 640, |
| 248 | .height = 480, |
| 249 | .high_dpi = true, |
| 250 | ... |
| 251 | }; |
| 252 | } |
| 253 | |
| 254 | The functions sapp_width(), sapp_height() and sapp_dpi_scale() will |
| 255 | return the following values: |
| 256 | |
| 257 | sapp_width -> 1280 |
| 258 | sapp_height -> 960 |
| 259 | sapp_dpi_scale -> 2.0 |
| 260 | |
| 261 | If the high_dpi flag is false, or you're not running on a Retina display, |
| 262 | the values would be: |
| 263 | |
| 264 | sapp_width -> 640 |
| 265 | sapp_height -> 480 |
| 266 | sapp_dpi_scale -> 1.0 |
| 267 | |
| 268 | FULLSCREEN |
| 269 | ========== |
| 270 | If the sapp_desc.fullscreen flag is true, sokol-app will try to create |
| 271 | a fullscreen window on platforms with a 'proper' window system |
| 272 | (mobile devices will always use fullscreen). The implementation details |
| 273 | depend on the target platform, in general sokol-app will use a |
| 274 | 'soft approach' which doesn't interfere too much with the platform's |
| 275 | window system (for instance borderless fullscreen window instead of |
| 276 | a 'real' fullscreen mode). Such details might change over time |
| 277 | as sokol-app is adapted for different needs. |
| 278 | |
| 279 | The most important effect of fullscreen mode to keep in mind is that |
| 280 | the requested canvas width and height will be ignored for the initial |
| 281 | window size, calling sapp_width() and sapp_height() will instead return |
| 282 | the resolution of the fullscreen canvas (however the provided size |
| 283 | might still be used for the non-fullscreen window, in case the user can |
| 284 | switch back from fullscreen- to windowed-mode). |
| 285 | |
| 286 | ONSCREEN KEYBOARD |
| 287 | ================= |
| 288 | On some platforms which don't provide a physical keyboard, sokol-app |
| 289 | can display the platform's integrated onscreen keyboard for text |
| 290 | input. To request that the onscreen keyboard is shown, call |
| 291 | |
| 292 | sapp_show_keyboard(true); |
| 293 | |
| 294 | Likewise, to hide the keyboard call: |
| 295 | |
| 296 | sapp_show_keyboard(false); |
| 297 | |
| 298 | Note that on the web platform, the keyboard can only be shown from |
| 299 | inside an input handler. On such platforms, sapp_show_keyboard() |
| 300 | will only work as expected when it is called from inside the |
| 301 | sokol-app event callback function. When called from other places, |
| 302 | an internal flag will be set, and the onscreen keyboard will be |
| 303 | called at the next 'legal' opportunity (when the next input event |
| 304 | is handled). |
| 305 | |
| 306 | zlib/libpng license |
| 307 | |
| 308 | Copyright (c) 2018 Andre Weissflog |
| 309 | |
| 310 | This software is provided 'as-is', without any express or implied warranty. |
| 311 | In no event will the authors be held liable for any damages arising from the |
| 312 | use of this software. |
| 313 | |
| 314 | Permission is granted to anyone to use this software for any purpose, |
| 315 | including commercial applications, and to alter it and redistribute it |
| 316 | freely, subject to the following restrictions: |
| 317 | |
| 318 | 1. The origin of this software must not be misrepresented; you must not |
| 319 | claim that you wrote the original software. If you use this software in a |
| 320 | product, an acknowledgment in the product documentation would be |
| 321 | appreciated but is not required. |
| 322 | |
| 323 | 2. Altered source versions must be plainly marked as such, and must not |
| 324 | be misrepresented as being the original software. |
| 325 | |
| 326 | 3. This notice may not be removed or altered from any source |
| 327 | distribution. |
| 328 | */ |
| 329 | #include <stdint.h> |
| 330 | #include <stdbool.h> |
| 331 | |
| 332 | #ifndef SOKOL_API_DECL |
| 333 | #define SOKOL_API_DECL extern |
| 334 | #endif |
| 335 | |
| 336 | #ifdef __cplusplus |
| 337 | extern "C" { |
| 338 | #endif |
| 339 | |
| 340 | enum { |
| 341 | SAPP_MAX_TOUCHPOINTS = 8, |
| 342 | SAPP_MAX_MOUSEBUTTONS = 3, |
| 343 | SAPP_MAX_KEYCODES = 512, |
| 344 | }; |
| 345 | |
| 346 | typedef enum { |
| 347 | SAPP_EVENTTYPE_INVALID, |
| 348 | SAPP_EVENTTYPE_KEY_DOWN, |
| 349 | SAPP_EVENTTYPE_KEY_UP, |
| 350 | SAPP_EVENTTYPE_CHAR, |
| 351 | SAPP_EVENTTYPE_MOUSE_DOWN, |
| 352 | SAPP_EVENTTYPE_MOUSE_UP, |
| 353 | SAPP_EVENTTYPE_MOUSE_SCROLL, |
| 354 | SAPP_EVENTTYPE_MOUSE_MOVE, |
| 355 | SAPP_EVENTTYPE_MOUSE_ENTER, |
| 356 | SAPP_EVENTTYPE_MOUSE_LEAVE, |
| 357 | SAPP_EVENTTYPE_TOUCHES_BEGAN, |
| 358 | SAPP_EVENTTYPE_TOUCHES_MOVED, |
| 359 | SAPP_EVENTTYPE_TOUCHES_ENDED, |
| 360 | SAPP_EVENTTYPE_TOUCHES_CANCELLED, |
| 361 | SAPP_EVENTTYPE_RESIZED, |
| 362 | SAPP_EVENTTYPE_ICONIFIED, |
| 363 | SAPP_EVENTTYPE_RESTORED, |
| 364 | SAPP_EVENTTYPE_SUSPENDED, |
| 365 | SAPP_EVENTTYPE_RESUMED, |
| 366 | SAPP_EVENTTYPE_UPDATE_CURSOR, |
| 367 | _SAPP_EVENTTYPE_NUM, |
| 368 | _SAPP_EVENTTYPE_FORCE_U32 = 0x7FFFFFF |
| 369 | } sapp_event_type; |
| 370 | |
| 371 | /* key codes are the same names and values as GLFW */ |
| 372 | typedef enum { |
| 373 | SAPP_KEYCODE_INVALID = 0, |
| 374 | SAPP_KEYCODE_SPACE = 32, |
| 375 | SAPP_KEYCODE_APOSTROPHE = 39, /* ' */ |
| 376 | SAPP_KEYCODE_COMMA = 44, /* , */ |
| 377 | SAPP_KEYCODE_MINUS = 45, /* - */ |
| 378 | SAPP_KEYCODE_PERIOD = 46, /* . */ |
| 379 | SAPP_KEYCODE_SLASH = 47, /* / */ |
| 380 | SAPP_KEYCODE_0 = 48, |
| 381 | SAPP_KEYCODE_1 = 49, |
| 382 | SAPP_KEYCODE_2 = 50, |
| 383 | SAPP_KEYCODE_3 = 51, |
| 384 | SAPP_KEYCODE_4 = 52, |
| 385 | SAPP_KEYCODE_5 = 53, |
| 386 | SAPP_KEYCODE_6 = 54, |
| 387 | SAPP_KEYCODE_7 = 55, |
| 388 | SAPP_KEYCODE_8 = 56, |
| 389 | SAPP_KEYCODE_9 = 57, |
| 390 | SAPP_KEYCODE_SEMICOLON = 59, /* ; */ |
| 391 | SAPP_KEYCODE_EQUAL = 61, /* = */ |
| 392 | SAPP_KEYCODE_A = 65, |
| 393 | SAPP_KEYCODE_B = 66, |
| 394 | SAPP_KEYCODE_C = 67, |
| 395 | SAPP_KEYCODE_D = 68, |
| 396 | SAPP_KEYCODE_E = 69, |
| 397 | SAPP_KEYCODE_F = 70, |
| 398 | SAPP_KEYCODE_G = 71, |
| 399 | SAPP_KEYCODE_H = 72, |
| 400 | SAPP_KEYCODE_I = 73, |
| 401 | SAPP_KEYCODE_J = 74, |
| 402 | SAPP_KEYCODE_K = 75, |
| 403 | SAPP_KEYCODE_L = 76, |
| 404 | SAPP_KEYCODE_M = 77, |
| 405 | SAPP_KEYCODE_N = 78, |
| 406 | SAPP_KEYCODE_O = 79, |
| 407 | SAPP_KEYCODE_P = 80, |
| 408 | SAPP_KEYCODE_Q = 81, |
| 409 | SAPP_KEYCODE_R = 82, |
| 410 | SAPP_KEYCODE_S = 83, |
| 411 | SAPP_KEYCODE_T = 84, |
| 412 | SAPP_KEYCODE_U = 85, |
| 413 | SAPP_KEYCODE_V = 86, |
| 414 | SAPP_KEYCODE_W = 87, |
| 415 | SAPP_KEYCODE_X = 88, |
| 416 | SAPP_KEYCODE_Y = 89, |
| 417 | SAPP_KEYCODE_Z = 90, |
| 418 | SAPP_KEYCODE_LEFT_BRACKET = 91, /* [ */ |
| 419 | SAPP_KEYCODE_BACKSLASH = 92, /* \ */ |
| 420 | SAPP_KEYCODE_RIGHT_BRACKET = 93, /* ] */ |
| 421 | SAPP_KEYCODE_GRAVE_ACCENT = 96, /* ` */ |
| 422 | SAPP_KEYCODE_WORLD_1 = 161, /* non-US #1 */ |
| 423 | SAPP_KEYCODE_WORLD_2 = 162, /* non-US #2 */ |
| 424 | SAPP_KEYCODE_ESCAPE = 256, |
| 425 | SAPP_KEYCODE_ENTER = 257, |
| 426 | SAPP_KEYCODE_TAB = 258, |
| 427 | SAPP_KEYCODE_BACKSPACE = 259, |
| 428 | SAPP_KEYCODE_INSERT = 260, |
| 429 | SAPP_KEYCODE_DELETE = 261, |
| 430 | SAPP_KEYCODE_RIGHT = 262, |
| 431 | SAPP_KEYCODE_LEFT = 263, |
| 432 | SAPP_KEYCODE_DOWN = 264, |
| 433 | SAPP_KEYCODE_UP = 265, |
| 434 | SAPP_KEYCODE_PAGE_UP = 266, |
| 435 | SAPP_KEYCODE_PAGE_DOWN = 267, |
| 436 | SAPP_KEYCODE_HOME = 268, |
| 437 | SAPP_KEYCODE_END = 269, |
| 438 | SAPP_KEYCODE_CAPS_LOCK = 280, |
| 439 | SAPP_KEYCODE_SCROLL_LOCK = 281, |
| 440 | SAPP_KEYCODE_NUM_LOCK = 282, |
| 441 | SAPP_KEYCODE_PRINT_SCREEN = 283, |
| 442 | SAPP_KEYCODE_PAUSE = 284, |
| 443 | SAPP_KEYCODE_F1 = 290, |
| 444 | SAPP_KEYCODE_F2 = 291, |
| 445 | SAPP_KEYCODE_F3 = 292, |
| 446 | SAPP_KEYCODE_F4 = 293, |
| 447 | SAPP_KEYCODE_F5 = 294, |
| 448 | SAPP_KEYCODE_F6 = 295, |
| 449 | SAPP_KEYCODE_F7 = 296, |
| 450 | SAPP_KEYCODE_F8 = 297, |
| 451 | SAPP_KEYCODE_F9 = 298, |
| 452 | SAPP_KEYCODE_F10 = 299, |
| 453 | SAPP_KEYCODE_F11 = 300, |
| 454 | SAPP_KEYCODE_F12 = 301, |
| 455 | SAPP_KEYCODE_F13 = 302, |
| 456 | SAPP_KEYCODE_F14 = 303, |
| 457 | SAPP_KEYCODE_F15 = 304, |
| 458 | SAPP_KEYCODE_F16 = 305, |
| 459 | SAPP_KEYCODE_F17 = 306, |
| 460 | SAPP_KEYCODE_F18 = 307, |
| 461 | SAPP_KEYCODE_F19 = 308, |
| 462 | SAPP_KEYCODE_F20 = 309, |
| 463 | SAPP_KEYCODE_F21 = 310, |
| 464 | SAPP_KEYCODE_F22 = 311, |
| 465 | SAPP_KEYCODE_F23 = 312, |
| 466 | SAPP_KEYCODE_F24 = 313, |
| 467 | SAPP_KEYCODE_F25 = 314, |
| 468 | SAPP_KEYCODE_KP_0 = 320, |
| 469 | SAPP_KEYCODE_KP_1 = 321, |
| 470 | SAPP_KEYCODE_KP_2 = 322, |
| 471 | SAPP_KEYCODE_KP_3 = 323, |
| 472 | SAPP_KEYCODE_KP_4 = 324, |
| 473 | SAPP_KEYCODE_KP_5 = 325, |
| 474 | SAPP_KEYCODE_KP_6 = 326, |
| 475 | SAPP_KEYCODE_KP_7 = 327, |
| 476 | SAPP_KEYCODE_KP_8 = 328, |
| 477 | SAPP_KEYCODE_KP_9 = 329, |
| 478 | SAPP_KEYCODE_KP_DECIMAL = 330, |
| 479 | SAPP_KEYCODE_KP_DIVIDE = 331, |
| 480 | SAPP_KEYCODE_KP_MULTIPLY = 332, |
| 481 | SAPP_KEYCODE_KP_SUBTRACT = 333, |
| 482 | SAPP_KEYCODE_KP_ADD = 334, |
| 483 | SAPP_KEYCODE_KP_ENTER = 335, |
| 484 | SAPP_KEYCODE_KP_EQUAL = 336, |
| 485 | SAPP_KEYCODE_LEFT_SHIFT = 340, |
| 486 | SAPP_KEYCODE_LEFT_CONTROL = 341, |
| 487 | SAPP_KEYCODE_LEFT_ALT = 342, |
| 488 | SAPP_KEYCODE_LEFT_SUPER = 343, |
| 489 | SAPP_KEYCODE_RIGHT_SHIFT = 344, |
| 490 | SAPP_KEYCODE_RIGHT_CONTROL = 345, |
| 491 | SAPP_KEYCODE_RIGHT_ALT = 346, |
| 492 | SAPP_KEYCODE_RIGHT_SUPER = 347, |
| 493 | = 348, |
| 494 | } sapp_keycode; |
| 495 | |
| 496 | typedef struct { |
| 497 | uintptr_t identifier; |
| 498 | float pos_x; |
| 499 | float pos_y; |
| 500 | bool changed; |
| 501 | } sapp_touchpoint; |
| 502 | |
| 503 | typedef enum { |
| 504 | SAPP_MOUSEBUTTON_INVALID = -1, |
| 505 | SAPP_MOUSEBUTTON_LEFT = 0, |
| 506 | SAPP_MOUSEBUTTON_RIGHT = 1, |
| 507 | SAPP_MOUSEBUTTON_MIDDLE = 2, |
| 508 | } sapp_mousebutton; |
| 509 | |
| 510 | enum { |
| 511 | SAPP_MODIFIER_SHIFT = (1<<0), |
| 512 | SAPP_MODIFIER_CTRL = (1<<1), |
| 513 | SAPP_MODIFIER_ALT = (1<<2), |
| 514 | SAPP_MODIFIER_SUPER = (1<<3) |
| 515 | }; |
| 516 | |
| 517 | typedef struct { |
| 518 | sapp_event_type type; |
| 519 | uint32_t frame_count; |
| 520 | sapp_keycode key_code; |
| 521 | uint32_t char_code; |
| 522 | uint32_t modifiers; |
| 523 | sapp_mousebutton mouse_button; |
| 524 | float mouse_x; |
| 525 | float mouse_y; |
| 526 | float scroll_x; |
| 527 | float scroll_y; |
| 528 | int num_touches; |
| 529 | sapp_touchpoint touches[SAPP_MAX_TOUCHPOINTS]; |
| 530 | int window_width; |
| 531 | int window_height; |
| 532 | int framebuffer_width; |
| 533 | int framebuffer_height; |
| 534 | } sapp_event; |
| 535 | |
| 536 | typedef struct { |
| 537 | void (*init_cb)(void); |
| 538 | void (*frame_cb)(void); |
| 539 | void (*cleanup_cb)(void); |
| 540 | void (*event_cb)(const sapp_event*); |
| 541 | void (*fail_cb)(const char*); |
| 542 | int width; |
| 543 | int height; |
| 544 | int sample_count; |
| 545 | int swap_interval; |
| 546 | bool high_dpi; |
| 547 | bool fullscreen; |
| 548 | bool alpha; |
| 549 | bool premultiplied_alpha; |
| 550 | bool preserve_drawing_buffer; |
| 551 | const char* window_title; |
| 552 | const char* html5_canvas_name; |
| 553 | bool html5_canvas_resize; |
| 554 | bool ios_keyboard_resizes_canvas; |
| 555 | /* use GLES2 even if GLES3 is available */ |
| 556 | bool gl_force_gles2; |
| 557 | /* if true, user is expected to manage cursor image and visibility on SAPP_EVENTTYPE_UPDATE_CURSOR */ |
| 558 | bool user_cursor; |
| 559 | } sapp_desc; |
| 560 | |
| 561 | /* user-provided functions */ |
| 562 | extern sapp_desc sokol_main(int argc, char* argv[]); |
| 563 | |
| 564 | /* sokol_app API functions */ |
| 565 | SOKOL_API_DECL bool sapp_isvalid(void); |
| 566 | SOKOL_API_DECL int sapp_width(void); |
| 567 | SOKOL_API_DECL int sapp_height(void); |
| 568 | SOKOL_API_DECL bool sapp_high_dpi(void); |
| 569 | SOKOL_API_DECL float sapp_dpi_scale(void); |
| 570 | SOKOL_API_DECL void sapp_show_keyboard(bool visible); |
| 571 | SOKOL_API_DECL bool sapp_keyboard_shown(void); |
| 572 | |
| 573 | /* GL/GLES specific functions */ |
| 574 | SOKOL_API_DECL bool sapp_gles2(void); |
| 575 | |
| 576 | /* OSX/Metal specific functions */ |
| 577 | SOKOL_API_DECL const void* sapp_metal_get_device(void); |
| 578 | SOKOL_API_DECL const void* sapp_metal_get_renderpass_descriptor(void); |
| 579 | SOKOL_API_DECL const void* sapp_metal_get_drawable(void); |
| 580 | SOKOL_API_DECL const void* sapp_macos_get_window(void); |
| 581 | SOKOL_API_DECL const void* sapp_ios_get_window(void); |
| 582 | |
| 583 | /* Win32/D3D11 specific functions */ |
| 584 | SOKOL_API_DECL const void* sapp_d3d11_get_device(void); |
| 585 | SOKOL_API_DECL const void* sapp_d3d11_get_device_context(void); |
| 586 | SOKOL_API_DECL const void* sapp_d3d11_get_render_target_view(void); |
| 587 | SOKOL_API_DECL const void* sapp_d3d11_get_depth_stencil_view(void); |
| 588 | SOKOL_API_DECL const void* sapp_win32_get_hwnd(void); |
| 589 | |
| 590 | #ifdef __cplusplus |
| 591 | } /* extern "C" */ |
| 592 | #endif |
| 593 | |
| 594 | /*-- IMPLEMENTATION ----------------------------------------------------------*/ |
| 595 | #ifdef SOKOL_IMPL |
| 596 | |
| 597 | #ifdef _MSC_VER |
| 598 | #pragma warning(push) |
| 599 | #pragma warning(disable:4201) /* nonstandard extension used: nameless struct/union */ |
| 600 | #pragma warning(disable:4115) /* named type definition in parentheses */ |
| 601 | #pragma warning(disable:4054) /* 'type cast': from function pointer */ |
| 602 | #pragma warning(disable:4055) /* 'type cast': from data pointer */ |
| 603 | #pragma warning(disable:4505) /* unreferenced local function has been removed */ |
| 604 | #endif |
| 605 | |
| 606 | #include <string.h> /* memset */ |
| 607 | |
| 608 | /* check if the config defines are alright */ |
| 609 | #if defined(__APPLE__) |
| 610 | #if !__has_feature(objc_arc) |
| 611 | #error "sokol_app.h requires ARC (Automatic Reference Counting) on MacOS and iOS" |
| 612 | #endif |
| 613 | #include <TargetConditionals.h> |
| 614 | #if TARGET_OS_IPHONE |
| 615 | /* iOS */ |
| 616 | #if !defined(SOKOL_METAL) && !defined(SOKOL_GLES3) |
| 617 | #error("sokol_app.h: unknown 3D API selected for iOS, must be SOKOL_METAL or SOKOL_GLES3") |
| 618 | #endif |
| 619 | #else |
| 620 | /* MacOS */ |
| 621 | #if !defined(SOKOL_METAL) |
| 622 | #error("sokol_app.h: unknown 3D API selected for MacOS, must be SOKOL_METAL") |
| 623 | #endif |
| 624 | #endif |
| 625 | #elif defined(__EMSCRIPTEN__) |
| 626 | /* emscripten (asm.js or wasm) */ |
| 627 | #if !defined(SOKOL_GLES3) && !defined(SOKOL_GLES2) |
| 628 | #error("sokol_app.h: unknown 3D API selected for emscripten, must be SOKOL_GLES3 or SOKOL_GLES2") |
| 629 | #endif |
| 630 | #elif defined(_WIN32) |
| 631 | /* Windows (D3D11 or GL) */ |
| 632 | #if !defined(SOKOL_D3D11) && !defined(SOKOL_GLCORE33) |
| 633 | #error("sokol_app.h: unknown 3D API selected for Win32, must be SOKOL_D3D11 or SOKOL_GLCORE33") |
| 634 | #endif |
| 635 | #elif defined(linux) |
| 636 | #if !defined(SOKOL_GLCORE33) |
| 637 | #error("sokol_app.h: unknown 3D API selected for Linux, must be SOKOL_GLCORE33") |
| 638 | #endif |
| 639 | #else |
| 640 | #error "sokol_app.h: Unknown platform" |
| 641 | #endif |
| 642 | |
| 643 | #ifndef SOKOL_API_IMPL |
| 644 | #define SOKOL_API_IMPL |
| 645 | #endif |
| 646 | #ifndef SOKOL_DEBUG |
| 647 | #ifdef _DEBUG |
| 648 | #define SOKOL_DEBUG (1) |
| 649 | #endif |
| 650 | #endif |
| 651 | #ifndef SOKOL_ASSERT |
| 652 | #include <assert.h> |
| 653 | #define SOKOL_ASSERT(c) assert(c) |
| 654 | #endif |
| 655 | #if !defined(SOKOL_CALLOC) && !defined(SOKOL_FREE) |
| 656 | #include <stdlib.h> |
| 657 | #endif |
| 658 | #if !defined(SOKOL_CALLOC) |
| 659 | #define SOKOL_CALLOC(n,s) calloc(n,s) |
| 660 | #endif |
| 661 | #if !defined(SOKOL_FREE) |
| 662 | #define SOKOL_FREE(p) free(p) |
| 663 | #endif |
| 664 | #ifndef SOKOL_LOG |
| 665 | #ifdef SOKOL_DEBUG |
| 666 | #include <stdio.h> |
| 667 | #define SOKOL_LOG(s) { SOKOL_ASSERT(s); puts(s); } |
| 668 | #else |
| 669 | #define SOKOL_LOG(s) |
| 670 | #endif |
| 671 | #endif |
| 672 | #ifndef SOKOL_ABORT |
| 673 | #include <stdlib.h> |
| 674 | #define SOKOL_ABORT() abort() |
| 675 | #endif |
| 676 | #ifndef _SOKOL_PRIVATE |
| 677 | #if defined(__GNUC__) |
| 678 | #define _SOKOL_PRIVATE __attribute__((unused)) static |
| 679 | #else |
| 680 | #define _SOKOL_PRIVATE static |
| 681 | #endif |
| 682 | #endif |
| 683 | #ifndef _SOKOL_UNUSED |
| 684 | #define _SOKOL_UNUSED(x) (void)(x) |
| 685 | #endif |
| 686 | |
| 687 | /* helper macros */ |
| 688 | #define _sapp_def(val, def) (((val) == 0) ? (def) : (val)) |
| 689 | #define _sapp_absf(a) (((a)<0.0f)?-(a):(a)) |
| 690 | |
| 691 | enum { |
| 692 | _SAPP_MAX_TITLE_LENGTH = 128, |
| 693 | }; |
| 694 | |
| 695 | typedef struct { |
| 696 | bool valid; |
| 697 | int window_width; |
| 698 | int window_height; |
| 699 | int framebuffer_width; |
| 700 | int framebuffer_height; |
| 701 | int sample_count; |
| 702 | int swap_interval; |
| 703 | float dpi_scale; |
| 704 | bool gles2_fallback; |
| 705 | bool first_frame; |
| 706 | bool init_called; |
| 707 | bool html5_canvas_resize; |
| 708 | const char* html5_canvas_name; |
| 709 | char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */ |
| 710 | wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */ |
| 711 | uint32_t frame_count; |
| 712 | float mouse_x; |
| 713 | float mouse_y; |
| 714 | bool win32_mouse_tracked; |
| 715 | bool onscreen_keyboard_shown; |
| 716 | sapp_event event; |
| 717 | sapp_desc desc; |
| 718 | int argc; |
| 719 | char** argv; |
| 720 | sapp_keycode keycodes[SAPP_MAX_KEYCODES]; |
| 721 | } _sapp_state; |
| 722 | static _sapp_state _sapp; |
| 723 | |
| 724 | _SOKOL_PRIVATE void _sapp_fail(const char* msg) { |
| 725 | if (_sapp.desc.fail_cb) { |
| 726 | _sapp.desc.fail_cb(msg); |
| 727 | } |
| 728 | else { |
| 729 | SOKOL_LOG(msg); |
| 730 | } |
| 731 | SOKOL_ABORT(); |
| 732 | } |
| 733 | |
| 734 | _SOKOL_PRIVATE void _sapp_strcpy(const char* src, char* dst, int max_len) { |
| 735 | SOKOL_ASSERT(src && dst && (max_len > 0)); |
| 736 | char* const end = &(dst[max_len-1]); |
| 737 | char c = 0; |
| 738 | for (int i = 0; i < max_len; i++) { |
| 739 | c = *src; |
| 740 | if (c != 0) { |
| 741 | src++; |
| 742 | } |
| 743 | *dst++ = c; |
| 744 | } |
| 745 | /* truncated? */ |
| 746 | if (c != 0) { |
| 747 | *end = 0; |
| 748 | } |
| 749 | } |
| 750 | |
| 751 | _SOKOL_PRIVATE void _sapp_init_state(sapp_desc* desc, int argc, char* argv[]) { |
| 752 | SOKOL_ASSERT(desc->init_cb); |
| 753 | SOKOL_ASSERT(desc->frame_cb); |
| 754 | SOKOL_ASSERT(desc->cleanup_cb); |
| 755 | memset(&_sapp, 0, sizeof(_sapp)); |
| 756 | _sapp.argc = argc; |
| 757 | _sapp.argv = argv; |
| 758 | _sapp.desc = *desc; |
| 759 | _sapp.first_frame = true; |
| 760 | _sapp.window_width = _sapp_def(_sapp.desc.width, 640); |
| 761 | _sapp.window_height = _sapp_def(_sapp.desc.height, 480); |
| 762 | _sapp.framebuffer_width = _sapp.window_width; |
| 763 | _sapp.framebuffer_height = _sapp.window_height; |
| 764 | _sapp.sample_count = _sapp_def(_sapp.desc.sample_count, 1); |
| 765 | _sapp.swap_interval = _sapp_def(_sapp.desc.swap_interval, 1); |
| 766 | _sapp.html5_canvas_name = _sapp_def(_sapp.desc.html5_canvas_name, "#canvas" ); |
| 767 | _sapp.html5_canvas_resize = _sapp.desc.html5_canvas_resize; |
| 768 | if (_sapp.desc.window_title) { |
| 769 | _sapp_strcpy(_sapp.desc.window_title, _sapp.window_title, sizeof(_sapp.window_title)); |
| 770 | } |
| 771 | else { |
| 772 | _sapp_strcpy("sokol_app" , _sapp.window_title, sizeof(_sapp.window_title)); |
| 773 | } |
| 774 | _sapp.dpi_scale = 1.0f; |
| 775 | } |
| 776 | |
| 777 | _SOKOL_PRIVATE void _sapp_init_event(sapp_event_type type) { |
| 778 | memset(&_sapp.event, 0, sizeof(_sapp.event)); |
| 779 | _sapp.event.type = type; |
| 780 | _sapp.event.frame_count = _sapp.frame_count; |
| 781 | _sapp.event.mouse_button = SAPP_MOUSEBUTTON_INVALID; |
| 782 | _sapp.event.window_width = _sapp.window_width; |
| 783 | _sapp.event.window_height = _sapp.window_height; |
| 784 | _sapp.event.framebuffer_width = _sapp.framebuffer_width; |
| 785 | _sapp.event.framebuffer_height = _sapp.framebuffer_height; |
| 786 | } |
| 787 | |
| 788 | _SOKOL_PRIVATE bool _sapp_events_enabled(void) { |
| 789 | /* only send events when an event callback is set, and the init function was called */ |
| 790 | return _sapp.desc.event_cb && _sapp.init_called; |
| 791 | } |
| 792 | |
| 793 | _SOKOL_PRIVATE sapp_keycode _sapp_translate_key(int scan_code) { |
| 794 | if ((scan_code >= 0) && (scan_code < SAPP_MAX_KEYCODES)) { |
| 795 | return _sapp.keycodes[scan_code]; |
| 796 | } |
| 797 | else { |
| 798 | return SAPP_KEYCODE_INVALID; |
| 799 | } |
| 800 | } |
| 801 | |
| 802 | _SOKOL_PRIVATE void _sapp_frame(void) { |
| 803 | if (_sapp.first_frame) { |
| 804 | _sapp.first_frame = false; |
| 805 | _sapp.desc.init_cb(); |
| 806 | _sapp.init_called = true; |
| 807 | } |
| 808 | _sapp.desc.frame_cb(); |
| 809 | _sapp.frame_count++; |
| 810 | } |
| 811 | |
| 812 | /*== MacOS/iOS ===============================================================*/ |
| 813 | |
| 814 | #if defined(__APPLE__) |
| 815 | |
| 816 | /*== MacOS ===================================================================*/ |
| 817 | #if !TARGET_OS_IPHONE |
| 818 | #import <Metal/Metal.h> |
| 819 | #import <MetalKit/MetalKit.h> |
| 820 | |
| 821 | @interface _sapp_macos_app_delegate : NSObject<NSApplicationDelegate> |
| 822 | @end |
| 823 | @interface _sapp_macos_window_delegate : NSObject<NSWindowDelegate> |
| 824 | @end |
| 825 | @interface _sapp_macos_mtk_view_dlg : NSObject<MTKViewDelegate> |
| 826 | @end |
| 827 | @interface _sapp_macos_view : MTKView |
| 828 | { |
| 829 | NSTrackingArea* trackingArea; |
| 830 | } |
| 831 | @end |
| 832 | |
| 833 | static NSWindow* _sapp_macos_window_obj; |
| 834 | static _sapp_macos_window_delegate* _sapp_macos_win_dlg_obj; |
| 835 | static _sapp_macos_app_delegate* _sapp_macos_app_dlg_obj; |
| 836 | static _sapp_macos_view* _sapp_view_obj; |
| 837 | static _sapp_macos_mtk_view_dlg* _sapp_macos_mtk_view_dlg_obj; |
| 838 | static id<MTLDevice> _sapp_mtl_device_obj; |
| 839 | static uint32_t _sapp_macos_flags_changed_store; |
| 840 | |
| 841 | _SOKOL_PRIVATE void _sapp_macos_init_keytable(void) { |
| 842 | _sapp.keycodes[0x1D] = SAPP_KEYCODE_0; |
| 843 | _sapp.keycodes[0x12] = SAPP_KEYCODE_1; |
| 844 | _sapp.keycodes[0x13] = SAPP_KEYCODE_2; |
| 845 | _sapp.keycodes[0x14] = SAPP_KEYCODE_3; |
| 846 | _sapp.keycodes[0x15] = SAPP_KEYCODE_4; |
| 847 | _sapp.keycodes[0x17] = SAPP_KEYCODE_5; |
| 848 | _sapp.keycodes[0x16] = SAPP_KEYCODE_6; |
| 849 | _sapp.keycodes[0x1A] = SAPP_KEYCODE_7; |
| 850 | _sapp.keycodes[0x1C] = SAPP_KEYCODE_8; |
| 851 | _sapp.keycodes[0x19] = SAPP_KEYCODE_9; |
| 852 | _sapp.keycodes[0x00] = SAPP_KEYCODE_A; |
| 853 | _sapp.keycodes[0x0B] = SAPP_KEYCODE_B; |
| 854 | _sapp.keycodes[0x08] = SAPP_KEYCODE_C; |
| 855 | _sapp.keycodes[0x02] = SAPP_KEYCODE_D; |
| 856 | _sapp.keycodes[0x0E] = SAPP_KEYCODE_E; |
| 857 | _sapp.keycodes[0x03] = SAPP_KEYCODE_F; |
| 858 | _sapp.keycodes[0x05] = SAPP_KEYCODE_G; |
| 859 | _sapp.keycodes[0x04] = SAPP_KEYCODE_H; |
| 860 | _sapp.keycodes[0x22] = SAPP_KEYCODE_I; |
| 861 | _sapp.keycodes[0x26] = SAPP_KEYCODE_J; |
| 862 | _sapp.keycodes[0x28] = SAPP_KEYCODE_K; |
| 863 | _sapp.keycodes[0x25] = SAPP_KEYCODE_L; |
| 864 | _sapp.keycodes[0x2E] = SAPP_KEYCODE_M; |
| 865 | _sapp.keycodes[0x2D] = SAPP_KEYCODE_N; |
| 866 | _sapp.keycodes[0x1F] = SAPP_KEYCODE_O; |
| 867 | _sapp.keycodes[0x23] = SAPP_KEYCODE_P; |
| 868 | _sapp.keycodes[0x0C] = SAPP_KEYCODE_Q; |
| 869 | _sapp.keycodes[0x0F] = SAPP_KEYCODE_R; |
| 870 | _sapp.keycodes[0x01] = SAPP_KEYCODE_S; |
| 871 | _sapp.keycodes[0x11] = SAPP_KEYCODE_T; |
| 872 | _sapp.keycodes[0x20] = SAPP_KEYCODE_U; |
| 873 | _sapp.keycodes[0x09] = SAPP_KEYCODE_V; |
| 874 | _sapp.keycodes[0x0D] = SAPP_KEYCODE_W; |
| 875 | _sapp.keycodes[0x07] = SAPP_KEYCODE_X; |
| 876 | _sapp.keycodes[0x10] = SAPP_KEYCODE_Y; |
| 877 | _sapp.keycodes[0x06] = SAPP_KEYCODE_Z; |
| 878 | _sapp.keycodes[0x27] = SAPP_KEYCODE_APOSTROPHE; |
| 879 | _sapp.keycodes[0x2A] = SAPP_KEYCODE_BACKSLASH; |
| 880 | _sapp.keycodes[0x2B] = SAPP_KEYCODE_COMMA; |
| 881 | _sapp.keycodes[0x18] = SAPP_KEYCODE_EQUAL; |
| 882 | _sapp.keycodes[0x32] = SAPP_KEYCODE_GRAVE_ACCENT; |
| 883 | _sapp.keycodes[0x21] = SAPP_KEYCODE_LEFT_BRACKET; |
| 884 | _sapp.keycodes[0x1B] = SAPP_KEYCODE_MINUS; |
| 885 | _sapp.keycodes[0x2F] = SAPP_KEYCODE_PERIOD; |
| 886 | _sapp.keycodes[0x1E] = SAPP_KEYCODE_RIGHT_BRACKET; |
| 887 | _sapp.keycodes[0x29] = SAPP_KEYCODE_SEMICOLON; |
| 888 | _sapp.keycodes[0x2C] = SAPP_KEYCODE_SLASH; |
| 889 | _sapp.keycodes[0x0A] = SAPP_KEYCODE_WORLD_1; |
| 890 | _sapp.keycodes[0x33] = SAPP_KEYCODE_BACKSPACE; |
| 891 | _sapp.keycodes[0x39] = SAPP_KEYCODE_CAPS_LOCK; |
| 892 | _sapp.keycodes[0x75] = SAPP_KEYCODE_DELETE; |
| 893 | _sapp.keycodes[0x7D] = SAPP_KEYCODE_DOWN; |
| 894 | _sapp.keycodes[0x77] = SAPP_KEYCODE_END; |
| 895 | _sapp.keycodes[0x24] = SAPP_KEYCODE_ENTER; |
| 896 | _sapp.keycodes[0x35] = SAPP_KEYCODE_ESCAPE; |
| 897 | _sapp.keycodes[0x7A] = SAPP_KEYCODE_F1; |
| 898 | _sapp.keycodes[0x78] = SAPP_KEYCODE_F2; |
| 899 | _sapp.keycodes[0x63] = SAPP_KEYCODE_F3; |
| 900 | _sapp.keycodes[0x76] = SAPP_KEYCODE_F4; |
| 901 | _sapp.keycodes[0x60] = SAPP_KEYCODE_F5; |
| 902 | _sapp.keycodes[0x61] = SAPP_KEYCODE_F6; |
| 903 | _sapp.keycodes[0x62] = SAPP_KEYCODE_F7; |
| 904 | _sapp.keycodes[0x64] = SAPP_KEYCODE_F8; |
| 905 | _sapp.keycodes[0x65] = SAPP_KEYCODE_F9; |
| 906 | _sapp.keycodes[0x6D] = SAPP_KEYCODE_F10; |
| 907 | _sapp.keycodes[0x67] = SAPP_KEYCODE_F11; |
| 908 | _sapp.keycodes[0x6F] = SAPP_KEYCODE_F12; |
| 909 | _sapp.keycodes[0x69] = SAPP_KEYCODE_F13; |
| 910 | _sapp.keycodes[0x6B] = SAPP_KEYCODE_F14; |
| 911 | _sapp.keycodes[0x71] = SAPP_KEYCODE_F15; |
| 912 | _sapp.keycodes[0x6A] = SAPP_KEYCODE_F16; |
| 913 | _sapp.keycodes[0x40] = SAPP_KEYCODE_F17; |
| 914 | _sapp.keycodes[0x4F] = SAPP_KEYCODE_F18; |
| 915 | _sapp.keycodes[0x50] = SAPP_KEYCODE_F19; |
| 916 | _sapp.keycodes[0x5A] = SAPP_KEYCODE_F20; |
| 917 | _sapp.keycodes[0x73] = SAPP_KEYCODE_HOME; |
| 918 | _sapp.keycodes[0x72] = SAPP_KEYCODE_INSERT; |
| 919 | _sapp.keycodes[0x7B] = SAPP_KEYCODE_LEFT; |
| 920 | _sapp.keycodes[0x3A] = SAPP_KEYCODE_LEFT_ALT; |
| 921 | _sapp.keycodes[0x3B] = SAPP_KEYCODE_LEFT_CONTROL; |
| 922 | _sapp.keycodes[0x38] = SAPP_KEYCODE_LEFT_SHIFT; |
| 923 | _sapp.keycodes[0x37] = SAPP_KEYCODE_LEFT_SUPER; |
| 924 | _sapp.keycodes[0x6E] = SAPP_KEYCODE_MENU; |
| 925 | _sapp.keycodes[0x47] = SAPP_KEYCODE_NUM_LOCK; |
| 926 | _sapp.keycodes[0x79] = SAPP_KEYCODE_PAGE_DOWN; |
| 927 | _sapp.keycodes[0x74] = SAPP_KEYCODE_PAGE_UP; |
| 928 | _sapp.keycodes[0x7C] = SAPP_KEYCODE_RIGHT; |
| 929 | _sapp.keycodes[0x3D] = SAPP_KEYCODE_RIGHT_ALT; |
| 930 | _sapp.keycodes[0x3E] = SAPP_KEYCODE_RIGHT_CONTROL; |
| 931 | _sapp.keycodes[0x3C] = SAPP_KEYCODE_RIGHT_SHIFT; |
| 932 | _sapp.keycodes[0x36] = SAPP_KEYCODE_RIGHT_SUPER; |
| 933 | _sapp.keycodes[0x31] = SAPP_KEYCODE_SPACE; |
| 934 | _sapp.keycodes[0x30] = SAPP_KEYCODE_TAB; |
| 935 | _sapp.keycodes[0x7E] = SAPP_KEYCODE_UP; |
| 936 | _sapp.keycodes[0x52] = SAPP_KEYCODE_KP_0; |
| 937 | _sapp.keycodes[0x53] = SAPP_KEYCODE_KP_1; |
| 938 | _sapp.keycodes[0x54] = SAPP_KEYCODE_KP_2; |
| 939 | _sapp.keycodes[0x55] = SAPP_KEYCODE_KP_3; |
| 940 | _sapp.keycodes[0x56] = SAPP_KEYCODE_KP_4; |
| 941 | _sapp.keycodes[0x57] = SAPP_KEYCODE_KP_5; |
| 942 | _sapp.keycodes[0x58] = SAPP_KEYCODE_KP_6; |
| 943 | _sapp.keycodes[0x59] = SAPP_KEYCODE_KP_7; |
| 944 | _sapp.keycodes[0x5B] = SAPP_KEYCODE_KP_8; |
| 945 | _sapp.keycodes[0x5C] = SAPP_KEYCODE_KP_9; |
| 946 | _sapp.keycodes[0x45] = SAPP_KEYCODE_KP_ADD; |
| 947 | _sapp.keycodes[0x41] = SAPP_KEYCODE_KP_DECIMAL; |
| 948 | _sapp.keycodes[0x4B] = SAPP_KEYCODE_KP_DIVIDE; |
| 949 | _sapp.keycodes[0x4C] = SAPP_KEYCODE_KP_ENTER; |
| 950 | _sapp.keycodes[0x51] = SAPP_KEYCODE_KP_EQUAL; |
| 951 | _sapp.keycodes[0x43] = SAPP_KEYCODE_KP_MULTIPLY; |
| 952 | _sapp.keycodes[0x4E] = SAPP_KEYCODE_KP_SUBTRACT; |
| 953 | } |
| 954 | |
| 955 | /* MacOS entry function */ |
| 956 | int main(int argc, char* argv[]) { |
| 957 | sapp_desc desc = sokol_main(argc, argv); |
| 958 | _sapp_init_state(&desc, argc, argv); |
| 959 | _sapp_macos_init_keytable(); |
| 960 | [NSApplication sharedApplication]; |
| 961 | NSApp.activationPolicy = NSApplicationActivationPolicyRegular; |
| 962 | _sapp_macos_app_dlg_obj = [[_sapp_macos_app_delegate alloc] init]; |
| 963 | NSApp.delegate = _sapp_macos_app_dlg_obj; |
| 964 | [NSApp activateIgnoringOtherApps:YES]; |
| 965 | [NSApp run]; |
| 966 | return 0; |
| 967 | } |
| 968 | |
| 969 | _SOKOL_PRIVATE void _sapp_macos_update_dimensions(void) { |
| 970 | const CGSize fb_size = [_sapp_view_obj drawableSize]; |
| 971 | _sapp.framebuffer_width = fb_size.width; |
| 972 | _sapp.framebuffer_height = fb_size.height; |
| 973 | const NSRect bounds = [_sapp_view_obj bounds]; |
| 974 | _sapp.window_width = bounds.size.width; |
| 975 | _sapp.window_height = bounds.size.height; |
| 976 | SOKOL_ASSERT((_sapp.framebuffer_width > 0) && (_sapp.framebuffer_height > 0)); |
| 977 | _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float)_sapp.window_width; |
| 978 | } |
| 979 | |
| 980 | _SOKOL_PRIVATE void _sapp_macos_frame(void) { |
| 981 | const NSPoint mouse_pos = [_sapp_macos_window_obj mouseLocationOutsideOfEventStream]; |
| 982 | _sapp.mouse_x = mouse_pos.x * _sapp.dpi_scale; |
| 983 | _sapp.mouse_y = _sapp.framebuffer_height - (mouse_pos.y * _sapp.dpi_scale) - 1; |
| 984 | _sapp_frame(); |
| 985 | } |
| 986 | |
| 987 | @implementation _sapp_macos_app_delegate |
| 988 | - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { |
| 989 | if (_sapp.desc.fullscreen) { |
| 990 | NSRect screen_rect = NSScreen.mainScreen.frame; |
| 991 | _sapp.window_width = screen_rect.size.width; |
| 992 | _sapp.window_height = screen_rect.size.height; |
| 993 | if (_sapp.desc.high_dpi) { |
| 994 | _sapp.framebuffer_width = 2 * _sapp.window_width; |
| 995 | _sapp.framebuffer_height = 2 * _sapp.window_height; |
| 996 | } |
| 997 | else { |
| 998 | _sapp.framebuffer_width = _sapp.window_width; |
| 999 | _sapp.framebuffer_height = _sapp.window_height; |
| 1000 | } |
| 1001 | _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float) _sapp.window_width; |
| 1002 | } |
| 1003 | const NSUInteger style = |
| 1004 | NSWindowStyleMaskTitled | |
| 1005 | NSWindowStyleMaskClosable | |
| 1006 | NSWindowStyleMaskMiniaturizable | |
| 1007 | NSWindowStyleMaskResizable; |
| 1008 | _sapp_macos_window_obj = [[NSWindow alloc] |
| 1009 | initWithContentRect:NSMakeRect(0, 0, _sapp.window_width, _sapp.window_height) |
| 1010 | styleMask:style |
| 1011 | backing:NSBackingStoreBuffered |
| 1012 | defer:NO]; |
| 1013 | _sapp_macos_window_obj.title = [NSString stringWithUTF8String:_sapp.window_title]; |
| 1014 | _sapp_macos_window_obj.acceptsMouseMovedEvents = YES; |
| 1015 | _sapp_macos_window_obj.restorable = YES; |
| 1016 | _sapp_macos_win_dlg_obj = [[_sapp_macos_window_delegate alloc] init]; |
| 1017 | _sapp_macos_window_obj.delegate = _sapp_macos_win_dlg_obj; |
| 1018 | _sapp_mtl_device_obj = MTLCreateSystemDefaultDevice(); |
| 1019 | _sapp_macos_mtk_view_dlg_obj = [[_sapp_macos_mtk_view_dlg alloc] init]; |
| 1020 | _sapp_view_obj = [[_sapp_macos_view alloc] init]; |
| 1021 | [_sapp_view_obj updateTrackingAreas]; |
| 1022 | _sapp_view_obj.preferredFramesPerSecond = 60 / _sapp.swap_interval; |
| 1023 | _sapp_view_obj.delegate = _sapp_macos_mtk_view_dlg_obj; |
| 1024 | _sapp_view_obj.device = _sapp_mtl_device_obj; |
| 1025 | _sapp_view_obj.colorPixelFormat = MTLPixelFormatBGRA8Unorm; |
| 1026 | _sapp_view_obj.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; |
| 1027 | _sapp_view_obj.sampleCount = _sapp.sample_count; |
| 1028 | _sapp_macos_window_obj.contentView = _sapp_view_obj; |
| 1029 | [_sapp_macos_window_obj makeFirstResponder:_sapp_view_obj]; |
| 1030 | if (!_sapp.desc.high_dpi) { |
| 1031 | CGSize drawable_size = { (CGFloat) _sapp.framebuffer_width, (CGFloat) _sapp.framebuffer_height }; |
| 1032 | _sapp_view_obj.drawableSize = drawable_size; |
| 1033 | } |
| 1034 | _sapp_macos_update_dimensions(); |
| 1035 | _sapp_view_obj.layer.magnificationFilter = kCAFilterNearest; |
| 1036 | if (_sapp.desc.fullscreen) { |
| 1037 | [_sapp_macos_window_obj toggleFullScreen:self]; |
| 1038 | } |
| 1039 | else { |
| 1040 | [_sapp_macos_window_obj center]; |
| 1041 | } |
| 1042 | [_sapp_macos_window_obj makeKeyAndOrderFront:nil]; |
| 1043 | _sapp.valid = true; |
| 1044 | } |
| 1045 | |
| 1046 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender { |
| 1047 | return YES; |
| 1048 | } |
| 1049 | @end |
| 1050 | |
| 1051 | _SOKOL_PRIVATE uint32_t _sapp_macos_mod(NSEventModifierFlags f) { |
| 1052 | uint32_t m = 0; |
| 1053 | if (f & NSEventModifierFlagShift) { |
| 1054 | m |= SAPP_MODIFIER_SHIFT; |
| 1055 | } |
| 1056 | if (f & NSEventModifierFlagControl) { |
| 1057 | m |= SAPP_MODIFIER_CTRL; |
| 1058 | } |
| 1059 | if (f & NSEventModifierFlagOption) { |
| 1060 | m |= SAPP_MODIFIER_ALT; |
| 1061 | } |
| 1062 | if (f & NSEventModifierFlagCommand) { |
| 1063 | m |= SAPP_MODIFIER_SUPER; |
| 1064 | } |
| 1065 | return m; |
| 1066 | } |
| 1067 | |
| 1068 | _SOKOL_PRIVATE void _sapp_macos_mouse_event(sapp_event_type type, sapp_mousebutton btn, uint32_t mod) { |
| 1069 | if (_sapp_events_enabled()) { |
| 1070 | _sapp_init_event(type); |
| 1071 | _sapp.event.mouse_button = btn; |
| 1072 | _sapp.event.modifiers = mod; |
| 1073 | _sapp.event.mouse_x = _sapp.mouse_x; |
| 1074 | _sapp.event.mouse_y = _sapp.mouse_y; |
| 1075 | _sapp.desc.event_cb(&_sapp.event); |
| 1076 | } |
| 1077 | } |
| 1078 | |
| 1079 | _SOKOL_PRIVATE void _sapp_macos_key_event(sapp_event_type type, sapp_keycode key, uint32_t mod) { |
| 1080 | if (_sapp_events_enabled()) { |
| 1081 | _sapp_init_event(type); |
| 1082 | _sapp.event.key_code = key; |
| 1083 | _sapp.event.modifiers = mod; |
| 1084 | _sapp.desc.event_cb(&_sapp.event); |
| 1085 | } |
| 1086 | } |
| 1087 | |
| 1088 | _SOKOL_PRIVATE void _sapp_macos_app_event(sapp_event_type type) { |
| 1089 | if (_sapp_events_enabled()) { |
| 1090 | _sapp_init_event(type); |
| 1091 | _sapp.desc.event_cb(&_sapp.event); |
| 1092 | } |
| 1093 | } |
| 1094 | |
| 1095 | @implementation _sapp_macos_window_delegate |
| 1096 | - (BOOL)windowShouldClose:(id)sender { |
| 1097 | _sapp.desc.cleanup_cb(); |
| 1098 | return YES; |
| 1099 | } |
| 1100 | |
| 1101 | - (void)windowDidResize:(NSNotification*)notification { |
| 1102 | _sapp_macos_update_dimensions(); |
| 1103 | _sapp_macos_app_event(SAPP_EVENTTYPE_RESIZED); |
| 1104 | } |
| 1105 | |
| 1106 | - (void)windowDidMiniaturize:(NSNotification*)notification { |
| 1107 | _sapp_macos_app_event(SAPP_EVENTTYPE_ICONIFIED); |
| 1108 | } |
| 1109 | |
| 1110 | - (void)windowDidDeminiaturize:(NSNotification*)notification { |
| 1111 | _sapp_macos_app_event(SAPP_EVENTTYPE_RESTORED); |
| 1112 | } |
| 1113 | @end |
| 1114 | |
| 1115 | @implementation _sapp_macos_mtk_view_dlg |
| 1116 | - (void)drawInMTKView:(MTKView*)view { |
| 1117 | @autoreleasepool { |
| 1118 | _sapp_macos_frame(); |
| 1119 | } |
| 1120 | } |
| 1121 | - (void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size { |
| 1122 | /* this is required by the protocol, but we can't do anything useful here */ |
| 1123 | } |
| 1124 | @end |
| 1125 | |
| 1126 | @implementation _sapp_macos_view |
| 1127 | - (BOOL)isOpaque { |
| 1128 | return YES; |
| 1129 | } |
| 1130 | - (BOOL)canBecomeKey { |
| 1131 | return YES; |
| 1132 | } |
| 1133 | - (BOOL)acceptsFirstResponder { |
| 1134 | return YES; |
| 1135 | } |
| 1136 | - (void)updateTrackingAreas { |
| 1137 | if (trackingArea != nil) { |
| 1138 | [self removeTrackingArea:trackingArea]; |
| 1139 | trackingArea = nil; |
| 1140 | } |
| 1141 | const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | |
| 1142 | NSTrackingActiveInKeyWindow | |
| 1143 | NSTrackingEnabledDuringMouseDrag | |
| 1144 | NSTrackingCursorUpdate | |
| 1145 | NSTrackingInVisibleRect | |
| 1146 | NSTrackingAssumeInside; |
| 1147 | trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil]; |
| 1148 | [self addTrackingArea:trackingArea]; |
| 1149 | [super updateTrackingAreas]; |
| 1150 | } |
| 1151 | - (void)mouseEntered:(NSEvent*)event { |
| 1152 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); |
| 1153 | } |
| 1154 | - (void)mouseExited:(NSEvent*)event { |
| 1155 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); |
| 1156 | } |
| 1157 | - (void)mouseDown:(NSEvent*)event { |
| 1158 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_LEFT, _sapp_macos_mod(event.modifierFlags)); |
| 1159 | } |
| 1160 | - (void)mouseUp:(NSEvent*)event { |
| 1161 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_LEFT, _sapp_macos_mod(event.modifierFlags)); |
| 1162 | } |
| 1163 | - (void)rightMouseDown:(NSEvent*)event { |
| 1164 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_RIGHT, _sapp_macos_mod(event.modifierFlags)); |
| 1165 | } |
| 1166 | - (void)rightMouseUp:(NSEvent*)event { |
| 1167 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_RIGHT, _sapp_macos_mod(event.modifierFlags)); |
| 1168 | } |
| 1169 | - (void)mouseMoved:(NSEvent*)event { |
| 1170 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_INVALID , _sapp_macos_mod(event.modifierFlags)); |
| 1171 | } |
| 1172 | - (void)mouseDragged:(NSEvent*)event { |
| 1173 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_INVALID , _sapp_macos_mod(event.modifierFlags)); |
| 1174 | } |
| 1175 | - (void)rightMouseDragged:(NSEvent*)event { |
| 1176 | _sapp_macos_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_INVALID, _sapp_macos_mod(event.modifierFlags)); |
| 1177 | } |
| 1178 | - (void)scrollWheel:(NSEvent*)event { |
| 1179 | if (_sapp_events_enabled()) { |
| 1180 | float dx = (float) event.scrollingDeltaX; |
| 1181 | float dy = (float) event.scrollingDeltaY; |
| 1182 | if (event.hasPreciseScrollingDeltas) { |
| 1183 | dx *= 0.1; |
| 1184 | dy *= 0.1; |
| 1185 | } |
| 1186 | if ((_sapp_absf(dx) > 0.0f) || (_sapp_absf(dy) > 0.0f)) { |
| 1187 | _sapp_init_event(SAPP_EVENTTYPE_MOUSE_SCROLL); |
| 1188 | _sapp.event.modifiers = _sapp_macos_mod(event.modifierFlags); |
| 1189 | _sapp.event.mouse_x = _sapp.mouse_x; |
| 1190 | _sapp.event.mouse_y = _sapp.mouse_y; |
| 1191 | _sapp.event.scroll_x = dx; |
| 1192 | _sapp.event.scroll_y = dy; |
| 1193 | _sapp.desc.event_cb(&_sapp.event); |
| 1194 | } |
| 1195 | } |
| 1196 | } |
| 1197 | - (void)keyDown:(NSEvent*)event { |
| 1198 | if (_sapp_events_enabled()) { |
| 1199 | const uint32_t mods = _sapp_macos_mod(event.modifierFlags); |
| 1200 | _sapp_macos_key_event(SAPP_EVENTTYPE_KEY_DOWN, _sapp_translate_key(event.keyCode), mods); |
| 1201 | const NSString* chars = event.characters; |
| 1202 | const NSUInteger len = chars.length; |
| 1203 | if (len > 0) { |
| 1204 | _sapp_init_event(SAPP_EVENTTYPE_CHAR); |
| 1205 | _sapp.event.modifiers = mods; |
| 1206 | for (NSUInteger i = 0; i < len; i++) { |
| 1207 | const unichar codepoint = [chars characterAtIndex:i]; |
| 1208 | if ((codepoint & 0xFF00) == 0xF700) { |
| 1209 | continue; |
| 1210 | } |
| 1211 | _sapp.event.char_code = codepoint; |
| 1212 | _sapp.desc.event_cb(&_sapp.event); |
| 1213 | } |
| 1214 | } |
| 1215 | } |
| 1216 | } |
| 1217 | - (void)keyUp:(NSEvent*)event { |
| 1218 | _sapp_macos_key_event(SAPP_EVENTTYPE_KEY_UP, |
| 1219 | _sapp_translate_key(event.keyCode), |
| 1220 | _sapp_macos_mod(event.modifierFlags)); |
| 1221 | } |
| 1222 | - (void)flagsChanged:(NSEvent*)event { |
| 1223 | const uint32_t old_f = _sapp_macos_flags_changed_store; |
| 1224 | const uint32_t new_f = event.modifierFlags; |
| 1225 | _sapp_macos_flags_changed_store = new_f; |
| 1226 | sapp_keycode key_code = SAPP_KEYCODE_INVALID; |
| 1227 | bool down = false; |
| 1228 | if ((new_f ^ old_f) & NSEventModifierFlagShift) { |
| 1229 | key_code = SAPP_KEYCODE_LEFT_SHIFT; |
| 1230 | down = 0 != (new_f & NSEventModifierFlagShift); |
| 1231 | } |
| 1232 | if ((new_f ^ old_f) & NSEventModifierFlagControl) { |
| 1233 | key_code = SAPP_KEYCODE_LEFT_CONTROL; |
| 1234 | down = 0 != (new_f & NSEventModifierFlagControl); |
| 1235 | } |
| 1236 | if ((new_f ^ old_f) & NSEventModifierFlagOption) { |
| 1237 | key_code = SAPP_KEYCODE_LEFT_ALT; |
| 1238 | down = 0 != (new_f & NSEventModifierFlagOption); |
| 1239 | } |
| 1240 | if ((new_f ^ old_f) & NSEventModifierFlagCommand) { |
| 1241 | key_code = SAPP_KEYCODE_LEFT_SUPER; |
| 1242 | down = 0 != (new_f & NSEventModifierFlagCommand); |
| 1243 | } |
| 1244 | if (key_code != SAPP_KEYCODE_INVALID) { |
| 1245 | _sapp_macos_key_event(down ? SAPP_EVENTTYPE_KEY_DOWN : SAPP_EVENTTYPE_KEY_UP, |
| 1246 | key_code, |
| 1247 | _sapp_macos_mod(event.modifierFlags)); |
| 1248 | } |
| 1249 | } |
| 1250 | - (void)cursorUpdate:(NSEvent*)event { |
| 1251 | if (_sapp.desc.user_cursor) { |
| 1252 | _sapp_macos_app_event(SAPP_EVENTTYPE_UPDATE_CURSOR); |
| 1253 | } |
| 1254 | } |
| 1255 | @end |
| 1256 | |
| 1257 | #endif /* MacOS */ |
| 1258 | |
| 1259 | /*== iOS =====================================================================*/ |
| 1260 | #if TARGET_OS_IPHONE |
| 1261 | #import <UIKit/UIKit.h> |
| 1262 | #if defined(SOKOL_METAL) |
| 1263 | #import <Metal/Metal.h> |
| 1264 | #import <MetalKit/MetalKit.h> |
| 1265 | #else |
| 1266 | #import <GLKit/GLKit.h> |
| 1267 | #include <OpenGLES/ES3/gl.h> |
| 1268 | #include <OpenGLES/ES3/glext.h> |
| 1269 | #endif |
| 1270 | |
| 1271 | @interface _sapp_app_delegate : NSObject<UIApplicationDelegate> |
| 1272 | @end |
| 1273 | @interface _sapp_textfield_dlg : NSObject<UITextFieldDelegate> |
| 1274 | - (void)keyboardWasShown:(NSNotification*)notif; |
| 1275 | - (void)keyboardWillBeHidden:(NSNotification*)notif; |
| 1276 | - (void)keyboardDidChangeFrame:(NSNotification*)notif; |
| 1277 | @end |
| 1278 | #if defined(SOKOL_METAL) |
| 1279 | @interface _sapp_ios_mtk_view_dlg : NSObject<MTKViewDelegate> |
| 1280 | @end |
| 1281 | @interface _sapp_ios_view : MTKView; |
| 1282 | @end |
| 1283 | #else |
| 1284 | @interface _sapp_ios_glk_view_dlg : NSObject<GLKViewDelegate> |
| 1285 | @end |
| 1286 | @interface _sapp_ios_view : GLKView |
| 1287 | @end |
| 1288 | #endif |
| 1289 | |
| 1290 | static bool _sapp_ios_suspended; |
| 1291 | static UIWindow* _sapp_ios_window_obj; |
| 1292 | static _sapp_ios_view* _sapp_view_obj; |
| 1293 | static UITextField* _sapp_ios_textfield_obj; |
| 1294 | static _sapp_textfield_dlg* _sapp_ios_textfield_dlg_obj; |
| 1295 | #if defined(SOKOL_METAL) |
| 1296 | static _sapp_ios_mtk_view_dlg* _sapp_ios_mtk_view_dlg_obj; |
| 1297 | static UIViewController<MTKViewDelegate>* _sapp_ios_view_ctrl_obj; |
| 1298 | static id<MTLDevice> _sapp_mtl_device_obj; |
| 1299 | #else |
| 1300 | static EAGLContext* _sapp_ios_eagl_ctx_obj; |
| 1301 | static _sapp_ios_glk_view_dlg* _sapp_ios_glk_view_dlg_obj; |
| 1302 | static GLKViewController* _sapp_ios_view_ctrl_obj; |
| 1303 | #endif |
| 1304 | |
| 1305 | /* iOS entry function */ |
| 1306 | int main(int argc, char** argv) { |
| 1307 | @autoreleasepool { |
| 1308 | sapp_desc desc = sokol_main(argc, argv); |
| 1309 | _sapp_init_state(&desc, argc, argv); |
| 1310 | UIApplicationMain(argc, argv, nil, NSStringFromClass([_sapp_app_delegate class])); |
| 1311 | } |
| 1312 | return 0; |
| 1313 | } |
| 1314 | |
| 1315 | _SOKOL_PRIVATE void _sapp_ios_app_event(sapp_event_type type) { |
| 1316 | if (_sapp_events_enabled()) { |
| 1317 | _sapp_init_event(type); |
| 1318 | _sapp.desc.event_cb(&_sapp.event); |
| 1319 | } |
| 1320 | } |
| 1321 | |
| 1322 | _SOKOL_PRIVATE void _sapp_ios_update_dimensions(void) { |
| 1323 | CGRect screen_rect = UIScreen.mainScreen.bounds; |
| 1324 | _sapp.window_width = (int) screen_rect.size.width; |
| 1325 | _sapp.window_height = (int) screen_rect.size.height; |
| 1326 | int cur_fb_width, cur_fb_height; |
| 1327 | #if defined(SOKOL_METAL) |
| 1328 | const CGSize fb_size = _sapp_view_obj.drawableSize; |
| 1329 | cur_fb_width = (int) fb_size.width; |
| 1330 | cur_fb_height = (int) fb_size.height; |
| 1331 | #else |
| 1332 | cur_fb_width = (int) _sapp_view_obj.drawableWidth; |
| 1333 | cur_fb_height = (int) _sapp_view_obj.drawableHeight; |
| 1334 | #endif |
| 1335 | const bool dim_changed = |
| 1336 | (_sapp.framebuffer_width != cur_fb_width) || |
| 1337 | (_sapp.framebuffer_height != cur_fb_height); |
| 1338 | _sapp.framebuffer_width = cur_fb_width; |
| 1339 | _sapp.framebuffer_height = cur_fb_height; |
| 1340 | SOKOL_ASSERT((_sapp.framebuffer_width > 0) && (_sapp.framebuffer_height > 0)); |
| 1341 | _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float) _sapp.window_width; |
| 1342 | if (dim_changed) { |
| 1343 | _sapp_ios_app_event(SAPP_EVENTTYPE_RESIZED); |
| 1344 | } |
| 1345 | } |
| 1346 | |
| 1347 | _SOKOL_PRIVATE void _sapp_ios_frame(void) { |
| 1348 | _sapp_ios_update_dimensions(); |
| 1349 | _sapp_frame(); |
| 1350 | } |
| 1351 | |
| 1352 | _SOKOL_PRIVATE void _sapp_ios_show_keyboard(bool shown) { |
| 1353 | /* if not happened yet, create an invisible text field */ |
| 1354 | if (nil == _sapp_ios_textfield_obj) { |
| 1355 | _sapp_ios_textfield_dlg_obj = [[_sapp_textfield_dlg alloc] init]; |
| 1356 | _sapp_ios_textfield_obj = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 100, 50)]; |
| 1357 | _sapp_ios_textfield_obj.keyboardType = UIKeyboardTypeDefault; |
| 1358 | _sapp_ios_textfield_obj.returnKeyType = UIReturnKeyDefault; |
| 1359 | _sapp_ios_textfield_obj.autocapitalizationType = UITextAutocapitalizationTypeNone; |
| 1360 | _sapp_ios_textfield_obj.autocorrectionType = UITextAutocorrectionTypeNo; |
| 1361 | _sapp_ios_textfield_obj.spellCheckingType = UITextSpellCheckingTypeNo; |
| 1362 | _sapp_ios_textfield_obj.hidden = YES; |
| 1363 | _sapp_ios_textfield_obj.text = @"x" ; |
| 1364 | _sapp_ios_textfield_obj.delegate = _sapp_ios_textfield_dlg_obj; |
| 1365 | [_sapp_ios_view_ctrl_obj.view addSubview:_sapp_ios_textfield_obj]; |
| 1366 | |
| 1367 | [[NSNotificationCenter defaultCenter] addObserver:_sapp_ios_textfield_dlg_obj |
| 1368 | selector:@selector(keyboardWasShown:) |
| 1369 | name:UIKeyboardDidShowNotification object:nil]; |
| 1370 | [[NSNotificationCenter defaultCenter] addObserver:_sapp_ios_textfield_dlg_obj |
| 1371 | selector:@selector(keyboardWillBeHidden:) |
| 1372 | name:UIKeyboardWillHideNotification object:nil]; |
| 1373 | [[NSNotificationCenter defaultCenter] addObserver:_sapp_ios_textfield_dlg_obj |
| 1374 | selector:@selector(keyboardDidChangeFrame:) |
| 1375 | name:UIKeyboardDidChangeFrameNotification object:nil]; |
| 1376 | } |
| 1377 | if (shown) { |
| 1378 | /* setting the text field as first responder brings up the onscreen keyboard */ |
| 1379 | [_sapp_ios_textfield_obj becomeFirstResponder]; |
| 1380 | } |
| 1381 | else { |
| 1382 | [_sapp_ios_textfield_obj resignFirstResponder]; |
| 1383 | } |
| 1384 | } |
| 1385 | |
| 1386 | @implementation _sapp_app_delegate |
| 1387 | - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { |
| 1388 | CGRect screen_rect = UIScreen.mainScreen.bounds; |
| 1389 | _sapp_ios_window_obj = [[UIWindow alloc] initWithFrame:screen_rect]; |
| 1390 | _sapp.window_width = screen_rect.size.width; |
| 1391 | _sapp.window_height = screen_rect.size.height; |
| 1392 | if (_sapp.desc.high_dpi) { |
| 1393 | _sapp.framebuffer_width = 2 * _sapp.window_width; |
| 1394 | _sapp.framebuffer_height = 2 * _sapp.window_height; |
| 1395 | } |
| 1396 | else { |
| 1397 | _sapp.framebuffer_width = _sapp.window_width; |
| 1398 | _sapp.framebuffer_height = _sapp.window_height; |
| 1399 | } |
| 1400 | _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float) _sapp.window_width; |
| 1401 | #if defined(SOKOL_METAL) |
| 1402 | _sapp_mtl_device_obj = MTLCreateSystemDefaultDevice(); |
| 1403 | _sapp_ios_mtk_view_dlg_obj = [[_sapp_ios_mtk_view_dlg alloc] init]; |
| 1404 | _sapp_view_obj = [[_sapp_ios_view alloc] init]; |
| 1405 | _sapp_view_obj.preferredFramesPerSecond = 60 / _sapp.swap_interval; |
| 1406 | _sapp_view_obj.delegate = _sapp_ios_mtk_view_dlg_obj; |
| 1407 | _sapp_view_obj.device = _sapp_mtl_device_obj; |
| 1408 | _sapp_view_obj.colorPixelFormat = MTLPixelFormatBGRA8Unorm; |
| 1409 | _sapp_view_obj.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; |
| 1410 | _sapp_view_obj.sampleCount = _sapp.sample_count; |
| 1411 | if (_sapp.desc.high_dpi) { |
| 1412 | _sapp_view_obj.contentScaleFactor = 2.0; |
| 1413 | } |
| 1414 | else { |
| 1415 | _sapp_view_obj.contentScaleFactor = 1.0; |
| 1416 | } |
| 1417 | _sapp_view_obj.userInteractionEnabled = YES; |
| 1418 | _sapp_view_obj.multipleTouchEnabled = YES; |
| 1419 | [_sapp_ios_window_obj addSubview:_sapp_view_obj]; |
| 1420 | _sapp_ios_view_ctrl_obj = [[UIViewController<MTKViewDelegate> alloc] init]; |
| 1421 | _sapp_ios_view_ctrl_obj.view = _sapp_view_obj; |
| 1422 | _sapp_ios_window_obj.rootViewController = _sapp_ios_view_ctrl_obj; |
| 1423 | #else |
| 1424 | if (_sapp.desc.gl_force_gles2) { |
| 1425 | _sapp_ios_eagl_ctx_obj = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; |
| 1426 | _sapp.gles2_fallback = true; |
| 1427 | } |
| 1428 | else { |
| 1429 | _sapp_ios_eagl_ctx_obj = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; |
| 1430 | if (_sapp_ios_eagl_ctx_obj == nil) { |
| 1431 | _sapp_ios_eagl_ctx_obj = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; |
| 1432 | _sapp.gles2_fallback = true; |
| 1433 | } |
| 1434 | } |
| 1435 | _sapp_ios_glk_view_dlg_obj = [[_sapp_ios_glk_view_dlg alloc] init]; |
| 1436 | _sapp_view_obj = [[_sapp_ios_view alloc] initWithFrame:screen_rect]; |
| 1437 | _sapp_view_obj.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; |
| 1438 | _sapp_view_obj.drawableDepthFormat = GLKViewDrawableDepthFormat24; |
| 1439 | _sapp_view_obj.drawableStencilFormat = GLKViewDrawableStencilFormatNone; |
| 1440 | _sapp_view_obj.drawableMultisample = GLKViewDrawableMultisampleNone; /* FIXME */ |
| 1441 | _sapp_view_obj.context = _sapp_ios_eagl_ctx_obj; |
| 1442 | _sapp_view_obj.delegate = _sapp_ios_glk_view_dlg_obj; |
| 1443 | _sapp_view_obj.enableSetNeedsDisplay = NO; |
| 1444 | _sapp_view_obj.userInteractionEnabled = YES; |
| 1445 | _sapp_view_obj.multipleTouchEnabled = YES; |
| 1446 | if (_sapp.desc.high_dpi) { |
| 1447 | _sapp_view_obj.contentScaleFactor = 2.0; |
| 1448 | } |
| 1449 | else { |
| 1450 | _sapp_view_obj.contentScaleFactor = 1.0; |
| 1451 | } |
| 1452 | [_sapp_ios_window_obj addSubview:_sapp_view_obj]; |
| 1453 | _sapp_ios_view_ctrl_obj = [[GLKViewController alloc] init]; |
| 1454 | _sapp_ios_view_ctrl_obj.view = _sapp_view_obj; |
| 1455 | _sapp_ios_view_ctrl_obj.preferredFramesPerSecond = 60 / _sapp.swap_interval; |
| 1456 | _sapp_ios_window_obj.rootViewController = _sapp_ios_view_ctrl_obj; |
| 1457 | #endif |
| 1458 | [_sapp_ios_window_obj makeKeyAndVisible]; |
| 1459 | |
| 1460 | _sapp.valid = true; |
| 1461 | return YES; |
| 1462 | } |
| 1463 | |
| 1464 | - (void)applicationWillResignActive:(UIApplication *)application { |
| 1465 | if (!_sapp_ios_suspended) { |
| 1466 | _sapp_ios_suspended = true; |
| 1467 | _sapp_ios_app_event(SAPP_EVENTTYPE_SUSPENDED); |
| 1468 | } |
| 1469 | } |
| 1470 | |
| 1471 | - (void)applicationDidBecomeActive:(UIApplication *)application { |
| 1472 | if (_sapp_ios_suspended) { |
| 1473 | _sapp_ios_suspended = false; |
| 1474 | _sapp_ios_app_event(SAPP_EVENTTYPE_RESUMED); |
| 1475 | } |
| 1476 | } |
| 1477 | @end |
| 1478 | |
| 1479 | @implementation _sapp_textfield_dlg |
| 1480 | - (void)keyboardWasShown:(NSNotification*)notif { |
| 1481 | _sapp.onscreen_keyboard_shown = true; |
| 1482 | /* query the keyboard's size, and modify the content view's size */ |
| 1483 | if (_sapp.desc.ios_keyboard_resizes_canvas) { |
| 1484 | NSDictionary* info = notif.userInfo; |
| 1485 | CGFloat kbd_h = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; |
| 1486 | CGRect view_frame = UIScreen.mainScreen.bounds; |
| 1487 | view_frame.size.height -= kbd_h; |
| 1488 | _sapp_view_obj.frame = view_frame; |
| 1489 | } |
| 1490 | } |
| 1491 | - (void)keyboardWillBeHidden:(NSNotification*)notif { |
| 1492 | _sapp.onscreen_keyboard_shown = false; |
| 1493 | if (_sapp.desc.ios_keyboard_resizes_canvas) { |
| 1494 | _sapp_view_obj.frame = UIScreen.mainScreen.bounds; |
| 1495 | } |
| 1496 | } |
| 1497 | - (void)keyboardDidChangeFrame:(NSNotification*)notif { |
| 1498 | /* this is for the case when the screen rotation changes while the keyboard is open */ |
| 1499 | if (_sapp.onscreen_keyboard_shown && _sapp.desc.ios_keyboard_resizes_canvas) { |
| 1500 | NSDictionary* info = notif.userInfo; |
| 1501 | CGFloat kbd_h = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; |
| 1502 | CGRect view_frame = UIScreen.mainScreen.bounds; |
| 1503 | view_frame.size.height -= kbd_h; |
| 1504 | _sapp_view_obj.frame = view_frame; |
| 1505 | } |
| 1506 | } |
| 1507 | - (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string { |
| 1508 | if (_sapp_events_enabled()) { |
| 1509 | const NSUInteger len = string.length; |
| 1510 | if (len > 0) { |
| 1511 | for (NSUInteger i = 0; i < len; i++) { |
| 1512 | unichar c = [string characterAtIndex:i]; |
| 1513 | if (c >= 32) { |
| 1514 | /* ignore surrogates for now */ |
| 1515 | if ((c < 0xD800) || (c > 0xDFFF)) { |
| 1516 | _sapp_init_event(SAPP_EVENTTYPE_CHAR); |
| 1517 | _sapp.event.char_code = c; |
| 1518 | _sapp.desc.event_cb(&_sapp.event); |
| 1519 | } |
| 1520 | } |
| 1521 | if (c <= 32) { |
| 1522 | sapp_keycode k = SAPP_KEYCODE_INVALID; |
| 1523 | switch (c) { |
| 1524 | case 10: k = SAPP_KEYCODE_ENTER; break; |
| 1525 | case 32: k = SAPP_KEYCODE_SPACE; break; |
| 1526 | default: break; |
| 1527 | } |
| 1528 | if (k != SAPP_KEYCODE_INVALID) { |
| 1529 | _sapp_init_event(SAPP_EVENTTYPE_KEY_DOWN); |
| 1530 | _sapp.event.key_code = k; |
| 1531 | _sapp.desc.event_cb(&_sapp.event); |
| 1532 | _sapp_init_event(SAPP_EVENTTYPE_KEY_UP); |
| 1533 | _sapp.event.key_code = k; |
| 1534 | _sapp.desc.event_cb(&_sapp.event); |
| 1535 | } |
| 1536 | } |
| 1537 | } |
| 1538 | } |
| 1539 | else { |
| 1540 | /* this was a backspace */ |
| 1541 | _sapp_init_event(SAPP_EVENTTYPE_KEY_DOWN); |
| 1542 | _sapp.event.key_code = SAPP_KEYCODE_BACKSPACE; |
| 1543 | _sapp.desc.event_cb(&_sapp.event); |
| 1544 | _sapp_init_event(SAPP_EVENTTYPE_KEY_UP); |
| 1545 | _sapp.event.key_code = SAPP_KEYCODE_BACKSPACE; |
| 1546 | _sapp.desc.event_cb(&_sapp.event); |
| 1547 | } |
| 1548 | } |
| 1549 | return NO; |
| 1550 | } |
| 1551 | @end |
| 1552 | |
| 1553 | #if defined(SOKOL_METAL) |
| 1554 | @implementation _sapp_ios_mtk_view_dlg |
| 1555 | - (void)drawInMTKView:(MTKView*)view { |
| 1556 | @autoreleasepool { |
| 1557 | _sapp_ios_frame(); |
| 1558 | } |
| 1559 | } |
| 1560 | |
| 1561 | - (void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size { |
| 1562 | /* this is required by the protocol, but we can't do anything useful here */ |
| 1563 | } |
| 1564 | @end |
| 1565 | #else |
| 1566 | @implementation _sapp_ios_glk_view_dlg |
| 1567 | - (void)glkView:(GLKView*)view drawInRect:(CGRect)rect { |
| 1568 | @autoreleasepool { |
| 1569 | _sapp_ios_frame(); |
| 1570 | } |
| 1571 | } |
| 1572 | @end |
| 1573 | #endif |
| 1574 | |
| 1575 | _SOKOL_PRIVATE void _sapp_ios_touch_event(sapp_event_type type, NSSet<UITouch *>* touches, UIEvent* event) { |
| 1576 | if (_sapp_events_enabled()) { |
| 1577 | _sapp_init_event(type); |
| 1578 | NSEnumerator* enumerator = event.allTouches.objectEnumerator; |
| 1579 | UITouch* ios_touch; |
| 1580 | while ((ios_touch = [enumerator nextObject])) { |
| 1581 | if ((_sapp.event.num_touches + 1) < SAPP_MAX_TOUCHPOINTS) { |
| 1582 | CGPoint ios_pos = [ios_touch locationInView:_sapp_view_obj]; |
| 1583 | sapp_touchpoint* cur_point = &_sapp.event.touches[_sapp.event.num_touches++]; |
| 1584 | cur_point->identifier = (uintptr_t) ios_touch; |
| 1585 | cur_point->pos_x = ios_pos.x * _sapp.dpi_scale; |
| 1586 | cur_point->pos_y = ios_pos.y * _sapp.dpi_scale; |
| 1587 | cur_point->changed = [touches containsObject:ios_touch]; |
| 1588 | } |
| 1589 | } |
| 1590 | if (_sapp.event.num_touches > 0) { |
| 1591 | _sapp.desc.event_cb(&_sapp.event); |
| 1592 | } |
| 1593 | } |
| 1594 | } |
| 1595 | |
| 1596 | @implementation _sapp_ios_view |
| 1597 | - (BOOL) isOpaque { |
| 1598 | return YES; |
| 1599 | } |
| 1600 | - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent*)event { |
| 1601 | _sapp_ios_touch_event(SAPP_EVENTTYPE_TOUCHES_BEGAN, touches, event); |
| 1602 | } |
| 1603 | - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent*)event { |
| 1604 | _sapp_ios_touch_event(SAPP_EVENTTYPE_TOUCHES_MOVED, touches, event); |
| 1605 | } |
| 1606 | - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent*)event { |
| 1607 | _sapp_ios_touch_event(SAPP_EVENTTYPE_TOUCHES_ENDED, touches, event); |
| 1608 | } |
| 1609 | - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent*)event { |
| 1610 | _sapp_ios_touch_event(SAPP_EVENTTYPE_TOUCHES_CANCELLED, touches, event); |
| 1611 | } |
| 1612 | @end |
| 1613 | #endif /* TARGET_OS_IPHONE */ |
| 1614 | |
| 1615 | #endif /* __APPLE__ */ |
| 1616 | |
| 1617 | /*== EMSCRIPTEN ==============================================================*/ |
| 1618 | #if defined(__EMSCRIPTEN__) |
| 1619 | #if defined(SOKOL_GLES3) |
| 1620 | #include <GLES3/gl3.h> |
| 1621 | #else |
| 1622 | #ifndef GL_EXT_PROTOTYPES |
| 1623 | #define GL_GLEXT_PROTOTYPES |
| 1624 | #endif |
| 1625 | #include <GLES2/gl2.h> |
| 1626 | #include <GLES2/gl2ext.h> |
| 1627 | #endif |
| 1628 | #include <emscripten/emscripten.h> |
| 1629 | #include <emscripten/html5.h> |
| 1630 | |
| 1631 | static bool _sapp_emsc_input_created; |
| 1632 | static bool _sapp_emsc_wants_show_keyboard; |
| 1633 | static bool _sapp_emsc_wants_hide_keyboard; |
| 1634 | |
| 1635 | /* this function is called from a JS event handler when the user hides |
| 1636 | the onscreen keyboard pressing the 'dismiss keyboard key' |
| 1637 | */ |
| 1638 | EMSCRIPTEN_KEEPALIVE void _sapp_emsc_notify_keyboard_hidden(void) { |
| 1639 | _sapp.onscreen_keyboard_shown = false; |
| 1640 | } |
| 1641 | |
| 1642 | /* Javascript helper functions for mobile virtual keyboard input */ |
| 1643 | EM_JS(void, _sapp_js_create_textfield, (), { |
| 1644 | var inp = document.createElement("input" ); |
| 1645 | inp.type = "text" ; |
| 1646 | inp.id = "_sokol_app_input_element" ; |
| 1647 | inp.autocapitalize = "none" ; |
| 1648 | inp.addEventListener("focusout" , function(e) { |
| 1649 | __sapp_emsc_notify_keyboard_hidden() |
| 1650 | |
| 1651 | }); |
| 1652 | document.body.append(x); |
| 1653 | }); |
| 1654 | |
| 1655 | EM_JS(void, _sapp_js_focus_textfield, (), { |
| 1656 | document.getElementById("_sokol_app_input_element" ).focus(); |
| 1657 | }); |
| 1658 | |
| 1659 | EM_JS(void, _sapp_js_unfocus_textfield, (), { |
| 1660 | document.getElementById("_sokol_app_input_element" ).blur(); |
| 1661 | }); |
| 1662 | |
| 1663 | /* called from the emscripten event handler to update the keyboard visibility |
| 1664 | state, this must happen from an JS input event handler, otherwise |
| 1665 | the request will be ignored by the browser |
| 1666 | */ |
| 1667 | _SOKOL_PRIVATE void _sapp_emsc_update_keyboard_state(void) { |
| 1668 | if (_sapp_emsc_wants_show_keyboard) { |
| 1669 | /* create input text field on demand */ |
| 1670 | if (!_sapp_emsc_input_created) { |
| 1671 | _sapp_emsc_input_created = true; |
| 1672 | _sapp_js_create_textfield(); |
| 1673 | } |
| 1674 | /* focus the text input field, this will bring up the keyboard */ |
| 1675 | _sapp.onscreen_keyboard_shown = true; |
| 1676 | _sapp_emsc_wants_show_keyboard = false; |
| 1677 | _sapp_js_focus_textfield(); |
| 1678 | } |
| 1679 | if (_sapp_emsc_wants_hide_keyboard) { |
| 1680 | /* unfocus the text input field */ |
| 1681 | if (_sapp_emsc_input_created) { |
| 1682 | _sapp.onscreen_keyboard_shown = false; |
| 1683 | _sapp_emsc_wants_hide_keyboard = false; |
| 1684 | _sapp_js_unfocus_textfield(); |
| 1685 | } |
| 1686 | } |
| 1687 | } |
| 1688 | |
| 1689 | /* actually showing the onscreen keyboard must be initiated from a JS |
| 1690 | input event handler, so we'll just keep track of the desired |
| 1691 | state, and the actual state change will happen with the next input event |
| 1692 | */ |
| 1693 | _SOKOL_PRIVATE void _sapp_emsc_show_keyboard(bool show) { |
| 1694 | if (show) { |
| 1695 | _sapp_emsc_wants_show_keyboard = true; |
| 1696 | } |
| 1697 | else { |
| 1698 | _sapp_emsc_wants_hide_keyboard = true; |
| 1699 | } |
| 1700 | } |
| 1701 | |
| 1702 | _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenUiEvent* ui_event, void* user_data) { |
| 1703 | double w, h; |
| 1704 | emscripten_get_element_css_size(_sapp.html5_canvas_name, &w, &h); |
| 1705 | /* The above method might report zero when toggling HTML5 fullscreen, |
| 1706 | in that case use the window's inner width reported by the |
| 1707 | emscripten event. This works ok when toggling *into* fullscreen |
| 1708 | but doesn't properly restore the previous canvas size when switching |
| 1709 | back from fullscreen. |
| 1710 | |
| 1711 | In general, due to the HTML5's fullscreen API's flaky nature it is |
| 1712 | recommended to use 'soft fullscreen' (stretching the WebGL canvas |
| 1713 | over the browser window's client rect) with a CSS definition like this: |
| 1714 | |
| 1715 | position: absolute; |
| 1716 | top: 0px; |
| 1717 | left: 0px; |
| 1718 | margin: 0px; |
| 1719 | border: 0; |
| 1720 | width: 100%; |
| 1721 | height: 100%; |
| 1722 | overflow: hidden; |
| 1723 | display: block; |
| 1724 | */ |
| 1725 | if (w < 1.0) { |
| 1726 | w = ui_event->windowInnerWidth; |
| 1727 | } |
| 1728 | else { |
| 1729 | _sapp.window_width = (int) w; |
| 1730 | } |
| 1731 | if (h < 1.0) { |
| 1732 | h = ui_event->windowInnerHeight; |
| 1733 | } |
| 1734 | else { |
| 1735 | _sapp.window_height = (int) h; |
| 1736 | } |
| 1737 | if (_sapp.desc.high_dpi) { |
| 1738 | _sapp.dpi_scale = emscripten_get_device_pixel_ratio(); |
| 1739 | w *= _sapp.dpi_scale; |
| 1740 | h *= _sapp.dpi_scale; |
| 1741 | } |
| 1742 | _sapp.framebuffer_width = (int) w; |
| 1743 | _sapp.framebuffer_height = (int) h; |
| 1744 | SOKOL_ASSERT((_sapp.framebuffer_width > 0) && (_sapp.framebuffer_height > 0)); |
| 1745 | emscripten_set_canvas_element_size(_sapp.html5_canvas_name, w, h); |
| 1746 | if (_sapp_events_enabled()) { |
| 1747 | _sapp_init_event(SAPP_EVENTTYPE_RESIZED); |
| 1748 | _sapp.desc.event_cb(&_sapp.event); |
| 1749 | } |
| 1750 | return true; |
| 1751 | } |
| 1752 | |
| 1753 | _SOKOL_PRIVATE void _sapp_emsc_frame(void) { |
| 1754 | if (_sapp.first_frame) { |
| 1755 | emscripten_set_main_loop_timing(EM_TIMING_RAF, _sapp.swap_interval); |
| 1756 | } |
| 1757 | _sapp_frame(); |
| 1758 | } |
| 1759 | |
| 1760 | _SOKOL_PRIVATE EM_BOOL _sapp_emsc_context_cb(int emsc_type, const void* reserved, void* user_data) { |
| 1761 | sapp_event_type type; |
| 1762 | switch (emsc_type) { |
| 1763 | case EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST: type = SAPP_EVENTTYPE_SUSPENDED; break; |
| 1764 | case EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED: type = SAPP_EVENTTYPE_RESUMED; break; |
| 1765 | default: type = SAPP_EVENTTYPE_INVALID; break; |
| 1766 | } |
| 1767 | if (_sapp_events_enabled() && (SAPP_EVENTTYPE_INVALID != type)) { |
| 1768 | _sapp_init_event(type); |
| 1769 | _sapp.desc.event_cb(&_sapp.event); |
| 1770 | } |
| 1771 | return true; |
| 1772 | } |
| 1773 | |
| 1774 | _SOKOL_PRIVATE EM_BOOL _sapp_emsc_mouse_cb(int emsc_type, const EmscriptenMouseEvent* emsc_event, void* user_data) { |
| 1775 | _sapp.mouse_x = (emsc_event->canvasX * _sapp.dpi_scale); |
| 1776 | _sapp.mouse_y = (emsc_event->canvasY * _sapp.dpi_scale); |
| 1777 | if (_sapp_events_enabled() && (emsc_event->button >= 0) && (emsc_event->button < SAPP_MAX_MOUSEBUTTONS)) { |
| 1778 | sapp_event_type type; |
| 1779 | bool is_button_event = false; |
| 1780 | switch (emsc_type) { |
| 1781 | case EMSCRIPTEN_EVENT_MOUSEDOWN: |
| 1782 | type = SAPP_EVENTTYPE_MOUSE_DOWN; |
| 1783 | is_button_event = true; |
| 1784 | break; |
| 1785 | case EMSCRIPTEN_EVENT_MOUSEUP: |
| 1786 | type = SAPP_EVENTTYPE_MOUSE_UP; |
| 1787 | is_button_event = true; |
| 1788 | break; |
| 1789 | case EMSCRIPTEN_EVENT_MOUSEMOVE: |
| 1790 | type = SAPP_EVENTTYPE_MOUSE_MOVE; |
| 1791 | break; |
| 1792 | case EMSCRIPTEN_EVENT_MOUSEENTER: |
| 1793 | type = SAPP_EVENTTYPE_MOUSE_ENTER; |
| 1794 | break; |
| 1795 | case EMSCRIPTEN_EVENT_MOUSELEAVE: |
| 1796 | type = SAPP_EVENTTYPE_MOUSE_LEAVE; |
| 1797 | break; |
| 1798 | default: |
| 1799 | type = SAPP_EVENTTYPE_INVALID; |
| 1800 | break; |
| 1801 | } |
| 1802 | if (type != SAPP_EVENTTYPE_INVALID) { |
| 1803 | _sapp_init_event(type); |
| 1804 | if (emsc_event->ctrlKey) { |
| 1805 | _sapp.event.modifiers |= SAPP_MODIFIER_CTRL; |
| 1806 | } |
| 1807 | if (emsc_event->shiftKey) { |
| 1808 | _sapp.event.modifiers |= SAPP_MODIFIER_SHIFT; |
| 1809 | } |
| 1810 | if (emsc_event->altKey) { |
| 1811 | _sapp.event.modifiers |= SAPP_MODIFIER_ALT; |
| 1812 | } |
| 1813 | if (emsc_event->metaKey) { |
| 1814 | _sapp.event.modifiers |= SAPP_MODIFIER_SUPER; |
| 1815 | } |
| 1816 | if (is_button_event) { |
| 1817 | switch (emsc_event->button) { |
| 1818 | case 0: _sapp.event.mouse_button = SAPP_MOUSEBUTTON_LEFT; break; |
| 1819 | case 1: _sapp.event.mouse_button = SAPP_MOUSEBUTTON_MIDDLE; break; |
| 1820 | case 2: _sapp.event.mouse_button = SAPP_MOUSEBUTTON_RIGHT; break; |
| 1821 | default: _sapp.event.mouse_button = emsc_event->button; break; |
| 1822 | } |
| 1823 | } |
| 1824 | else { |
| 1825 | _sapp.event.mouse_button = SAPP_MOUSEBUTTON_INVALID; |
| 1826 | } |
| 1827 | _sapp.event.mouse_x = _sapp.mouse_x; |
| 1828 | _sapp.event.mouse_y = _sapp.mouse_y; |
| 1829 | _sapp.desc.event_cb(&_sapp.event); |
| 1830 | } |
| 1831 | } |
| 1832 | _sapp_emsc_update_keyboard_state(); |
| 1833 | return true; |
| 1834 | } |
| 1835 | |
| 1836 | _SOKOL_PRIVATE EM_BOOL _sapp_emsc_wheel_cb(int emsc_type, const EmscriptenWheelEvent* emsc_event, void* user_data) { |
| 1837 | if (_sapp_events_enabled()) { |
| 1838 | _sapp_init_event(SAPP_EVENTTYPE_MOUSE_SCROLL); |
| 1839 | if (emsc_event->mouse.ctrlKey) { |
| 1840 | _sapp.event.modifiers |= SAPP_MODIFIER_CTRL; |
| 1841 | } |
| 1842 | if (emsc_event->mouse.shiftKey) { |
| 1843 | _sapp.event.modifiers |= SAPP_MODIFIER_SHIFT; |
| 1844 | } |
| 1845 | if (emsc_event->mouse.altKey) { |
| 1846 | _sapp.event.modifiers |= SAPP_MODIFIER_ALT; |
| 1847 | } |
| 1848 | if (emsc_event->mouse.metaKey) { |
| 1849 | _sapp.event.modifiers |= SAPP_MODIFIER_SUPER; |
| 1850 | } |
| 1851 | _sapp.event.scroll_x = -0.1 * (float)emsc_event->deltaX; |
| 1852 | _sapp.event.scroll_y = -0.1 * (float)emsc_event->deltaY; |
| 1853 | _sapp.desc.event_cb(&_sapp.event); |
| 1854 | } |
| 1855 | _sapp_emsc_update_keyboard_state(); |
| 1856 | return true; |
| 1857 | } |
| 1858 | |
| 1859 | _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboardEvent* emsc_event, void* user_data) { |
| 1860 | bool retval = true; |
| 1861 | if (_sapp_events_enabled()) { |
| 1862 | sapp_event_type type; |
| 1863 | switch (emsc_type) { |
| 1864 | case EMSCRIPTEN_EVENT_KEYDOWN: |
| 1865 | type = SAPP_EVENTTYPE_KEY_DOWN; |
| 1866 | break; |
| 1867 | case EMSCRIPTEN_EVENT_KEYUP: |
| 1868 | type = SAPP_EVENTTYPE_KEY_UP; |
| 1869 | break; |
| 1870 | case EMSCRIPTEN_EVENT_KEYPRESS: |
| 1871 | type = SAPP_EVENTTYPE_CHAR; |
| 1872 | break; |
| 1873 | default: |
| 1874 | type = SAPP_EVENTTYPE_INVALID; |
| 1875 | break; |
| 1876 | } |
| 1877 | if (type != SAPP_EVENTTYPE_INVALID) { |
| 1878 | _sapp_init_event(type); |
| 1879 | if (emsc_event->ctrlKey) { |
| 1880 | _sapp.event.modifiers |= SAPP_MODIFIER_CTRL; |
| 1881 | } |
| 1882 | if (emsc_event->shiftKey) { |
| 1883 | _sapp.event.modifiers |= SAPP_MODIFIER_SHIFT; |
| 1884 | } |
| 1885 | if (emsc_event->altKey) { |
| 1886 | _sapp.event.modifiers |= SAPP_MODIFIER_ALT; |
| 1887 | } |
| 1888 | if (emsc_event->metaKey) { |
| 1889 | _sapp.event.modifiers |= SAPP_MODIFIER_SUPER; |
| 1890 | } |
| 1891 | if (type == SAPP_EVENTTYPE_CHAR) { |
| 1892 | _sapp.event.char_code = emsc_event->charCode; |
| 1893 | } |
| 1894 | else { |
| 1895 | _sapp.event.key_code = _sapp_translate_key(emsc_event->keyCode); |
| 1896 | /* only forward a certain key ranges to the browser */ |
| 1897 | switch (_sapp.event.key_code) { |
| 1898 | case SAPP_KEYCODE_WORLD_1: |
| 1899 | case SAPP_KEYCODE_WORLD_2: |
| 1900 | case SAPP_KEYCODE_ESCAPE: |
| 1901 | case SAPP_KEYCODE_ENTER: |
| 1902 | case SAPP_KEYCODE_TAB: |
| 1903 | case SAPP_KEYCODE_BACKSPACE: |
| 1904 | case SAPP_KEYCODE_INSERT: |
| 1905 | case SAPP_KEYCODE_DELETE: |
| 1906 | case SAPP_KEYCODE_RIGHT: |
| 1907 | case SAPP_KEYCODE_LEFT: |
| 1908 | case SAPP_KEYCODE_DOWN: |
| 1909 | case SAPP_KEYCODE_UP: |
| 1910 | case SAPP_KEYCODE_PAGE_UP: |
| 1911 | case SAPP_KEYCODE_PAGE_DOWN: |
| 1912 | case SAPP_KEYCODE_HOME: |
| 1913 | case SAPP_KEYCODE_END: |
| 1914 | case SAPP_KEYCODE_CAPS_LOCK: |
| 1915 | case SAPP_KEYCODE_SCROLL_LOCK: |
| 1916 | case SAPP_KEYCODE_NUM_LOCK: |
| 1917 | case SAPP_KEYCODE_PRINT_SCREEN: |
| 1918 | case SAPP_KEYCODE_PAUSE: |
| 1919 | case SAPP_KEYCODE_F1: |
| 1920 | case SAPP_KEYCODE_F2: |
| 1921 | case SAPP_KEYCODE_F3: |
| 1922 | case SAPP_KEYCODE_F4: |
| 1923 | case SAPP_KEYCODE_F5: |
| 1924 | case SAPP_KEYCODE_F6: |
| 1925 | case SAPP_KEYCODE_F7: |
| 1926 | case SAPP_KEYCODE_F8: |
| 1927 | case SAPP_KEYCODE_F9: |
| 1928 | case SAPP_KEYCODE_F10: |
| 1929 | case SAPP_KEYCODE_F11: |
| 1930 | case SAPP_KEYCODE_F12: |
| 1931 | case SAPP_KEYCODE_F13: |
| 1932 | case SAPP_KEYCODE_F14: |
| 1933 | case SAPP_KEYCODE_F15: |
| 1934 | case SAPP_KEYCODE_F16: |
| 1935 | case SAPP_KEYCODE_F17: |
| 1936 | case SAPP_KEYCODE_F18: |
| 1937 | case SAPP_KEYCODE_F19: |
| 1938 | case SAPP_KEYCODE_F20: |
| 1939 | case SAPP_KEYCODE_F21: |
| 1940 | case SAPP_KEYCODE_F22: |
| 1941 | case SAPP_KEYCODE_F23: |
| 1942 | case SAPP_KEYCODE_F24: |
| 1943 | case SAPP_KEYCODE_F25: |
| 1944 | case SAPP_KEYCODE_LEFT_SHIFT: |
| 1945 | case SAPP_KEYCODE_LEFT_CONTROL: |
| 1946 | case SAPP_KEYCODE_LEFT_ALT: |
| 1947 | case SAPP_KEYCODE_LEFT_SUPER: |
| 1948 | case SAPP_KEYCODE_RIGHT_SHIFT: |
| 1949 | case SAPP_KEYCODE_RIGHT_CONTROL: |
| 1950 | case SAPP_KEYCODE_RIGHT_ALT: |
| 1951 | case SAPP_KEYCODE_RIGHT_SUPER: |
| 1952 | case SAPP_KEYCODE_MENU: |
| 1953 | /* consume the event */ |
| 1954 | break; |
| 1955 | default: |
| 1956 | /* forward key to browser */ |
| 1957 | retval = false; |
| 1958 | break; |
| 1959 | } |
| 1960 | } |
| 1961 | _sapp.desc.event_cb(&_sapp.event); |
| 1962 | } |
| 1963 | } |
| 1964 | _sapp_emsc_update_keyboard_state(); |
| 1965 | return retval; |
| 1966 | } |
| 1967 | |
| 1968 | _SOKOL_PRIVATE EM_BOOL _sapp_emsc_touch_cb(int emsc_type, const EmscriptenTouchEvent* emsc_event, void* user_data) { |
| 1969 | bool retval = true; |
| 1970 | if (_sapp_events_enabled()) { |
| 1971 | sapp_event_type type; |
| 1972 | switch (emsc_type) { |
| 1973 | case EMSCRIPTEN_EVENT_TOUCHSTART: |
| 1974 | type = SAPP_EVENTTYPE_TOUCHES_BEGAN; |
| 1975 | break; |
| 1976 | case EMSCRIPTEN_EVENT_TOUCHMOVE: |
| 1977 | type = SAPP_EVENTTYPE_TOUCHES_MOVED; |
| 1978 | break; |
| 1979 | case EMSCRIPTEN_EVENT_TOUCHEND: |
| 1980 | type = SAPP_EVENTTYPE_TOUCHES_ENDED; |
| 1981 | break; |
| 1982 | case EMSCRIPTEN_EVENT_TOUCHCANCEL: |
| 1983 | type = SAPP_EVENTTYPE_TOUCHES_CANCELLED; |
| 1984 | break; |
| 1985 | default: |
| 1986 | type = SAPP_EVENTTYPE_INVALID; |
| 1987 | retval = false; |
| 1988 | break; |
| 1989 | } |
| 1990 | if (type != SAPP_EVENTTYPE_INVALID) { |
| 1991 | _sapp_init_event(type); |
| 1992 | if (emsc_event->ctrlKey) { |
| 1993 | _sapp.event.modifiers |= SAPP_MODIFIER_CTRL; |
| 1994 | } |
| 1995 | if (emsc_event->shiftKey) { |
| 1996 | _sapp.event.modifiers |= SAPP_MODIFIER_SHIFT; |
| 1997 | } |
| 1998 | if (emsc_event->altKey) { |
| 1999 | _sapp.event.modifiers |= SAPP_MODIFIER_ALT; |
| 2000 | } |
| 2001 | if (emsc_event->metaKey) { |
| 2002 | _sapp.event.modifiers |= SAPP_MODIFIER_SUPER; |
| 2003 | } |
| 2004 | _sapp.event.num_touches = emsc_event->numTouches; |
| 2005 | if (_sapp.event.num_touches > SAPP_MAX_TOUCHPOINTS) { |
| 2006 | _sapp.event.num_touches = SAPP_MAX_TOUCHPOINTS; |
| 2007 | } |
| 2008 | for (int i = 0; i < _sapp.event.num_touches; i++) { |
| 2009 | const EmscriptenTouchPoint* src = &emsc_event->touches[i]; |
| 2010 | sapp_touchpoint* dst = &_sapp.event.touches[i]; |
| 2011 | dst->identifier = src->identifier; |
| 2012 | dst->pos_x = src->canvasX * _sapp.dpi_scale; |
| 2013 | dst->pos_y = src->canvasY * _sapp.dpi_scale; |
| 2014 | dst->changed = src->isChanged; |
| 2015 | } |
| 2016 | _sapp.desc.event_cb(&_sapp.event); |
| 2017 | } |
| 2018 | } |
| 2019 | _sapp_emsc_update_keyboard_state(); |
| 2020 | return retval; |
| 2021 | } |
| 2022 | |
| 2023 | _SOKOL_PRIVATE void _sapp_emsc_init_keytable(void) { |
| 2024 | _sapp.keycodes[8] = SAPP_KEYCODE_BACKSPACE; |
| 2025 | _sapp.keycodes[9] = SAPP_KEYCODE_TAB; |
| 2026 | _sapp.keycodes[13] = SAPP_KEYCODE_ENTER; |
| 2027 | _sapp.keycodes[16] = SAPP_KEYCODE_LEFT_SHIFT; |
| 2028 | _sapp.keycodes[17] = SAPP_KEYCODE_LEFT_CONTROL; |
| 2029 | _sapp.keycodes[18] = SAPP_KEYCODE_LEFT_ALT; |
| 2030 | _sapp.keycodes[19] = SAPP_KEYCODE_PAUSE; |
| 2031 | _sapp.keycodes[27] = SAPP_KEYCODE_ESCAPE; |
| 2032 | _sapp.keycodes[32] = SAPP_KEYCODE_SPACE; |
| 2033 | _sapp.keycodes[33] = SAPP_KEYCODE_PAGE_UP; |
| 2034 | _sapp.keycodes[34] = SAPP_KEYCODE_PAGE_DOWN; |
| 2035 | _sapp.keycodes[35] = SAPP_KEYCODE_END; |
| 2036 | _sapp.keycodes[36] = SAPP_KEYCODE_HOME; |
| 2037 | _sapp.keycodes[37] = SAPP_KEYCODE_LEFT; |
| 2038 | _sapp.keycodes[38] = SAPP_KEYCODE_UP; |
| 2039 | _sapp.keycodes[39] = SAPP_KEYCODE_RIGHT; |
| 2040 | _sapp.keycodes[40] = SAPP_KEYCODE_DOWN; |
| 2041 | _sapp.keycodes[45] = SAPP_KEYCODE_INSERT; |
| 2042 | _sapp.keycodes[46] = SAPP_KEYCODE_DELETE; |
| 2043 | _sapp.keycodes[48] = SAPP_KEYCODE_0; |
| 2044 | _sapp.keycodes[49] = SAPP_KEYCODE_1; |
| 2045 | _sapp.keycodes[50] = SAPP_KEYCODE_2; |
| 2046 | _sapp.keycodes[51] = SAPP_KEYCODE_3; |
| 2047 | _sapp.keycodes[52] = SAPP_KEYCODE_4; |
| 2048 | _sapp.keycodes[53] = SAPP_KEYCODE_5; |
| 2049 | _sapp.keycodes[54] = SAPP_KEYCODE_6; |
| 2050 | _sapp.keycodes[55] = SAPP_KEYCODE_7; |
| 2051 | _sapp.keycodes[56] = SAPP_KEYCODE_8; |
| 2052 | _sapp.keycodes[57] = SAPP_KEYCODE_9; |
| 2053 | _sapp.keycodes[59] = SAPP_KEYCODE_SEMICOLON; |
| 2054 | _sapp.keycodes[64] = SAPP_KEYCODE_EQUAL; |
| 2055 | _sapp.keycodes[65] = SAPP_KEYCODE_A; |
| 2056 | _sapp.keycodes[66] = SAPP_KEYCODE_B; |
| 2057 | _sapp.keycodes[67] = SAPP_KEYCODE_C; |
| 2058 | _sapp.keycodes[68] = SAPP_KEYCODE_D; |
| 2059 | _sapp.keycodes[69] = SAPP_KEYCODE_E; |
| 2060 | _sapp.keycodes[70] = SAPP_KEYCODE_F; |
| 2061 | _sapp.keycodes[71] = SAPP_KEYCODE_G; |
| 2062 | _sapp.keycodes[72] = SAPP_KEYCODE_H; |
| 2063 | _sapp.keycodes[73] = SAPP_KEYCODE_I; |
| 2064 | _sapp.keycodes[74] = SAPP_KEYCODE_J; |
| 2065 | _sapp.keycodes[75] = SAPP_KEYCODE_K; |
| 2066 | _sapp.keycodes[76] = SAPP_KEYCODE_L; |
| 2067 | _sapp.keycodes[77] = SAPP_KEYCODE_M; |
| 2068 | _sapp.keycodes[78] = SAPP_KEYCODE_N; |
| 2069 | _sapp.keycodes[79] = SAPP_KEYCODE_O; |
| 2070 | _sapp.keycodes[80] = SAPP_KEYCODE_P; |
| 2071 | _sapp.keycodes[81] = SAPP_KEYCODE_Q; |
| 2072 | _sapp.keycodes[82] = SAPP_KEYCODE_R; |
| 2073 | _sapp.keycodes[83] = SAPP_KEYCODE_S; |
| 2074 | _sapp.keycodes[84] = SAPP_KEYCODE_T; |
| 2075 | _sapp.keycodes[85] = SAPP_KEYCODE_U; |
| 2076 | _sapp.keycodes[86] = SAPP_KEYCODE_V; |
| 2077 | _sapp.keycodes[87] = SAPP_KEYCODE_W; |
| 2078 | _sapp.keycodes[88] = SAPP_KEYCODE_X; |
| 2079 | _sapp.keycodes[89] = SAPP_KEYCODE_Y; |
| 2080 | _sapp.keycodes[90] = SAPP_KEYCODE_Z; |
| 2081 | _sapp.keycodes[91] = SAPP_KEYCODE_LEFT_SUPER; |
| 2082 | _sapp.keycodes[93] = SAPP_KEYCODE_MENU; |
| 2083 | _sapp.keycodes[96] = SAPP_KEYCODE_KP_0; |
| 2084 | _sapp.keycodes[97] = SAPP_KEYCODE_KP_1; |
| 2085 | _sapp.keycodes[98] = SAPP_KEYCODE_KP_2; |
| 2086 | _sapp.keycodes[99] = SAPP_KEYCODE_KP_3; |
| 2087 | _sapp.keycodes[100] = SAPP_KEYCODE_KP_4; |
| 2088 | _sapp.keycodes[101] = SAPP_KEYCODE_KP_5; |
| 2089 | _sapp.keycodes[102] = SAPP_KEYCODE_KP_6; |
| 2090 | _sapp.keycodes[103] = SAPP_KEYCODE_KP_7; |
| 2091 | _sapp.keycodes[104] = SAPP_KEYCODE_KP_8; |
| 2092 | _sapp.keycodes[105] = SAPP_KEYCODE_KP_9; |
| 2093 | _sapp.keycodes[106] = SAPP_KEYCODE_KP_MULTIPLY; |
| 2094 | _sapp.keycodes[107] = SAPP_KEYCODE_KP_ADD; |
| 2095 | _sapp.keycodes[109] = SAPP_KEYCODE_KP_SUBTRACT; |
| 2096 | _sapp.keycodes[110] = SAPP_KEYCODE_KP_DECIMAL; |
| 2097 | _sapp.keycodes[111] = SAPP_KEYCODE_KP_DIVIDE; |
| 2098 | _sapp.keycodes[112] = SAPP_KEYCODE_F1; |
| 2099 | _sapp.keycodes[113] = SAPP_KEYCODE_F2; |
| 2100 | _sapp.keycodes[114] = SAPP_KEYCODE_F3; |
| 2101 | _sapp.keycodes[115] = SAPP_KEYCODE_F4; |
| 2102 | _sapp.keycodes[116] = SAPP_KEYCODE_F5; |
| 2103 | _sapp.keycodes[117] = SAPP_KEYCODE_F6; |
| 2104 | _sapp.keycodes[118] = SAPP_KEYCODE_F7; |
| 2105 | _sapp.keycodes[119] = SAPP_KEYCODE_F8; |
| 2106 | _sapp.keycodes[120] = SAPP_KEYCODE_F9; |
| 2107 | _sapp.keycodes[121] = SAPP_KEYCODE_F10; |
| 2108 | _sapp.keycodes[122] = SAPP_KEYCODE_F11; |
| 2109 | _sapp.keycodes[123] = SAPP_KEYCODE_F12; |
| 2110 | _sapp.keycodes[144] = SAPP_KEYCODE_NUM_LOCK; |
| 2111 | _sapp.keycodes[145] = SAPP_KEYCODE_SCROLL_LOCK; |
| 2112 | _sapp.keycodes[173] = SAPP_KEYCODE_MINUS; |
| 2113 | _sapp.keycodes[186] = SAPP_KEYCODE_SEMICOLON; |
| 2114 | _sapp.keycodes[187] = SAPP_KEYCODE_EQUAL; |
| 2115 | _sapp.keycodes[188] = SAPP_KEYCODE_COMMA; |
| 2116 | _sapp.keycodes[189] = SAPP_KEYCODE_MINUS; |
| 2117 | _sapp.keycodes[190] = SAPP_KEYCODE_PERIOD; |
| 2118 | _sapp.keycodes[191] = SAPP_KEYCODE_SLASH; |
| 2119 | _sapp.keycodes[192] = SAPP_KEYCODE_GRAVE_ACCENT; |
| 2120 | _sapp.keycodes[219] = SAPP_KEYCODE_LEFT_BRACKET; |
| 2121 | _sapp.keycodes[220] = SAPP_KEYCODE_BACKSLASH; |
| 2122 | _sapp.keycodes[221] = SAPP_KEYCODE_RIGHT_BRACKET; |
| 2123 | _sapp.keycodes[222] = SAPP_KEYCODE_APOSTROPHE; |
| 2124 | _sapp.keycodes[224] = SAPP_KEYCODE_LEFT_SUPER; |
| 2125 | } |
| 2126 | |
| 2127 | int main(int argc, char* argv[]) { |
| 2128 | sapp_desc desc = sokol_main(argc, argv); |
| 2129 | _sapp_init_state(&desc, 0, 0); |
| 2130 | _sapp_emsc_init_keytable(); |
| 2131 | double w, h; |
| 2132 | if (_sapp.html5_canvas_resize) { |
| 2133 | w = (double) desc.width; |
| 2134 | h = (double) desc.height; |
| 2135 | } |
| 2136 | else { |
| 2137 | emscripten_get_element_css_size(_sapp.html5_canvas_name, &w, &h); |
| 2138 | emscripten_set_resize_callback(0, 0, false, _sapp_emsc_size_changed); |
| 2139 | } |
| 2140 | if (_sapp.desc.high_dpi) { |
| 2141 | _sapp.dpi_scale = emscripten_get_device_pixel_ratio(); |
| 2142 | w *= _sapp.dpi_scale; |
| 2143 | h *= _sapp.dpi_scale; |
| 2144 | } |
| 2145 | emscripten_set_canvas_element_size(_sapp.html5_canvas_name, w, h); |
| 2146 | _sapp.framebuffer_width = (int) w; |
| 2147 | _sapp.framebuffer_height = (int) h; |
| 2148 | EmscriptenWebGLContextAttributes attrs; |
| 2149 | emscripten_webgl_init_context_attributes(&attrs); |
| 2150 | attrs.alpha = _sapp.desc.alpha; |
| 2151 | attrs.depth = true; |
| 2152 | attrs.stencil = true; |
| 2153 | attrs.antialias = _sapp.sample_count > 1; |
| 2154 | attrs.premultipliedAlpha = _sapp.desc.premultiplied_alpha; |
| 2155 | attrs.preserveDrawingBuffer = _sapp.desc.preserve_drawing_buffer; |
| 2156 | attrs.enableExtensionsByDefault = true; |
| 2157 | #if defined(SOKOL_GLES3) |
| 2158 | if (desc.gl_force_gles2) { |
| 2159 | attrs.majorVersion = 1; |
| 2160 | _sapp.gles2_fallback = true; |
| 2161 | } |
| 2162 | else { |
| 2163 | attrs.majorVersion = 2; |
| 2164 | } |
| 2165 | #endif |
| 2166 | EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(0, &attrs); |
| 2167 | if (!ctx) { |
| 2168 | attrs.majorVersion = 1; |
| 2169 | ctx = emscripten_webgl_create_context(0, &attrs); |
| 2170 | _sapp.gles2_fallback = true; |
| 2171 | } |
| 2172 | emscripten_webgl_make_context_current(ctx); |
| 2173 | _sapp.valid = true; |
| 2174 | emscripten_set_mousedown_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_mouse_cb); |
| 2175 | emscripten_set_mouseup_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_mouse_cb); |
| 2176 | emscripten_set_mousemove_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_mouse_cb); |
| 2177 | emscripten_set_mouseenter_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_mouse_cb); |
| 2178 | emscripten_set_mouseleave_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_mouse_cb); |
| 2179 | emscripten_set_wheel_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_wheel_cb); |
| 2180 | emscripten_set_keydown_callback(0, 0, true, _sapp_emsc_key_cb); |
| 2181 | emscripten_set_keyup_callback(0, 0, true, _sapp_emsc_key_cb); |
| 2182 | emscripten_set_keypress_callback(0, 0, true, _sapp_emsc_key_cb); |
| 2183 | emscripten_set_touchstart_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_touch_cb); |
| 2184 | emscripten_set_touchmove_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_touch_cb); |
| 2185 | emscripten_set_touchend_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_touch_cb); |
| 2186 | emscripten_set_touchcancel_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_touch_cb); |
| 2187 | emscripten_set_webglcontextlost_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_context_cb); |
| 2188 | emscripten_set_webglcontextrestored_callback(_sapp.html5_canvas_name, 0, true, _sapp_emsc_context_cb); |
| 2189 | emscripten_set_main_loop(_sapp_emsc_frame, 0, 1); |
| 2190 | return 0; |
| 2191 | } |
| 2192 | #endif /* __EMSCRIPTEN__ */ |
| 2193 | |
| 2194 | /*== MISC GL SUPPORT FUNCTIONS ================================================*/ |
| 2195 | #if defined(SOKOL_GLCORE33) |
| 2196 | typedef struct { |
| 2197 | int red_bits; |
| 2198 | int green_bits; |
| 2199 | int blue_bits; |
| 2200 | int alpha_bits; |
| 2201 | int depth_bits; |
| 2202 | int stencil_bits; |
| 2203 | int samples; |
| 2204 | bool doublebuffer; |
| 2205 | uintptr_t handle; |
| 2206 | } _sapp_gl_fbconfig; |
| 2207 | |
| 2208 | _SOKOL_PRIVATE void _sapp_gl_init_fbconfig(_sapp_gl_fbconfig* fbconfig) { |
| 2209 | memset(fbconfig, 0, sizeof(_sapp_gl_fbconfig)); |
| 2210 | /* -1 means "don't care" */ |
| 2211 | fbconfig->red_bits = -1; |
| 2212 | fbconfig->green_bits = -1; |
| 2213 | fbconfig->blue_bits = -1; |
| 2214 | fbconfig->alpha_bits = -1; |
| 2215 | fbconfig->depth_bits = -1; |
| 2216 | fbconfig->stencil_bits = -1; |
| 2217 | fbconfig->samples = -1; |
| 2218 | } |
| 2219 | |
| 2220 | _SOKOL_PRIVATE const _sapp_gl_fbconfig* _sapp_gl_choose_fbconfig(const _sapp_gl_fbconfig* desired, const _sapp_gl_fbconfig* alternatives, unsigned int count) { |
| 2221 | unsigned int i; |
| 2222 | unsigned int missing, least_missing = 1000000; |
| 2223 | unsigned int color_diff, least_color_diff = 10000000; |
| 2224 | unsigned int extra_diff, least_extra_diff = 10000000; |
| 2225 | const _sapp_gl_fbconfig* current; |
| 2226 | const _sapp_gl_fbconfig* closest = NULL; |
| 2227 | for (i = 0; i < count; i++) { |
| 2228 | current = alternatives + i; |
| 2229 | if (desired->doublebuffer != current->doublebuffer) { |
| 2230 | continue; |
| 2231 | } |
| 2232 | missing = 0; |
| 2233 | if (desired->alpha_bits > 0 && current->alpha_bits == 0) { |
| 2234 | missing++; |
| 2235 | } |
| 2236 | if (desired->depth_bits > 0 && current->depth_bits == 0) { |
| 2237 | missing++; |
| 2238 | } |
| 2239 | if (desired->stencil_bits > 0 && current->stencil_bits == 0) { |
| 2240 | missing++; |
| 2241 | } |
| 2242 | if (desired->samples > 0 && current->samples == 0) { |
| 2243 | /* Technically, several multisampling buffers could be |
| 2244 | involved, but that's a lower level implementation detail and |
| 2245 | not important to us here, so we count them as one |
| 2246 | */ |
| 2247 | missing++; |
| 2248 | } |
| 2249 | |
| 2250 | /* These polynomials make many small channel size differences matter |
| 2251 | less than one large channel size difference |
| 2252 | Calculate color channel size difference value |
| 2253 | */ |
| 2254 | color_diff = 0; |
| 2255 | if (desired->red_bits != -1) { |
| 2256 | color_diff += (desired->red_bits - current->red_bits) * (desired->red_bits - current->red_bits); |
| 2257 | } |
| 2258 | if (desired->green_bits != -1) { |
| 2259 | color_diff += (desired->green_bits - current->green_bits) * (desired->green_bits - current->green_bits); |
| 2260 | } |
| 2261 | if (desired->blue_bits != -1) { |
| 2262 | color_diff += (desired->blue_bits - current->blue_bits) * (desired->blue_bits - current->blue_bits); |
| 2263 | } |
| 2264 | |
| 2265 | /* Calculate non-color channel size difference value */ |
| 2266 | extra_diff = 0; |
| 2267 | if (desired->alpha_bits != -1) { |
| 2268 | extra_diff += (desired->alpha_bits - current->alpha_bits) * (desired->alpha_bits - current->alpha_bits); |
| 2269 | } |
| 2270 | if (desired->depth_bits != -1) { |
| 2271 | extra_diff += (desired->depth_bits - current->depth_bits) * (desired->depth_bits - current->depth_bits); |
| 2272 | } |
| 2273 | if (desired->stencil_bits != -1) { |
| 2274 | extra_diff += (desired->stencil_bits - current->stencil_bits) * (desired->stencil_bits - current->stencil_bits); |
| 2275 | } |
| 2276 | if (desired->samples != -1) { |
| 2277 | extra_diff += (desired->samples - current->samples) * (desired->samples - current->samples); |
| 2278 | } |
| 2279 | |
| 2280 | /* Figure out if the current one is better than the best one found so far |
| 2281 | Least number of missing buffers is the most important heuristic, |
| 2282 | then color buffer size match and lastly size match for other buffers |
| 2283 | */ |
| 2284 | if (missing < least_missing) { |
| 2285 | closest = current; |
| 2286 | } |
| 2287 | else if (missing == least_missing) { |
| 2288 | if ((color_diff < least_color_diff) || |
| 2289 | (color_diff == least_color_diff && extra_diff < least_extra_diff)) |
| 2290 | { |
| 2291 | closest = current; |
| 2292 | } |
| 2293 | } |
| 2294 | if (current == closest) { |
| 2295 | least_missing = missing; |
| 2296 | least_color_diff = color_diff; |
| 2297 | least_extra_diff = extra_diff; |
| 2298 | } |
| 2299 | } |
| 2300 | return closest; |
| 2301 | } |
| 2302 | #endif |
| 2303 | |
| 2304 | /*== WINDOWS ==================================================================*/ |
| 2305 | #if defined(_WIN32) |
| 2306 | #ifndef WIN32_LEAN_AND_MEAN |
| 2307 | #define WIN32_LEAN_AND_MEAN |
| 2308 | #endif |
| 2309 | #include <windows.h> |
| 2310 | #include <windowsx.h> |
| 2311 | |
| 2312 | #if defined(SOKOL_D3D11) |
| 2313 | #ifndef D3D11_NO_HELPERS |
| 2314 | #define D3D11_NO_HELPERS |
| 2315 | #endif |
| 2316 | #ifndef CINTERFACE |
| 2317 | #define CINTERFACE |
| 2318 | #endif |
| 2319 | #ifndef COBJMACROS |
| 2320 | #define COBJMACROS |
| 2321 | #endif |
| 2322 | #include <windows.h> |
| 2323 | #include <d3d11.h> |
| 2324 | #include <dxgi.h> |
| 2325 | #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) |
| 2326 | #pragma comment (lib, "WindowsApp.lib") |
| 2327 | #else |
| 2328 | #pragma comment (lib, "user32.lib") |
| 2329 | #pragma comment (lib, "dxgi.lib") |
| 2330 | #pragma comment (lib, "d3d11.lib") |
| 2331 | #pragma comment (lib, "dxguid.lib") |
| 2332 | #endif |
| 2333 | #endif |
| 2334 | |
| 2335 | #ifndef DPI_ENUMS_DECLARED |
| 2336 | typedef enum PROCESS_DPI_AWARENESS |
| 2337 | { |
| 2338 | PROCESS_DPI_UNAWARE = 0, |
| 2339 | PROCESS_SYSTEM_DPI_AWARE = 1, |
| 2340 | PROCESS_PER_MONITOR_DPI_AWARE = 2 |
| 2341 | } PROCESS_DPI_AWARENESS; |
| 2342 | typedef enum MONITOR_DPI_TYPE { |
| 2343 | MDT_EFFECTIVE_DPI = 0, |
| 2344 | MDT_ANGULAR_DPI = 1, |
| 2345 | MDT_RAW_DPI = 2, |
| 2346 | MDT_DEFAULT = MDT_EFFECTIVE_DPI |
| 2347 | } MONITOR_DPI_TYPE; |
| 2348 | #endif /*DPI_ENUMS_DECLARED*/ |
| 2349 | |
| 2350 | static HWND _sapp_win32_hwnd; |
| 2351 | static HDC _sapp_win32_dc; |
| 2352 | static bool _sapp_win32_in_create_window; |
| 2353 | static bool _sapp_win32_dpi_aware; |
| 2354 | static int _sapp_win32_content_scale; |
| 2355 | static int _sapp_win32_window_scale; |
| 2356 | static float _sapp_win32_mouse_scale; |
| 2357 | static bool _sapp_win32_iconified; |
| 2358 | typedef BOOL(WINAPI * SETPROCESSDPIAWARE_T)(void); |
| 2359 | typedef HRESULT(WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS); |
| 2360 | typedef HRESULT(WINAPI * GETDPIFORMONITOR_T)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); |
| 2361 | static SETPROCESSDPIAWARE_T _sapp_win32_setprocessdpiaware; |
| 2362 | static SETPROCESSDPIAWARENESS_T _sapp_win32_setprocessdpiawareness; |
| 2363 | static GETDPIFORMONITOR_T _sapp_win32_getdpiformonitor; |
| 2364 | #if defined(SOKOL_D3D11) |
| 2365 | static ID3D11Device* _sapp_d3d11_device; |
| 2366 | static ID3D11DeviceContext* _sapp_d3d11_device_context; |
| 2367 | static DXGI_SWAP_CHAIN_DESC _sapp_dxgi_swap_chain_desc; |
| 2368 | static IDXGISwapChain* _sapp_dxgi_swap_chain; |
| 2369 | static ID3D11Texture2D* _sapp_d3d11_rt; |
| 2370 | static ID3D11RenderTargetView* _sapp_d3d11_rtv; |
| 2371 | static ID3D11Texture2D* _sapp_d3d11_ds; |
| 2372 | static ID3D11DepthStencilView* _sapp_d3d11_dsv; |
| 2373 | #endif |
| 2374 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 |
| 2375 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 |
| 2376 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 |
| 2377 | #define WGL_PIXEL_TYPE_ARB 0x2013 |
| 2378 | #define WGL_TYPE_RGBA_ARB 0x202b |
| 2379 | #define WGL_ACCELERATION_ARB 0x2003 |
| 2380 | #define WGL_NO_ACCELERATION_ARB 0x2025 |
| 2381 | #define WGL_RED_BITS_ARB 0x2015 |
| 2382 | #define WGL_RED_SHIFT_ARB 0x2016 |
| 2383 | #define WGL_GREEN_BITS_ARB 0x2017 |
| 2384 | #define WGL_GREEN_SHIFT_ARB 0x2018 |
| 2385 | #define WGL_BLUE_BITS_ARB 0x2019 |
| 2386 | #define WGL_BLUE_SHIFT_ARB 0x201a |
| 2387 | #define WGL_ALPHA_BITS_ARB 0x201b |
| 2388 | #define WGL_ALPHA_SHIFT_ARB 0x201c |
| 2389 | #define WGL_ACCUM_BITS_ARB 0x201d |
| 2390 | #define WGL_ACCUM_RED_BITS_ARB 0x201e |
| 2391 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201f |
| 2392 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 |
| 2393 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 |
| 2394 | #define WGL_DEPTH_BITS_ARB 0x2022 |
| 2395 | #define WGL_STENCIL_BITS_ARB 0x2023 |
| 2396 | #define WGL_AUX_BUFFERS_ARB 0x2024 |
| 2397 | #define WGL_STEREO_ARB 0x2012 |
| 2398 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 |
| 2399 | #define WGL_SAMPLES_ARB 0x2042 |
| 2400 | #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 |
| 2401 | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 |
| 2402 | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 |
| 2403 | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 |
| 2404 | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 |
| 2405 | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 |
| 2406 | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 |
| 2407 | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 |
| 2408 | #define WGL_CONTEXT_FLAGS_ARB 0x2094 |
| 2409 | #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 |
| 2410 | #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 |
| 2411 | #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 |
| 2412 | #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 |
| 2413 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 |
| 2414 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 |
| 2415 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 |
| 2416 | #define WGL_COLORSPACE_EXT 0x309d |
| 2417 | #define WGL_COLORSPACE_SRGB_EXT 0x3089 |
| 2418 | #define ERROR_INVALID_VERSION_ARB 0x2095 |
| 2419 | #define ERROR_INVALID_PROFILE_ARB 0x2096 |
| 2420 | #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 |
| 2421 | typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int); |
| 2422 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*); |
| 2423 | typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void); |
| 2424 | typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC); |
| 2425 | typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*); |
| 2426 | typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC); |
| 2427 | typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC); |
| 2428 | typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR); |
| 2429 | typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void); |
| 2430 | typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC); |
| 2431 | static HINSTANCE _sapp_opengl32; |
| 2432 | static HGLRC _sapp_gl_ctx; |
| 2433 | static PFN_wglCreateContext _sapp_wglCreateContext; |
| 2434 | static PFN_wglDeleteContext _sapp_wglDeleteContext; |
| 2435 | static PFN_wglGetProcAddress _sapp_wglGetProcAddress; |
| 2436 | static PFN_wglGetCurrentDC _sapp_wglGetCurrentDC; |
| 2437 | static PFN_wglMakeCurrent _sapp_wglMakeCurrent; |
| 2438 | static PFNWGLSWAPINTERVALEXTPROC _sapp_SwapIntervalEXT; |
| 2439 | static PFNWGLGETPIXELFORMATATTRIBIVARBPROC _sapp_GetPixelFormatAttribivARB; |
| 2440 | static PFNWGLGETEXTENSIONSSTRINGEXTPROC _sapp_GetExtensionsStringEXT; |
| 2441 | static PFNWGLGETEXTENSIONSSTRINGARBPROC _sapp_GetExtensionsStringARB; |
| 2442 | static PFNWGLCREATECONTEXTATTRIBSARBPROC _sapp_CreateContextAttribsARB; |
| 2443 | static bool _sapp_ext_swap_control; |
| 2444 | static bool _sapp_arb_multisample; |
| 2445 | static bool _sapp_arb_pixel_format; |
| 2446 | static bool _sapp_arb_create_context; |
| 2447 | static bool _sapp_arb_create_context_profile; |
| 2448 | static HWND _sapp_win32_msg_hwnd; |
| 2449 | static HDC _sapp_win32_msg_dc; |
| 2450 | |
| 2451 | /* NOTE: the optional GL loader only contains the GL constants and functions required for sokol_gfx.h, if you need |
| 2452 | more, you'll need to use you own gl header-generator/loader |
| 2453 | */ |
| 2454 | #if !defined(SOKOL_WIN32_NO_GL_LOADER) |
| 2455 | #if defined(SOKOL_GLCORE33) |
| 2456 | #define __gl_h_ 1 |
| 2457 | #define __gl32_h_ 1 |
| 2458 | #define __gl31_h_ 1 |
| 2459 | #define __GL_H__ 1 |
| 2460 | #define __glext_h_ 1 |
| 2461 | #define __GLEXT_H_ 1 |
| 2462 | #define __gltypes_h_ 1 |
| 2463 | #define __glcorearb_h_ 1 |
| 2464 | #define __gl_glcorearb_h_ 1 |
| 2465 | #define GL_APIENTRY APIENTRY |
| 2466 | |
| 2467 | typedef unsigned int GLenum; |
| 2468 | typedef unsigned int GLuint; |
| 2469 | typedef int GLsizei; |
| 2470 | typedef char GLchar; |
| 2471 | typedef ptrdiff_t GLintptr; |
| 2472 | typedef ptrdiff_t GLsizeiptr; |
| 2473 | typedef double GLclampd; |
| 2474 | typedef unsigned short GLushort; |
| 2475 | typedef unsigned char GLubyte; |
| 2476 | typedef unsigned char GLboolean; |
| 2477 | typedef uint64_t GLuint64; |
| 2478 | typedef double GLdouble; |
| 2479 | typedef unsigned short GLhalf; |
| 2480 | typedef float GLclampf; |
| 2481 | typedef unsigned int GLbitfield; |
| 2482 | typedef signed char GLbyte; |
| 2483 | typedef short GLshort; |
| 2484 | typedef void GLvoid; |
| 2485 | typedef int64_t GLint64; |
| 2486 | typedef float GLfloat; |
| 2487 | typedef struct __GLsync * GLsync; |
| 2488 | typedef int GLint; |
| 2489 | #define GL_INT_2_10_10_10_REV 0x8D9F |
| 2490 | #define GL_R32F 0x822E |
| 2491 | #define GL_PROGRAM_POINT_SIZE 0x8642 |
| 2492 | #define GL_STENCIL_ATTACHMENT 0x8D20 |
| 2493 | #define GL_DEPTH_ATTACHMENT 0x8D00 |
| 2494 | #define GL_COLOR_ATTACHMENT2 0x8CE2 |
| 2495 | #define GL_COLOR_ATTACHMENT0 0x8CE0 |
| 2496 | #define GL_R16F 0x822D |
| 2497 | #define GL_COLOR_ATTACHMENT22 0x8CF6 |
| 2498 | #define GL_DRAW_FRAMEBUFFER 0x8CA9 |
| 2499 | #define GL_FRAMEBUFFER_COMPLETE 0x8CD5 |
| 2500 | #define GL_NUM_EXTENSIONS 0x821D |
| 2501 | #define GL_INFO_LOG_LENGTH 0x8B84 |
| 2502 | #define GL_VERTEX_SHADER 0x8B31 |
| 2503 | #define GL_INCR 0x1E02 |
| 2504 | #define GL_DYNAMIC_DRAW 0x88E8 |
| 2505 | #define GL_STATIC_DRAW 0x88E4 |
| 2506 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 |
| 2507 | #define GL_TEXTURE_CUBE_MAP 0x8513 |
| 2508 | #define GL_FUNC_SUBTRACT 0x800A |
| 2509 | #define GL_FUNC_REVERSE_SUBTRACT 0x800B |
| 2510 | #define GL_CONSTANT_COLOR 0x8001 |
| 2511 | #define GL_DECR_WRAP 0x8508 |
| 2512 | #define GL_R8 0x8229 |
| 2513 | #define GL_LINEAR_MIPMAP_LINEAR 0x2703 |
| 2514 | #define GL_ELEMENT_ARRAY_BUFFER 0x8893 |
| 2515 | #define GL_SHORT 0x1402 |
| 2516 | #define GL_DEPTH_TEST 0x0B71 |
| 2517 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 |
| 2518 | #define GL_LINK_STATUS 0x8B82 |
| 2519 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 |
| 2520 | #define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E |
| 2521 | #define GL_RGBA16F 0x881A |
| 2522 | #define GL_CONSTANT_ALPHA 0x8003 |
| 2523 | #define GL_READ_FRAMEBUFFER 0x8CA8 |
| 2524 | #define GL_TEXTURE0 0x84C0 |
| 2525 | #define GL_TEXTURE_MIN_LOD 0x813A |
| 2526 | #define GL_CLAMP_TO_EDGE 0x812F |
| 2527 | #define GL_UNSIGNED_SHORT_5_6_5 0x8363 |
| 2528 | #define GL_TEXTURE_WRAP_R 0x8072 |
| 2529 | #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 |
| 2530 | #define GL_NEAREST_MIPMAP_NEAREST 0x2700 |
| 2531 | #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 |
| 2532 | #define GL_SRC_ALPHA_SATURATE 0x0308 |
| 2533 | #define GL_STREAM_DRAW 0x88E0 |
| 2534 | #define GL_ONE 1 |
| 2535 | #define GL_NEAREST_MIPMAP_LINEAR 0x2702 |
| 2536 | #define GL_RGB10_A2 0x8059 |
| 2537 | #define GL_RGBA8 0x8058 |
| 2538 | #define GL_COLOR_ATTACHMENT1 0x8CE1 |
| 2539 | #define GL_RGBA4 0x8056 |
| 2540 | #define GL_RGB8 0x8051 |
| 2541 | #define GL_ARRAY_BUFFER 0x8892 |
| 2542 | #define GL_STENCIL 0x1802 |
| 2543 | #define GL_TEXTURE_2D 0x0DE1 |
| 2544 | #define GL_DEPTH 0x1801 |
| 2545 | #define GL_FRONT 0x0404 |
| 2546 | #define GL_STENCIL_BUFFER_BIT 0x00000400 |
| 2547 | #define GL_REPEAT 0x2901 |
| 2548 | #define GL_RGBA 0x1908 |
| 2549 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 |
| 2550 | #define GL_DECR 0x1E03 |
| 2551 | #define GL_FRAGMENT_SHADER 0x8B30 |
| 2552 | #define GL_FLOAT 0x1406 |
| 2553 | #define GL_TEXTURE_MAX_LOD 0x813B |
| 2554 | #define GL_DEPTH_COMPONENT 0x1902 |
| 2555 | #define GL_ONE_MINUS_DST_ALPHA 0x0305 |
| 2556 | #define GL_COLOR 0x1800 |
| 2557 | #define GL_TEXTURE_2D_ARRAY 0x8C1A |
| 2558 | #define GL_TRIANGLES 0x0004 |
| 2559 | #define GL_UNSIGNED_BYTE 0x1401 |
| 2560 | #define GL_TEXTURE_MAG_FILTER 0x2800 |
| 2561 | #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 |
| 2562 | #define GL_NONE 0 |
| 2563 | #define GL_SRC_COLOR 0x0300 |
| 2564 | #define GL_BYTE 0x1400 |
| 2565 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A |
| 2566 | #define GL_LINE_STRIP 0x0003 |
| 2567 | #define GL_TEXTURE_3D 0x806F |
| 2568 | #define GL_CW 0x0900 |
| 2569 | #define GL_LINEAR 0x2601 |
| 2570 | #define GL_RENDERBUFFER 0x8D41 |
| 2571 | #define GL_GEQUAL 0x0206 |
| 2572 | #define GL_COLOR_BUFFER_BIT 0x00004000 |
| 2573 | #define GL_RGBA32F 0x8814 |
| 2574 | #define GL_BLEND 0x0BE2 |
| 2575 | #define GL_ONE_MINUS_SRC_ALPHA 0x0303 |
| 2576 | #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 |
| 2577 | #define GL_TEXTURE_WRAP_T 0x2803 |
| 2578 | #define GL_TEXTURE_WRAP_S 0x2802 |
| 2579 | #define GL_TEXTURE_MIN_FILTER 0x2801 |
| 2580 | #define GL_LINEAR_MIPMAP_NEAREST 0x2701 |
| 2581 | #define GL_EXTENSIONS 0x1F03 |
| 2582 | #define GL_NO_ERROR 0 |
| 2583 | #define GL_REPLACE 0x1E01 |
| 2584 | #define GL_KEEP 0x1E00 |
| 2585 | #define GL_CCW 0x0901 |
| 2586 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 |
| 2587 | #define GL_RGB 0x1907 |
| 2588 | #define GL_TRIANGLE_STRIP 0x0005 |
| 2589 | #define GL_FALSE 0 |
| 2590 | #define GL_ZERO 0 |
| 2591 | #define GL_CULL_FACE 0x0B44 |
| 2592 | #define GL_INVERT 0x150A |
| 2593 | #define GL_UNSIGNED_INT 0x1405 |
| 2594 | #define GL_UNSIGNED_SHORT 0x1403 |
| 2595 | #define GL_NEAREST 0x2600 |
| 2596 | #define GL_SCISSOR_TEST 0x0C11 |
| 2597 | #define GL_LEQUAL 0x0203 |
| 2598 | #define GL_STENCIL_TEST 0x0B90 |
| 2599 | #define GL_DITHER 0x0BD0 |
| 2600 | #define GL_DEPTH_COMPONENT16 0x81A5 |
| 2601 | #define GL_EQUAL 0x0202 |
| 2602 | #define GL_FRAMEBUFFER 0x8D40 |
| 2603 | #define GL_RGB5 0x8050 |
| 2604 | #define GL_LINES 0x0001 |
| 2605 | #define GL_DEPTH_BUFFER_BIT 0x00000100 |
| 2606 | #define GL_SRC_ALPHA 0x0302 |
| 2607 | #define GL_INCR_WRAP 0x8507 |
| 2608 | #define GL_LESS 0x0201 |
| 2609 | #define GL_MULTISAMPLE 0x809D |
| 2610 | #define GL_FRAMEBUFFER_BINDING 0x8CA6 |
| 2611 | #define GL_BACK 0x0405 |
| 2612 | #define GL_ALWAYS 0x0207 |
| 2613 | #define GL_FUNC_ADD 0x8006 |
| 2614 | #define GL_ONE_MINUS_DST_COLOR 0x0307 |
| 2615 | #define GL_NOTEQUAL 0x0205 |
| 2616 | #define GL_DST_COLOR 0x0306 |
| 2617 | #define GL_COMPILE_STATUS 0x8B81 |
| 2618 | #define GL_RED 0x1903 |
| 2619 | #define GL_COLOR_ATTACHMENT3 0x8CE3 |
| 2620 | #define GL_DST_ALPHA 0x0304 |
| 2621 | #define GL_RGB5_A1 0x8057 |
| 2622 | #define GL_GREATER 0x0204 |
| 2623 | #define GL_POLYGON_OFFSET_FILL 0x8037 |
| 2624 | #define GL_TRUE 1 |
| 2625 | #define GL_NEVER 0x0200 |
| 2626 | #define GL_POINTS 0x0000 |
| 2627 | #define GL_ONE_MINUS_SRC_COLOR 0x0301 |
| 2628 | #define GL_MIRRORED_REPEAT 0x8370 |
| 2629 | |
| 2630 | typedef void (GL_APIENTRY *PFN_glBindVertexArray)(GLuint array); |
| 2631 | static PFN_glBindVertexArray _sapp_glBindVertexArray; |
| 2632 | typedef void (GL_APIENTRY *PFN_glFramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); |
| 2633 | static PFN_glFramebufferTextureLayer _sapp_glFramebufferTextureLayer; |
| 2634 | typedef void (GL_APIENTRY *PFN_glGenFramebuffers)(GLsizei n, GLuint * framebuffers); |
| 2635 | static PFN_glGenFramebuffers _sapp_glGenFramebuffers; |
| 2636 | typedef void (GL_APIENTRY *PFN_glBindFramebuffer)(GLenum target, GLuint framebuffer); |
| 2637 | static PFN_glBindFramebuffer _sapp_glBindFramebuffer; |
| 2638 | typedef void (GL_APIENTRY *PFN_glBindRenderbuffer)(GLenum target, GLuint renderbuffer); |
| 2639 | static PFN_glBindRenderbuffer _sapp_glBindRenderbuffer; |
| 2640 | typedef const GLubyte * (GL_APIENTRY *PFN_glGetStringi)(GLenum name, GLuint index); |
| 2641 | static PFN_glGetStringi _sapp_glGetStringi; |
| 2642 | typedef void (GL_APIENTRY *PFN_glClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); |
| 2643 | static PFN_glClearBufferfi _sapp_glClearBufferfi; |
| 2644 | typedef void (GL_APIENTRY *PFN_glClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat * value); |
| 2645 | static PFN_glClearBufferfv _sapp_glClearBufferfv; |
| 2646 | typedef void (GL_APIENTRY *PFN_glClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint * value); |
| 2647 | static PFN_glClearBufferuiv _sapp_glClearBufferuiv; |
| 2648 | typedef void (GL_APIENTRY *PFN_glDeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers); |
| 2649 | static PFN_glDeleteRenderbuffers _sapp_glDeleteRenderbuffers; |
| 2650 | typedef void (GL_APIENTRY *PFN_glUniform4fv)(GLint location, GLsizei count, const GLfloat * value); |
| 2651 | static PFN_glUniform4fv _sapp_glUniform4fv; |
| 2652 | typedef void (GL_APIENTRY *PFN_glUniform2fv)(GLint location, GLsizei count, const GLfloat * value); |
| 2653 | static PFN_glUniform2fv _sapp_glUniform2fv; |
| 2654 | typedef void (GL_APIENTRY *PFN_glUseProgram)(GLuint program); |
| 2655 | static PFN_glUseProgram _sapp_glUseProgram; |
| 2656 | typedef void (GL_APIENTRY *PFN_glShaderSource)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); |
| 2657 | static PFN_glShaderSource _sapp_glShaderSource; |
| 2658 | typedef void (GL_APIENTRY *PFN_glLinkProgram)(GLuint program); |
| 2659 | static PFN_glLinkProgram _sapp_glLinkProgram; |
| 2660 | typedef GLint (GL_APIENTRY *PFN_glGetUniformLocation)(GLuint program, const GLchar * name); |
| 2661 | static PFN_glGetUniformLocation _sapp_glGetUniformLocation; |
| 2662 | typedef void (GL_APIENTRY *PFN_glGetShaderiv)(GLuint shader, GLenum pname, GLint * params); |
| 2663 | static PFN_glGetShaderiv _sapp_glGetShaderiv; |
| 2664 | typedef void (GL_APIENTRY *PFN_glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); |
| 2665 | static PFN_glGetProgramInfoLog _sapp_glGetProgramInfoLog; |
| 2666 | typedef GLint (GL_APIENTRY *PFN_glGetAttribLocation)(GLuint program, const GLchar * name); |
| 2667 | static PFN_glGetAttribLocation _sapp_glGetAttribLocation; |
| 2668 | typedef void (GL_APIENTRY *PFN_glDisableVertexAttribArray)(GLuint index); |
| 2669 | static PFN_glDisableVertexAttribArray _sapp_glDisableVertexAttribArray; |
| 2670 | typedef void (GL_APIENTRY *PFN_glDeleteShader)(GLuint shader); |
| 2671 | static PFN_glDeleteShader _sapp_glDeleteShader; |
| 2672 | typedef void (GL_APIENTRY *PFN_glDeleteProgram)(GLuint program); |
| 2673 | static PFN_glDeleteProgram _sapp_glDeleteProgram; |
| 2674 | typedef void (GL_APIENTRY *PFN_glCompileShader)(GLuint shader); |
| 2675 | static PFN_glCompileShader _sapp_glCompileShader; |
| 2676 | typedef void (GL_APIENTRY *PFN_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); |
| 2677 | static PFN_glStencilFuncSeparate _sapp_glStencilFuncSeparate; |
| 2678 | typedef void (GL_APIENTRY *PFN_glStencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); |
| 2679 | static PFN_glStencilOpSeparate _sapp_glStencilOpSeparate; |
| 2680 | typedef void (GL_APIENTRY *PFN_glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); |
| 2681 | static PFN_glRenderbufferStorageMultisample _sapp_glRenderbufferStorageMultisample; |
| 2682 | typedef void (GL_APIENTRY *PFN_glDrawBuffers)(GLsizei n, const GLenum * bufs); |
| 2683 | static PFN_glDrawBuffers _sapp_glDrawBuffers; |
| 2684 | typedef void (GL_APIENTRY *PFN_glVertexAttribDivisor)(GLuint index, GLuint divisor); |
| 2685 | static PFN_glVertexAttribDivisor _sapp_glVertexAttribDivisor; |
| 2686 | typedef void (GL_APIENTRY *PFN_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); |
| 2687 | static PFN_glBufferSubData _sapp_glBufferSubData; |
| 2688 | typedef void (GL_APIENTRY *PFN_glGenBuffers)(GLsizei n, GLuint * buffers); |
| 2689 | static PFN_glGenBuffers _sapp_glGenBuffers; |
| 2690 | typedef GLenum (GL_APIENTRY *PFN_glCheckFramebufferStatus)(GLenum target); |
| 2691 | static PFN_glCheckFramebufferStatus _sapp_glCheckFramebufferStatus; |
| 2692 | typedef void (GL_APIENTRY *PFN_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); |
| 2693 | static PFN_glFramebufferRenderbuffer _sapp_glFramebufferRenderbuffer; |
| 2694 | typedef void (GL_APIENTRY *PFN_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); |
| 2695 | static PFN_glCompressedTexImage2D _sapp_glCompressedTexImage2D; |
| 2696 | typedef void (GL_APIENTRY *PFN_glCompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); |
| 2697 | static PFN_glCompressedTexImage3D _sapp_glCompressedTexImage3D; |
| 2698 | typedef void (GL_APIENTRY *PFN_glActiveTexture)(GLenum texture); |
| 2699 | static PFN_glActiveTexture _sapp_glActiveTexture; |
| 2700 | typedef void (GL_APIENTRY *PFN_glTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); |
| 2701 | static PFN_glTexSubImage3D _sapp_glTexSubImage3D; |
| 2702 | typedef void (GL_APIENTRY *PFN_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); |
| 2703 | static PFN_glUniformMatrix4fv _sapp_glUniformMatrix4fv; |
| 2704 | typedef void (GL_APIENTRY *PFN_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); |
| 2705 | static PFN_glRenderbufferStorage _sapp_glRenderbufferStorage; |
| 2706 | typedef void (GL_APIENTRY *PFN_glGenTextures)(GLsizei n, GLuint * textures); |
| 2707 | static PFN_glGenTextures _sapp_glGenTextures; |
| 2708 | typedef void (GL_APIENTRY *PFN_glPolygonOffset)(GLfloat factor, GLfloat units); |
| 2709 | static PFN_glPolygonOffset _sapp_glPolygonOffset; |
| 2710 | typedef void (GL_APIENTRY *PFN_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void * indices); |
| 2711 | static PFN_glDrawElements _sapp_glDrawElements; |
| 2712 | typedef void (GL_APIENTRY *PFN_glDeleteFramebuffers)(GLsizei n, const GLuint * framebuffers); |
| 2713 | static PFN_glDeleteFramebuffers _sapp_glDeleteFramebuffers; |
| 2714 | typedef void (GL_APIENTRY *PFN_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); |
| 2715 | static PFN_glBlendEquationSeparate _sapp_glBlendEquationSeparate; |
| 2716 | typedef void (GL_APIENTRY *PFN_glDeleteTextures)(GLsizei n, const GLuint * textures); |
| 2717 | static PFN_glDeleteTextures _sapp_glDeleteTextures; |
| 2718 | typedef void (GL_APIENTRY *PFN_glGetProgramiv)(GLuint program, GLenum pname, GLint * params); |
| 2719 | static PFN_glGetProgramiv _sapp_glGetProgramiv; |
| 2720 | typedef void (GL_APIENTRY *PFN_glBindTexture)(GLenum target, GLuint texture); |
| 2721 | static PFN_glBindTexture _sapp_glBindTexture; |
| 2722 | typedef void (GL_APIENTRY *PFN_glTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); |
| 2723 | static PFN_glTexImage3D _sapp_glTexImage3D; |
| 2724 | typedef GLuint (GL_APIENTRY *PFN_glCreateShader)(GLenum type); |
| 2725 | static PFN_glCreateShader _sapp_glCreateShader; |
| 2726 | typedef void (GL_APIENTRY *PFN_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); |
| 2727 | static PFN_glTexSubImage2D _sapp_glTexSubImage2D; |
| 2728 | typedef void (GL_APIENTRY *PFN_glClearDepth)(GLdouble depth); |
| 2729 | static PFN_glClearDepth _sapp_glClearDepth; |
| 2730 | typedef void (GL_APIENTRY *PFN_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); |
| 2731 | static PFN_glFramebufferTexture2D _sapp_glFramebufferTexture2D; |
| 2732 | typedef GLuint (GL_APIENTRY *PFN_glCreateProgram)(); |
| 2733 | static PFN_glCreateProgram _sapp_glCreateProgram; |
| 2734 | typedef void (GL_APIENTRY *PFN_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height); |
| 2735 | static PFN_glViewport _sapp_glViewport; |
| 2736 | typedef void (GL_APIENTRY *PFN_glDeleteBuffers)(GLsizei n, const GLuint * buffers); |
| 2737 | static PFN_glDeleteBuffers _sapp_glDeleteBuffers; |
| 2738 | typedef void (GL_APIENTRY *PFN_glDrawArrays)(GLenum mode, GLint first, GLsizei count); |
| 2739 | static PFN_glDrawArrays _sapp_glDrawArrays; |
| 2740 | typedef void (GL_APIENTRY *PFN_glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); |
| 2741 | static PFN_glDrawElementsInstanced _sapp_glDrawElementsInstanced; |
| 2742 | typedef void (GL_APIENTRY *PFN_glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); |
| 2743 | static PFN_glVertexAttribPointer _sapp_glVertexAttribPointer; |
| 2744 | typedef void (GL_APIENTRY *PFN_glUniform1i)(GLint location, GLint v0); |
| 2745 | static PFN_glUniform1i _sapp_glUniform1i; |
| 2746 | typedef void (GL_APIENTRY *PFN_glDisable)(GLenum cap); |
| 2747 | static PFN_glDisable _sapp_glDisable; |
| 2748 | typedef void (GL_APIENTRY *PFN_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); |
| 2749 | static PFN_glColorMask _sapp_glColorMask; |
| 2750 | typedef void (GL_APIENTRY *PFN_glBindBuffer)(GLenum target, GLuint buffer); |
| 2751 | static PFN_glBindBuffer _sapp_glBindBuffer; |
| 2752 | typedef void (GL_APIENTRY *PFN_glDeleteVertexArrays)(GLsizei n, const GLuint * arrays); |
| 2753 | static PFN_glDeleteVertexArrays _sapp_glDeleteVertexArrays; |
| 2754 | typedef void (GL_APIENTRY *PFN_glDepthMask)(GLboolean flag); |
| 2755 | static PFN_glDepthMask _sapp_glDepthMask; |
| 2756 | typedef void (GL_APIENTRY *PFN_glDrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); |
| 2757 | static PFN_glDrawArraysInstanced _sapp_glDrawArraysInstanced; |
| 2758 | typedef void (GL_APIENTRY *PFN_glClearStencil)(GLint s); |
| 2759 | static PFN_glClearStencil _sapp_glClearStencil; |
| 2760 | typedef void (GL_APIENTRY *PFN_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height); |
| 2761 | static PFN_glScissor _sapp_glScissor; |
| 2762 | typedef void (GL_APIENTRY *PFN_glUniform3fv)(GLint location, GLsizei count, const GLfloat * value); |
| 2763 | static PFN_glUniform3fv _sapp_glUniform3fv; |
| 2764 | typedef void (GL_APIENTRY *PFN_glGenRenderbuffers)(GLsizei n, GLuint * renderbuffers); |
| 2765 | static PFN_glGenRenderbuffers _sapp_glGenRenderbuffers; |
| 2766 | typedef void (GL_APIENTRY *PFN_glBufferData)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); |
| 2767 | static PFN_glBufferData _sapp_glBufferData; |
| 2768 | typedef void (GL_APIENTRY *PFN_glBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); |
| 2769 | static PFN_glBlendFuncSeparate _sapp_glBlendFuncSeparate; |
| 2770 | typedef void (GL_APIENTRY *PFN_glTexParameteri)(GLenum target, GLenum pname, GLint param); |
| 2771 | static PFN_glTexParameteri _sapp_glTexParameteri; |
| 2772 | typedef void (GL_APIENTRY *PFN_glGetIntegerv)(GLenum pname, GLint * data); |
| 2773 | static PFN_glGetIntegerv _sapp_glGetIntegerv; |
| 2774 | typedef void (GL_APIENTRY *PFN_glEnable)(GLenum cap); |
| 2775 | static PFN_glEnable _sapp_glEnable; |
| 2776 | typedef void (GL_APIENTRY *PFN_glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); |
| 2777 | static PFN_glBlitFramebuffer _sapp_glBlitFramebuffer; |
| 2778 | typedef void (GL_APIENTRY *PFN_glStencilMask)(GLuint mask); |
| 2779 | static PFN_glStencilMask _sapp_glStencilMask; |
| 2780 | typedef void (GL_APIENTRY *PFN_glAttachShader)(GLuint program, GLuint shader); |
| 2781 | static PFN_glAttachShader _sapp_glAttachShader; |
| 2782 | typedef GLenum (GL_APIENTRY *PFN_glGetError)(); |
| 2783 | static PFN_glGetError _sapp_glGetError; |
| 2784 | typedef void (GL_APIENTRY *PFN_glClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); |
| 2785 | static PFN_glClearColor _sapp_glClearColor; |
| 2786 | typedef void (GL_APIENTRY *PFN_glBlendColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); |
| 2787 | static PFN_glBlendColor _sapp_glBlendColor; |
| 2788 | typedef void (GL_APIENTRY *PFN_glTexParameterf)(GLenum target, GLenum pname, GLfloat param); |
| 2789 | static PFN_glTexParameterf _sapp_glTexParameterf; |
| 2790 | typedef void (GL_APIENTRY *PFN_glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); |
| 2791 | static PFN_glGetShaderInfoLog _sapp_glGetShaderInfoLog; |
| 2792 | typedef void (GL_APIENTRY *PFN_glDepthFunc)(GLenum func); |
| 2793 | static PFN_glDepthFunc _sapp_glDepthFunc; |
| 2794 | typedef void (GL_APIENTRY *PFN_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass); |
| 2795 | static PFN_glStencilOp _sapp_glStencilOp; |
| 2796 | typedef void (GL_APIENTRY *PFN_glStencilFunc)(GLenum func, GLint ref, GLuint mask); |
| 2797 | static PFN_glStencilFunc _sapp_glStencilFunc; |
| 2798 | typedef void (GL_APIENTRY *PFN_glEnableVertexAttribArray)(GLuint index); |
| 2799 | static PFN_glEnableVertexAttribArray _sapp_glEnableVertexAttribArray; |
| 2800 | typedef void (GL_APIENTRY *PFN_glBlendFunc)(GLenum sfactor, GLenum dfactor); |
| 2801 | static PFN_glBlendFunc _sapp_glBlendFunc; |
| 2802 | typedef void (GL_APIENTRY *PFN_glUniform1fv)(GLint location, GLsizei count, const GLfloat * value); |
| 2803 | static PFN_glUniform1fv _sapp_glUniform1fv; |
| 2804 | typedef void (GL_APIENTRY *PFN_glReadBuffer)(GLenum src); |
| 2805 | static PFN_glReadBuffer _sapp_glReadBuffer; |
| 2806 | typedef void (GL_APIENTRY *PFN_glClear)(GLbitfield mask); |
| 2807 | static PFN_glClear _sapp_glClear; |
| 2808 | typedef void (GL_APIENTRY *PFN_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); |
| 2809 | static PFN_glTexImage2D _sapp_glTexImage2D; |
| 2810 | typedef void (GL_APIENTRY *PFN_glGenVertexArrays)(GLsizei n, GLuint * arrays); |
| 2811 | static PFN_glGenVertexArrays _sapp_glGenVertexArrays; |
| 2812 | typedef void (GL_APIENTRY *PFN_glFrontFace)(GLenum mode); |
| 2813 | static PFN_glFrontFace _sapp_glFrontFace; |
| 2814 | typedef void (GL_APIENTRY *PFN_glCullFace)(GLenum mode); |
| 2815 | static PFN_glCullFace _sapp_glCullFace; |
| 2816 | |
| 2817 | _SOKOL_PRIVATE void* _sapp_win32_glgetprocaddr(const char* name) { |
| 2818 | void* proc_addr = (void*) _sapp_wglGetProcAddress(name); |
| 2819 | if (0 == proc_addr) { |
| 2820 | proc_addr = (void*) GetProcAddress(_sapp_opengl32, name); |
| 2821 | } |
| 2822 | SOKOL_ASSERT(proc_addr); |
| 2823 | return proc_addr; |
| 2824 | } |
| 2825 | |
| 2826 | #define _SAPP_GLPROC(name) _sapp_ ## name = (PFN_ ## name) _sapp_win32_glgetprocaddr(#name) |
| 2827 | |
| 2828 | _SOKOL_PRIVATE void _sapp_win32_gl_loadfuncs(void) { |
| 2829 | SOKOL_ASSERT(_sapp_wglGetProcAddress); |
| 2830 | SOKOL_ASSERT(_sapp_opengl32); |
| 2831 | _SAPP_GLPROC(glBindVertexArray); |
| 2832 | _SAPP_GLPROC(glFramebufferTextureLayer); |
| 2833 | _SAPP_GLPROC(glGenFramebuffers); |
| 2834 | _SAPP_GLPROC(glBindFramebuffer); |
| 2835 | _SAPP_GLPROC(glBindRenderbuffer); |
| 2836 | _SAPP_GLPROC(glGetStringi); |
| 2837 | _SAPP_GLPROC(glClearBufferfi); |
| 2838 | _SAPP_GLPROC(glClearBufferfv); |
| 2839 | _SAPP_GLPROC(glClearBufferuiv); |
| 2840 | _SAPP_GLPROC(glDeleteRenderbuffers); |
| 2841 | _SAPP_GLPROC(glUniform4fv); |
| 2842 | _SAPP_GLPROC(glUniform2fv); |
| 2843 | _SAPP_GLPROC(glUseProgram); |
| 2844 | _SAPP_GLPROC(glShaderSource); |
| 2845 | _SAPP_GLPROC(glLinkProgram); |
| 2846 | _SAPP_GLPROC(glGetUniformLocation); |
| 2847 | _SAPP_GLPROC(glGetShaderiv); |
| 2848 | _SAPP_GLPROC(glGetProgramInfoLog); |
| 2849 | _SAPP_GLPROC(glGetAttribLocation); |
| 2850 | _SAPP_GLPROC(glDisableVertexAttribArray); |
| 2851 | _SAPP_GLPROC(glDeleteShader); |
| 2852 | _SAPP_GLPROC(glDeleteProgram); |
| 2853 | _SAPP_GLPROC(glCompileShader); |
| 2854 | _SAPP_GLPROC(glStencilFuncSeparate); |
| 2855 | _SAPP_GLPROC(glStencilOpSeparate); |
| 2856 | _SAPP_GLPROC(glRenderbufferStorageMultisample); |
| 2857 | _SAPP_GLPROC(glDrawBuffers); |
| 2858 | _SAPP_GLPROC(glVertexAttribDivisor); |
| 2859 | _SAPP_GLPROC(glBufferSubData); |
| 2860 | _SAPP_GLPROC(glGenBuffers); |
| 2861 | _SAPP_GLPROC(glCheckFramebufferStatus); |
| 2862 | _SAPP_GLPROC(glFramebufferRenderbuffer); |
| 2863 | _SAPP_GLPROC(glCompressedTexImage2D); |
| 2864 | _SAPP_GLPROC(glCompressedTexImage3D); |
| 2865 | _SAPP_GLPROC(glActiveTexture); |
| 2866 | _SAPP_GLPROC(glTexSubImage3D); |
| 2867 | _SAPP_GLPROC(glUniformMatrix4fv); |
| 2868 | _SAPP_GLPROC(glRenderbufferStorage); |
| 2869 | _SAPP_GLPROC(glGenTextures); |
| 2870 | _SAPP_GLPROC(glPolygonOffset); |
| 2871 | _SAPP_GLPROC(glDrawElements); |
| 2872 | _SAPP_GLPROC(glDeleteFramebuffers); |
| 2873 | _SAPP_GLPROC(glBlendEquationSeparate); |
| 2874 | _SAPP_GLPROC(glDeleteTextures); |
| 2875 | _SAPP_GLPROC(glGetProgramiv); |
| 2876 | _SAPP_GLPROC(glBindTexture); |
| 2877 | _SAPP_GLPROC(glTexImage3D); |
| 2878 | _SAPP_GLPROC(glCreateShader); |
| 2879 | _SAPP_GLPROC(glTexSubImage2D); |
| 2880 | _SAPP_GLPROC(glClearDepth); |
| 2881 | _SAPP_GLPROC(glFramebufferTexture2D); |
| 2882 | _SAPP_GLPROC(glCreateProgram); |
| 2883 | _SAPP_GLPROC(glViewport); |
| 2884 | _SAPP_GLPROC(glDeleteBuffers); |
| 2885 | _SAPP_GLPROC(glDrawArrays); |
| 2886 | _SAPP_GLPROC(glDrawElementsInstanced); |
| 2887 | _SAPP_GLPROC(glVertexAttribPointer); |
| 2888 | _SAPP_GLPROC(glUniform1i); |
| 2889 | _SAPP_GLPROC(glDisable); |
| 2890 | _SAPP_GLPROC(glColorMask); |
| 2891 | _SAPP_GLPROC(glBindBuffer); |
| 2892 | _SAPP_GLPROC(glDeleteVertexArrays); |
| 2893 | _SAPP_GLPROC(glDepthMask); |
| 2894 | _SAPP_GLPROC(glDrawArraysInstanced); |
| 2895 | _SAPP_GLPROC(glClearStencil); |
| 2896 | _SAPP_GLPROC(glScissor); |
| 2897 | _SAPP_GLPROC(glUniform3fv); |
| 2898 | _SAPP_GLPROC(glGenRenderbuffers); |
| 2899 | _SAPP_GLPROC(glBufferData); |
| 2900 | _SAPP_GLPROC(glBlendFuncSeparate); |
| 2901 | _SAPP_GLPROC(glTexParameteri); |
| 2902 | _SAPP_GLPROC(glGetIntegerv); |
| 2903 | _SAPP_GLPROC(glEnable); |
| 2904 | _SAPP_GLPROC(glBlitFramebuffer); |
| 2905 | _SAPP_GLPROC(glStencilMask); |
| 2906 | _SAPP_GLPROC(glAttachShader); |
| 2907 | _SAPP_GLPROC(glGetError); |
| 2908 | _SAPP_GLPROC(glClearColor); |
| 2909 | _SAPP_GLPROC(glBlendColor); |
| 2910 | _SAPP_GLPROC(glTexParameterf); |
| 2911 | _SAPP_GLPROC(glGetShaderInfoLog); |
| 2912 | _SAPP_GLPROC(glDepthFunc); |
| 2913 | _SAPP_GLPROC(glStencilOp); |
| 2914 | _SAPP_GLPROC(glStencilFunc); |
| 2915 | _SAPP_GLPROC(glEnableVertexAttribArray); |
| 2916 | _SAPP_GLPROC(glBlendFunc); |
| 2917 | _SAPP_GLPROC(glUniform1fv); |
| 2918 | _SAPP_GLPROC(glReadBuffer); |
| 2919 | _SAPP_GLPROC(glClear); |
| 2920 | _SAPP_GLPROC(glTexImage2D); |
| 2921 | _SAPP_GLPROC(glGenVertexArrays); |
| 2922 | _SAPP_GLPROC(glFrontFace); |
| 2923 | _SAPP_GLPROC(glCullFace); |
| 2924 | } |
| 2925 | #define glBindVertexArray _sapp_glBindVertexArray |
| 2926 | #define glFramebufferTextureLayer _sapp_glFramebufferTextureLayer |
| 2927 | #define glGenFramebuffers _sapp_glGenFramebuffers |
| 2928 | #define glBindFramebuffer _sapp_glBindFramebuffer |
| 2929 | #define glBindRenderbuffer _sapp_glBindRenderbuffer |
| 2930 | #define glGetStringi _sapp_glGetStringi |
| 2931 | #define glClearBufferfi _sapp_glClearBufferfi |
| 2932 | #define glClearBufferfv _sapp_glClearBufferfv |
| 2933 | #define glClearBufferuiv _sapp_glClearBufferuiv |
| 2934 | #define glDeleteRenderbuffers _sapp_glDeleteRenderbuffers |
| 2935 | #define glUniform4fv _sapp_glUniform4fv |
| 2936 | #define glUniform2fv _sapp_glUniform2fv |
| 2937 | #define glUseProgram _sapp_glUseProgram |
| 2938 | #define glShaderSource _sapp_glShaderSource |
| 2939 | #define glLinkProgram _sapp_glLinkProgram |
| 2940 | #define glGetUniformLocation _sapp_glGetUniformLocation |
| 2941 | #define glGetShaderiv _sapp_glGetShaderiv |
| 2942 | #define glGetProgramInfoLog _sapp_glGetProgramInfoLog |
| 2943 | #define glGetAttribLocation _sapp_glGetAttribLocation |
| 2944 | #define glDisableVertexAttribArray _sapp_glDisableVertexAttribArray |
| 2945 | #define glDeleteShader _sapp_glDeleteShader |
| 2946 | #define glDeleteProgram _sapp_glDeleteProgram |
| 2947 | #define glCompileShader _sapp_glCompileShader |
| 2948 | #define glStencilFuncSeparate _sapp_glStencilFuncSeparate |
| 2949 | #define glStencilOpSeparate _sapp_glStencilOpSeparate |
| 2950 | #define glRenderbufferStorageMultisample _sapp_glRenderbufferStorageMultisample |
| 2951 | #define glDrawBuffers _sapp_glDrawBuffers |
| 2952 | #define glVertexAttribDivisor _sapp_glVertexAttribDivisor |
| 2953 | #define glBufferSubData _sapp_glBufferSubData |
| 2954 | #define glGenBuffers _sapp_glGenBuffers |
| 2955 | #define glCheckFramebufferStatus _sapp_glCheckFramebufferStatus |
| 2956 | #define glFramebufferRenderbuffer _sapp_glFramebufferRenderbuffer |
| 2957 | #define glCompressedTexImage2D _sapp_glCompressedTexImage2D |
| 2958 | #define glCompressedTexImage3D _sapp_glCompressedTexImage3D |
| 2959 | #define glActiveTexture _sapp_glActiveTexture |
| 2960 | #define glTexSubImage3D _sapp_glTexSubImage3D |
| 2961 | #define glUniformMatrix4fv _sapp_glUniformMatrix4fv |
| 2962 | #define glRenderbufferStorage _sapp_glRenderbufferStorage |
| 2963 | #define glGenTextures _sapp_glGenTextures |
| 2964 | #define glPolygonOffset _sapp_glPolygonOffset |
| 2965 | #define glDrawElements _sapp_glDrawElements |
| 2966 | #define glDeleteFramebuffers _sapp_glDeleteFramebuffers |
| 2967 | #define glBlendEquationSeparate _sapp_glBlendEquationSeparate |
| 2968 | #define glDeleteTextures _sapp_glDeleteTextures |
| 2969 | #define glGetProgramiv _sapp_glGetProgramiv |
| 2970 | #define glBindTexture _sapp_glBindTexture |
| 2971 | #define glTexImage3D _sapp_glTexImage3D |
| 2972 | #define glCreateShader _sapp_glCreateShader |
| 2973 | #define glTexSubImage2D _sapp_glTexSubImage2D |
| 2974 | #define glClearDepth _sapp_glClearDepth |
| 2975 | #define glFramebufferTexture2D _sapp_glFramebufferTexture2D |
| 2976 | #define glCreateProgram _sapp_glCreateProgram |
| 2977 | #define glViewport _sapp_glViewport |
| 2978 | #define glDeleteBuffers _sapp_glDeleteBuffers |
| 2979 | #define glDrawArrays _sapp_glDrawArrays |
| 2980 | #define glDrawElementsInstanced _sapp_glDrawElementsInstanced |
| 2981 | #define glVertexAttribPointer _sapp_glVertexAttribPointer |
| 2982 | #define glUniform1i _sapp_glUniform1i |
| 2983 | #define glDisable _sapp_glDisable |
| 2984 | #define glColorMask _sapp_glColorMask |
| 2985 | #define glBindBuffer _sapp_glBindBuffer |
| 2986 | #define glDeleteVertexArrays _sapp_glDeleteVertexArrays |
| 2987 | #define glDepthMask _sapp_glDepthMask |
| 2988 | #define glDrawArraysInstanced _sapp_glDrawArraysInstanced |
| 2989 | #define glClearStencil _sapp_glClearStencil |
| 2990 | #define glScissor _sapp_glScissor |
| 2991 | #define glUniform3fv _sapp_glUniform3fv |
| 2992 | #define glGenRenderbuffers _sapp_glGenRenderbuffers |
| 2993 | #define glBufferData _sapp_glBufferData |
| 2994 | #define glBlendFuncSeparate _sapp_glBlendFuncSeparate |
| 2995 | #define glTexParameteri _sapp_glTexParameteri |
| 2996 | #define glGetIntegerv _sapp_glGetIntegerv |
| 2997 | #define glEnable _sapp_glEnable |
| 2998 | #define glBlitFramebuffer _sapp_glBlitFramebuffer |
| 2999 | #define glStencilMask _sapp_glStencilMask |
| 3000 | #define glAttachShader _sapp_glAttachShader |
| 3001 | #define glGetError _sapp_glGetError |
| 3002 | #define glClearColor _sapp_glClearColor |
| 3003 | #define glBlendColor _sapp_glBlendColor |
| 3004 | #define glTexParameterf _sapp_glTexParameterf |
| 3005 | #define glGetShaderInfoLog _sapp_glGetShaderInfoLog |
| 3006 | #define glDepthFunc _sapp_glDepthFunc |
| 3007 | #define glStencilOp _sapp_glStencilOp |
| 3008 | #define glStencilFunc _sapp_glStencilFunc |
| 3009 | #define glEnableVertexAttribArray _sapp_glEnableVertexAttribArray |
| 3010 | #define glBlendFunc _sapp_glBlendFunc |
| 3011 | #define glUniform1fv _sapp_glUniform1fv |
| 3012 | #define glReadBuffer _sapp_glReadBuffer |
| 3013 | #define glClear _sapp_glClear |
| 3014 | #define glTexImage2D _sapp_glTexImage2D |
| 3015 | #define glGenVertexArrays _sapp_glGenVertexArrays |
| 3016 | #define glFrontFace _sapp_glFrontFace |
| 3017 | #define glCullFace _sapp_glCullFace |
| 3018 | |
| 3019 | #endif /* SOKOL_WIN32_NO_GL_LOADER */ |
| 3020 | |
| 3021 | #endif /* SOKOL_GLCORE33 */ |
| 3022 | |
| 3023 | #if defined(SOKOL_D3D11) |
| 3024 | #define _SAPP_SAFE_RELEASE(class, obj) if (obj) { class##_Release(obj); obj=0; } |
| 3025 | _SOKOL_PRIVATE void _sapp_d3d11_create_device_and_swapchain(void) { |
| 3026 | DXGI_SWAP_CHAIN_DESC* sc_desc = &_sapp_dxgi_swap_chain_desc; |
| 3027 | sc_desc->BufferDesc.Width = _sapp.framebuffer_width; |
| 3028 | sc_desc->BufferDesc.Height = _sapp.framebuffer_height; |
| 3029 | sc_desc->BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; |
| 3030 | sc_desc->BufferDesc.RefreshRate.Numerator = 60; |
| 3031 | sc_desc->BufferDesc.RefreshRate.Denominator = 1; |
| 3032 | sc_desc->OutputWindow = _sapp_win32_hwnd; |
| 3033 | sc_desc->Windowed = true; |
| 3034 | sc_desc->SwapEffect = DXGI_SWAP_EFFECT_DISCARD; |
| 3035 | sc_desc->BufferCount = 1; |
| 3036 | sc_desc->SampleDesc.Count = _sapp.sample_count; |
| 3037 | sc_desc->SampleDesc.Quality = _sapp.sample_count > 1 ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0; |
| 3038 | sc_desc->BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
| 3039 | int create_flags = D3D11_CREATE_DEVICE_SINGLETHREADED; |
| 3040 | #if defined(SOKOL_DEBUG) |
| 3041 | create_flags |= D3D11_CREATE_DEVICE_DEBUG; |
| 3042 | #endif |
| 3043 | D3D_FEATURE_LEVEL feature_level; |
| 3044 | HRESULT hr = D3D11CreateDeviceAndSwapChain( |
| 3045 | NULL, /* pAdapter (use default) */ |
| 3046 | D3D_DRIVER_TYPE_HARDWARE, /* DriverType */ |
| 3047 | NULL, /* Software */ |
| 3048 | create_flags, /* Flags */ |
| 3049 | NULL, /* pFeatureLevels */ |
| 3050 | 0, /* FeatureLevels */ |
| 3051 | D3D11_SDK_VERSION, /* SDKVersion */ |
| 3052 | sc_desc, /* pSwapChainDesc */ |
| 3053 | &_sapp_dxgi_swap_chain, /* ppSwapChain */ |
| 3054 | &_sapp_d3d11_device, /* ppDevice */ |
| 3055 | &feature_level, /* pFeatureLevel */ |
| 3056 | &_sapp_d3d11_device_context); /* ppImmediateContext */ |
| 3057 | _SOKOL_UNUSED(hr); |
| 3058 | SOKOL_ASSERT(SUCCEEDED(hr) && _sapp_dxgi_swap_chain && _sapp_d3d11_device && _sapp_d3d11_device_context); |
| 3059 | } |
| 3060 | |
| 3061 | _SOKOL_PRIVATE void _sapp_d3d11_destroy_device_and_swapchain(void) { |
| 3062 | _SAPP_SAFE_RELEASE(IDXGISwapChain, _sapp_dxgi_swap_chain); |
| 3063 | _SAPP_SAFE_RELEASE(ID3D11DeviceContext, _sapp_d3d11_device_context); |
| 3064 | _SAPP_SAFE_RELEASE(ID3D11Device, _sapp_d3d11_device); |
| 3065 | } |
| 3066 | |
| 3067 | _SOKOL_PRIVATE void _sapp_d3d11_create_default_render_target(void) { |
| 3068 | HRESULT hr; |
| 3069 | #ifdef __cplusplus |
| 3070 | hr = IDXGISwapChain_GetBuffer(_sapp_dxgi_swap_chain, 0, IID_ID3D11Texture2D, (void**)&_sapp_d3d11_rt); |
| 3071 | #else |
| 3072 | hr = IDXGISwapChain_GetBuffer(_sapp_dxgi_swap_chain, 0, &IID_ID3D11Texture2D, (void**)&_sapp_d3d11_rt); |
| 3073 | #endif |
| 3074 | SOKOL_ASSERT(SUCCEEDED(hr) && _sapp_d3d11_rt); |
| 3075 | hr = ID3D11Device_CreateRenderTargetView(_sapp_d3d11_device, (ID3D11Resource*)_sapp_d3d11_rt, NULL, &_sapp_d3d11_rtv); |
| 3076 | SOKOL_ASSERT(SUCCEEDED(hr) && _sapp_d3d11_rtv); |
| 3077 | D3D11_TEXTURE2D_DESC ds_desc; |
| 3078 | memset(&ds_desc, 0, sizeof(ds_desc)); |
| 3079 | ds_desc.Width = _sapp.framebuffer_width; |
| 3080 | ds_desc.Height = _sapp.framebuffer_height; |
| 3081 | ds_desc.MipLevels = 1; |
| 3082 | ds_desc.ArraySize = 1; |
| 3083 | ds_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; |
| 3084 | ds_desc.SampleDesc = _sapp_dxgi_swap_chain_desc.SampleDesc; |
| 3085 | ds_desc.Usage = D3D11_USAGE_DEFAULT; |
| 3086 | ds_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; |
| 3087 | hr = ID3D11Device_CreateTexture2D(_sapp_d3d11_device, &ds_desc, NULL, &_sapp_d3d11_ds); |
| 3088 | SOKOL_ASSERT(SUCCEEDED(hr) && _sapp_d3d11_ds); |
| 3089 | D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc; |
| 3090 | memset(&dsv_desc, 0, sizeof(dsv_desc)); |
| 3091 | dsv_desc.Format = ds_desc.Format; |
| 3092 | dsv_desc.ViewDimension = _sapp.sample_count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; |
| 3093 | hr = ID3D11Device_CreateDepthStencilView(_sapp_d3d11_device, (ID3D11Resource*)_sapp_d3d11_ds, &dsv_desc, &_sapp_d3d11_dsv); |
| 3094 | SOKOL_ASSERT(SUCCEEDED(hr) && _sapp_d3d11_dsv); |
| 3095 | } |
| 3096 | |
| 3097 | _SOKOL_PRIVATE void _sapp_d3d11_destroy_default_render_target(void) { |
| 3098 | _SAPP_SAFE_RELEASE(ID3D11Texture2D, _sapp_d3d11_rt); |
| 3099 | _SAPP_SAFE_RELEASE(ID3D11RenderTargetView, _sapp_d3d11_rtv); |
| 3100 | _SAPP_SAFE_RELEASE(ID3D11Texture2D, _sapp_d3d11_ds); |
| 3101 | _SAPP_SAFE_RELEASE(ID3D11DepthStencilView, _sapp_d3d11_dsv); |
| 3102 | } |
| 3103 | |
| 3104 | _SOKOL_PRIVATE void _sapp_d3d11_resize_default_render_target(void) { |
| 3105 | if (_sapp_dxgi_swap_chain) { |
| 3106 | _sapp_d3d11_destroy_default_render_target(); |
| 3107 | IDXGISwapChain_ResizeBuffers(_sapp_dxgi_swap_chain, 1, _sapp.framebuffer_width, _sapp.framebuffer_height, DXGI_FORMAT_R8G8B8A8_UNORM, 0); |
| 3108 | _sapp_d3d11_create_default_render_target(); |
| 3109 | } |
| 3110 | } |
| 3111 | #endif |
| 3112 | |
| 3113 | #if defined(SOKOL_GLCORE33) |
| 3114 | _SOKOL_PRIVATE void _sapp_wgl_init(void) { |
| 3115 | _sapp_opengl32 = LoadLibraryA("opengl32.dll" ); |
| 3116 | if (!_sapp_opengl32) { |
| 3117 | _sapp_fail("Failed to load opengl32.dll\n" ); |
| 3118 | } |
| 3119 | SOKOL_ASSERT(_sapp_opengl32); |
| 3120 | _sapp_wglCreateContext = (PFN_wglCreateContext) GetProcAddress(_sapp_opengl32, "wglCreateContext" ); |
| 3121 | SOKOL_ASSERT(_sapp_wglCreateContext); |
| 3122 | _sapp_wglDeleteContext = (PFN_wglDeleteContext) GetProcAddress(_sapp_opengl32, "wglDeleteContext" ); |
| 3123 | SOKOL_ASSERT(_sapp_wglDeleteContext); |
| 3124 | _sapp_wglGetProcAddress = (PFN_wglGetProcAddress) GetProcAddress(_sapp_opengl32, "wglGetProcAddress" ); |
| 3125 | SOKOL_ASSERT(_sapp_wglGetProcAddress); |
| 3126 | _sapp_wglGetCurrentDC = (PFN_wglGetCurrentDC) GetProcAddress(_sapp_opengl32, "wglGetCurrentDC" ); |
| 3127 | SOKOL_ASSERT(_sapp_wglGetCurrentDC); |
| 3128 | _sapp_wglMakeCurrent = (PFN_wglMakeCurrent) GetProcAddress(_sapp_opengl32, "wglMakeCurrent" ); |
| 3129 | SOKOL_ASSERT(_sapp_wglMakeCurrent); |
| 3130 | |
| 3131 | _sapp_win32_msg_hwnd = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, |
| 3132 | L"SOKOLAPP" , |
| 3133 | L"sokol-app message window" , |
| 3134 | WS_CLIPSIBLINGS|WS_CLIPCHILDREN, |
| 3135 | 0, 0, 1, 1, |
| 3136 | NULL, NULL, |
| 3137 | GetModuleHandleW(NULL), |
| 3138 | NULL); |
| 3139 | if (!_sapp_win32_msg_hwnd) { |
| 3140 | _sapp_fail("Win32: failed to create helper window!\n" ); |
| 3141 | } |
| 3142 | ShowWindow(_sapp_win32_msg_hwnd, SW_HIDE); |
| 3143 | MSG msg; |
| 3144 | while (PeekMessageW(&msg, _sapp_win32_msg_hwnd, 0, 0, PM_REMOVE)) { |
| 3145 | TranslateMessage(&msg); |
| 3146 | DispatchMessageW(&msg); |
| 3147 | } |
| 3148 | _sapp_win32_msg_dc = GetDC(_sapp_win32_msg_hwnd); |
| 3149 | if (!_sapp_win32_msg_dc) { |
| 3150 | _sapp_fail("Win32: failed to obtain helper window DC!\n" ); |
| 3151 | } |
| 3152 | } |
| 3153 | |
| 3154 | _SOKOL_PRIVATE void _sapp_wgl_shutdown(void) { |
| 3155 | SOKOL_ASSERT(_sapp_opengl32 && _sapp_win32_msg_hwnd); |
| 3156 | DestroyWindow(_sapp_win32_msg_hwnd); _sapp_win32_msg_hwnd = 0; |
| 3157 | FreeLibrary(_sapp_opengl32); _sapp_opengl32 = 0; |
| 3158 | } |
| 3159 | |
| 3160 | _SOKOL_PRIVATE bool _sapp_wgl_has_ext(const char* ext, const char* extensions) { |
| 3161 | SOKOL_ASSERT(ext && extensions); |
| 3162 | const char* start = extensions; |
| 3163 | while (true) { |
| 3164 | const char* where = strstr(start, ext); |
| 3165 | if (!where) { |
| 3166 | return false; |
| 3167 | } |
| 3168 | const char* terminator = where + strlen(ext); |
| 3169 | if ((where == start) || (*(where - 1) == ' ')) { |
| 3170 | if (*terminator == ' ' || *terminator == '\0') { |
| 3171 | break; |
| 3172 | } |
| 3173 | } |
| 3174 | start = terminator; |
| 3175 | } |
| 3176 | return true; |
| 3177 | } |
| 3178 | |
| 3179 | _SOKOL_PRIVATE bool _sapp_wgl_ext_supported(const char* ext) { |
| 3180 | SOKOL_ASSERT(ext); |
| 3181 | if (_sapp_GetExtensionsStringEXT) { |
| 3182 | const char* extensions = _sapp_GetExtensionsStringEXT(); |
| 3183 | if (extensions) { |
| 3184 | if (_sapp_wgl_has_ext(ext, extensions)) { |
| 3185 | return true; |
| 3186 | } |
| 3187 | } |
| 3188 | } |
| 3189 | if (_sapp_GetExtensionsStringARB) { |
| 3190 | const char* extensions = _sapp_GetExtensionsStringARB(_sapp_wglGetCurrentDC()); |
| 3191 | if (extensions) { |
| 3192 | if (_sapp_wgl_has_ext(ext, extensions)) { |
| 3193 | return true; |
| 3194 | } |
| 3195 | } |
| 3196 | } |
| 3197 | return false; |
| 3198 | } |
| 3199 | |
| 3200 | _SOKOL_PRIVATE void _sapp_wgl_load_extensions(void) { |
| 3201 | SOKOL_ASSERT(_sapp_win32_msg_dc); |
| 3202 | PIXELFORMATDESCRIPTOR pfd; |
| 3203 | memset(&pfd, 0, sizeof(pfd)); |
| 3204 | pfd.nSize = sizeof(pfd); |
| 3205 | pfd.nVersion = 1; |
| 3206 | pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; |
| 3207 | pfd.iPixelType = PFD_TYPE_RGBA; |
| 3208 | pfd.cColorBits = 24; |
| 3209 | if (!SetPixelFormat(_sapp_win32_msg_dc, ChoosePixelFormat(_sapp_win32_msg_dc, &pfd), &pfd)) { |
| 3210 | _sapp_fail("WGL: failed to set pixel format for dummy context\n" ); |
| 3211 | } |
| 3212 | HGLRC rc = _sapp_wglCreateContext(_sapp_win32_msg_dc); |
| 3213 | if (!rc) { |
| 3214 | _sapp_fail("WGL: Failed to create dummy context\n" ); |
| 3215 | } |
| 3216 | if (!_sapp_wglMakeCurrent(_sapp_win32_msg_dc, rc)) { |
| 3217 | _sapp_fail("WGL: Failed to make context current\n" ); |
| 3218 | } |
| 3219 | _sapp_GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) _sapp_wglGetProcAddress("wglGetExtensionsStringEXT" ); |
| 3220 | _sapp_GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) _sapp_wglGetProcAddress("wglGetExtensionsStringARB" ); |
| 3221 | _sapp_CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) _sapp_wglGetProcAddress("wglCreateContextAttribsARB" ); |
| 3222 | _sapp_SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) _sapp_wglGetProcAddress("wglSwapIntervalEXT" ); |
| 3223 | _sapp_GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) _sapp_wglGetProcAddress("wglGetPixelFormatAttribivARB" ); |
| 3224 | _sapp_arb_multisample = _sapp_wgl_ext_supported("WGL_ARB_multisample" ); |
| 3225 | _sapp_arb_create_context = _sapp_wgl_ext_supported("WGL_ARB_create_context" ); |
| 3226 | _sapp_arb_create_context_profile = _sapp_wgl_ext_supported("WGL_ARB_create_context_profile" ); |
| 3227 | _sapp_ext_swap_control = _sapp_wgl_ext_supported("WGL_EXT_swap_control" ); |
| 3228 | _sapp_arb_pixel_format = _sapp_wgl_ext_supported("WGL_ARB_pixel_format" ); |
| 3229 | _sapp_wglMakeCurrent(_sapp_win32_msg_dc, 0); |
| 3230 | _sapp_wglDeleteContext(rc); |
| 3231 | } |
| 3232 | |
| 3233 | _SOKOL_PRIVATE int _sapp_wgl_attrib(int pixel_format, int attrib) { |
| 3234 | SOKOL_ASSERT(_sapp_arb_pixel_format); |
| 3235 | int value = 0; |
| 3236 | if (!_sapp_GetPixelFormatAttribivARB(_sapp_win32_dc, pixel_format, 0, 1, &attrib, &value)) { |
| 3237 | _sapp_fail("WGL: Failed to retrieve pixel format attribute\n" ); |
| 3238 | } |
| 3239 | return value; |
| 3240 | } |
| 3241 | |
| 3242 | _SOKOL_PRIVATE int _sapp_wgl_find_pixel_format(void) { |
| 3243 | SOKOL_ASSERT(_sapp_win32_dc); |
| 3244 | SOKOL_ASSERT(_sapp_arb_pixel_format); |
| 3245 | const _sapp_gl_fbconfig* closest; |
| 3246 | |
| 3247 | int native_count = _sapp_wgl_attrib(1, WGL_NUMBER_PIXEL_FORMATS_ARB); |
| 3248 | _sapp_gl_fbconfig* usable_configs = (_sapp_gl_fbconfig*) SOKOL_CALLOC(native_count, sizeof(_sapp_gl_fbconfig)); |
| 3249 | int usable_count = 0; |
| 3250 | for (int i = 0; i < native_count; i++) { |
| 3251 | const int n = i + 1; |
| 3252 | _sapp_gl_fbconfig* u = usable_configs + usable_count; |
| 3253 | _sapp_gl_init_fbconfig(u); |
| 3254 | if (!_sapp_wgl_attrib(n, WGL_SUPPORT_OPENGL_ARB) || !_sapp_wgl_attrib(n, WGL_DRAW_TO_WINDOW_ARB)) { |
| 3255 | continue; |
| 3256 | } |
| 3257 | if (_sapp_wgl_attrib(n, WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB) { |
| 3258 | continue; |
| 3259 | } |
| 3260 | if (_sapp_wgl_attrib(n, WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB) { |
| 3261 | continue; |
| 3262 | } |
| 3263 | u->red_bits = _sapp_wgl_attrib(n, WGL_RED_BITS_ARB); |
| 3264 | u->green_bits = _sapp_wgl_attrib(n, WGL_GREEN_BITS_ARB); |
| 3265 | u->blue_bits = _sapp_wgl_attrib(n, WGL_BLUE_BITS_ARB); |
| 3266 | u->alpha_bits = _sapp_wgl_attrib(n, WGL_ALPHA_BITS_ARB); |
| 3267 | u->depth_bits = _sapp_wgl_attrib(n, WGL_DEPTH_BITS_ARB); |
| 3268 | u->stencil_bits = _sapp_wgl_attrib(n, WGL_STENCIL_BITS_ARB); |
| 3269 | if (_sapp_wgl_attrib(n, WGL_DOUBLE_BUFFER_ARB)) { |
| 3270 | u->doublebuffer = true; |
| 3271 | } |
| 3272 | if (_sapp_arb_multisample) { |
| 3273 | u->samples = _sapp_wgl_attrib(n, WGL_SAMPLES_ARB); |
| 3274 | } |
| 3275 | u->handle = n; |
| 3276 | usable_count++; |
| 3277 | } |
| 3278 | SOKOL_ASSERT(usable_count > 0); |
| 3279 | _sapp_gl_fbconfig desired; |
| 3280 | _sapp_gl_init_fbconfig(&desired); |
| 3281 | desired.red_bits = 8; |
| 3282 | desired.green_bits = 8; |
| 3283 | desired.blue_bits = 8; |
| 3284 | desired.alpha_bits = 8; |
| 3285 | desired.depth_bits = 24; |
| 3286 | desired.stencil_bits = 8; |
| 3287 | desired.doublebuffer = true; |
| 3288 | desired.samples = _sapp.sample_count > 1 ? _sapp.sample_count : 0; |
| 3289 | closest = _sapp_gl_choose_fbconfig(&desired, usable_configs, usable_count); |
| 3290 | int pixel_format = 0; |
| 3291 | if (closest) { |
| 3292 | pixel_format = (int) closest->handle; |
| 3293 | } |
| 3294 | SOKOL_FREE(usable_configs); |
| 3295 | return pixel_format; |
| 3296 | } |
| 3297 | |
| 3298 | _SOKOL_PRIVATE void _sapp_wgl_create_context(void) { |
| 3299 | int pixel_format = _sapp_wgl_find_pixel_format(); |
| 3300 | if (0 == pixel_format) { |
| 3301 | _sapp_fail("WGL: Didn't find matching pixel format.\n" ); |
| 3302 | } |
| 3303 | PIXELFORMATDESCRIPTOR pfd; |
| 3304 | if (!DescribePixelFormat(_sapp_win32_dc, pixel_format, sizeof(pfd), &pfd)) { |
| 3305 | _sapp_fail("WGL: Failed to retrieve PFD for selected pixel format!\n" ); |
| 3306 | } |
| 3307 | if (!SetPixelFormat(_sapp_win32_dc, pixel_format, &pfd)) { |
| 3308 | _sapp_fail("WGL: Failed to set selected pixel format!\n" ); |
| 3309 | } |
| 3310 | if (!_sapp_arb_create_context) { |
| 3311 | _sapp_fail("WGL: ARB_create_context required!\n" ); |
| 3312 | } |
| 3313 | if (!_sapp_arb_create_context_profile) { |
| 3314 | _sapp_fail("WGL: ARB_create_context_profile required!\n" ); |
| 3315 | } |
| 3316 | const int attrs[] = { |
| 3317 | WGL_CONTEXT_MAJOR_VERSION_ARB, 3, |
| 3318 | WGL_CONTEXT_MINOR_VERSION_ARB, 3, |
| 3319 | WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, |
| 3320 | WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, |
| 3321 | 0, 0 |
| 3322 | }; |
| 3323 | _sapp_gl_ctx = _sapp_CreateContextAttribsARB(_sapp_win32_dc, 0, attrs); |
| 3324 | if (!_sapp_gl_ctx) { |
| 3325 | const DWORD err = GetLastError(); |
| 3326 | if (err == (0xc0070000 | ERROR_INVALID_VERSION_ARB)) { |
| 3327 | _sapp_fail("WGL: Driver does not support OpenGL version 3.3\n" ); |
| 3328 | } |
| 3329 | else if (err == (0xc0070000 | ERROR_INVALID_PROFILE_ARB)) { |
| 3330 | _sapp_fail("WGL: Driver does not support the requested OpenGL profile" ); |
| 3331 | } |
| 3332 | else if (err == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB)) { |
| 3333 | _sapp_fail("WGL: The share context is not compatible with the requested context" ); |
| 3334 | } |
| 3335 | else { |
| 3336 | _sapp_fail("WGL: Failed to create OpenGL context" ); |
| 3337 | } |
| 3338 | } |
| 3339 | _sapp_wglMakeCurrent(_sapp_win32_dc, _sapp_gl_ctx); |
| 3340 | if (_sapp_ext_swap_control) { |
| 3341 | /* FIXME: DwmIsCompositionEnabled() (see GLFW) */ |
| 3342 | _sapp_SwapIntervalEXT(_sapp.swap_interval); |
| 3343 | } |
| 3344 | } |
| 3345 | |
| 3346 | _SOKOL_PRIVATE void _sapp_wgl_destroy_context(void) { |
| 3347 | SOKOL_ASSERT(_sapp_gl_ctx); |
| 3348 | _sapp_wglDeleteContext(_sapp_gl_ctx); |
| 3349 | _sapp_gl_ctx = 0; |
| 3350 | } |
| 3351 | |
| 3352 | _SOKOL_PRIVATE void _sapp_wgl_swap_buffers(void) { |
| 3353 | SOKOL_ASSERT(_sapp_win32_dc); |
| 3354 | /* FIXME: DwmIsCompositionEnabled? (see GLFW) */ |
| 3355 | SwapBuffers(_sapp_win32_dc); |
| 3356 | } |
| 3357 | #endif |
| 3358 | |
| 3359 | _SOKOL_PRIVATE bool _sapp_win32_utf8_to_wide(const char* src, wchar_t* dst, int dst_num_bytes) { |
| 3360 | SOKOL_ASSERT(src && dst && (dst_num_bytes > 1)); |
| 3361 | memset(dst, 0, dst_num_bytes); |
| 3362 | const int dst_chars = dst_num_bytes / sizeof(wchar_t); |
| 3363 | const int dst_needed = MultiByteToWideChar(CP_UTF8, 0, src, -1, 0, 0); |
| 3364 | if ((dst_needed > 0) && (dst_needed < dst_chars)) { |
| 3365 | MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, dst_chars); |
| 3366 | return true; |
| 3367 | } |
| 3368 | else { |
| 3369 | /* input string doesn't fit into destination buffer */ |
| 3370 | return false; |
| 3371 | } |
| 3372 | } |
| 3373 | |
| 3374 | _SOKOL_PRIVATE void _sapp_win32_init_keytable(void) { |
| 3375 | /* same as GLFW */ |
| 3376 | _sapp.keycodes[0x00B] = SAPP_KEYCODE_0; |
| 3377 | _sapp.keycodes[0x002] = SAPP_KEYCODE_1; |
| 3378 | _sapp.keycodes[0x003] = SAPP_KEYCODE_2; |
| 3379 | _sapp.keycodes[0x004] = SAPP_KEYCODE_3; |
| 3380 | _sapp.keycodes[0x005] = SAPP_KEYCODE_4; |
| 3381 | _sapp.keycodes[0x006] = SAPP_KEYCODE_5; |
| 3382 | _sapp.keycodes[0x007] = SAPP_KEYCODE_6; |
| 3383 | _sapp.keycodes[0x008] = SAPP_KEYCODE_7; |
| 3384 | _sapp.keycodes[0x009] = SAPP_KEYCODE_8; |
| 3385 | _sapp.keycodes[0x00A] = SAPP_KEYCODE_9; |
| 3386 | _sapp.keycodes[0x01E] = SAPP_KEYCODE_A; |
| 3387 | _sapp.keycodes[0x030] = SAPP_KEYCODE_B; |
| 3388 | _sapp.keycodes[0x02E] = SAPP_KEYCODE_C; |
| 3389 | _sapp.keycodes[0x020] = SAPP_KEYCODE_D; |
| 3390 | _sapp.keycodes[0x012] = SAPP_KEYCODE_E; |
| 3391 | _sapp.keycodes[0x021] = SAPP_KEYCODE_F; |
| 3392 | _sapp.keycodes[0x022] = SAPP_KEYCODE_G; |
| 3393 | _sapp.keycodes[0x023] = SAPP_KEYCODE_H; |
| 3394 | _sapp.keycodes[0x017] = SAPP_KEYCODE_I; |
| 3395 | _sapp.keycodes[0x024] = SAPP_KEYCODE_J; |
| 3396 | _sapp.keycodes[0x025] = SAPP_KEYCODE_K; |
| 3397 | _sapp.keycodes[0x026] = SAPP_KEYCODE_L; |
| 3398 | _sapp.keycodes[0x032] = SAPP_KEYCODE_M; |
| 3399 | _sapp.keycodes[0x031] = SAPP_KEYCODE_N; |
| 3400 | _sapp.keycodes[0x018] = SAPP_KEYCODE_O; |
| 3401 | _sapp.keycodes[0x019] = SAPP_KEYCODE_P; |
| 3402 | _sapp.keycodes[0x010] = SAPP_KEYCODE_Q; |
| 3403 | _sapp.keycodes[0x013] = SAPP_KEYCODE_R; |
| 3404 | _sapp.keycodes[0x01F] = SAPP_KEYCODE_S; |
| 3405 | _sapp.keycodes[0x014] = SAPP_KEYCODE_T; |
| 3406 | _sapp.keycodes[0x016] = SAPP_KEYCODE_U; |
| 3407 | _sapp.keycodes[0x02F] = SAPP_KEYCODE_V; |
| 3408 | _sapp.keycodes[0x011] = SAPP_KEYCODE_W; |
| 3409 | _sapp.keycodes[0x02D] = SAPP_KEYCODE_X; |
| 3410 | _sapp.keycodes[0x015] = SAPP_KEYCODE_Y; |
| 3411 | _sapp.keycodes[0x02C] = SAPP_KEYCODE_Z; |
| 3412 | _sapp.keycodes[0x028] = SAPP_KEYCODE_APOSTROPHE; |
| 3413 | _sapp.keycodes[0x02B] = SAPP_KEYCODE_BACKSLASH; |
| 3414 | _sapp.keycodes[0x033] = SAPP_KEYCODE_COMMA; |
| 3415 | _sapp.keycodes[0x00D] = SAPP_KEYCODE_EQUAL; |
| 3416 | _sapp.keycodes[0x029] = SAPP_KEYCODE_GRAVE_ACCENT; |
| 3417 | _sapp.keycodes[0x01A] = SAPP_KEYCODE_LEFT_BRACKET; |
| 3418 | _sapp.keycodes[0x00C] = SAPP_KEYCODE_MINUS; |
| 3419 | _sapp.keycodes[0x034] = SAPP_KEYCODE_PERIOD; |
| 3420 | _sapp.keycodes[0x01B] = SAPP_KEYCODE_RIGHT_BRACKET; |
| 3421 | _sapp.keycodes[0x027] = SAPP_KEYCODE_SEMICOLON; |
| 3422 | _sapp.keycodes[0x035] = SAPP_KEYCODE_SLASH; |
| 3423 | _sapp.keycodes[0x056] = SAPP_KEYCODE_WORLD_2; |
| 3424 | _sapp.keycodes[0x00E] = SAPP_KEYCODE_BACKSPACE; |
| 3425 | _sapp.keycodes[0x153] = SAPP_KEYCODE_DELETE; |
| 3426 | _sapp.keycodes[0x14F] = SAPP_KEYCODE_END; |
| 3427 | _sapp.keycodes[0x01C] = SAPP_KEYCODE_ENTER; |
| 3428 | _sapp.keycodes[0x001] = SAPP_KEYCODE_ESCAPE; |
| 3429 | _sapp.keycodes[0x147] = SAPP_KEYCODE_HOME; |
| 3430 | _sapp.keycodes[0x152] = SAPP_KEYCODE_INSERT; |
| 3431 | _sapp.keycodes[0x15D] = SAPP_KEYCODE_MENU; |
| 3432 | _sapp.keycodes[0x151] = SAPP_KEYCODE_PAGE_DOWN; |
| 3433 | _sapp.keycodes[0x149] = SAPP_KEYCODE_PAGE_UP; |
| 3434 | _sapp.keycodes[0x045] = SAPP_KEYCODE_PAUSE; |
| 3435 | _sapp.keycodes[0x146] = SAPP_KEYCODE_PAUSE; |
| 3436 | _sapp.keycodes[0x039] = SAPP_KEYCODE_SPACE; |
| 3437 | _sapp.keycodes[0x00F] = SAPP_KEYCODE_TAB; |
| 3438 | _sapp.keycodes[0x03A] = SAPP_KEYCODE_CAPS_LOCK; |
| 3439 | _sapp.keycodes[0x145] = SAPP_KEYCODE_NUM_LOCK; |
| 3440 | _sapp.keycodes[0x046] = SAPP_KEYCODE_SCROLL_LOCK; |
| 3441 | _sapp.keycodes[0x03B] = SAPP_KEYCODE_F1; |
| 3442 | _sapp.keycodes[0x03C] = SAPP_KEYCODE_F2; |
| 3443 | _sapp.keycodes[0x03D] = SAPP_KEYCODE_F3; |
| 3444 | _sapp.keycodes[0x03E] = SAPP_KEYCODE_F4; |
| 3445 | _sapp.keycodes[0x03F] = SAPP_KEYCODE_F5; |
| 3446 | _sapp.keycodes[0x040] = SAPP_KEYCODE_F6; |
| 3447 | _sapp.keycodes[0x041] = SAPP_KEYCODE_F7; |
| 3448 | _sapp.keycodes[0x042] = SAPP_KEYCODE_F8; |
| 3449 | _sapp.keycodes[0x043] = SAPP_KEYCODE_F9; |
| 3450 | _sapp.keycodes[0x044] = SAPP_KEYCODE_F10; |
| 3451 | _sapp.keycodes[0x057] = SAPP_KEYCODE_F11; |
| 3452 | _sapp.keycodes[0x058] = SAPP_KEYCODE_F12; |
| 3453 | _sapp.keycodes[0x064] = SAPP_KEYCODE_F13; |
| 3454 | _sapp.keycodes[0x065] = SAPP_KEYCODE_F14; |
| 3455 | _sapp.keycodes[0x066] = SAPP_KEYCODE_F15; |
| 3456 | _sapp.keycodes[0x067] = SAPP_KEYCODE_F16; |
| 3457 | _sapp.keycodes[0x068] = SAPP_KEYCODE_F17; |
| 3458 | _sapp.keycodes[0x069] = SAPP_KEYCODE_F18; |
| 3459 | _sapp.keycodes[0x06A] = SAPP_KEYCODE_F19; |
| 3460 | _sapp.keycodes[0x06B] = SAPP_KEYCODE_F20; |
| 3461 | _sapp.keycodes[0x06C] = SAPP_KEYCODE_F21; |
| 3462 | _sapp.keycodes[0x06D] = SAPP_KEYCODE_F22; |
| 3463 | _sapp.keycodes[0x06E] = SAPP_KEYCODE_F23; |
| 3464 | _sapp.keycodes[0x076] = SAPP_KEYCODE_F24; |
| 3465 | _sapp.keycodes[0x038] = SAPP_KEYCODE_LEFT_ALT; |
| 3466 | _sapp.keycodes[0x01D] = SAPP_KEYCODE_LEFT_CONTROL; |
| 3467 | _sapp.keycodes[0x02A] = SAPP_KEYCODE_LEFT_SHIFT; |
| 3468 | _sapp.keycodes[0x15B] = SAPP_KEYCODE_LEFT_SUPER; |
| 3469 | _sapp.keycodes[0x137] = SAPP_KEYCODE_PRINT_SCREEN; |
| 3470 | _sapp.keycodes[0x138] = SAPP_KEYCODE_RIGHT_ALT; |
| 3471 | _sapp.keycodes[0x11D] = SAPP_KEYCODE_RIGHT_CONTROL; |
| 3472 | _sapp.keycodes[0x036] = SAPP_KEYCODE_RIGHT_SHIFT; |
| 3473 | _sapp.keycodes[0x15C] = SAPP_KEYCODE_RIGHT_SUPER; |
| 3474 | _sapp.keycodes[0x150] = SAPP_KEYCODE_DOWN; |
| 3475 | _sapp.keycodes[0x14B] = SAPP_KEYCODE_LEFT; |
| 3476 | _sapp.keycodes[0x14D] = SAPP_KEYCODE_RIGHT; |
| 3477 | _sapp.keycodes[0x148] = SAPP_KEYCODE_UP; |
| 3478 | _sapp.keycodes[0x052] = SAPP_KEYCODE_KP_0; |
| 3479 | _sapp.keycodes[0x04F] = SAPP_KEYCODE_KP_1; |
| 3480 | _sapp.keycodes[0x050] = SAPP_KEYCODE_KP_2; |
| 3481 | _sapp.keycodes[0x051] = SAPP_KEYCODE_KP_3; |
| 3482 | _sapp.keycodes[0x04B] = SAPP_KEYCODE_KP_4; |
| 3483 | _sapp.keycodes[0x04C] = SAPP_KEYCODE_KP_5; |
| 3484 | _sapp.keycodes[0x04D] = SAPP_KEYCODE_KP_6; |
| 3485 | _sapp.keycodes[0x047] = SAPP_KEYCODE_KP_7; |
| 3486 | _sapp.keycodes[0x048] = SAPP_KEYCODE_KP_8; |
| 3487 | _sapp.keycodes[0x049] = SAPP_KEYCODE_KP_9; |
| 3488 | _sapp.keycodes[0x04E] = SAPP_KEYCODE_KP_ADD; |
| 3489 | _sapp.keycodes[0x053] = SAPP_KEYCODE_KP_DECIMAL; |
| 3490 | _sapp.keycodes[0x135] = SAPP_KEYCODE_KP_DIVIDE; |
| 3491 | _sapp.keycodes[0x11C] = SAPP_KEYCODE_KP_ENTER; |
| 3492 | _sapp.keycodes[0x037] = SAPP_KEYCODE_KP_MULTIPLY; |
| 3493 | _sapp.keycodes[0x04A] = SAPP_KEYCODE_KP_SUBTRACT; |
| 3494 | } |
| 3495 | |
| 3496 | /* updates current window and framebuffer size from the window's client rect, returns true if size has changed */ |
| 3497 | _SOKOL_PRIVATE bool _sapp_win32_update_dimensions(void) { |
| 3498 | RECT rect; |
| 3499 | if (GetClientRect(_sapp_win32_hwnd, &rect)) { |
| 3500 | const int cur_width = (rect.right - rect.left) / _sapp_win32_window_scale; |
| 3501 | const int cur_height = (rect.bottom - rect.top) / _sapp_win32_window_scale; |
| 3502 | if ((cur_width != _sapp.window_width) || (cur_height != _sapp.window_height)) { |
| 3503 | _sapp.window_width = cur_width; |
| 3504 | _sapp.window_height = cur_height; |
| 3505 | _sapp.framebuffer_width = _sapp.window_width * _sapp_win32_content_scale; |
| 3506 | _sapp.framebuffer_height = _sapp.window_height * _sapp_win32_content_scale; |
| 3507 | /* prevent a framebuffer size of 0 when window is minimized */ |
| 3508 | if (_sapp.framebuffer_width == 0) { |
| 3509 | _sapp.framebuffer_width = 1; |
| 3510 | } |
| 3511 | if (_sapp.framebuffer_height == 0) { |
| 3512 | _sapp.framebuffer_height = 1; |
| 3513 | } |
| 3514 | return true; |
| 3515 | } |
| 3516 | } |
| 3517 | else { |
| 3518 | _sapp.window_width = _sapp.window_height = 1; |
| 3519 | _sapp.framebuffer_width = _sapp.framebuffer_height = 1; |
| 3520 | } |
| 3521 | return false; |
| 3522 | } |
| 3523 | |
| 3524 | _SOKOL_PRIVATE uint32_t _sapp_win32_mods(void) { |
| 3525 | uint32_t mods = 0; |
| 3526 | if (GetKeyState(VK_SHIFT) & (1<<31)) { |
| 3527 | mods |= SAPP_MODIFIER_SHIFT; |
| 3528 | } |
| 3529 | if (GetKeyState(VK_CONTROL) & (1<<31)) { |
| 3530 | mods |= SAPP_MODIFIER_CTRL; |
| 3531 | } |
| 3532 | if (GetKeyState(VK_MENU) & (1<<31)) { |
| 3533 | mods |= SAPP_MODIFIER_ALT; |
| 3534 | } |
| 3535 | if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & (1<<31)) { |
| 3536 | mods |= SAPP_MODIFIER_SUPER; |
| 3537 | } |
| 3538 | return mods; |
| 3539 | } |
| 3540 | |
| 3541 | _SOKOL_PRIVATE void _sapp_win32_mouse_event(sapp_event_type type, sapp_mousebutton btn) { |
| 3542 | if (_sapp_events_enabled()) { |
| 3543 | _sapp_init_event(type); |
| 3544 | _sapp.event.modifiers = _sapp_win32_mods(); |
| 3545 | _sapp.event.mouse_button = btn; |
| 3546 | _sapp.event.mouse_x = _sapp.mouse_x; |
| 3547 | _sapp.event.mouse_y = _sapp.mouse_y; |
| 3548 | _sapp.desc.event_cb(&_sapp.event); |
| 3549 | } |
| 3550 | } |
| 3551 | |
| 3552 | _SOKOL_PRIVATE void _sapp_win32_scroll_event(float x, float y) { |
| 3553 | if (_sapp_events_enabled()) { |
| 3554 | _sapp_init_event(SAPP_EVENTTYPE_MOUSE_SCROLL); |
| 3555 | _sapp.event.modifiers = _sapp_win32_mods(); |
| 3556 | _sapp.event.scroll_x = -x / 30.0f; |
| 3557 | _sapp.event.scroll_y = y / 30.0f; |
| 3558 | _sapp.desc.event_cb(&_sapp.event); |
| 3559 | } |
| 3560 | } |
| 3561 | |
| 3562 | _SOKOL_PRIVATE void _sapp_win32_key_event(sapp_event_type type, int vk) { |
| 3563 | if (_sapp_events_enabled() && (vk < SAPP_MAX_KEYCODES)) { |
| 3564 | _sapp_init_event(type); |
| 3565 | _sapp.event.modifiers = _sapp_win32_mods(); |
| 3566 | _sapp.event.key_code = _sapp.keycodes[vk]; |
| 3567 | _sapp.desc.event_cb(&_sapp.event); |
| 3568 | } |
| 3569 | } |
| 3570 | |
| 3571 | _SOKOL_PRIVATE void _sapp_win32_char_event(uint32_t c) { |
| 3572 | if (_sapp_events_enabled() && (c >= 32)) { |
| 3573 | _sapp_init_event(SAPP_EVENTTYPE_CHAR); |
| 3574 | _sapp.event.modifiers = _sapp_win32_mods(); |
| 3575 | _sapp.event.char_code = c; |
| 3576 | _sapp.desc.event_cb(&_sapp.event); |
| 3577 | } |
| 3578 | } |
| 3579 | |
| 3580 | _SOKOL_PRIVATE void _sapp_win32_app_event(sapp_event_type type) { |
| 3581 | if (_sapp_events_enabled()) { |
| 3582 | _sapp_init_event(type); |
| 3583 | _sapp.desc.event_cb(&_sapp.event); |
| 3584 | } |
| 3585 | } |
| 3586 | |
| 3587 | _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { |
| 3588 | /* FIXME: refresh rendering during resize with a WM_TIMER event */ |
| 3589 | if (!_sapp_win32_in_create_window) { |
| 3590 | switch (uMsg) { |
| 3591 | case WM_CLOSE: |
| 3592 | PostQuitMessage(0); |
| 3593 | return 0; |
| 3594 | case WM_SYSCOMMAND: |
| 3595 | switch (wParam & 0xFFF0) { |
| 3596 | case SC_SCREENSAVE: |
| 3597 | case SC_MONITORPOWER: |
| 3598 | if (_sapp.desc.fullscreen) { |
| 3599 | /* disable screen saver and blanking in fullscreen mode */ |
| 3600 | return 0; |
| 3601 | } |
| 3602 | break; |
| 3603 | case SC_KEYMENU: |
| 3604 | /* user trying to access menu via ALT */ |
| 3605 | return 0; |
| 3606 | } |
| 3607 | break; |
| 3608 | case WM_ERASEBKGND: |
| 3609 | return 1; |
| 3610 | case WM_SIZE: |
| 3611 | { |
| 3612 | const bool iconified = wParam == SIZE_MINIMIZED; |
| 3613 | if (iconified != _sapp_win32_iconified) { |
| 3614 | _sapp_win32_iconified = iconified; |
| 3615 | if (iconified) { |
| 3616 | _sapp_win32_app_event(SAPP_EVENTTYPE_ICONIFIED); |
| 3617 | } |
| 3618 | else { |
| 3619 | _sapp_win32_app_event(SAPP_EVENTTYPE_RESTORED); |
| 3620 | } |
| 3621 | } |
| 3622 | if (_sapp_win32_update_dimensions()) { |
| 3623 | #if defined(SOKOL_D3D11) |
| 3624 | _sapp_d3d11_resize_default_render_target(); |
| 3625 | #endif |
| 3626 | _sapp_win32_app_event(SAPP_EVENTTYPE_RESIZED); |
| 3627 | } |
| 3628 | } |
| 3629 | break; |
| 3630 | case WM_SETCURSOR: |
| 3631 | if (_sapp.desc.user_cursor) { |
| 3632 | if (LOWORD(lParam) == HTCLIENT) { |
| 3633 | _sapp_win32_app_event(SAPP_EVENTTYPE_UPDATE_CURSOR); |
| 3634 | return 1; |
| 3635 | } |
| 3636 | } |
| 3637 | break; |
| 3638 | case WM_LBUTTONDOWN: |
| 3639 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_LEFT); |
| 3640 | break; |
| 3641 | case WM_RBUTTONDOWN: |
| 3642 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_RIGHT); |
| 3643 | break; |
| 3644 | case WM_MBUTTONDOWN: |
| 3645 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, SAPP_MOUSEBUTTON_MIDDLE); |
| 3646 | break; |
| 3647 | case WM_LBUTTONUP: |
| 3648 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_LEFT); |
| 3649 | break; |
| 3650 | case WM_RBUTTONUP: |
| 3651 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_RIGHT); |
| 3652 | break; |
| 3653 | case WM_MBUTTONUP: |
| 3654 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, SAPP_MOUSEBUTTON_MIDDLE); |
| 3655 | break; |
| 3656 | case WM_MOUSEMOVE: |
| 3657 | _sapp.mouse_x = (float)GET_X_LPARAM(lParam) * _sapp_win32_mouse_scale; |
| 3658 | _sapp.mouse_y = (float)GET_Y_LPARAM(lParam) * _sapp_win32_mouse_scale; |
| 3659 | if (!_sapp.win32_mouse_tracked) { |
| 3660 | _sapp.win32_mouse_tracked = true; |
| 3661 | TRACKMOUSEEVENT tme; |
| 3662 | memset(&tme, 0, sizeof(tme)); |
| 3663 | tme.cbSize = sizeof(tme); |
| 3664 | tme.dwFlags = TME_LEAVE; |
| 3665 | tme.hwndTrack = _sapp_win32_hwnd; |
| 3666 | TrackMouseEvent(&tme); |
| 3667 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID); |
| 3668 | } |
| 3669 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_INVALID); |
| 3670 | break; |
| 3671 | case WM_MOUSELEAVE: |
| 3672 | _sapp.win32_mouse_tracked = false; |
| 3673 | _sapp_win32_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID); |
| 3674 | break; |
| 3675 | case WM_MOUSEWHEEL: |
| 3676 | _sapp_win32_scroll_event(0.0f, (float)((SHORT)HIWORD(wParam))); |
| 3677 | break; |
| 3678 | case WM_MOUSEHWHEEL: |
| 3679 | _sapp_win32_scroll_event((float)((SHORT)HIWORD(wParam)), 0.0f); |
| 3680 | break; |
| 3681 | case WM_CHAR: |
| 3682 | _sapp_win32_char_event((uint32_t)wParam); |
| 3683 | break; |
| 3684 | case WM_KEYDOWN: |
| 3685 | case WM_SYSKEYDOWN: |
| 3686 | _sapp_win32_key_event(SAPP_EVENTTYPE_KEY_DOWN, (int)(HIWORD(lParam)&0x1FF)); |
| 3687 | break; |
| 3688 | case WM_KEYUP: |
| 3689 | case WM_SYSKEYUP: |
| 3690 | _sapp_win32_key_event(SAPP_EVENTTYPE_KEY_UP, (int)(HIWORD(lParam)&0x1FF)); |
| 3691 | break; |
| 3692 | default: |
| 3693 | break; |
| 3694 | } |
| 3695 | } |
| 3696 | return DefWindowProcW(hWnd, uMsg, wParam, lParam); |
| 3697 | } |
| 3698 | |
| 3699 | _SOKOL_PRIVATE void _sapp_win32_create_window(void) { |
| 3700 | WNDCLASSW wndclassw; |
| 3701 | memset(&wndclassw, 0, sizeof(wndclassw)); |
| 3702 | wndclassw.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; |
| 3703 | wndclassw.lpfnWndProc = (WNDPROC) _sapp_win32_wndproc; |
| 3704 | wndclassw.hInstance = GetModuleHandleW(NULL); |
| 3705 | wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW); |
| 3706 | wndclassw.hIcon = LoadIcon(NULL, IDI_WINLOGO); |
| 3707 | wndclassw.lpszClassName = L"SOKOLAPP" ; |
| 3708 | RegisterClassW(&wndclassw); |
| 3709 | |
| 3710 | DWORD win_style; |
| 3711 | const DWORD win_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; |
| 3712 | RECT rect = { 0, 0, 0, 0 }; |
| 3713 | if (_sapp.desc.fullscreen) { |
| 3714 | win_style = WS_POPUP | WS_SYSMENU | WS_VISIBLE; |
| 3715 | rect.right = GetSystemMetrics(SM_CXSCREEN); |
| 3716 | rect.bottom = GetSystemMetrics(SM_CYSCREEN); |
| 3717 | } |
| 3718 | else { |
| 3719 | win_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX; |
| 3720 | rect.right = (int) (_sapp.window_width * _sapp_win32_window_scale); |
| 3721 | rect.bottom = (int) (_sapp.window_height * _sapp_win32_window_scale); |
| 3722 | } |
| 3723 | AdjustWindowRectEx(&rect, win_style, FALSE, win_ex_style); |
| 3724 | const int win_width = rect.right - rect.left; |
| 3725 | const int win_height = rect.bottom - rect.top; |
| 3726 | _sapp_win32_in_create_window = true; |
| 3727 | _sapp_win32_hwnd = CreateWindowExW( |
| 3728 | win_ex_style, /* dwExStyle */ |
| 3729 | L"SOKOLAPP" , /* lpClassName */ |
| 3730 | _sapp.window_title_wide, /* lpWindowName */ |
| 3731 | win_style, /* dwStyle */ |
| 3732 | CW_USEDEFAULT, /* X */ |
| 3733 | CW_USEDEFAULT, /* Y */ |
| 3734 | win_width, /* nWidth */ |
| 3735 | win_height, /* nHeight */ |
| 3736 | NULL, /* hWndParent */ |
| 3737 | NULL, /* hMenu */ |
| 3738 | GetModuleHandle(NULL), /* hInstance */ |
| 3739 | NULL); /* lParam */ |
| 3740 | ShowWindow(_sapp_win32_hwnd, SW_SHOW); |
| 3741 | _sapp_win32_in_create_window = false; |
| 3742 | _sapp_win32_dc = GetDC(_sapp_win32_hwnd); |
| 3743 | SOKOL_ASSERT(_sapp_win32_dc); |
| 3744 | _sapp_win32_update_dimensions(); |
| 3745 | } |
| 3746 | |
| 3747 | _SOKOL_PRIVATE void _sapp_win32_destroy_window(void) { |
| 3748 | DestroyWindow(_sapp_win32_hwnd); _sapp_win32_hwnd = 0; |
| 3749 | UnregisterClassW(L"SOKOLAPP" , GetModuleHandleW(NULL)); |
| 3750 | } |
| 3751 | |
| 3752 | _SOKOL_PRIVATE void _sapp_win32_init_dpi(void) { |
| 3753 | SOKOL_ASSERT(0 == _sapp_win32_setprocessdpiaware); |
| 3754 | SOKOL_ASSERT(0 == _sapp_win32_setprocessdpiawareness); |
| 3755 | SOKOL_ASSERT(0 == _sapp_win32_getdpiformonitor); |
| 3756 | HINSTANCE user32 = LoadLibraryA("user32.dll" ); |
| 3757 | if (user32) { |
| 3758 | _sapp_win32_setprocessdpiaware = (SETPROCESSDPIAWARE_T) GetProcAddress(user32, "SetProcessDPIAware" ); |
| 3759 | } |
| 3760 | HINSTANCE shcore = LoadLibraryA("shcore.dll" ); |
| 3761 | if (shcore) { |
| 3762 | _sapp_win32_setprocessdpiawareness = (SETPROCESSDPIAWARENESS_T) GetProcAddress(shcore, "SetProcessDpiAwareness" ); |
| 3763 | _sapp_win32_getdpiformonitor = (GETDPIFORMONITOR_T) GetProcAddress(shcore, "GetDpiForMonitor" ); |
| 3764 | } |
| 3765 | if (_sapp_win32_setprocessdpiawareness) { |
| 3766 | /* if the app didn't request HighDPI rendering, let Windows do the upscaling */ |
| 3767 | PROCESS_DPI_AWARENESS process_dpi_awareness = PROCESS_SYSTEM_DPI_AWARE; |
| 3768 | _sapp_win32_dpi_aware = true; |
| 3769 | if (!_sapp.desc.high_dpi) { |
| 3770 | process_dpi_awareness = PROCESS_DPI_UNAWARE; |
| 3771 | _sapp_win32_dpi_aware = false; |
| 3772 | } |
| 3773 | _sapp_win32_setprocessdpiawareness(process_dpi_awareness); |
| 3774 | } |
| 3775 | else if (_sapp_win32_setprocessdpiaware) { |
| 3776 | _sapp_win32_setprocessdpiaware(); |
| 3777 | _sapp_win32_dpi_aware = true; |
| 3778 | } |
| 3779 | /* get dpi scale factor for main monitor */ |
| 3780 | if (_sapp_win32_getdpiformonitor && _sapp_win32_dpi_aware) { |
| 3781 | POINT pt = { 1, 1 }; |
| 3782 | HMONITOR hm = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); |
| 3783 | UINT dpix, dpiy; |
| 3784 | HRESULT hr = _sapp_win32_getdpiformonitor(hm, MDT_EFFECTIVE_DPI, &dpix, &dpiy); |
| 3785 | _SOKOL_UNUSED(hr); |
| 3786 | SOKOL_ASSERT(SUCCEEDED(hr)); |
| 3787 | /* clamp window scale to an integer factor */ |
| 3788 | _sapp_win32_window_scale = (int)((float)dpix / 96.0f); |
| 3789 | } |
| 3790 | else { |
| 3791 | _sapp_win32_window_scale = 1; |
| 3792 | } |
| 3793 | if (_sapp.desc.high_dpi) { |
| 3794 | _sapp_win32_content_scale = _sapp_win32_window_scale; |
| 3795 | _sapp_win32_mouse_scale = 1.0f; |
| 3796 | } |
| 3797 | else { |
| 3798 | _sapp_win32_content_scale = 1; |
| 3799 | _sapp_win32_mouse_scale = 1.0f / _sapp_win32_window_scale; |
| 3800 | } |
| 3801 | _sapp.dpi_scale = (float) _sapp_win32_content_scale; |
| 3802 | if (user32) { |
| 3803 | FreeLibrary(user32); |
| 3804 | } |
| 3805 | if (shcore) { |
| 3806 | FreeLibrary(shcore); |
| 3807 | } |
| 3808 | } |
| 3809 | |
| 3810 | #if defined(SOKOL_WIN32_FORCE_MAIN) |
| 3811 | int main(int argc, char** argv) { |
| 3812 | #else |
| 3813 | int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { |
| 3814 | _SOKOL_UNUSED(hInstance); |
| 3815 | _SOKOL_UNUSED(hPrevInstance); |
| 3816 | _SOKOL_UNUSED(lpCmdLine); |
| 3817 | _SOKOL_UNUSED(nCmdShow); |
| 3818 | int argc = __argc; |
| 3819 | char** argv = __argv; |
| 3820 | #endif |
| 3821 | sapp_desc desc = sokol_main(argc, argv); |
| 3822 | _sapp_init_state(&desc, argc, argv); |
| 3823 | _sapp_win32_init_keytable(); |
| 3824 | _sapp_win32_utf8_to_wide(_sapp.window_title, _sapp.window_title_wide, sizeof(_sapp.window_title_wide)); |
| 3825 | _sapp_win32_init_dpi(); |
| 3826 | _sapp_win32_create_window(); |
| 3827 | #if defined(SOKOL_D3D11) |
| 3828 | _sapp_d3d11_create_device_and_swapchain(); |
| 3829 | _sapp_d3d11_create_default_render_target(); |
| 3830 | #endif |
| 3831 | #if defined(SOKOL_GLCORE33) |
| 3832 | _sapp_wgl_init(); |
| 3833 | _sapp_wgl_load_extensions(); |
| 3834 | _sapp_wgl_create_context(); |
| 3835 | #if !defined(SOKOL_WIN32_NO_GL_LOADER) |
| 3836 | _sapp_win32_gl_loadfuncs(); |
| 3837 | #endif |
| 3838 | #endif |
| 3839 | _sapp.valid = true; |
| 3840 | |
| 3841 | bool done = false; |
| 3842 | while (!done) { |
| 3843 | MSG msg; |
| 3844 | while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { |
| 3845 | if (WM_QUIT == msg.message) { |
| 3846 | done = true; |
| 3847 | } |
| 3848 | else { |
| 3849 | TranslateMessage(&msg); |
| 3850 | DispatchMessage(&msg); |
| 3851 | } |
| 3852 | } |
| 3853 | _sapp_frame(); |
| 3854 | #if defined(SOKOL_D3D11) |
| 3855 | IDXGISwapChain_Present(_sapp_dxgi_swap_chain, _sapp.swap_interval, 0); |
| 3856 | #endif |
| 3857 | #if defined(SOKOL_GLCORE33) |
| 3858 | _sapp_wgl_swap_buffers(); |
| 3859 | #endif |
| 3860 | } |
| 3861 | _sapp.desc.cleanup_cb(); |
| 3862 | |
| 3863 | #if defined(SOKOL_D3D11) |
| 3864 | _sapp_d3d11_destroy_default_render_target(); |
| 3865 | _sapp_d3d11_destroy_device_and_swapchain(); |
| 3866 | #else |
| 3867 | _sapp_wgl_destroy_context(); |
| 3868 | _sapp_wgl_shutdown(); |
| 3869 | #endif |
| 3870 | _sapp_win32_destroy_window(); |
| 3871 | return 0; |
| 3872 | } |
| 3873 | |
| 3874 | #undef _SAPP_SAFE_RELEASE |
| 3875 | #endif /* WINDOWS */ |
| 3876 | |
| 3877 | /*== LINUX ==================================================================*/ |
| 3878 | #if defined(linux) |
| 3879 | #define GL_GLEXT_PROTOTYPES |
| 3880 | #include <X11/X.h> |
| 3881 | #include <X11/Xlib.h> |
| 3882 | #include <X11/Xresource.h> |
| 3883 | #include <X11/extensions/Xrandr.h> |
| 3884 | #include <X11/Xmd.h> /* CARD32 */ |
| 3885 | #include <GL/gl.h> |
| 3886 | #include <dlfcn.h> /* dlopen, dlsym, dlclose */ |
| 3887 | #include <limits.h> /* LONG_MAX */ |
| 3888 | |
| 3889 | #define GLX_VENDOR 1 |
| 3890 | #define GLX_RGBA_BIT 0x00000001 |
| 3891 | #define GLX_WINDOW_BIT 0x00000001 |
| 3892 | #define GLX_DRAWABLE_TYPE 0x8010 |
| 3893 | #define GLX_RENDER_TYPE 0x8011 |
| 3894 | #define GLX_RGBA_TYPE 0x8014 |
| 3895 | #define GLX_DOUBLEBUFFER 5 |
| 3896 | #define GLX_STEREO 6 |
| 3897 | #define GLX_AUX_BUFFERS 7 |
| 3898 | #define GLX_RED_SIZE 8 |
| 3899 | #define GLX_GREEN_SIZE 9 |
| 3900 | #define GLX_BLUE_SIZE 10 |
| 3901 | #define GLX_ALPHA_SIZE 11 |
| 3902 | #define GLX_DEPTH_SIZE 12 |
| 3903 | #define GLX_STENCIL_SIZE 13 |
| 3904 | #define GLX_ACCUM_RED_SIZE 14 |
| 3905 | #define GLX_ACCUM_GREEN_SIZE 15 |
| 3906 | #define GLX_ACCUM_BLUE_SIZE 16 |
| 3907 | #define GLX_ACCUM_ALPHA_SIZE 17 |
| 3908 | #define GLX_SAMPLES 0x186a1 |
| 3909 | #define GLX_VISUAL_ID 0x800b |
| 3910 | |
| 3911 | #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2 |
| 3912 | #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 |
| 3913 | #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 |
| 3914 | #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 |
| 3915 | #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 |
| 3916 | #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 |
| 3917 | #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 |
| 3918 | #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 |
| 3919 | #define GLX_CONTEXT_FLAGS_ARB 0x2094 |
| 3920 | #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 |
| 3921 | #define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 |
| 3922 | #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 |
| 3923 | #define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 |
| 3924 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 |
| 3925 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 |
| 3926 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 |
| 3927 | |
| 3928 | typedef XID GLXWindow; |
| 3929 | typedef XID GLXDrawable; |
| 3930 | typedef struct __GLXFBConfig* GLXFBConfig; |
| 3931 | typedef struct __GLXcontext* GLXContext; |
| 3932 | typedef void (*__GLXextproc)(void); |
| 3933 | |
| 3934 | typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*); |
| 3935 | typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int); |
| 3936 | typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*); |
| 3937 | typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*); |
| 3938 | typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext); |
| 3939 | typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext); |
| 3940 | typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable); |
| 3941 | typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int); |
| 3942 | typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*); |
| 3943 | typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool); |
| 3944 | typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName); |
| 3945 | typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int); |
| 3946 | typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig); |
| 3947 | typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*); |
| 3948 | typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); |
| 3949 | |
| 3950 | typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int); |
| 3951 | typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*); |
| 3952 | |
| 3953 | static bool _sapp_x11_quit_requested; |
| 3954 | static Display* _sapp_x11_display; |
| 3955 | static int _sapp_x11_screen; |
| 3956 | static Window _sapp_x11_root; |
| 3957 | static Colormap _sapp_x11_colormap; |
| 3958 | static Window _sapp_x11_window; |
| 3959 | static float _sapp_x11_dpi; |
| 3960 | static int _sapp_x11_window_state; |
| 3961 | static unsigned char _sapp_x11_error_code; |
| 3962 | static void* _sapp_glx_libgl; |
| 3963 | static int _sapp_glx_major; |
| 3964 | static int _sapp_glx_minor; |
| 3965 | static int _sapp_glx_eventbase; |
| 3966 | static int _sapp_glx_errorbase; |
| 3967 | static GLXContext _sapp_glx_ctx; |
| 3968 | static GLXWindow _sapp_glx_window; |
| 3969 | static Atom _sapp_x11_UTF8_STRING; |
| 3970 | static Atom _sapp_x11_WM_PROTOCOLS; |
| 3971 | static Atom _sapp_x11_WM_DELETE_WINDOW; |
| 3972 | static Atom _sapp_x11_WM_STATE; |
| 3973 | static Atom _sapp_x11_NET_WM_NAME; |
| 3974 | static Atom _sapp_x11_NET_WM_ICON_NAME; |
| 3975 | // GLX 1.3 functions |
| 3976 | static PFNGLXGETFBCONFIGSPROC _sapp_glx_GetFBConfigs; |
| 3977 | static PFNGLXGETFBCONFIGATTRIBPROC _sapp_glx_GetFBConfigAttrib; |
| 3978 | static PFNGLXGETCLIENTSTRINGPROC _sapp_glx_GetClientString; |
| 3979 | static PFNGLXQUERYEXTENSIONPROC _sapp_glx_QueryExtension; |
| 3980 | static PFNGLXQUERYVERSIONPROC _sapp_glx_QueryVersion; |
| 3981 | static PFNGLXDESTROYCONTEXTPROC _sapp_glx_DestroyContext; |
| 3982 | static PFNGLXMAKECURRENTPROC _sapp_glx_MakeCurrent; |
| 3983 | static PFNGLXSWAPBUFFERSPROC _sapp_glx_SwapBuffers; |
| 3984 | static PFNGLXQUERYEXTENSIONSSTRINGPROC _sapp_glx_QueryExtensionsString; |
| 3985 | static PFNGLXCREATENEWCONTEXTPROC _sapp_glx_CreateNewContext; |
| 3986 | static PFNGLXGETVISUALFROMFBCONFIGPROC _sapp_glx_GetVisualFromFBConfig; |
| 3987 | static PFNGLXCREATEWINDOWPROC _sapp_glx_CreateWindow; |
| 3988 | static PFNGLXDESTROYWINDOWPROC _sapp_glx_DestroyWindow; |
| 3989 | |
| 3990 | // GLX 1.4 and extension functions |
| 3991 | static PFNGLXGETPROCADDRESSPROC _sapp_glx_GetProcAddress; |
| 3992 | static PFNGLXGETPROCADDRESSPROC _sapp_glx_GetProcAddressARB; |
| 3993 | static PFNGLXSWAPINTERVALEXTPROC _sapp_glx_SwapIntervalEXT; |
| 3994 | static PFNGLXSWAPINTERVALMESAPROC _sapp_glx_SwapIntervalMESA; |
| 3995 | static PFNGLXCREATECONTEXTATTRIBSARBPROC _sapp_glx_CreateContextAttribsARB; |
| 3996 | static bool _sapp_glx_EXT_swap_control; |
| 3997 | static bool _sapp_glx_MESA_swap_control; |
| 3998 | static bool _sapp_glx_ARB_multisample; |
| 3999 | static bool _sapp_glx_ARB_framebuffer_sRGB; |
| 4000 | static bool _sapp_glx_EXT_framebuffer_sRGB; |
| 4001 | static bool _sapp_glx_ARB_create_context; |
| 4002 | static bool _sapp_glx_ARB_create_context_profile; |
| 4003 | |
| 4004 | /* see GLFW's xkb_unicode.c */ |
| 4005 | static const struct _sapp_x11_codepair { |
| 4006 | uint16_t keysym; |
| 4007 | uint16_t ucs; |
| 4008 | } _sapp_x11_keysymtab[] = { |
| 4009 | { 0x01a1, 0x0104 }, |
| 4010 | { 0x01a2, 0x02d8 }, |
| 4011 | { 0x01a3, 0x0141 }, |
| 4012 | { 0x01a5, 0x013d }, |
| 4013 | { 0x01a6, 0x015a }, |
| 4014 | { 0x01a9, 0x0160 }, |
| 4015 | { 0x01aa, 0x015e }, |
| 4016 | { 0x01ab, 0x0164 }, |
| 4017 | { 0x01ac, 0x0179 }, |
| 4018 | { 0x01ae, 0x017d }, |
| 4019 | { 0x01af, 0x017b }, |
| 4020 | { 0x01b1, 0x0105 }, |
| 4021 | { 0x01b2, 0x02db }, |
| 4022 | { 0x01b3, 0x0142 }, |
| 4023 | { 0x01b5, 0x013e }, |
| 4024 | { 0x01b6, 0x015b }, |
| 4025 | { 0x01b7, 0x02c7 }, |
| 4026 | { 0x01b9, 0x0161 }, |
| 4027 | { 0x01ba, 0x015f }, |
| 4028 | { 0x01bb, 0x0165 }, |
| 4029 | { 0x01bc, 0x017a }, |
| 4030 | { 0x01bd, 0x02dd }, |
| 4031 | { 0x01be, 0x017e }, |
| 4032 | { 0x01bf, 0x017c }, |
| 4033 | { 0x01c0, 0x0154 }, |
| 4034 | { 0x01c3, 0x0102 }, |
| 4035 | { 0x01c5, 0x0139 }, |
| 4036 | { 0x01c6, 0x0106 }, |
| 4037 | { 0x01c8, 0x010c }, |
| 4038 | { 0x01ca, 0x0118 }, |
| 4039 | { 0x01cc, 0x011a }, |
| 4040 | { 0x01cf, 0x010e }, |
| 4041 | { 0x01d0, 0x0110 }, |
| 4042 | { 0x01d1, 0x0143 }, |
| 4043 | { 0x01d2, 0x0147 }, |
| 4044 | { 0x01d5, 0x0150 }, |
| 4045 | { 0x01d8, 0x0158 }, |
| 4046 | { 0x01d9, 0x016e }, |
| 4047 | { 0x01db, 0x0170 }, |
| 4048 | { 0x01de, 0x0162 }, |
| 4049 | { 0x01e0, 0x0155 }, |
| 4050 | { 0x01e3, 0x0103 }, |
| 4051 | { 0x01e5, 0x013a }, |
| 4052 | { 0x01e6, 0x0107 }, |
| 4053 | { 0x01e8, 0x010d }, |
| 4054 | { 0x01ea, 0x0119 }, |
| 4055 | { 0x01ec, 0x011b }, |
| 4056 | { 0x01ef, 0x010f }, |
| 4057 | { 0x01f0, 0x0111 }, |
| 4058 | { 0x01f1, 0x0144 }, |
| 4059 | { 0x01f2, 0x0148 }, |
| 4060 | { 0x01f5, 0x0151 }, |
| 4061 | { 0x01f8, 0x0159 }, |
| 4062 | { 0x01f9, 0x016f }, |
| 4063 | { 0x01fb, 0x0171 }, |
| 4064 | { 0x01fe, 0x0163 }, |
| 4065 | { 0x01ff, 0x02d9 }, |
| 4066 | { 0x02a1, 0x0126 }, |
| 4067 | { 0x02a6, 0x0124 }, |
| 4068 | { 0x02a9, 0x0130 }, |
| 4069 | { 0x02ab, 0x011e }, |
| 4070 | { 0x02ac, 0x0134 }, |
| 4071 | { 0x02b1, 0x0127 }, |
| 4072 | { 0x02b6, 0x0125 }, |
| 4073 | { 0x02b9, 0x0131 }, |
| 4074 | { 0x02bb, 0x011f }, |
| 4075 | { 0x02bc, 0x0135 }, |
| 4076 | { 0x02c5, 0x010a }, |
| 4077 | { 0x02c6, 0x0108 }, |
| 4078 | { 0x02d5, 0x0120 }, |
| 4079 | { 0x02d8, 0x011c }, |
| 4080 | { 0x02dd, 0x016c }, |
| 4081 | { 0x02de, 0x015c }, |
| 4082 | { 0x02e5, 0x010b }, |
| 4083 | { 0x02e6, 0x0109 }, |
| 4084 | { 0x02f5, 0x0121 }, |
| 4085 | { 0x02f8, 0x011d }, |
| 4086 | { 0x02fd, 0x016d }, |
| 4087 | { 0x02fe, 0x015d }, |
| 4088 | { 0x03a2, 0x0138 }, |
| 4089 | { 0x03a3, 0x0156 }, |
| 4090 | { 0x03a5, 0x0128 }, |
| 4091 | { 0x03a6, 0x013b }, |
| 4092 | { 0x03aa, 0x0112 }, |
| 4093 | { 0x03ab, 0x0122 }, |
| 4094 | { 0x03ac, 0x0166 }, |
| 4095 | { 0x03b3, 0x0157 }, |
| 4096 | { 0x03b5, 0x0129 }, |
| 4097 | { 0x03b6, 0x013c }, |
| 4098 | { 0x03ba, 0x0113 }, |
| 4099 | { 0x03bb, 0x0123 }, |
| 4100 | { 0x03bc, 0x0167 }, |
| 4101 | { 0x03bd, 0x014a }, |
| 4102 | { 0x03bf, 0x014b }, |
| 4103 | { 0x03c0, 0x0100 }, |
| 4104 | { 0x03c7, 0x012e }, |
| 4105 | { 0x03cc, 0x0116 }, |
| 4106 | { 0x03cf, 0x012a }, |
| 4107 | { 0x03d1, 0x0145 }, |
| 4108 | { 0x03d2, 0x014c }, |
| 4109 | { 0x03d3, 0x0136 }, |
| 4110 | { 0x03d9, 0x0172 }, |
| 4111 | { 0x03dd, 0x0168 }, |
| 4112 | { 0x03de, 0x016a }, |
| 4113 | { 0x03e0, 0x0101 }, |
| 4114 | { 0x03e7, 0x012f }, |
| 4115 | { 0x03ec, 0x0117 }, |
| 4116 | { 0x03ef, 0x012b }, |
| 4117 | { 0x03f1, 0x0146 }, |
| 4118 | { 0x03f2, 0x014d }, |
| 4119 | { 0x03f3, 0x0137 }, |
| 4120 | { 0x03f9, 0x0173 }, |
| 4121 | { 0x03fd, 0x0169 }, |
| 4122 | { 0x03fe, 0x016b }, |
| 4123 | { 0x047e, 0x203e }, |
| 4124 | { 0x04a1, 0x3002 }, |
| 4125 | { 0x04a2, 0x300c }, |
| 4126 | { 0x04a3, 0x300d }, |
| 4127 | { 0x04a4, 0x3001 }, |
| 4128 | { 0x04a5, 0x30fb }, |
| 4129 | { 0x04a6, 0x30f2 }, |
| 4130 | { 0x04a7, 0x30a1 }, |
| 4131 | { 0x04a8, 0x30a3 }, |
| 4132 | { 0x04a9, 0x30a5 }, |
| 4133 | { 0x04aa, 0x30a7 }, |
| 4134 | { 0x04ab, 0x30a9 }, |
| 4135 | { 0x04ac, 0x30e3 }, |
| 4136 | { 0x04ad, 0x30e5 }, |
| 4137 | { 0x04ae, 0x30e7 }, |
| 4138 | { 0x04af, 0x30c3 }, |
| 4139 | { 0x04b0, 0x30fc }, |
| 4140 | { 0x04b1, 0x30a2 }, |
| 4141 | { 0x04b2, 0x30a4 }, |
| 4142 | { 0x04b3, 0x30a6 }, |
| 4143 | { 0x04b4, 0x30a8 }, |
| 4144 | { 0x04b5, 0x30aa }, |
| 4145 | { 0x04b6, 0x30ab }, |
| 4146 | { 0x04b7, 0x30ad }, |
| 4147 | { 0x04b8, 0x30af }, |
| 4148 | { 0x04b9, 0x30b1 }, |
| 4149 | { 0x04ba, 0x30b3 }, |
| 4150 | { 0x04bb, 0x30b5 }, |
| 4151 | { 0x04bc, 0x30b7 }, |
| 4152 | { 0x04bd, 0x30b9 }, |
| 4153 | { 0x04be, 0x30bb }, |
| 4154 | { 0x04bf, 0x30bd }, |
| 4155 | { 0x04c0, 0x30bf }, |
| 4156 | { 0x04c1, 0x30c1 }, |
| 4157 | { 0x04c2, 0x30c4 }, |
| 4158 | { 0x04c3, 0x30c6 }, |
| 4159 | { 0x04c4, 0x30c8 }, |
| 4160 | { 0x04c5, 0x30ca }, |
| 4161 | { 0x04c6, 0x30cb }, |
| 4162 | { 0x04c7, 0x30cc }, |
| 4163 | { 0x04c8, 0x30cd }, |
| 4164 | { 0x04c9, 0x30ce }, |
| 4165 | { 0x04ca, 0x30cf }, |
| 4166 | { 0x04cb, 0x30d2 }, |
| 4167 | { 0x04cc, 0x30d5 }, |
| 4168 | { 0x04cd, 0x30d8 }, |
| 4169 | { 0x04ce, 0x30db }, |
| 4170 | { 0x04cf, 0x30de }, |
| 4171 | { 0x04d0, 0x30df }, |
| 4172 | { 0x04d1, 0x30e0 }, |
| 4173 | { 0x04d2, 0x30e1 }, |
| 4174 | { 0x04d3, 0x30e2 }, |
| 4175 | { 0x04d4, 0x30e4 }, |
| 4176 | { 0x04d5, 0x30e6 }, |
| 4177 | { 0x04d6, 0x30e8 }, |
| 4178 | { 0x04d7, 0x30e9 }, |
| 4179 | { 0x04d8, 0x30ea }, |
| 4180 | { 0x04d9, 0x30eb }, |
| 4181 | { 0x04da, 0x30ec }, |
| 4182 | { 0x04db, 0x30ed }, |
| 4183 | { 0x04dc, 0x30ef }, |
| 4184 | { 0x04dd, 0x30f3 }, |
| 4185 | { 0x04de, 0x309b }, |
| 4186 | { 0x04df, 0x309c }, |
| 4187 | { 0x05ac, 0x060c }, |
| 4188 | { 0x05bb, 0x061b }, |
| 4189 | { 0x05bf, 0x061f }, |
| 4190 | { 0x05c1, 0x0621 }, |
| 4191 | { 0x05c2, 0x0622 }, |
| 4192 | { 0x05c3, 0x0623 }, |
| 4193 | { 0x05c4, 0x0624 }, |
| 4194 | { 0x05c5, 0x0625 }, |
| 4195 | { 0x05c6, 0x0626 }, |
| 4196 | { 0x05c7, 0x0627 }, |
| 4197 | { 0x05c8, 0x0628 }, |
| 4198 | { 0x05c9, 0x0629 }, |
| 4199 | { 0x05ca, 0x062a }, |
| 4200 | { 0x05cb, 0x062b }, |
| 4201 | { 0x05cc, 0x062c }, |
| 4202 | { 0x05cd, 0x062d }, |
| 4203 | { 0x05ce, 0x062e }, |
| 4204 | { 0x05cf, 0x062f }, |
| 4205 | { 0x05d0, 0x0630 }, |
| 4206 | { 0x05d1, 0x0631 }, |
| 4207 | { 0x05d2, 0x0632 }, |
| 4208 | { 0x05d3, 0x0633 }, |
| 4209 | { 0x05d4, 0x0634 }, |
| 4210 | { 0x05d5, 0x0635 }, |
| 4211 | { 0x05d6, 0x0636 }, |
| 4212 | { 0x05d7, 0x0637 }, |
| 4213 | { 0x05d8, 0x0638 }, |
| 4214 | { 0x05d9, 0x0639 }, |
| 4215 | { 0x05da, 0x063a }, |
| 4216 | { 0x05e0, 0x0640 }, |
| 4217 | { 0x05e1, 0x0641 }, |
| 4218 | { 0x05e2, 0x0642 }, |
| 4219 | { 0x05e3, 0x0643 }, |
| 4220 | { 0x05e4, 0x0644 }, |
| 4221 | { 0x05e5, 0x0645 }, |
| 4222 | { 0x05e6, 0x0646 }, |
| 4223 | { 0x05e7, 0x0647 }, |
| 4224 | { 0x05e8, 0x0648 }, |
| 4225 | { 0x05e9, 0x0649 }, |
| 4226 | { 0x05ea, 0x064a }, |
| 4227 | { 0x05eb, 0x064b }, |
| 4228 | { 0x05ec, 0x064c }, |
| 4229 | { 0x05ed, 0x064d }, |
| 4230 | { 0x05ee, 0x064e }, |
| 4231 | { 0x05ef, 0x064f }, |
| 4232 | { 0x05f0, 0x0650 }, |
| 4233 | { 0x05f1, 0x0651 }, |
| 4234 | { 0x05f2, 0x0652 }, |
| 4235 | { 0x06a1, 0x0452 }, |
| 4236 | { 0x06a2, 0x0453 }, |
| 4237 | { 0x06a3, 0x0451 }, |
| 4238 | { 0x06a4, 0x0454 }, |
| 4239 | { 0x06a5, 0x0455 }, |
| 4240 | { 0x06a6, 0x0456 }, |
| 4241 | { 0x06a7, 0x0457 }, |
| 4242 | { 0x06a8, 0x0458 }, |
| 4243 | { 0x06a9, 0x0459 }, |
| 4244 | { 0x06aa, 0x045a }, |
| 4245 | { 0x06ab, 0x045b }, |
| 4246 | { 0x06ac, 0x045c }, |
| 4247 | { 0x06ae, 0x045e }, |
| 4248 | { 0x06af, 0x045f }, |
| 4249 | { 0x06b0, 0x2116 }, |
| 4250 | { 0x06b1, 0x0402 }, |
| 4251 | { 0x06b2, 0x0403 }, |
| 4252 | { 0x06b3, 0x0401 }, |
| 4253 | { 0x06b4, 0x0404 }, |
| 4254 | { 0x06b5, 0x0405 }, |
| 4255 | { 0x06b6, 0x0406 }, |
| 4256 | { 0x06b7, 0x0407 }, |
| 4257 | { 0x06b8, 0x0408 }, |
| 4258 | { 0x06b9, 0x0409 }, |
| 4259 | { 0x06ba, 0x040a }, |
| 4260 | { 0x06bb, 0x040b }, |
| 4261 | { 0x06bc, 0x040c }, |
| 4262 | { 0x06be, 0x040e }, |
| 4263 | { 0x06bf, 0x040f }, |
| 4264 | { 0x06c0, 0x044e }, |
| 4265 | { 0x06c1, 0x0430 }, |
| 4266 | { 0x06c2, 0x0431 }, |
| 4267 | { 0x06c3, 0x0446 }, |
| 4268 | { 0x06c4, 0x0434 }, |
| 4269 | { 0x06c5, 0x0435 }, |
| 4270 | { 0x06c6, 0x0444 }, |
| 4271 | { 0x06c7, 0x0433 }, |
| 4272 | { 0x06c8, 0x0445 }, |
| 4273 | { 0x06c9, 0x0438 }, |
| 4274 | { 0x06ca, 0x0439 }, |
| 4275 | { 0x06cb, 0x043a }, |
| 4276 | { 0x06cc, 0x043b }, |
| 4277 | { 0x06cd, 0x043c }, |
| 4278 | { 0x06ce, 0x043d }, |
| 4279 | { 0x06cf, 0x043e }, |
| 4280 | { 0x06d0, 0x043f }, |
| 4281 | { 0x06d1, 0x044f }, |
| 4282 | { 0x06d2, 0x0440 }, |
| 4283 | { 0x06d3, 0x0441 }, |
| 4284 | { 0x06d4, 0x0442 }, |
| 4285 | { 0x06d5, 0x0443 }, |
| 4286 | { 0x06d6, 0x0436 }, |
| 4287 | { 0x06d7, 0x0432 }, |
| 4288 | { 0x06d8, 0x044c }, |
| 4289 | { 0x06d9, 0x044b }, |
| 4290 | { 0x06da, 0x0437 }, |
| 4291 | { 0x06db, 0x0448 }, |
| 4292 | { 0x06dc, 0x044d }, |
| 4293 | { 0x06dd, 0x0449 }, |
| 4294 | { 0x06de, 0x0447 }, |
| 4295 | { 0x06df, 0x044a }, |
| 4296 | { 0x06e0, 0x042e }, |
| 4297 | { 0x06e1, 0x0410 }, |
| 4298 | { 0x06e2, 0x0411 }, |
| 4299 | { 0x06e3, 0x0426 }, |
| 4300 | { 0x06e4, 0x0414 }, |
| 4301 | { 0x06e5, 0x0415 }, |
| 4302 | { 0x06e6, 0x0424 }, |
| 4303 | { 0x06e7, 0x0413 }, |
| 4304 | { 0x06e8, 0x0425 }, |
| 4305 | { 0x06e9, 0x0418 }, |
| 4306 | { 0x06ea, 0x0419 }, |
| 4307 | { 0x06eb, 0x041a }, |
| 4308 | { 0x06ec, 0x041b }, |
| 4309 | { 0x06ed, 0x041c }, |
| 4310 | { 0x06ee, 0x041d }, |
| 4311 | { 0x06ef, 0x041e }, |
| 4312 | { 0x06f0, 0x041f }, |
| 4313 | { 0x06f1, 0x042f }, |
| 4314 | { 0x06f2, 0x0420 }, |
| 4315 | { 0x06f3, 0x0421 }, |
| 4316 | { 0x06f4, 0x0422 }, |
| 4317 | { 0x06f5, 0x0423 }, |
| 4318 | { 0x06f6, 0x0416 }, |
| 4319 | { 0x06f7, 0x0412 }, |
| 4320 | { 0x06f8, 0x042c }, |
| 4321 | { 0x06f9, 0x042b }, |
| 4322 | { 0x06fa, 0x0417 }, |
| 4323 | { 0x06fb, 0x0428 }, |
| 4324 | { 0x06fc, 0x042d }, |
| 4325 | { 0x06fd, 0x0429 }, |
| 4326 | { 0x06fe, 0x0427 }, |
| 4327 | { 0x06ff, 0x042a }, |
| 4328 | { 0x07a1, 0x0386 }, |
| 4329 | { 0x07a2, 0x0388 }, |
| 4330 | { 0x07a3, 0x0389 }, |
| 4331 | { 0x07a4, 0x038a }, |
| 4332 | { 0x07a5, 0x03aa }, |
| 4333 | { 0x07a7, 0x038c }, |
| 4334 | { 0x07a8, 0x038e }, |
| 4335 | { 0x07a9, 0x03ab }, |
| 4336 | { 0x07ab, 0x038f }, |
| 4337 | { 0x07ae, 0x0385 }, |
| 4338 | { 0x07af, 0x2015 }, |
| 4339 | { 0x07b1, 0x03ac }, |
| 4340 | { 0x07b2, 0x03ad }, |
| 4341 | { 0x07b3, 0x03ae }, |
| 4342 | { 0x07b4, 0x03af }, |
| 4343 | { 0x07b5, 0x03ca }, |
| 4344 | { 0x07b6, 0x0390 }, |
| 4345 | { 0x07b7, 0x03cc }, |
| 4346 | { 0x07b8, 0x03cd }, |
| 4347 | { 0x07b9, 0x03cb }, |
| 4348 | { 0x07ba, 0x03b0 }, |
| 4349 | { 0x07bb, 0x03ce }, |
| 4350 | { 0x07c1, 0x0391 }, |
| 4351 | { 0x07c2, 0x0392 }, |
| 4352 | { 0x07c3, 0x0393 }, |
| 4353 | { 0x07c4, 0x0394 }, |
| 4354 | { 0x07c5, 0x0395 }, |
| 4355 | { 0x07c6, 0x0396 }, |
| 4356 | { 0x07c7, 0x0397 }, |
| 4357 | { 0x07c8, 0x0398 }, |
| 4358 | { 0x07c9, 0x0399 }, |
| 4359 | { 0x07ca, 0x039a }, |
| 4360 | { 0x07cb, 0x039b }, |
| 4361 | { 0x07cc, 0x039c }, |
| 4362 | { 0x07cd, 0x039d }, |
| 4363 | { 0x07ce, 0x039e }, |
| 4364 | { 0x07cf, 0x039f }, |
| 4365 | { 0x07d0, 0x03a0 }, |
| 4366 | { 0x07d1, 0x03a1 }, |
| 4367 | { 0x07d2, 0x03a3 }, |
| 4368 | { 0x07d4, 0x03a4 }, |
| 4369 | { 0x07d5, 0x03a5 }, |
| 4370 | { 0x07d6, 0x03a6 }, |
| 4371 | { 0x07d7, 0x03a7 }, |
| 4372 | { 0x07d8, 0x03a8 }, |
| 4373 | { 0x07d9, 0x03a9 }, |
| 4374 | { 0x07e1, 0x03b1 }, |
| 4375 | { 0x07e2, 0x03b2 }, |
| 4376 | { 0x07e3, 0x03b3 }, |
| 4377 | { 0x07e4, 0x03b4 }, |
| 4378 | { 0x07e5, 0x03b5 }, |
| 4379 | { 0x07e6, 0x03b6 }, |
| 4380 | { 0x07e7, 0x03b7 }, |
| 4381 | { 0x07e8, 0x03b8 }, |
| 4382 | { 0x07e9, 0x03b9 }, |
| 4383 | { 0x07ea, 0x03ba }, |
| 4384 | { 0x07eb, 0x03bb }, |
| 4385 | { 0x07ec, 0x03bc }, |
| 4386 | { 0x07ed, 0x03bd }, |
| 4387 | { 0x07ee, 0x03be }, |
| 4388 | { 0x07ef, 0x03bf }, |
| 4389 | { 0x07f0, 0x03c0 }, |
| 4390 | { 0x07f1, 0x03c1 }, |
| 4391 | { 0x07f2, 0x03c3 }, |
| 4392 | { 0x07f3, 0x03c2 }, |
| 4393 | { 0x07f4, 0x03c4 }, |
| 4394 | { 0x07f5, 0x03c5 }, |
| 4395 | { 0x07f6, 0x03c6 }, |
| 4396 | { 0x07f7, 0x03c7 }, |
| 4397 | { 0x07f8, 0x03c8 }, |
| 4398 | { 0x07f9, 0x03c9 }, |
| 4399 | { 0x08a1, 0x23b7 }, |
| 4400 | { 0x08a2, 0x250c }, |
| 4401 | { 0x08a3, 0x2500 }, |
| 4402 | { 0x08a4, 0x2320 }, |
| 4403 | { 0x08a5, 0x2321 }, |
| 4404 | { 0x08a6, 0x2502 }, |
| 4405 | { 0x08a7, 0x23a1 }, |
| 4406 | { 0x08a8, 0x23a3 }, |
| 4407 | { 0x08a9, 0x23a4 }, |
| 4408 | { 0x08aa, 0x23a6 }, |
| 4409 | { 0x08ab, 0x239b }, |
| 4410 | { 0x08ac, 0x239d }, |
| 4411 | { 0x08ad, 0x239e }, |
| 4412 | { 0x08ae, 0x23a0 }, |
| 4413 | { 0x08af, 0x23a8 }, |
| 4414 | { 0x08b0, 0x23ac }, |
| 4415 | { 0x08bc, 0x2264 }, |
| 4416 | { 0x08bd, 0x2260 }, |
| 4417 | { 0x08be, 0x2265 }, |
| 4418 | { 0x08bf, 0x222b }, |
| 4419 | { 0x08c0, 0x2234 }, |
| 4420 | { 0x08c1, 0x221d }, |
| 4421 | { 0x08c2, 0x221e }, |
| 4422 | { 0x08c5, 0x2207 }, |
| 4423 | { 0x08c8, 0x223c }, |
| 4424 | { 0x08c9, 0x2243 }, |
| 4425 | { 0x08cd, 0x21d4 }, |
| 4426 | { 0x08ce, 0x21d2 }, |
| 4427 | { 0x08cf, 0x2261 }, |
| 4428 | { 0x08d6, 0x221a }, |
| 4429 | { 0x08da, 0x2282 }, |
| 4430 | { 0x08db, 0x2283 }, |
| 4431 | { 0x08dc, 0x2229 }, |
| 4432 | { 0x08dd, 0x222a }, |
| 4433 | { 0x08de, 0x2227 }, |
| 4434 | { 0x08df, 0x2228 }, |
| 4435 | { 0x08ef, 0x2202 }, |
| 4436 | { 0x08f6, 0x0192 }, |
| 4437 | { 0x08fb, 0x2190 }, |
| 4438 | { 0x08fc, 0x2191 }, |
| 4439 | { 0x08fd, 0x2192 }, |
| 4440 | { 0x08fe, 0x2193 }, |
| 4441 | { 0x09e0, 0x25c6 }, |
| 4442 | { 0x09e1, 0x2592 }, |
| 4443 | { 0x09e2, 0x2409 }, |
| 4444 | { 0x09e3, 0x240c }, |
| 4445 | { 0x09e4, 0x240d }, |
| 4446 | { 0x09e5, 0x240a }, |
| 4447 | { 0x09e8, 0x2424 }, |
| 4448 | { 0x09e9, 0x240b }, |
| 4449 | { 0x09ea, 0x2518 }, |
| 4450 | { 0x09eb, 0x2510 }, |
| 4451 | { 0x09ec, 0x250c }, |
| 4452 | { 0x09ed, 0x2514 }, |
| 4453 | { 0x09ee, 0x253c }, |
| 4454 | { 0x09ef, 0x23ba }, |
| 4455 | { 0x09f0, 0x23bb }, |
| 4456 | { 0x09f1, 0x2500 }, |
| 4457 | { 0x09f2, 0x23bc }, |
| 4458 | { 0x09f3, 0x23bd }, |
| 4459 | { 0x09f4, 0x251c }, |
| 4460 | { 0x09f5, 0x2524 }, |
| 4461 | { 0x09f6, 0x2534 }, |
| 4462 | { 0x09f7, 0x252c }, |
| 4463 | { 0x09f8, 0x2502 }, |
| 4464 | { 0x0aa1, 0x2003 }, |
| 4465 | { 0x0aa2, 0x2002 }, |
| 4466 | { 0x0aa3, 0x2004 }, |
| 4467 | { 0x0aa4, 0x2005 }, |
| 4468 | { 0x0aa5, 0x2007 }, |
| 4469 | { 0x0aa6, 0x2008 }, |
| 4470 | { 0x0aa7, 0x2009 }, |
| 4471 | { 0x0aa8, 0x200a }, |
| 4472 | { 0x0aa9, 0x2014 }, |
| 4473 | { 0x0aaa, 0x2013 }, |
| 4474 | { 0x0aae, 0x2026 }, |
| 4475 | { 0x0aaf, 0x2025 }, |
| 4476 | { 0x0ab0, 0x2153 }, |
| 4477 | { 0x0ab1, 0x2154 }, |
| 4478 | { 0x0ab2, 0x2155 }, |
| 4479 | { 0x0ab3, 0x2156 }, |
| 4480 | { 0x0ab4, 0x2157 }, |
| 4481 | { 0x0ab5, 0x2158 }, |
| 4482 | { 0x0ab6, 0x2159 }, |
| 4483 | { 0x0ab7, 0x215a }, |
| 4484 | { 0x0ab8, 0x2105 }, |
| 4485 | { 0x0abb, 0x2012 }, |
| 4486 | { 0x0abc, 0x2329 }, |
| 4487 | { 0x0abe, 0x232a }, |
| 4488 | { 0x0ac3, 0x215b }, |
| 4489 | { 0x0ac4, 0x215c }, |
| 4490 | { 0x0ac5, 0x215d }, |
| 4491 | { 0x0ac6, 0x215e }, |
| 4492 | { 0x0ac9, 0x2122 }, |
| 4493 | { 0x0aca, 0x2613 }, |
| 4494 | { 0x0acc, 0x25c1 }, |
| 4495 | { 0x0acd, 0x25b7 }, |
| 4496 | { 0x0ace, 0x25cb }, |
| 4497 | { 0x0acf, 0x25af }, |
| 4498 | { 0x0ad0, 0x2018 }, |
| 4499 | { 0x0ad1, 0x2019 }, |
| 4500 | { 0x0ad2, 0x201c }, |
| 4501 | { 0x0ad3, 0x201d }, |
| 4502 | { 0x0ad4, 0x211e }, |
| 4503 | { 0x0ad6, 0x2032 }, |
| 4504 | { 0x0ad7, 0x2033 }, |
| 4505 | { 0x0ad9, 0x271d }, |
| 4506 | { 0x0adb, 0x25ac }, |
| 4507 | { 0x0adc, 0x25c0 }, |
| 4508 | { 0x0add, 0x25b6 }, |
| 4509 | { 0x0ade, 0x25cf }, |
| 4510 | { 0x0adf, 0x25ae }, |
| 4511 | { 0x0ae0, 0x25e6 }, |
| 4512 | { 0x0ae1, 0x25ab }, |
| 4513 | { 0x0ae2, 0x25ad }, |
| 4514 | { 0x0ae3, 0x25b3 }, |
| 4515 | { 0x0ae4, 0x25bd }, |
| 4516 | { 0x0ae5, 0x2606 }, |
| 4517 | { 0x0ae6, 0x2022 }, |
| 4518 | { 0x0ae7, 0x25aa }, |
| 4519 | { 0x0ae8, 0x25b2 }, |
| 4520 | { 0x0ae9, 0x25bc }, |
| 4521 | { 0x0aea, 0x261c }, |
| 4522 | { 0x0aeb, 0x261e }, |
| 4523 | { 0x0aec, 0x2663 }, |
| 4524 | { 0x0aed, 0x2666 }, |
| 4525 | { 0x0aee, 0x2665 }, |
| 4526 | { 0x0af0, 0x2720 }, |
| 4527 | { 0x0af1, 0x2020 }, |
| 4528 | { 0x0af2, 0x2021 }, |
| 4529 | { 0x0af3, 0x2713 }, |
| 4530 | { 0x0af4, 0x2717 }, |
| 4531 | { 0x0af5, 0x266f }, |
| 4532 | { 0x0af6, 0x266d }, |
| 4533 | { 0x0af7, 0x2642 }, |
| 4534 | { 0x0af8, 0x2640 }, |
| 4535 | { 0x0af9, 0x260e }, |
| 4536 | { 0x0afa, 0x2315 }, |
| 4537 | { 0x0afb, 0x2117 }, |
| 4538 | { 0x0afc, 0x2038 }, |
| 4539 | { 0x0afd, 0x201a }, |
| 4540 | { 0x0afe, 0x201e }, |
| 4541 | { 0x0ba3, 0x003c }, |
| 4542 | { 0x0ba6, 0x003e }, |
| 4543 | { 0x0ba8, 0x2228 }, |
| 4544 | { 0x0ba9, 0x2227 }, |
| 4545 | { 0x0bc0, 0x00af }, |
| 4546 | { 0x0bc2, 0x22a5 }, |
| 4547 | { 0x0bc3, 0x2229 }, |
| 4548 | { 0x0bc4, 0x230a }, |
| 4549 | { 0x0bc6, 0x005f }, |
| 4550 | { 0x0bca, 0x2218 }, |
| 4551 | { 0x0bcc, 0x2395 }, |
| 4552 | { 0x0bce, 0x22a4 }, |
| 4553 | { 0x0bcf, 0x25cb }, |
| 4554 | { 0x0bd3, 0x2308 }, |
| 4555 | { 0x0bd6, 0x222a }, |
| 4556 | { 0x0bd8, 0x2283 }, |
| 4557 | { 0x0bda, 0x2282 }, |
| 4558 | { 0x0bdc, 0x22a2 }, |
| 4559 | { 0x0bfc, 0x22a3 }, |
| 4560 | { 0x0cdf, 0x2017 }, |
| 4561 | { 0x0ce0, 0x05d0 }, |
| 4562 | { 0x0ce1, 0x05d1 }, |
| 4563 | { 0x0ce2, 0x05d2 }, |
| 4564 | { 0x0ce3, 0x05d3 }, |
| 4565 | { 0x0ce4, 0x05d4 }, |
| 4566 | { 0x0ce5, 0x05d5 }, |
| 4567 | { 0x0ce6, 0x05d6 }, |
| 4568 | { 0x0ce7, 0x05d7 }, |
| 4569 | { 0x0ce8, 0x05d8 }, |
| 4570 | { 0x0ce9, 0x05d9 }, |
| 4571 | { 0x0cea, 0x05da }, |
| 4572 | { 0x0ceb, 0x05db }, |
| 4573 | { 0x0cec, 0x05dc }, |
| 4574 | { 0x0ced, 0x05dd }, |
| 4575 | { 0x0cee, 0x05de }, |
| 4576 | { 0x0cef, 0x05df }, |
| 4577 | { 0x0cf0, 0x05e0 }, |
| 4578 | { 0x0cf1, 0x05e1 }, |
| 4579 | { 0x0cf2, 0x05e2 }, |
| 4580 | { 0x0cf3, 0x05e3 }, |
| 4581 | { 0x0cf4, 0x05e4 }, |
| 4582 | { 0x0cf5, 0x05e5 }, |
| 4583 | { 0x0cf6, 0x05e6 }, |
| 4584 | { 0x0cf7, 0x05e7 }, |
| 4585 | { 0x0cf8, 0x05e8 }, |
| 4586 | { 0x0cf9, 0x05e9 }, |
| 4587 | { 0x0cfa, 0x05ea }, |
| 4588 | { 0x0da1, 0x0e01 }, |
| 4589 | { 0x0da2, 0x0e02 }, |
| 4590 | { 0x0da3, 0x0e03 }, |
| 4591 | { 0x0da4, 0x0e04 }, |
| 4592 | { 0x0da5, 0x0e05 }, |
| 4593 | { 0x0da6, 0x0e06 }, |
| 4594 | { 0x0da7, 0x0e07 }, |
| 4595 | { 0x0da8, 0x0e08 }, |
| 4596 | { 0x0da9, 0x0e09 }, |
| 4597 | { 0x0daa, 0x0e0a }, |
| 4598 | { 0x0dab, 0x0e0b }, |
| 4599 | { 0x0dac, 0x0e0c }, |
| 4600 | { 0x0dad, 0x0e0d }, |
| 4601 | { 0x0dae, 0x0e0e }, |
| 4602 | { 0x0daf, 0x0e0f }, |
| 4603 | { 0x0db0, 0x0e10 }, |
| 4604 | { 0x0db1, 0x0e11 }, |
| 4605 | { 0x0db2, 0x0e12 }, |
| 4606 | { 0x0db3, 0x0e13 }, |
| 4607 | { 0x0db4, 0x0e14 }, |
| 4608 | { 0x0db5, 0x0e15 }, |
| 4609 | { 0x0db6, 0x0e16 }, |
| 4610 | { 0x0db7, 0x0e17 }, |
| 4611 | { 0x0db8, 0x0e18 }, |
| 4612 | { 0x0db9, 0x0e19 }, |
| 4613 | { 0x0dba, 0x0e1a }, |
| 4614 | { 0x0dbb, 0x0e1b }, |
| 4615 | { 0x0dbc, 0x0e1c }, |
| 4616 | { 0x0dbd, 0x0e1d }, |
| 4617 | { 0x0dbe, 0x0e1e }, |
| 4618 | { 0x0dbf, 0x0e1f }, |
| 4619 | { 0x0dc0, 0x0e20 }, |
| 4620 | { 0x0dc1, 0x0e21 }, |
| 4621 | { 0x0dc2, 0x0e22 }, |
| 4622 | { 0x0dc3, 0x0e23 }, |
| 4623 | { 0x0dc4, 0x0e24 }, |
| 4624 | { 0x0dc5, 0x0e25 }, |
| 4625 | { 0x0dc6, 0x0e26 }, |
| 4626 | { 0x0dc7, 0x0e27 }, |
| 4627 | { 0x0dc8, 0x0e28 }, |
| 4628 | { 0x0dc9, 0x0e29 }, |
| 4629 | { 0x0dca, 0x0e2a }, |
| 4630 | { 0x0dcb, 0x0e2b }, |
| 4631 | { 0x0dcc, 0x0e2c }, |
| 4632 | { 0x0dcd, 0x0e2d }, |
| 4633 | { 0x0dce, 0x0e2e }, |
| 4634 | { 0x0dcf, 0x0e2f }, |
| 4635 | { 0x0dd0, 0x0e30 }, |
| 4636 | { 0x0dd1, 0x0e31 }, |
| 4637 | { 0x0dd2, 0x0e32 }, |
| 4638 | { 0x0dd3, 0x0e33 }, |
| 4639 | { 0x0dd4, 0x0e34 }, |
| 4640 | { 0x0dd5, 0x0e35 }, |
| 4641 | { 0x0dd6, 0x0e36 }, |
| 4642 | { 0x0dd7, 0x0e37 }, |
| 4643 | { 0x0dd8, 0x0e38 }, |
| 4644 | { 0x0dd9, 0x0e39 }, |
| 4645 | { 0x0dda, 0x0e3a }, |
| 4646 | { 0x0ddf, 0x0e3f }, |
| 4647 | { 0x0de0, 0x0e40 }, |
| 4648 | { 0x0de1, 0x0e41 }, |
| 4649 | { 0x0de2, 0x0e42 }, |
| 4650 | { 0x0de3, 0x0e43 }, |
| 4651 | { 0x0de4, 0x0e44 }, |
| 4652 | { 0x0de5, 0x0e45 }, |
| 4653 | { 0x0de6, 0x0e46 }, |
| 4654 | { 0x0de7, 0x0e47 }, |
| 4655 | { 0x0de8, 0x0e48 }, |
| 4656 | { 0x0de9, 0x0e49 }, |
| 4657 | { 0x0dea, 0x0e4a }, |
| 4658 | { 0x0deb, 0x0e4b }, |
| 4659 | { 0x0dec, 0x0e4c }, |
| 4660 | { 0x0ded, 0x0e4d }, |
| 4661 | { 0x0df0, 0x0e50 }, |
| 4662 | { 0x0df1, 0x0e51 }, |
| 4663 | { 0x0df2, 0x0e52 }, |
| 4664 | { 0x0df3, 0x0e53 }, |
| 4665 | { 0x0df4, 0x0e54 }, |
| 4666 | { 0x0df5, 0x0e55 }, |
| 4667 | { 0x0df6, 0x0e56 }, |
| 4668 | { 0x0df7, 0x0e57 }, |
| 4669 | { 0x0df8, 0x0e58 }, |
| 4670 | { 0x0df9, 0x0e59 }, |
| 4671 | { 0x0ea1, 0x3131 }, |
| 4672 | { 0x0ea2, 0x3132 }, |
| 4673 | { 0x0ea3, 0x3133 }, |
| 4674 | { 0x0ea4, 0x3134 }, |
| 4675 | { 0x0ea5, 0x3135 }, |
| 4676 | { 0x0ea6, 0x3136 }, |
| 4677 | { 0x0ea7, 0x3137 }, |
| 4678 | { 0x0ea8, 0x3138 }, |
| 4679 | { 0x0ea9, 0x3139 }, |
| 4680 | { 0x0eaa, 0x313a }, |
| 4681 | { 0x0eab, 0x313b }, |
| 4682 | { 0x0eac, 0x313c }, |
| 4683 | { 0x0ead, 0x313d }, |
| 4684 | { 0x0eae, 0x313e }, |
| 4685 | { 0x0eaf, 0x313f }, |
| 4686 | { 0x0eb0, 0x3140 }, |
| 4687 | { 0x0eb1, 0x3141 }, |
| 4688 | { 0x0eb2, 0x3142 }, |
| 4689 | { 0x0eb3, 0x3143 }, |
| 4690 | { 0x0eb4, 0x3144 }, |
| 4691 | { 0x0eb5, 0x3145 }, |
| 4692 | { 0x0eb6, 0x3146 }, |
| 4693 | { 0x0eb7, 0x3147 }, |
| 4694 | { 0x0eb8, 0x3148 }, |
| 4695 | { 0x0eb9, 0x3149 }, |
| 4696 | { 0x0eba, 0x314a }, |
| 4697 | { 0x0ebb, 0x314b }, |
| 4698 | { 0x0ebc, 0x314c }, |
| 4699 | { 0x0ebd, 0x314d }, |
| 4700 | { 0x0ebe, 0x314e }, |
| 4701 | { 0x0ebf, 0x314f }, |
| 4702 | { 0x0ec0, 0x3150 }, |
| 4703 | { 0x0ec1, 0x3151 }, |
| 4704 | { 0x0ec2, 0x3152 }, |
| 4705 | { 0x0ec3, 0x3153 }, |
| 4706 | { 0x0ec4, 0x3154 }, |
| 4707 | { 0x0ec5, 0x3155 }, |
| 4708 | { 0x0ec6, 0x3156 }, |
| 4709 | { 0x0ec7, 0x3157 }, |
| 4710 | { 0x0ec8, 0x3158 }, |
| 4711 | { 0x0ec9, 0x3159 }, |
| 4712 | { 0x0eca, 0x315a }, |
| 4713 | { 0x0ecb, 0x315b }, |
| 4714 | { 0x0ecc, 0x315c }, |
| 4715 | { 0x0ecd, 0x315d }, |
| 4716 | { 0x0ece, 0x315e }, |
| 4717 | { 0x0ecf, 0x315f }, |
| 4718 | { 0x0ed0, 0x3160 }, |
| 4719 | { 0x0ed1, 0x3161 }, |
| 4720 | { 0x0ed2, 0x3162 }, |
| 4721 | { 0x0ed3, 0x3163 }, |
| 4722 | { 0x0ed4, 0x11a8 }, |
| 4723 | { 0x0ed5, 0x11a9 }, |
| 4724 | { 0x0ed6, 0x11aa }, |
| 4725 | { 0x0ed7, 0x11ab }, |
| 4726 | { 0x0ed8, 0x11ac }, |
| 4727 | { 0x0ed9, 0x11ad }, |
| 4728 | { 0x0eda, 0x11ae }, |
| 4729 | { 0x0edb, 0x11af }, |
| 4730 | { 0x0edc, 0x11b0 }, |
| 4731 | { 0x0edd, 0x11b1 }, |
| 4732 | { 0x0ede, 0x11b2 }, |
| 4733 | { 0x0edf, 0x11b3 }, |
| 4734 | { 0x0ee0, 0x11b4 }, |
| 4735 | { 0x0ee1, 0x11b5 }, |
| 4736 | { 0x0ee2, 0x11b6 }, |
| 4737 | { 0x0ee3, 0x11b7 }, |
| 4738 | { 0x0ee4, 0x11b8 }, |
| 4739 | { 0x0ee5, 0x11b9 }, |
| 4740 | { 0x0ee6, 0x11ba }, |
| 4741 | { 0x0ee7, 0x11bb }, |
| 4742 | { 0x0ee8, 0x11bc }, |
| 4743 | { 0x0ee9, 0x11bd }, |
| 4744 | { 0x0eea, 0x11be }, |
| 4745 | { 0x0eeb, 0x11bf }, |
| 4746 | { 0x0eec, 0x11c0 }, |
| 4747 | { 0x0eed, 0x11c1 }, |
| 4748 | { 0x0eee, 0x11c2 }, |
| 4749 | { 0x0eef, 0x316d }, |
| 4750 | { 0x0ef0, 0x3171 }, |
| 4751 | { 0x0ef1, 0x3178 }, |
| 4752 | { 0x0ef2, 0x317f }, |
| 4753 | { 0x0ef3, 0x3181 }, |
| 4754 | { 0x0ef4, 0x3184 }, |
| 4755 | { 0x0ef5, 0x3186 }, |
| 4756 | { 0x0ef6, 0x318d }, |
| 4757 | { 0x0ef7, 0x318e }, |
| 4758 | { 0x0ef8, 0x11eb }, |
| 4759 | { 0x0ef9, 0x11f0 }, |
| 4760 | { 0x0efa, 0x11f9 }, |
| 4761 | { 0x0eff, 0x20a9 }, |
| 4762 | { 0x13a4, 0x20ac }, |
| 4763 | { 0x13bc, 0x0152 }, |
| 4764 | { 0x13bd, 0x0153 }, |
| 4765 | { 0x13be, 0x0178 }, |
| 4766 | { 0x20ac, 0x20ac }, |
| 4767 | { 0xfe50, '`' }, |
| 4768 | { 0xfe51, 0x00b4 }, |
| 4769 | { 0xfe52, '^' }, |
| 4770 | { 0xfe53, '~' }, |
| 4771 | { 0xfe54, 0x00af }, |
| 4772 | { 0xfe55, 0x02d8 }, |
| 4773 | { 0xfe56, 0x02d9 }, |
| 4774 | { 0xfe57, 0x00a8 }, |
| 4775 | { 0xfe58, 0x02da }, |
| 4776 | { 0xfe59, 0x02dd }, |
| 4777 | { 0xfe5a, 0x02c7 }, |
| 4778 | { 0xfe5b, 0x00b8 }, |
| 4779 | { 0xfe5c, 0x02db }, |
| 4780 | { 0xfe5d, 0x037a }, |
| 4781 | { 0xfe5e, 0x309b }, |
| 4782 | { 0xfe5f, 0x309c }, |
| 4783 | { 0xfe63, '/' }, |
| 4784 | { 0xfe64, 0x02bc }, |
| 4785 | { 0xfe65, 0x02bd }, |
| 4786 | { 0xfe66, 0x02f5 }, |
| 4787 | { 0xfe67, 0x02f3 }, |
| 4788 | { 0xfe68, 0x02cd }, |
| 4789 | { 0xfe69, 0xa788 }, |
| 4790 | { 0xfe6a, 0x02f7 }, |
| 4791 | { 0xfe6e, ',' }, |
| 4792 | { 0xfe6f, 0x00a4 }, |
| 4793 | { 0xfe80, 'a' }, /* XK_dead_a */ |
| 4794 | { 0xfe81, 'A' }, /* XK_dead_A */ |
| 4795 | { 0xfe82, 'e' }, /* XK_dead_e */ |
| 4796 | { 0xfe83, 'E' }, /* XK_dead_E */ |
| 4797 | { 0xfe84, 'i' }, /* XK_dead_i */ |
| 4798 | { 0xfe85, 'I' }, /* XK_dead_I */ |
| 4799 | { 0xfe86, 'o' }, /* XK_dead_o */ |
| 4800 | { 0xfe87, 'O' }, /* XK_dead_O */ |
| 4801 | { 0xfe88, 'u' }, /* XK_dead_u */ |
| 4802 | { 0xfe89, 'U' }, /* XK_dead_U */ |
| 4803 | { 0xfe8a, 0x0259 }, |
| 4804 | { 0xfe8b, 0x018f }, |
| 4805 | { 0xfe8c, 0x00b5 }, |
| 4806 | { 0xfe90, '_' }, |
| 4807 | { 0xfe91, 0x02c8 }, |
| 4808 | { 0xfe92, 0x02cc }, |
| 4809 | { 0xff80 /*XKB_KEY_KP_Space*/, ' ' }, |
| 4810 | { 0xff95 /*XKB_KEY_KP_7*/, 0x0037 }, |
| 4811 | { 0xff96 /*XKB_KEY_KP_4*/, 0x0034 }, |
| 4812 | { 0xff97 /*XKB_KEY_KP_8*/, 0x0038 }, |
| 4813 | { 0xff98 /*XKB_KEY_KP_6*/, 0x0036 }, |
| 4814 | { 0xff99 /*XKB_KEY_KP_2*/, 0x0032 }, |
| 4815 | { 0xff9a /*XKB_KEY_KP_9*/, 0x0039 }, |
| 4816 | { 0xff9b /*XKB_KEY_KP_3*/, 0x0033 }, |
| 4817 | { 0xff9c /*XKB_KEY_KP_1*/, 0x0031 }, |
| 4818 | { 0xff9d /*XKB_KEY_KP_5*/, 0x0035 }, |
| 4819 | { 0xff9e /*XKB_KEY_KP_0*/, 0x0030 }, |
| 4820 | { 0xffaa /*XKB_KEY_KP_Multiply*/, '*' }, |
| 4821 | { 0xffab /*XKB_KEY_KP_Add*/, '+' }, |
| 4822 | { 0xffac /*XKB_KEY_KP_Separator*/, ',' }, |
| 4823 | { 0xffad /*XKB_KEY_KP_Subtract*/, '-' }, |
| 4824 | { 0xffae /*XKB_KEY_KP_Decimal*/, '.' }, |
| 4825 | { 0xffaf /*XKB_KEY_KP_Divide*/, '/' }, |
| 4826 | { 0xffb0 /*XKB_KEY_KP_0*/, 0x0030 }, |
| 4827 | { 0xffb1 /*XKB_KEY_KP_1*/, 0x0031 }, |
| 4828 | { 0xffb2 /*XKB_KEY_KP_2*/, 0x0032 }, |
| 4829 | { 0xffb3 /*XKB_KEY_KP_3*/, 0x0033 }, |
| 4830 | { 0xffb4 /*XKB_KEY_KP_4*/, 0x0034 }, |
| 4831 | { 0xffb5 /*XKB_KEY_KP_5*/, 0x0035 }, |
| 4832 | { 0xffb6 /*XKB_KEY_KP_6*/, 0x0036 }, |
| 4833 | { 0xffb7 /*XKB_KEY_KP_7*/, 0x0037 }, |
| 4834 | { 0xffb8 /*XKB_KEY_KP_8*/, 0x0038 }, |
| 4835 | { 0xffb9 /*XKB_KEY_KP_9*/, 0x0039 }, |
| 4836 | { 0xffbd /*XKB_KEY_KP_Equal*/, '=' } |
| 4837 | }; |
| 4838 | |
| 4839 | _SOKOL_PRIVATE int _sapp_x11_error_handler(Display* display, XErrorEvent* event) { |
| 4840 | _sapp_x11_error_code = event->error_code; |
| 4841 | return 0; |
| 4842 | } |
| 4843 | |
| 4844 | _SOKOL_PRIVATE void _sapp_x11_grab_error_handler(void) { |
| 4845 | _sapp_x11_error_code = Success; |
| 4846 | XSetErrorHandler(_sapp_x11_error_handler); |
| 4847 | } |
| 4848 | |
| 4849 | _SOKOL_PRIVATE void _sapp_x11_release_error_handler(void) { |
| 4850 | XSync(_sapp_x11_display, False); |
| 4851 | XSetErrorHandler(NULL); |
| 4852 | } |
| 4853 | |
| 4854 | _SOKOL_PRIVATE void _sapp_x11_init_extensions(void) { |
| 4855 | _sapp_x11_UTF8_STRING = XInternAtom(_sapp_x11_display, "UTF8_STRING" , False); |
| 4856 | _sapp_x11_WM_PROTOCOLS = XInternAtom(_sapp_x11_display, "WM_PROTOCOLS" , False); |
| 4857 | _sapp_x11_WM_DELETE_WINDOW = XInternAtom(_sapp_x11_display, "WM_DELETE_WINDOW" , False); |
| 4858 | _sapp_x11_WM_STATE = XInternAtom(_sapp_x11_display, "WM_STATE" , False); |
| 4859 | _sapp_x11_NET_WM_NAME = XInternAtom(_sapp_x11_display, "_NET_WM_NAME" , False); |
| 4860 | _sapp_x11_NET_WM_ICON_NAME = XInternAtom(_sapp_x11_display, "_NET_WM_ICON_NAME" , False); |
| 4861 | } |
| 4862 | |
| 4863 | _SOKOL_PRIVATE void _sapp_x11_query_system_dpi(void) { |
| 4864 | /* from GLFW: |
| 4865 | |
| 4866 | NOTE: Default to the display-wide DPI as we don't currently have a policy |
| 4867 | for which monitor a window is considered to be on |
| 4868 | _sapp_x11_dpi = DisplayWidth(_sapp_x11_display, _sapp_x11_screen) * |
| 4869 | 25.4f / DisplayWidthMM(_sapp_x11_display, _sapp_x11_screen); |
| 4870 | |
| 4871 | NOTE: Basing the scale on Xft.dpi where available should provide the most |
| 4872 | consistent user experience (matches Qt, Gtk, etc), although not |
| 4873 | always the most accurate one |
| 4874 | */ |
| 4875 | char* rms = XResourceManagerString(_sapp_x11_display); |
| 4876 | if (rms) { |
| 4877 | XrmDatabase db = XrmGetStringDatabase(rms); |
| 4878 | if (db) { |
| 4879 | XrmValue value; |
| 4880 | char* type = NULL; |
| 4881 | if (XrmGetResource(db, "Xft.dpi" , "Xft.Dpi" , &type, &value)) { |
| 4882 | if (type && strcmp(type, "String" ) == 0) { |
| 4883 | _sapp_x11_dpi = atof(value.addr); |
| 4884 | } |
| 4885 | } |
| 4886 | XrmDestroyDatabase(db); |
| 4887 | } |
| 4888 | } |
| 4889 | } |
| 4890 | |
| 4891 | _SOKOL_PRIVATE bool _sapp_glx_has_ext(const char* ext, const char* extensions) { |
| 4892 | SOKOL_ASSERT(ext); |
| 4893 | const char* start = extensions; |
| 4894 | while (true) { |
| 4895 | const char* where = strstr(start, ext); |
| 4896 | if (!where) { |
| 4897 | return false; |
| 4898 | } |
| 4899 | const char* terminator = where + strlen(ext); |
| 4900 | if ((where == start) || (*(where - 1) == ' ')) { |
| 4901 | if (*terminator == ' ' || *terminator == '\0') { |
| 4902 | break; |
| 4903 | } |
| 4904 | } |
| 4905 | start = terminator; |
| 4906 | } |
| 4907 | return true; |
| 4908 | } |
| 4909 | |
| 4910 | _SOKOL_PRIVATE bool _sapp_glx_extsupported(const char* ext, const char* extensions) { |
| 4911 | if (extensions) { |
| 4912 | return _sapp_glx_has_ext(ext, extensions); |
| 4913 | } |
| 4914 | else { |
| 4915 | return false; |
| 4916 | } |
| 4917 | } |
| 4918 | |
| 4919 | _SOKOL_PRIVATE void* _sapp_glx_getprocaddr(const char* procname) |
| 4920 | { |
| 4921 | if (_sapp_glx_GetProcAddress) { |
| 4922 | return _sapp_glx_GetProcAddress((const GLubyte*) procname); |
| 4923 | } |
| 4924 | else if (_sapp_glx_GetProcAddressARB) { |
| 4925 | return _sapp_glx_GetProcAddressARB((const GLubyte*) procname); |
| 4926 | } |
| 4927 | else { |
| 4928 | return dlsym(_sapp_glx_libgl, procname); |
| 4929 | } |
| 4930 | } |
| 4931 | |
| 4932 | _SOKOL_PRIVATE void _sapp_glx_init() { |
| 4933 | const char* sonames[] = { "libGL.so.1" , "libGL.so" , 0 }; |
| 4934 | for (int i = 0; sonames[i]; i++) { |
| 4935 | _sapp_glx_libgl = dlopen(sonames[i], RTLD_LAZY|RTLD_GLOBAL); |
| 4936 | if (_sapp_glx_libgl) { |
| 4937 | break; |
| 4938 | } |
| 4939 | } |
| 4940 | if (!_sapp_glx_libgl) { |
| 4941 | _sapp_fail("GLX: failed to load libGL" ); |
| 4942 | } |
| 4943 | _sapp_glx_GetFBConfigs = dlsym(_sapp_glx_libgl, "glXGetFBConfigs" ); |
| 4944 | _sapp_glx_GetFBConfigAttrib = dlsym(_sapp_glx_libgl, "glXGetFBConfigAttrib" ); |
| 4945 | _sapp_glx_GetClientString = dlsym(_sapp_glx_libgl, "glXGetClientString" ); |
| 4946 | _sapp_glx_QueryExtension = dlsym(_sapp_glx_libgl, "glXQueryExtension" ); |
| 4947 | _sapp_glx_QueryVersion = dlsym(_sapp_glx_libgl, "glXQueryVersion" ); |
| 4948 | _sapp_glx_DestroyContext = dlsym(_sapp_glx_libgl, "glXDestroyContext" ); |
| 4949 | _sapp_glx_MakeCurrent = dlsym(_sapp_glx_libgl, "glXMakeCurrent" ); |
| 4950 | _sapp_glx_SwapBuffers = dlsym(_sapp_glx_libgl, "glXSwapBuffers" ); |
| 4951 | _sapp_glx_QueryExtensionsString = dlsym(_sapp_glx_libgl, "glXQueryExtensionsString" ); |
| 4952 | _sapp_glx_CreateNewContext = dlsym(_sapp_glx_libgl, "glXCreateNewContext" ); |
| 4953 | _sapp_glx_CreateWindow = dlsym(_sapp_glx_libgl, "glXCreateWindow" ); |
| 4954 | _sapp_glx_DestroyWindow = dlsym(_sapp_glx_libgl, "glXDestroyWindow" ); |
| 4955 | _sapp_glx_GetProcAddress = dlsym(_sapp_glx_libgl, "glXGetProcAddress" ); |
| 4956 | _sapp_glx_GetProcAddressARB = dlsym(_sapp_glx_libgl, "glXGetProcAddressARB" ); |
| 4957 | _sapp_glx_GetVisualFromFBConfig = dlsym(_sapp_glx_libgl, "glXGetVisualFromFBConfig" ); |
| 4958 | if (!_sapp_glx_GetFBConfigs || |
| 4959 | !_sapp_glx_GetFBConfigAttrib || |
| 4960 | !_sapp_glx_GetClientString || |
| 4961 | !_sapp_glx_QueryExtension || |
| 4962 | !_sapp_glx_QueryVersion || |
| 4963 | !_sapp_glx_DestroyContext || |
| 4964 | !_sapp_glx_MakeCurrent || |
| 4965 | !_sapp_glx_SwapBuffers || |
| 4966 | !_sapp_glx_QueryExtensionsString || |
| 4967 | !_sapp_glx_CreateNewContext || |
| 4968 | !_sapp_glx_CreateWindow || |
| 4969 | !_sapp_glx_DestroyWindow || |
| 4970 | !_sapp_glx_GetProcAddress || |
| 4971 | !_sapp_glx_GetProcAddressARB || |
| 4972 | !_sapp_glx_GetVisualFromFBConfig) |
| 4973 | { |
| 4974 | _sapp_fail("GLX: failed to load required entry points" ); |
| 4975 | } |
| 4976 | |
| 4977 | if (!_sapp_glx_QueryExtension(_sapp_x11_display, |
| 4978 | &_sapp_glx_errorbase, |
| 4979 | &_sapp_glx_eventbase)) |
| 4980 | { |
| 4981 | _sapp_fail("GLX: GLX extension not found" ); |
| 4982 | } |
| 4983 | if (!_sapp_glx_QueryVersion(_sapp_x11_display, &_sapp_glx_major, &_sapp_glx_minor)) { |
| 4984 | _sapp_fail("GLX: Failed to query GLX version" ); |
| 4985 | } |
| 4986 | if (_sapp_glx_major == 1 && _sapp_glx_minor < 3) { |
| 4987 | _sapp_fail("GLX: GLX version 1.3 is required" ); |
| 4988 | } |
| 4989 | const char* exts = _sapp_glx_QueryExtensionsString(_sapp_x11_display, _sapp_x11_screen); |
| 4990 | if (_sapp_glx_extsupported("GLX_EXT_swap_control" , exts)) { |
| 4991 | _sapp_glx_SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) _sapp_glx_getprocaddr("glXSwapIntervalEXT" ); |
| 4992 | _sapp_glx_EXT_swap_control = 0 != _sapp_glx_SwapIntervalEXT; |
| 4993 | } |
| 4994 | if (_sapp_glx_extsupported("GLX_MESA_swap_control" , exts)) { |
| 4995 | _sapp_glx_SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) _sapp_glx_getprocaddr("glXSwapIntervalMESA" ); |
| 4996 | _sapp_glx_MESA_swap_control = 0 != _sapp_glx_SwapIntervalMESA; |
| 4997 | } |
| 4998 | _sapp_glx_ARB_multisample = _sapp_glx_extsupported("GLX_ARB_multisample" , exts); |
| 4999 | _sapp_glx_ARB_framebuffer_sRGB = _sapp_glx_extsupported("GLX_ARB_framebuffer_sRGB" , exts); |
| 5000 | _sapp_glx_EXT_framebuffer_sRGB = _sapp_glx_extsupported("GLX_EXT_framebuffer_sRGB" , exts); |
| 5001 | if (_sapp_glx_extsupported("GLX_ARB_create_context" , exts)) { |
| 5002 | _sapp_glx_CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) _sapp_glx_getprocaddr("glXCreateContextAttribsARB" ); |
| 5003 | _sapp_glx_ARB_create_context = 0 != _sapp_glx_CreateContextAttribsARB; |
| 5004 | } |
| 5005 | _sapp_glx_ARB_create_context_profile = _sapp_glx_extsupported("GLX_ARB_create_context_profile" , exts); |
| 5006 | } |
| 5007 | |
| 5008 | _SOKOL_PRIVATE int _sapp_glx_attrib(GLXFBConfig fbconfig, int attrib) { |
| 5009 | int value; |
| 5010 | _sapp_glx_GetFBConfigAttrib(_sapp_x11_display, fbconfig, attrib, &value); |
| 5011 | return value; |
| 5012 | } |
| 5013 | |
| 5014 | _SOKOL_PRIVATE GLXFBConfig _sapp_glx_choosefbconfig() { |
| 5015 | GLXFBConfig* native_configs; |
| 5016 | _sapp_gl_fbconfig* usable_configs; |
| 5017 | const _sapp_gl_fbconfig* closest; |
| 5018 | int i, native_count, usable_count; |
| 5019 | const char* vendor; |
| 5020 | bool trust_window_bit = true; |
| 5021 | |
| 5022 | /* HACK: This is a (hopefully temporary) workaround for Chromium |
| 5023 | (VirtualBox GL) not setting the window bit on any GLXFBConfigs |
| 5024 | */ |
| 5025 | vendor = _sapp_glx_GetClientString(_sapp_x11_display, GLX_VENDOR); |
| 5026 | if (vendor && strcmp(vendor, "Chromium" ) == 0) { |
| 5027 | trust_window_bit = false; |
| 5028 | } |
| 5029 | |
| 5030 | native_configs = _sapp_glx_GetFBConfigs(_sapp_x11_display, _sapp_x11_screen, &native_count); |
| 5031 | if (!native_configs || !native_count) { |
| 5032 | _sapp_fail("GLX: No GLXFBConfigs returned" ); |
| 5033 | } |
| 5034 | |
| 5035 | usable_configs = (_sapp_gl_fbconfig*) SOKOL_CALLOC(native_count, sizeof(_sapp_gl_fbconfig)); |
| 5036 | usable_count = 0; |
| 5037 | for (i = 0; i < native_count; i++) { |
| 5038 | const GLXFBConfig n = native_configs[i]; |
| 5039 | _sapp_gl_fbconfig* u = usable_configs + usable_count; |
| 5040 | _sapp_gl_init_fbconfig(u); |
| 5041 | |
| 5042 | /* Only consider RGBA GLXFBConfigs */ |
| 5043 | if (!_sapp_glx_attrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT) { |
| 5044 | continue; |
| 5045 | } |
| 5046 | /* Only consider window GLXFBConfigs */ |
| 5047 | if (!_sapp_glx_attrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT) { |
| 5048 | if (trust_window_bit) { |
| 5049 | continue; |
| 5050 | } |
| 5051 | } |
| 5052 | u->red_bits = _sapp_glx_attrib(n, GLX_RED_SIZE); |
| 5053 | u->green_bits = _sapp_glx_attrib(n, GLX_GREEN_SIZE); |
| 5054 | u->blue_bits = _sapp_glx_attrib(n, GLX_BLUE_SIZE); |
| 5055 | u->alpha_bits = _sapp_glx_attrib(n, GLX_ALPHA_SIZE); |
| 5056 | u->depth_bits = _sapp_glx_attrib(n, GLX_DEPTH_SIZE); |
| 5057 | u->stencil_bits = _sapp_glx_attrib(n, GLX_STENCIL_SIZE); |
| 5058 | if (_sapp_glx_attrib(n, GLX_DOUBLEBUFFER)) { |
| 5059 | u->doublebuffer = true; |
| 5060 | } |
| 5061 | if (_sapp_glx_ARB_multisample) { |
| 5062 | u->samples = _sapp_glx_attrib(n, GLX_SAMPLES); |
| 5063 | } |
| 5064 | u->handle = (uintptr_t) n; |
| 5065 | usable_count++; |
| 5066 | } |
| 5067 | _sapp_gl_fbconfig desired; |
| 5068 | _sapp_gl_init_fbconfig(&desired); |
| 5069 | desired.red_bits = 8; |
| 5070 | desired.green_bits = 8; |
| 5071 | desired.blue_bits = 8; |
| 5072 | desired.alpha_bits = 8; |
| 5073 | desired.depth_bits = 24; |
| 5074 | desired.stencil_bits = 8; |
| 5075 | desired.doublebuffer = true; |
| 5076 | desired.samples = _sapp.sample_count > 1 ? _sapp.sample_count : 0; |
| 5077 | closest = _sapp_gl_choose_fbconfig(&desired, usable_configs, usable_count); |
| 5078 | GLXFBConfig result = 0; |
| 5079 | if (closest) { |
| 5080 | result = (GLXFBConfig) closest->handle; |
| 5081 | } |
| 5082 | XFree(native_configs); |
| 5083 | SOKOL_FREE(usable_configs); |
| 5084 | return result; |
| 5085 | } |
| 5086 | |
| 5087 | _SOKOL_PRIVATE void _sapp_glx_choose_visual(Visual** visual, int* depth) { |
| 5088 | GLXFBConfig native = _sapp_glx_choosefbconfig(); |
| 5089 | if (0 == native) { |
| 5090 | _sapp_fail("GLX: Failed to find a suitable GLXFBConfig" ); |
| 5091 | } |
| 5092 | XVisualInfo* result = _sapp_glx_GetVisualFromFBConfig(_sapp_x11_display, native); |
| 5093 | if (!result) { |
| 5094 | _sapp_fail("GLX: Failed to retrieve Visual for GLXFBConfig" ); |
| 5095 | } |
| 5096 | *visual = result->visual; |
| 5097 | *depth = result->depth; |
| 5098 | XFree(result); |
| 5099 | } |
| 5100 | |
| 5101 | _SOKOL_PRIVATE void _sapp_glx_create_context(void) { |
| 5102 | GLXFBConfig native = _sapp_glx_choosefbconfig(); |
| 5103 | if (0 == native){ |
| 5104 | _sapp_fail("GLX: Failed to find a suitable GLXFBConfig (2)" ); |
| 5105 | } |
| 5106 | if (!(_sapp_glx_ARB_create_context && _sapp_glx_ARB_create_context_profile)) { |
| 5107 | _sapp_fail("GLX: ARB_create_context and ARB_create_context_profile required" ); |
| 5108 | } |
| 5109 | _sapp_x11_grab_error_handler(); |
| 5110 | const int attribs[] = { |
| 5111 | GLX_CONTEXT_MAJOR_VERSION_ARB, 3, |
| 5112 | GLX_CONTEXT_MINOR_VERSION_ARB, 3, |
| 5113 | GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, |
| 5114 | GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, |
| 5115 | 0, 0 |
| 5116 | }; |
| 5117 | _sapp_glx_ctx = _sapp_glx_CreateContextAttribsARB(_sapp_x11_display, native, NULL, True, attribs); |
| 5118 | if (!_sapp_glx_ctx) { |
| 5119 | _sapp_fail("GLX: failed to create GL context" ); |
| 5120 | } |
| 5121 | _sapp_x11_release_error_handler(); |
| 5122 | _sapp_glx_window = _sapp_glx_CreateWindow(_sapp_x11_display, native, _sapp_x11_window, NULL); |
| 5123 | if (!_sapp_glx_window) { |
| 5124 | _sapp_fail("GLX: failed to create window" ); |
| 5125 | } |
| 5126 | } |
| 5127 | |
| 5128 | _SOKOL_PRIVATE void _sapp_glx_destroy_context(void) { |
| 5129 | if (_sapp_glx_window) { |
| 5130 | _sapp_glx_DestroyWindow(_sapp_x11_display, _sapp_glx_window); |
| 5131 | _sapp_glx_window = 0; |
| 5132 | } |
| 5133 | if (_sapp_glx_ctx) { |
| 5134 | _sapp_glx_DestroyContext(_sapp_x11_display, _sapp_glx_ctx); |
| 5135 | _sapp_glx_ctx = 0; |
| 5136 | } |
| 5137 | } |
| 5138 | |
| 5139 | _SOKOL_PRIVATE void _sapp_glx_make_current(void) { |
| 5140 | _sapp_glx_MakeCurrent(_sapp_x11_display, _sapp_glx_window, _sapp_glx_ctx); |
| 5141 | } |
| 5142 | |
| 5143 | _SOKOL_PRIVATE void _sapp_glx_swap_buffers(void) { |
| 5144 | _sapp_glx_SwapBuffers(_sapp_x11_display, _sapp_glx_window); |
| 5145 | } |
| 5146 | |
| 5147 | _SOKOL_PRIVATE void _sapp_glx_swapinterval(int interval) { |
| 5148 | _sapp_glx_make_current(); |
| 5149 | if (_sapp_glx_EXT_swap_control) { |
| 5150 | _sapp_glx_SwapIntervalEXT(_sapp_x11_display, _sapp_glx_window, interval); |
| 5151 | } |
| 5152 | else if (_sapp_glx_MESA_swap_control) { |
| 5153 | _sapp_glx_SwapIntervalMESA(interval); |
| 5154 | } |
| 5155 | } |
| 5156 | |
| 5157 | _SOKOL_PRIVATE void _sapp_x11_update_window_title(void) { |
| 5158 | Xutf8SetWMProperties(_sapp_x11_display, |
| 5159 | _sapp_x11_window, |
| 5160 | _sapp.window_title, _sapp.window_title, |
| 5161 | NULL, 0, NULL, NULL, NULL); |
| 5162 | XChangeProperty(_sapp_x11_display, _sapp_x11_window, |
| 5163 | _sapp_x11_NET_WM_NAME, _sapp_x11_UTF8_STRING, 8, |
| 5164 | PropModeReplace, |
| 5165 | (unsigned char*)_sapp.window_title, |
| 5166 | strlen(_sapp.window_title)); |
| 5167 | XChangeProperty(_sapp_x11_display, _sapp_x11_window, |
| 5168 | _sapp_x11_NET_WM_ICON_NAME, _sapp_x11_UTF8_STRING, 8, |
| 5169 | PropModeReplace, |
| 5170 | (unsigned char*)_sapp.window_title, |
| 5171 | strlen(_sapp.window_title)); |
| 5172 | XFlush(_sapp_x11_display); |
| 5173 | } |
| 5174 | |
| 5175 | _SOKOL_PRIVATE void _sapp_x11_query_window_size(void) { |
| 5176 | XWindowAttributes attribs; |
| 5177 | XGetWindowAttributes(_sapp_x11_display, _sapp_x11_window, &attribs); |
| 5178 | _sapp.window_width = attribs.width; |
| 5179 | _sapp.window_height = attribs.height; |
| 5180 | _sapp.framebuffer_width = _sapp.window_width; |
| 5181 | _sapp.framebuffer_height = _sapp.framebuffer_height; |
| 5182 | } |
| 5183 | |
| 5184 | _SOKOL_PRIVATE void _sapp_x11_create_window(Visual* visual, int depth) { |
| 5185 | _sapp_x11_colormap = XCreateColormap(_sapp_x11_display, _sapp_x11_root, visual, AllocNone); |
| 5186 | XSetWindowAttributes wa; |
| 5187 | memset(&wa, 0, sizeof(wa)); |
| 5188 | const uint32_t wamask = CWBorderPixel | CWColormap | CWEventMask; |
| 5189 | wa.colormap = _sapp_x11_colormap; |
| 5190 | wa.border_pixel = 0; |
| 5191 | wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | |
| 5192 | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | |
| 5193 | ExposureMask | FocusChangeMask | VisibilityChangeMask | |
| 5194 | EnterWindowMask | LeaveWindowMask | PropertyChangeMask; |
| 5195 | _sapp_x11_grab_error_handler(); |
| 5196 | _sapp_x11_window = XCreateWindow(_sapp_x11_display, |
| 5197 | _sapp_x11_root, |
| 5198 | 0, 0, |
| 5199 | _sapp.window_width, |
| 5200 | _sapp.window_height, |
| 5201 | 0, /* border width */ |
| 5202 | depth, /* color depth */ |
| 5203 | InputOutput, |
| 5204 | visual, |
| 5205 | wamask, |
| 5206 | &wa); |
| 5207 | _sapp_x11_release_error_handler(); |
| 5208 | if (!_sapp_x11_window) { |
| 5209 | _sapp_fail("X11: Failed to create window" ); |
| 5210 | } |
| 5211 | |
| 5212 | Atom protocols[] = { |
| 5213 | _sapp_x11_WM_DELETE_WINDOW |
| 5214 | }; |
| 5215 | XSetWMProtocols(_sapp_x11_display, _sapp_x11_window, protocols, 1); |
| 5216 | |
| 5217 | XSizeHints* hints = XAllocSizeHints(); |
| 5218 | hints->flags |= PWinGravity; |
| 5219 | hints->win_gravity = StaticGravity; |
| 5220 | XSetWMNormalHints(_sapp_x11_display, _sapp_x11_window, hints); |
| 5221 | XFree(hints); |
| 5222 | |
| 5223 | _sapp_x11_update_window_title(); |
| 5224 | _sapp_x11_query_window_size(); |
| 5225 | } |
| 5226 | |
| 5227 | _SOKOL_PRIVATE void _sapp_x11_destroy_window(void) { |
| 5228 | if (_sapp_x11_window) { |
| 5229 | XUnmapWindow(_sapp_x11_display, _sapp_x11_window); |
| 5230 | XDestroyWindow(_sapp_x11_display, _sapp_x11_window); |
| 5231 | _sapp_x11_window = 0; |
| 5232 | } |
| 5233 | if (_sapp_x11_colormap) { |
| 5234 | XFreeColormap(_sapp_x11_display, _sapp_x11_colormap); |
| 5235 | _sapp_x11_colormap = 0; |
| 5236 | } |
| 5237 | XFlush(_sapp_x11_display); |
| 5238 | } |
| 5239 | |
| 5240 | _SOKOL_PRIVATE bool _sapp_x11_window_visible(void) { |
| 5241 | XWindowAttributes wa; |
| 5242 | XGetWindowAttributes(_sapp_x11_display, _sapp_x11_window, &wa); |
| 5243 | return wa.map_state == IsViewable; |
| 5244 | } |
| 5245 | |
| 5246 | _SOKOL_PRIVATE void _sapp_x11_show_window(void) { |
| 5247 | if (!_sapp_x11_window_visible()) { |
| 5248 | XMapWindow(_sapp_x11_display, _sapp_x11_window); |
| 5249 | XRaiseWindow(_sapp_x11_display, _sapp_x11_window); |
| 5250 | XFlush(_sapp_x11_display); |
| 5251 | } |
| 5252 | } |
| 5253 | |
| 5254 | _SOKOL_PRIVATE void _sapp_x11_hide_window(void) { |
| 5255 | XUnmapWindow(_sapp_x11_display, _sapp_x11_window); |
| 5256 | XFlush(_sapp_x11_display); |
| 5257 | } |
| 5258 | |
| 5259 | _SOKOL_PRIVATE unsigned long _sapp_x11_get_window_property(Atom property, Atom type, unsigned char** value) { |
| 5260 | Atom actualType; |
| 5261 | int actualFormat; |
| 5262 | unsigned long itemCount, bytesAfter; |
| 5263 | XGetWindowProperty(_sapp_x11_display, |
| 5264 | _sapp_x11_window, |
| 5265 | property, |
| 5266 | 0, |
| 5267 | LONG_MAX, |
| 5268 | False, |
| 5269 | type, |
| 5270 | &actualType, |
| 5271 | &actualFormat, |
| 5272 | &itemCount, |
| 5273 | &bytesAfter, |
| 5274 | value); |
| 5275 | return itemCount; |
| 5276 | } |
| 5277 | |
| 5278 | _SOKOL_PRIVATE int _sapp_x11_get_window_state(void) { |
| 5279 | int result = WithdrawnState; |
| 5280 | struct { |
| 5281 | CARD32 state; |
| 5282 | Window icon; |
| 5283 | } *state = NULL; |
| 5284 | |
| 5285 | if (_sapp_x11_get_window_property(_sapp_x11_WM_STATE, _sapp_x11_WM_STATE, (unsigned char**)&state) >= 2) { |
| 5286 | result = state->state; |
| 5287 | } |
| 5288 | if (state) { |
| 5289 | XFree(state); |
| 5290 | } |
| 5291 | return result; |
| 5292 | } |
| 5293 | |
| 5294 | _SOKOL_PRIVATE uint32_t _sapp_x11_mod(int x11_mods) { |
| 5295 | uint32_t mods = 0; |
| 5296 | if (x11_mods & ShiftMask) { |
| 5297 | mods |= SAPP_MODIFIER_SHIFT; |
| 5298 | } |
| 5299 | if (x11_mods & ControlMask) { |
| 5300 | mods |= SAPP_MODIFIER_CTRL; |
| 5301 | } |
| 5302 | if (x11_mods & Mod1Mask) { |
| 5303 | mods |= SAPP_MODIFIER_ALT; |
| 5304 | } |
| 5305 | if (x11_mods & Mod4Mask) { |
| 5306 | mods |= SAPP_MODIFIER_SUPER; |
| 5307 | } |
| 5308 | return mods; |
| 5309 | } |
| 5310 | |
| 5311 | _SOKOL_PRIVATE void _sapp_x11_app_event(sapp_event_type type) { |
| 5312 | if (_sapp_events_enabled()) { |
| 5313 | _sapp_init_event(type); |
| 5314 | _sapp.desc.event_cb(&_sapp.event); |
| 5315 | } |
| 5316 | } |
| 5317 | |
| 5318 | _SOKOL_PRIVATE sapp_mousebutton _sapp_x11_translate_button(const XEvent* event) { |
| 5319 | switch (event->xbutton.button) { |
| 5320 | case Button1: return SAPP_MOUSEBUTTON_LEFT; |
| 5321 | case Button2: return SAPP_MOUSEBUTTON_MIDDLE; |
| 5322 | case Button3: return SAPP_MOUSEBUTTON_RIGHT; |
| 5323 | default: return SAPP_MOUSEBUTTON_INVALID; |
| 5324 | } |
| 5325 | } |
| 5326 | |
| 5327 | _SOKOL_PRIVATE void _sapp_x11_mouse_event(sapp_event_type type, sapp_mousebutton btn, uint32_t mods) { |
| 5328 | if (_sapp_events_enabled()) { |
| 5329 | _sapp_init_event(type); |
| 5330 | _sapp.event.mouse_button = btn; |
| 5331 | _sapp.event.modifiers = mods; |
| 5332 | _sapp.event.mouse_x = _sapp.mouse_x; |
| 5333 | _sapp.event.mouse_y = _sapp.mouse_y; |
| 5334 | _sapp.desc.event_cb(&_sapp.event); |
| 5335 | } |
| 5336 | } |
| 5337 | |
| 5338 | _SOKOL_PRIVATE void _sapp_x11_scroll_event(float x, float y, uint32_t mods) { |
| 5339 | if (_sapp_events_enabled()) { |
| 5340 | _sapp_init_event(SAPP_EVENTTYPE_MOUSE_SCROLL); |
| 5341 | _sapp.event.modifiers = mods; |
| 5342 | _sapp.event.scroll_x = x; |
| 5343 | _sapp.event.scroll_y = y; |
| 5344 | _sapp.desc.event_cb(&_sapp.event); |
| 5345 | } |
| 5346 | } |
| 5347 | |
| 5348 | _SOKOL_PRIVATE void _sapp_x11_key_event(sapp_event_type type, sapp_keycode key, uint32_t mods) { |
| 5349 | if (_sapp_events_enabled()) { |
| 5350 | _sapp_init_event(type); |
| 5351 | _sapp.event.key_code = key; |
| 5352 | _sapp.event.modifiers = mods; |
| 5353 | _sapp.desc.event_cb(&_sapp.event); |
| 5354 | } |
| 5355 | } |
| 5356 | |
| 5357 | _SOKOL_PRIVATE void _sapp_x11_char_event(uint32_t chr, uint32_t mods) { |
| 5358 | if (_sapp_events_enabled()) { |
| 5359 | _sapp_init_event(SAPP_EVENTTYPE_CHAR); |
| 5360 | _sapp.event.char_code = chr; |
| 5361 | _sapp.event.modifiers = mods; |
| 5362 | _sapp.desc.event_cb(&_sapp.event); |
| 5363 | } |
| 5364 | } |
| 5365 | |
| 5366 | _SOKOL_PRIVATE sapp_keycode _sapp_x11_translate_key(int scancode) { |
| 5367 | int dummy; |
| 5368 | KeySym* keysyms = XGetKeyboardMapping(_sapp_x11_display, scancode, 1, &dummy); |
| 5369 | SOKOL_ASSERT(keysyms); |
| 5370 | KeySym keysym = keysyms[0]; |
| 5371 | XFree(keysyms); |
| 5372 | switch (keysym) { |
| 5373 | case XK_Escape: return SAPP_KEYCODE_ESCAPE; |
| 5374 | case XK_Tab: return SAPP_KEYCODE_TAB; |
| 5375 | case XK_Shift_L: return SAPP_KEYCODE_LEFT_SHIFT; |
| 5376 | case XK_Shift_R: return SAPP_KEYCODE_RIGHT_SHIFT; |
| 5377 | case XK_Control_L: return SAPP_KEYCODE_LEFT_CONTROL; |
| 5378 | case XK_Control_R: return SAPP_KEYCODE_RIGHT_CONTROL; |
| 5379 | case XK_Meta_L: |
| 5380 | case XK_Alt_L: return SAPP_KEYCODE_LEFT_ALT; |
| 5381 | case XK_Mode_switch: /* Mapped to Alt_R on many keyboards */ |
| 5382 | case XK_ISO_Level3_Shift: /* AltGr on at least some machines */ |
| 5383 | case XK_Meta_R: |
| 5384 | case XK_Alt_R: return SAPP_KEYCODE_RIGHT_ALT; |
| 5385 | case XK_Super_L: return SAPP_KEYCODE_LEFT_SUPER; |
| 5386 | case XK_Super_R: return SAPP_KEYCODE_RIGHT_SUPER; |
| 5387 | case XK_Menu: return SAPP_KEYCODE_MENU; |
| 5388 | case XK_Num_Lock: return SAPP_KEYCODE_NUM_LOCK; |
| 5389 | case XK_Caps_Lock: return SAPP_KEYCODE_CAPS_LOCK; |
| 5390 | case XK_Print: return SAPP_KEYCODE_PRINT_SCREEN; |
| 5391 | case XK_Scroll_Lock: return SAPP_KEYCODE_SCROLL_LOCK; |
| 5392 | case XK_Pause: return SAPP_KEYCODE_PAUSE; |
| 5393 | case XK_Delete: return SAPP_KEYCODE_DELETE; |
| 5394 | case XK_BackSpace: return SAPP_KEYCODE_BACKSPACE; |
| 5395 | case XK_Return: return SAPP_KEYCODE_ENTER; |
| 5396 | case XK_Home: return SAPP_KEYCODE_HOME; |
| 5397 | case XK_End: return SAPP_KEYCODE_END; |
| 5398 | case XK_Page_Up: return SAPP_KEYCODE_PAGE_UP; |
| 5399 | case XK_Page_Down: return SAPP_KEYCODE_PAGE_DOWN; |
| 5400 | case XK_Insert: return SAPP_KEYCODE_INSERT; |
| 5401 | case XK_Left: return SAPP_KEYCODE_LEFT; |
| 5402 | case XK_Right: return SAPP_KEYCODE_RIGHT; |
| 5403 | case XK_Down: return SAPP_KEYCODE_DOWN; |
| 5404 | case XK_Up: return SAPP_KEYCODE_UP; |
| 5405 | case XK_F1: return SAPP_KEYCODE_F1; |
| 5406 | case XK_F2: return SAPP_KEYCODE_F2; |
| 5407 | case XK_F3: return SAPP_KEYCODE_F3; |
| 5408 | case XK_F4: return SAPP_KEYCODE_F4; |
| 5409 | case XK_F5: return SAPP_KEYCODE_F5; |
| 5410 | case XK_F6: return SAPP_KEYCODE_F6; |
| 5411 | case XK_F7: return SAPP_KEYCODE_F7; |
| 5412 | case XK_F8: return SAPP_KEYCODE_F8; |
| 5413 | case XK_F9: return SAPP_KEYCODE_F9; |
| 5414 | case XK_F10: return SAPP_KEYCODE_F10; |
| 5415 | case XK_F11: return SAPP_KEYCODE_F11; |
| 5416 | case XK_F12: return SAPP_KEYCODE_F12; |
| 5417 | case XK_F13: return SAPP_KEYCODE_F13; |
| 5418 | case XK_F14: return SAPP_KEYCODE_F14; |
| 5419 | case XK_F15: return SAPP_KEYCODE_F15; |
| 5420 | case XK_F16: return SAPP_KEYCODE_F16; |
| 5421 | case XK_F17: return SAPP_KEYCODE_F17; |
| 5422 | case XK_F18: return SAPP_KEYCODE_F18; |
| 5423 | case XK_F19: return SAPP_KEYCODE_F19; |
| 5424 | case XK_F20: return SAPP_KEYCODE_F20; |
| 5425 | case XK_F21: return SAPP_KEYCODE_F21; |
| 5426 | case XK_F22: return SAPP_KEYCODE_F22; |
| 5427 | case XK_F23: return SAPP_KEYCODE_F23; |
| 5428 | case XK_F24: return SAPP_KEYCODE_F24; |
| 5429 | case XK_F25: return SAPP_KEYCODE_F25; |
| 5430 | |
| 5431 | case XK_KP_Divide: return SAPP_KEYCODE_KP_DIVIDE; |
| 5432 | case XK_KP_Multiply: return SAPP_KEYCODE_KP_MULTIPLY; |
| 5433 | case XK_KP_Subtract: return SAPP_KEYCODE_KP_SUBTRACT; |
| 5434 | case XK_KP_Add: return SAPP_KEYCODE_KP_ADD; |
| 5435 | |
| 5436 | case XK_KP_Insert: return SAPP_KEYCODE_KP_0; |
| 5437 | case XK_KP_End: return SAPP_KEYCODE_KP_1; |
| 5438 | case XK_KP_Down: return SAPP_KEYCODE_KP_2; |
| 5439 | case XK_KP_Page_Down: return SAPP_KEYCODE_KP_3; |
| 5440 | case XK_KP_Left: return SAPP_KEYCODE_KP_4; |
| 5441 | case XK_KP_Right: return SAPP_KEYCODE_KP_6; |
| 5442 | case XK_KP_Home: return SAPP_KEYCODE_KP_7; |
| 5443 | case XK_KP_Up: return SAPP_KEYCODE_KP_8; |
| 5444 | case XK_KP_Page_Up: return SAPP_KEYCODE_KP_9; |
| 5445 | case XK_KP_Delete: return SAPP_KEYCODE_KP_DECIMAL; |
| 5446 | case XK_KP_Equal: return SAPP_KEYCODE_KP_EQUAL; |
| 5447 | case XK_KP_Enter: return SAPP_KEYCODE_KP_ENTER; |
| 5448 | |
| 5449 | case XK_a: return SAPP_KEYCODE_A; |
| 5450 | case XK_b: return SAPP_KEYCODE_B; |
| 5451 | case XK_c: return SAPP_KEYCODE_C; |
| 5452 | case XK_d: return SAPP_KEYCODE_D; |
| 5453 | case XK_e: return SAPP_KEYCODE_E; |
| 5454 | case XK_f: return SAPP_KEYCODE_F; |
| 5455 | case XK_g: return SAPP_KEYCODE_G; |
| 5456 | case XK_h: return SAPP_KEYCODE_H; |
| 5457 | case XK_i: return SAPP_KEYCODE_I; |
| 5458 | case XK_j: return SAPP_KEYCODE_J; |
| 5459 | case XK_k: return SAPP_KEYCODE_K; |
| 5460 | case XK_l: return SAPP_KEYCODE_L; |
| 5461 | case XK_m: return SAPP_KEYCODE_M; |
| 5462 | case XK_n: return SAPP_KEYCODE_N; |
| 5463 | case XK_o: return SAPP_KEYCODE_O; |
| 5464 | case XK_p: return SAPP_KEYCODE_P; |
| 5465 | case XK_q: return SAPP_KEYCODE_Q; |
| 5466 | case XK_r: return SAPP_KEYCODE_R; |
| 5467 | case XK_s: return SAPP_KEYCODE_S; |
| 5468 | case XK_t: return SAPP_KEYCODE_T; |
| 5469 | case XK_u: return SAPP_KEYCODE_U; |
| 5470 | case XK_v: return SAPP_KEYCODE_V; |
| 5471 | case XK_w: return SAPP_KEYCODE_W; |
| 5472 | case XK_x: return SAPP_KEYCODE_X; |
| 5473 | case XK_y: return SAPP_KEYCODE_Y; |
| 5474 | case XK_z: return SAPP_KEYCODE_Z; |
| 5475 | case XK_1: return SAPP_KEYCODE_1; |
| 5476 | case XK_2: return SAPP_KEYCODE_2; |
| 5477 | case XK_3: return SAPP_KEYCODE_3; |
| 5478 | case XK_4: return SAPP_KEYCODE_4; |
| 5479 | case XK_5: return SAPP_KEYCODE_5; |
| 5480 | case XK_6: return SAPP_KEYCODE_6; |
| 5481 | case XK_7: return SAPP_KEYCODE_7; |
| 5482 | case XK_8: return SAPP_KEYCODE_8; |
| 5483 | case XK_9: return SAPP_KEYCODE_9; |
| 5484 | case XK_0: return SAPP_KEYCODE_0; |
| 5485 | case XK_space: return SAPP_KEYCODE_SPACE; |
| 5486 | case XK_minus: return SAPP_KEYCODE_MINUS; |
| 5487 | case XK_equal: return SAPP_KEYCODE_EQUAL; |
| 5488 | case XK_bracketleft: return SAPP_KEYCODE_LEFT_BRACKET; |
| 5489 | case XK_bracketright: return SAPP_KEYCODE_RIGHT_BRACKET; |
| 5490 | case XK_backslash: return SAPP_KEYCODE_BACKSLASH; |
| 5491 | case XK_semicolon: return SAPP_KEYCODE_SEMICOLON; |
| 5492 | case XK_apostrophe: return SAPP_KEYCODE_APOSTROPHE; |
| 5493 | case XK_grave: return SAPP_KEYCODE_GRAVE_ACCENT; |
| 5494 | case XK_comma: return SAPP_KEYCODE_COMMA; |
| 5495 | case XK_period: return SAPP_KEYCODE_PERIOD; |
| 5496 | case XK_slash: return SAPP_KEYCODE_SLASH; |
| 5497 | case XK_less: return SAPP_KEYCODE_WORLD_1; /* At least in some layouts... */ |
| 5498 | default: return SAPP_KEYCODE_INVALID; |
| 5499 | } |
| 5500 | } |
| 5501 | |
| 5502 | _SOKOL_PRIVATE int32_t _sapp_x11_keysym_to_unicode(KeySym keysym) { |
| 5503 | int min = 0; |
| 5504 | int max = sizeof(_sapp_x11_keysymtab) / sizeof(struct _sapp_x11_codepair) - 1; |
| 5505 | int mid; |
| 5506 | |
| 5507 | /* First check for Latin-1 characters (1:1 mapping) */ |
| 5508 | if ((keysym >= 0x0020 && keysym <= 0x007e) || |
| 5509 | (keysym >= 0x00a0 && keysym <= 0x00ff)) |
| 5510 | { |
| 5511 | return keysym; |
| 5512 | } |
| 5513 | |
| 5514 | /* Also check for directly encoded 24-bit UCS characters */ |
| 5515 | if ((keysym & 0xff000000) == 0x01000000) { |
| 5516 | return keysym & 0x00ffffff; |
| 5517 | } |
| 5518 | |
| 5519 | /* Binary search in table */ |
| 5520 | while (max >= min) { |
| 5521 | mid = (min + max) / 2; |
| 5522 | if (_sapp_x11_keysymtab[mid].keysym < keysym) { |
| 5523 | min = mid + 1; |
| 5524 | } |
| 5525 | else if (_sapp_x11_keysymtab[mid].keysym > keysym) { |
| 5526 | max = mid - 1; |
| 5527 | } |
| 5528 | else { |
| 5529 | return _sapp_x11_keysymtab[mid].ucs; |
| 5530 | } |
| 5531 | } |
| 5532 | |
| 5533 | /* No matching Unicode value found */ |
| 5534 | return -1; |
| 5535 | } |
| 5536 | |
| 5537 | _SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) { |
| 5538 | switch (event->type) { |
| 5539 | case KeyPress: |
| 5540 | { |
| 5541 | const sapp_keycode key = _sapp_x11_translate_key(event->xkey.keycode); |
| 5542 | const uint32_t mods = _sapp_x11_mod(event->xkey.state); |
| 5543 | if (key != SAPP_KEYCODE_INVALID) { |
| 5544 | _sapp_x11_key_event(SAPP_EVENTTYPE_KEY_DOWN, key, mods); |
| 5545 | } |
| 5546 | KeySym keysym; |
| 5547 | XLookupString(&event->xkey, NULL, 0, &keysym, NULL); |
| 5548 | int32_t chr = _sapp_x11_keysym_to_unicode(keysym); |
| 5549 | if (chr > 0) { |
| 5550 | _sapp_x11_char_event((uint32_t)chr, mods); |
| 5551 | } |
| 5552 | } |
| 5553 | break; |
| 5554 | case KeyRelease: |
| 5555 | { |
| 5556 | const sapp_keycode key = _sapp_x11_translate_key(event->xkey.keycode); |
| 5557 | if (key != SAPP_KEYCODE_INVALID) { |
| 5558 | const uint32_t mods = _sapp_x11_mod(event->xkey.state); |
| 5559 | _sapp_x11_key_event(SAPP_EVENTTYPE_KEY_UP, key, mods); |
| 5560 | } |
| 5561 | } |
| 5562 | break; |
| 5563 | case ButtonPress: |
| 5564 | { |
| 5565 | const sapp_mousebutton btn = _sapp_x11_translate_button(event); |
| 5566 | const uint32_t mods = _sapp_x11_mod(event->xbutton.state); |
| 5567 | if (btn != SAPP_MOUSEBUTTON_INVALID) { |
| 5568 | _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_DOWN, btn, mods); |
| 5569 | } |
| 5570 | else { |
| 5571 | /* might be a scroll event */ |
| 5572 | switch (event->xbutton.button) { |
| 5573 | case 4: _sapp_x11_scroll_event(0.0f, 1.0f, mods); break; |
| 5574 | case 5: _sapp_x11_scroll_event(0.0f, -1.0f, mods); break; |
| 5575 | case 6: _sapp_x11_scroll_event(1.0f, 0.0f, mods); break; |
| 5576 | case 7: _sapp_x11_scroll_event(-1.0f, 0.0f, mods); break; |
| 5577 | } |
| 5578 | } |
| 5579 | } |
| 5580 | break; |
| 5581 | case ButtonRelease: |
| 5582 | { |
| 5583 | const sapp_mousebutton btn = _sapp_x11_translate_button(event); |
| 5584 | if (btn != SAPP_MOUSEBUTTON_INVALID) { |
| 5585 | _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_UP, btn, _sapp_x11_mod(event->xbutton.state)); |
| 5586 | } |
| 5587 | } |
| 5588 | break; |
| 5589 | case EnterNotify: |
| 5590 | _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_ENTER, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); |
| 5591 | break; |
| 5592 | case LeaveNotify: |
| 5593 | _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_LEAVE, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xcrossing.state)); |
| 5594 | break; |
| 5595 | case MotionNotify: |
| 5596 | _sapp.mouse_x = event->xmotion.x; |
| 5597 | _sapp.mouse_y = event->xmotion.y; |
| 5598 | _sapp_x11_mouse_event(SAPP_EVENTTYPE_MOUSE_MOVE, SAPP_MOUSEBUTTON_INVALID, _sapp_x11_mod(event->xmotion.state)); |
| 5599 | break; |
| 5600 | case ConfigureNotify: |
| 5601 | if ((event->xconfigure.width != _sapp.window_width) || (event->xconfigure.height != _sapp.window_height)) { |
| 5602 | _sapp.window_width = event->xconfigure.width; |
| 5603 | _sapp.window_height = event->xconfigure.height; |
| 5604 | _sapp.framebuffer_width = _sapp.window_width; |
| 5605 | _sapp.framebuffer_height = _sapp.window_height; |
| 5606 | _sapp_x11_app_event(SAPP_EVENTTYPE_RESIZED); |
| 5607 | } |
| 5608 | break; |
| 5609 | case PropertyNotify: |
| 5610 | if (event->xproperty.state == PropertyNewValue) { |
| 5611 | if (event->xproperty.atom == _sapp_x11_WM_STATE) { |
| 5612 | const int state = _sapp_x11_get_window_state(); |
| 5613 | if (state != _sapp_x11_window_state) { |
| 5614 | _sapp_x11_window_state = state; |
| 5615 | if (state == IconicState) { |
| 5616 | _sapp_x11_app_event(SAPP_EVENTTYPE_ICONIFIED); |
| 5617 | } |
| 5618 | else if (state == NormalState) { |
| 5619 | _sapp_x11_app_event(SAPP_EVENTTYPE_RESTORED); |
| 5620 | } |
| 5621 | } |
| 5622 | } |
| 5623 | } |
| 5624 | break; |
| 5625 | case ClientMessage: |
| 5626 | if (event->xclient.message_type == _sapp_x11_WM_PROTOCOLS) { |
| 5627 | const Atom protocol = event->xclient.data.l[0]; |
| 5628 | if (protocol == _sapp_x11_WM_DELETE_WINDOW) { |
| 5629 | _sapp_x11_quit_requested = true; |
| 5630 | } |
| 5631 | } |
| 5632 | break; |
| 5633 | case DestroyNotify: |
| 5634 | break; |
| 5635 | } |
| 5636 | } |
| 5637 | |
| 5638 | int main(int argc, char* argv[]) { |
| 5639 | sapp_desc desc = sokol_main(argc, argv); |
| 5640 | _sapp_init_state(&desc, argc, argv); |
| 5641 | _sapp_x11_quit_requested = false; |
| 5642 | _sapp_x11_window_state = NormalState; |
| 5643 | |
| 5644 | XInitThreads(); |
| 5645 | XrmInitialize(); |
| 5646 | _sapp_x11_display = XOpenDisplay(NULL); |
| 5647 | if (!_sapp_x11_display) { |
| 5648 | _sapp_fail("XOpenDisplay() failed!\n" ); |
| 5649 | } |
| 5650 | _sapp_x11_screen = DefaultScreen(_sapp_x11_display); |
| 5651 | _sapp_x11_root = DefaultRootWindow(_sapp_x11_display); |
| 5652 | _sapp_x11_query_system_dpi(); |
| 5653 | _sapp.dpi_scale = _sapp_x11_dpi / 96.0f; |
| 5654 | _sapp_x11_init_extensions(); |
| 5655 | _sapp_glx_init(); |
| 5656 | Visual* visual = 0; |
| 5657 | int depth = 0; |
| 5658 | _sapp_glx_choose_visual(&visual, &depth); |
| 5659 | _sapp_x11_create_window(visual, depth); |
| 5660 | _sapp_glx_create_context(); |
| 5661 | _sapp.valid = true; |
| 5662 | _sapp_x11_show_window(); |
| 5663 | _sapp_glx_swapinterval(_sapp.swap_interval); |
| 5664 | XFlush(_sapp_x11_display); |
| 5665 | while (!_sapp_x11_quit_requested) { |
| 5666 | _sapp_glx_make_current(); |
| 5667 | int count = XPending(_sapp_x11_display); |
| 5668 | while (count--) { |
| 5669 | XEvent event; |
| 5670 | XNextEvent(_sapp_x11_display, &event); |
| 5671 | _sapp_x11_process_event(&event); |
| 5672 | } |
| 5673 | _sapp_frame(); |
| 5674 | _sapp_glx_swap_buffers(); |
| 5675 | XFlush(_sapp_x11_display); |
| 5676 | } |
| 5677 | _sapp.desc.cleanup_cb(); |
| 5678 | _sapp_glx_destroy_context(); |
| 5679 | _sapp_x11_destroy_window(); |
| 5680 | XCloseDisplay(_sapp_x11_display); |
| 5681 | return 0; |
| 5682 | } |
| 5683 | |
| 5684 | #endif /* LINUX */ |
| 5685 | |
| 5686 | /*== PUBLIC API FUNCTIONS ====================================================*/ |
| 5687 | SOKOL_API_IMPL bool sapp_isvalid(void) { |
| 5688 | return _sapp.valid; |
| 5689 | } |
| 5690 | |
| 5691 | SOKOL_API_IMPL int sapp_width(void) { |
| 5692 | return (_sapp.framebuffer_width > 0) ? _sapp.framebuffer_width : 1; |
| 5693 | } |
| 5694 | |
| 5695 | SOKOL_API_IMPL int sapp_height(void) { |
| 5696 | return (_sapp.framebuffer_height > 0) ? _sapp.framebuffer_height : 1; |
| 5697 | } |
| 5698 | |
| 5699 | SOKOL_API_IMPL bool sapp_high_dpi(void) { |
| 5700 | return _sapp.desc.high_dpi && (_sapp.dpi_scale > 1.5f); |
| 5701 | } |
| 5702 | |
| 5703 | SOKOL_API_IMPL float sapp_dpi_scale(void) { |
| 5704 | return _sapp.dpi_scale; |
| 5705 | } |
| 5706 | |
| 5707 | SOKOL_API_IMPL bool sapp_gles2(void) { |
| 5708 | return _sapp.gles2_fallback; |
| 5709 | } |
| 5710 | |
| 5711 | SOKOL_API_IMPL void sapp_show_keyboard(bool shown) { |
| 5712 | #if TARGET_OS_IPHONE |
| 5713 | _sapp_ios_show_keyboard(shown); |
| 5714 | #elif __EMSCRIPTEN__ |
| 5715 | _sapp_emsc_show_keyboard(shown); |
| 5716 | #else |
| 5717 | _SOKOL_UNUSED(shown); |
| 5718 | #endif |
| 5719 | } |
| 5720 | |
| 5721 | SOKOL_API_IMPL bool sapp_keyboard_shown(void) { |
| 5722 | return _sapp.onscreen_keyboard_shown; |
| 5723 | } |
| 5724 | |
| 5725 | SOKOL_API_IMPL const void* sapp_metal_get_device(void) { |
| 5726 | SOKOL_ASSERT(_sapp.valid); |
| 5727 | #if defined(SOKOL_METAL) |
| 5728 | const void* obj = (__bridge const void*) _sapp_mtl_device_obj; |
| 5729 | SOKOL_ASSERT(obj); |
| 5730 | return obj; |
| 5731 | #else |
| 5732 | return 0; |
| 5733 | #endif |
| 5734 | } |
| 5735 | |
| 5736 | SOKOL_API_IMPL const void* sapp_metal_get_renderpass_descriptor(void) { |
| 5737 | SOKOL_ASSERT(_sapp.valid); |
| 5738 | #if defined(SOKOL_METAL) |
| 5739 | const void* obj = (__bridge const void*) [_sapp_view_obj currentRenderPassDescriptor]; |
| 5740 | SOKOL_ASSERT(obj); |
| 5741 | return obj; |
| 5742 | #else |
| 5743 | return 0; |
| 5744 | #endif |
| 5745 | } |
| 5746 | |
| 5747 | SOKOL_API_IMPL const void* sapp_metal_get_drawable(void) { |
| 5748 | SOKOL_ASSERT(_sapp.valid); |
| 5749 | #if defined(SOKOL_METAL) |
| 5750 | const void* obj = (__bridge const void*) [_sapp_view_obj currentDrawable]; |
| 5751 | SOKOL_ASSERT(obj); |
| 5752 | return obj; |
| 5753 | #else |
| 5754 | return 0; |
| 5755 | #endif |
| 5756 | } |
| 5757 | |
| 5758 | SOKOL_API_IMPL const void* sapp_macos_get_window(void) { |
| 5759 | #if defined(__APPLE__) && !TARGET_OS_IPHONE |
| 5760 | const void* obj = (__bridge const void*) _sapp_macos_window_obj; |
| 5761 | SOKOL_ASSERT(obj); |
| 5762 | return obj; |
| 5763 | #else |
| 5764 | return 0; |
| 5765 | #endif |
| 5766 | } |
| 5767 | |
| 5768 | SOKOL_API_IMPL const void* sapp_ios_get_window(void) { |
| 5769 | #if defined(__APPLE__) && TARGET_OS_IPHONE |
| 5770 | const void* obj = (__bridge const void*) _sapp_ios_window_obj; |
| 5771 | SOKOL_ASSERT(obj); |
| 5772 | return obj; |
| 5773 | #else |
| 5774 | return 0; |
| 5775 | #endif |
| 5776 | |
| 5777 | } |
| 5778 | |
| 5779 | SOKOL_API_IMPL const void* sapp_d3d11_get_device(void) { |
| 5780 | SOKOL_ASSERT(_sapp.valid); |
| 5781 | #if defined(SOKOL_D3D11) |
| 5782 | return _sapp_d3d11_device; |
| 5783 | #else |
| 5784 | return 0; |
| 5785 | #endif |
| 5786 | } |
| 5787 | |
| 5788 | SOKOL_API_IMPL const void* sapp_d3d11_get_device_context(void) { |
| 5789 | SOKOL_ASSERT(_sapp.valid); |
| 5790 | #if defined(SOKOL_D3D11) |
| 5791 | return _sapp_d3d11_device_context; |
| 5792 | #else |
| 5793 | return 0; |
| 5794 | #endif |
| 5795 | } |
| 5796 | |
| 5797 | SOKOL_API_IMPL const void* sapp_d3d11_get_render_target_view(void) { |
| 5798 | SOKOL_ASSERT(_sapp.valid); |
| 5799 | #if defined(SOKOL_D3D11) |
| 5800 | return _sapp_d3d11_rtv; |
| 5801 | #else |
| 5802 | return 0; |
| 5803 | #endif |
| 5804 | } |
| 5805 | |
| 5806 | SOKOL_API_IMPL const void* sapp_d3d11_get_depth_stencil_view(void) { |
| 5807 | SOKOL_ASSERT(_sapp.valid); |
| 5808 | #if defined(SOKOL_D3D11) |
| 5809 | return _sapp_d3d11_dsv; |
| 5810 | #else |
| 5811 | return 0; |
| 5812 | #endif |
| 5813 | } |
| 5814 | |
| 5815 | SOKOL_API_IMPL const void* sapp_win32_get_hwnd(void) { |
| 5816 | SOKOL_ASSERT(_sapp.valid); |
| 5817 | #if defined(_WIN32) |
| 5818 | return _sapp_win32_hwnd; |
| 5819 | #else |
| 5820 | return 0; |
| 5821 | #endif |
| 5822 | } |
| 5823 | |
| 5824 | #undef _sapp_def |
| 5825 | |
| 5826 | #ifdef _MSC_VER |
| 5827 | #pragma warning(pop) |
| 5828 | #endif |
| 5829 | |
| 5830 | #endif /* SOKOL_IMPL */ |
| 5831 | |