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 | |