• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // GLFW 3.2 - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
6 //
7 // This software is provided 'as-is', without any express or implied
8 // warranty. In no event will the authors be held liable for any damages
9 // arising from the use of this software.
10 //
11 // Permission is granted to anyone to use this software for any purpose,
12 // including commercial applications, and to alter it and redistribute it
13 // freely, subject to the following restrictions:
14 //
15 // 1. The origin of this software must not be misrepresented; you must not
16 //    claim that you wrote the original software. If you use this software
17 //    in a product, an acknowledgment in the product documentation would
18 //    be appreciated but is not required.
19 //
20 // 2. Altered source versions must be plainly marked as such, and must not
21 //    be misrepresented as being the original software.
22 //
23 // 3. This notice may not be removed or altered from any source
24 //    distribution.
25 //
26 //========================================================================
27 
28 #include "internal.h"
29 
30 #include <assert.h>
31 #include <float.h>
32 #include <stdlib.h>
33 
34 // Internal key state used for sticky keys
35 #define _GLFW_STICK 3
36 
37 
38 //////////////////////////////////////////////////////////////////////////
39 //////                         GLFW event API                       //////
40 //////////////////////////////////////////////////////////////////////////
41 
_glfwInputKey(_GLFWwindow * window,int key,int scancode,int action,int mods)42 void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
43 {
44     if (key >= 0 && key <= GLFW_KEY_LAST)
45     {
46         GLFWbool repeated = GLFW_FALSE;
47 
48         if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
49             return;
50 
51         if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
52             repeated = GLFW_TRUE;
53 
54         if (action == GLFW_RELEASE && window->stickyKeys)
55             window->keys[key] = _GLFW_STICK;
56         else
57             window->keys[key] = (char) action;
58 
59         if (repeated)
60             action = GLFW_REPEAT;
61     }
62 
63     if (window->callbacks.key)
64         window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
65 }
66 
_glfwInputChar(_GLFWwindow * window,unsigned int codepoint,int mods,GLFWbool plain)67 void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
68 {
69     if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
70         return;
71 
72     if (window->callbacks.charmods)
73         window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
74 
75     if (plain)
76     {
77         if (window->callbacks.character)
78             window->callbacks.character((GLFWwindow*) window, codepoint);
79     }
80 }
81 
_glfwInputScroll(_GLFWwindow * window,double xoffset,double yoffset)82 void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
83 {
84     if (window->callbacks.scroll)
85         window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
86 }
87 
_glfwInputMouseClick(_GLFWwindow * window,int button,int action,int mods)88 void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
89 {
90     if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
91         return;
92 
93     // Register mouse button action
94     if (action == GLFW_RELEASE && window->stickyMouseButtons)
95         window->mouseButtons[button] = _GLFW_STICK;
96     else
97         window->mouseButtons[button] = (char) action;
98 
99     if (window->callbacks.mouseButton)
100         window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
101 }
102 
_glfwInputCursorPos(_GLFWwindow * window,double xpos,double ypos)103 void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
104 {
105     if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
106         return;
107 
108     window->virtualCursorPosX = xpos;
109     window->virtualCursorPosY = ypos;
110 
111     if (window->callbacks.cursorPos)
112         window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
113 }
114 
_glfwInputCursorEnter(_GLFWwindow * window,GLFWbool entered)115 void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
116 {
117     if (window->callbacks.cursorEnter)
118         window->callbacks.cursorEnter((GLFWwindow*) window, entered);
119 }
120 
_glfwInputDrop(_GLFWwindow * window,int count,const char ** paths)121 void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
122 {
123     if (window->callbacks.drop)
124         window->callbacks.drop((GLFWwindow*) window, count, paths);
125 }
126 
_glfwInputJoystickChange(int joy,int event)127 void _glfwInputJoystickChange(int joy, int event)
128 {
129     if (_glfw.callbacks.joystick)
130         _glfw.callbacks.joystick(joy, event);
131 }
132 
133 
134 //////////////////////////////////////////////////////////////////////////
135 //////                       GLFW internal API                      //////
136 //////////////////////////////////////////////////////////////////////////
137 
_glfwIsPrintable(int key)138 GLFWbool _glfwIsPrintable(int key)
139 {
140     return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
141            (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
142            key == GLFW_KEY_KP_EQUAL;
143 }
144 
145 
146 //////////////////////////////////////////////////////////////////////////
147 //////                        GLFW public API                       //////
148 //////////////////////////////////////////////////////////////////////////
149 
glfwGetInputMode(GLFWwindow * handle,int mode)150 GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
151 {
152     _GLFWwindow* window = (_GLFWwindow*) handle;
153     assert(window != NULL);
154 
155     _GLFW_REQUIRE_INIT_OR_RETURN(0);
156 
157     switch (mode)
158     {
159         case GLFW_CURSOR:
160             return window->cursorMode;
161         case GLFW_STICKY_KEYS:
162             return window->stickyKeys;
163         case GLFW_STICKY_MOUSE_BUTTONS:
164             return window->stickyMouseButtons;
165         default:
166             _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
167             return 0;
168     }
169 }
170 
glfwSetInputMode(GLFWwindow * handle,int mode,int value)171 GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
172 {
173     _GLFWwindow* window = (_GLFWwindow*) handle;
174     assert(window != NULL);
175 
176     _GLFW_REQUIRE_INIT();
177 
178     switch (mode)
179     {
180         case GLFW_CURSOR:
181         {
182             if (value != GLFW_CURSOR_NORMAL &&
183                 value != GLFW_CURSOR_HIDDEN &&
184                 value != GLFW_CURSOR_DISABLED)
185             {
186                 _glfwInputError(GLFW_INVALID_ENUM,
187                                 "Invalid cursor mode %i",
188                                 value);
189                 return;
190             }
191 
192             if (window->cursorMode == value)
193                 return;
194 
195             window->cursorMode = value;
196 
197             _glfwPlatformGetCursorPos(window,
198                                       &window->virtualCursorPosX,
199                                       &window->virtualCursorPosY);
200 
201             if (_glfwPlatformWindowFocused(window))
202                 _glfwPlatformSetCursorMode(window, value);
203 
204             return;
205         }
206 
207         case GLFW_STICKY_KEYS:
208         {
209             if (window->stickyKeys == value)
210                 return;
211 
212             if (!value)
213             {
214                 int i;
215 
216                 // Release all sticky keys
217                 for (i = 0;  i <= GLFW_KEY_LAST;  i++)
218                 {
219                     if (window->keys[i] == _GLFW_STICK)
220                         window->keys[i] = GLFW_RELEASE;
221                 }
222             }
223 
224             window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
225             return;
226         }
227 
228         case GLFW_STICKY_MOUSE_BUTTONS:
229         {
230             if (window->stickyMouseButtons == value)
231                 return;
232 
233             if (!value)
234             {
235                 int i;
236 
237                 // Release all sticky mouse buttons
238                 for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
239                 {
240                     if (window->mouseButtons[i] == _GLFW_STICK)
241                         window->mouseButtons[i] = GLFW_RELEASE;
242                 }
243             }
244 
245             window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
246             return;
247         }
248     }
249 
250     _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
251 }
252 
glfwGetKeyName(int key,int scancode)253 GLFWAPI const char* glfwGetKeyName(int key, int scancode)
254 {
255     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
256     return _glfwPlatformGetKeyName(key, scancode);
257 }
258 
glfwGetKey(GLFWwindow * handle,int key)259 GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
260 {
261     _GLFWwindow* window = (_GLFWwindow*) handle;
262     assert(window != NULL);
263 
264     _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
265 
266     if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
267     {
268         _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
269         return GLFW_RELEASE;
270     }
271 
272     if (window->keys[key] == _GLFW_STICK)
273     {
274         // Sticky mode: release key now
275         window->keys[key] = GLFW_RELEASE;
276         return GLFW_PRESS;
277     }
278 
279     return (int) window->keys[key];
280 }
281 
glfwGetMouseButton(GLFWwindow * handle,int button)282 GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
283 {
284     _GLFWwindow* window = (_GLFWwindow*) handle;
285     assert(window != NULL);
286 
287     _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
288 
289     if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
290     {
291         _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
292         return GLFW_RELEASE;
293     }
294 
295     if (window->mouseButtons[button] == _GLFW_STICK)
296     {
297         // Sticky mode: release mouse button now
298         window->mouseButtons[button] = GLFW_RELEASE;
299         return GLFW_PRESS;
300     }
301 
302     return (int) window->mouseButtons[button];
303 }
304 
glfwGetCursorPos(GLFWwindow * handle,double * xpos,double * ypos)305 GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
306 {
307     _GLFWwindow* window = (_GLFWwindow*) handle;
308     assert(window != NULL);
309 
310     if (xpos)
311         *xpos = 0;
312     if (ypos)
313         *ypos = 0;
314 
315     _GLFW_REQUIRE_INIT();
316 
317     if (window->cursorMode == GLFW_CURSOR_DISABLED)
318     {
319         if (xpos)
320             *xpos = window->virtualCursorPosX;
321         if (ypos)
322             *ypos = window->virtualCursorPosY;
323     }
324     else
325         _glfwPlatformGetCursorPos(window, xpos, ypos);
326 }
327 
glfwSetCursorPos(GLFWwindow * handle,double xpos,double ypos)328 GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
329 {
330     _GLFWwindow* window = (_GLFWwindow*) handle;
331     assert(window != NULL);
332 
333     _GLFW_REQUIRE_INIT();
334 
335     if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
336         ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
337     {
338         _glfwInputError(GLFW_INVALID_VALUE,
339                         "Invalid cursor position %f %f",
340                         xpos, ypos);
341         return;
342     }
343 
344     if (!_glfwPlatformWindowFocused(window))
345         return;
346 
347     if (window->cursorMode == GLFW_CURSOR_DISABLED)
348     {
349         // Only update the accumulated position if the cursor is disabled
350         window->virtualCursorPosX = xpos;
351         window->virtualCursorPosY = ypos;
352     }
353     else
354     {
355         // Update system cursor position
356         _glfwPlatformSetCursorPos(window, xpos, ypos);
357     }
358 }
359 
glfwCreateCursor(const GLFWimage * image,int xhot,int yhot)360 GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
361 {
362     _GLFWcursor* cursor;
363 
364     assert(image != NULL);
365 
366     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
367 
368     cursor = calloc(1, sizeof(_GLFWcursor));
369     cursor->next = _glfw.cursorListHead;
370     _glfw.cursorListHead = cursor;
371 
372     if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot))
373     {
374         glfwDestroyCursor((GLFWcursor*) cursor);
375         return NULL;
376     }
377 
378     return (GLFWcursor*) cursor;
379 }
380 
glfwCreateStandardCursor(int shape)381 GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
382 {
383     _GLFWcursor* cursor;
384 
385     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
386 
387     if (shape != GLFW_ARROW_CURSOR &&
388         shape != GLFW_IBEAM_CURSOR &&
389         shape != GLFW_CROSSHAIR_CURSOR &&
390         shape != GLFW_HAND_CURSOR &&
391         shape != GLFW_HRESIZE_CURSOR &&
392         shape != GLFW_VRESIZE_CURSOR)
393     {
394         _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
395         return NULL;
396     }
397 
398     cursor = calloc(1, sizeof(_GLFWcursor));
399     cursor->next = _glfw.cursorListHead;
400     _glfw.cursorListHead = cursor;
401 
402     if (!_glfwPlatformCreateStandardCursor(cursor, shape))
403     {
404         glfwDestroyCursor((GLFWcursor*) cursor);
405         return NULL;
406     }
407 
408     return (GLFWcursor*) cursor;
409 }
410 
glfwDestroyCursor(GLFWcursor * handle)411 GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
412 {
413     _GLFWcursor* cursor = (_GLFWcursor*) handle;
414 
415     _GLFW_REQUIRE_INIT();
416 
417     if (cursor == NULL)
418         return;
419 
420     // Make sure the cursor is not being used by any window
421     {
422         _GLFWwindow* window;
423 
424         for (window = _glfw.windowListHead;  window;  window = window->next)
425         {
426             if (window->cursor == cursor)
427                 glfwSetCursor((GLFWwindow*) window, NULL);
428         }
429     }
430 
431     _glfwPlatformDestroyCursor(cursor);
432 
433     // Unlink cursor from global linked list
434     {
435         _GLFWcursor** prev = &_glfw.cursorListHead;
436 
437         while (*prev != cursor)
438             prev = &((*prev)->next);
439 
440         *prev = cursor->next;
441     }
442 
443     free(cursor);
444 }
445 
glfwSetCursor(GLFWwindow * windowHandle,GLFWcursor * cursorHandle)446 GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
447 {
448     _GLFWwindow* window = (_GLFWwindow*) windowHandle;
449     _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
450     assert(window != NULL);
451 
452     _GLFW_REQUIRE_INIT();
453 
454     window->cursor = cursor;
455 
456     _glfwPlatformSetCursor(window, cursor);
457 }
458 
glfwSetKeyCallback(GLFWwindow * handle,GLFWkeyfun cbfun)459 GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
460 {
461     _GLFWwindow* window = (_GLFWwindow*) handle;
462     assert(window != NULL);
463 
464     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
465     _GLFW_SWAP_POINTERS(window->callbacks.key, cbfun);
466     return cbfun;
467 }
468 
glfwSetCharCallback(GLFWwindow * handle,GLFWcharfun cbfun)469 GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
470 {
471     _GLFWwindow* window = (_GLFWwindow*) handle;
472     assert(window != NULL);
473 
474     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
475     _GLFW_SWAP_POINTERS(window->callbacks.character, cbfun);
476     return cbfun;
477 }
478 
glfwSetCharModsCallback(GLFWwindow * handle,GLFWcharmodsfun cbfun)479 GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
480 {
481     _GLFWwindow* window = (_GLFWwindow*) handle;
482     assert(window != NULL);
483 
484     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
485     _GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun);
486     return cbfun;
487 }
488 
glfwSetMouseButtonCallback(GLFWwindow * handle,GLFWmousebuttonfun cbfun)489 GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
490                                                       GLFWmousebuttonfun cbfun)
491 {
492     _GLFWwindow* window = (_GLFWwindow*) handle;
493     assert(window != NULL);
494 
495     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
496     _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
497     return cbfun;
498 }
499 
glfwSetCursorPosCallback(GLFWwindow * handle,GLFWcursorposfun cbfun)500 GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
501                                                   GLFWcursorposfun cbfun)
502 {
503     _GLFWwindow* window = (_GLFWwindow*) handle;
504     assert(window != NULL);
505 
506     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
507     _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
508     return cbfun;
509 }
510 
glfwSetCursorEnterCallback(GLFWwindow * handle,GLFWcursorenterfun cbfun)511 GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
512                                                       GLFWcursorenterfun cbfun)
513 {
514     _GLFWwindow* window = (_GLFWwindow*) handle;
515     assert(window != NULL);
516 
517     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
518     _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
519     return cbfun;
520 }
521 
glfwSetScrollCallback(GLFWwindow * handle,GLFWscrollfun cbfun)522 GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
523                                             GLFWscrollfun cbfun)
524 {
525     _GLFWwindow* window = (_GLFWwindow*) handle;
526     assert(window != NULL);
527 
528     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
529     _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
530     return cbfun;
531 }
532 
glfwSetDropCallback(GLFWwindow * handle,GLFWdropfun cbfun)533 GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
534 {
535     _GLFWwindow* window = (_GLFWwindow*) handle;
536     assert(window != NULL);
537 
538     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
539     _GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun);
540     return cbfun;
541 }
542 
glfwJoystickPresent(int joy)543 GLFWAPI int glfwJoystickPresent(int joy)
544 {
545     _GLFW_REQUIRE_INIT_OR_RETURN(0);
546 
547     if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
548     {
549         _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
550         return 0;
551     }
552 
553     return _glfwPlatformJoystickPresent(joy);
554 }
555 
glfwGetJoystickAxes(int joy,int * count)556 GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
557 {
558     assert(count != NULL);
559     *count = 0;
560 
561     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
562 
563     if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
564     {
565         _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
566         return NULL;
567     }
568 
569     return _glfwPlatformGetJoystickAxes(joy, count);
570 }
571 
glfwGetJoystickButtons(int joy,int * count)572 GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
573 {
574     assert(count != NULL);
575     *count = 0;
576 
577     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
578 
579     if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
580     {
581         _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
582         return NULL;
583     }
584 
585     return _glfwPlatformGetJoystickButtons(joy, count);
586 }
587 
glfwGetJoystickName(int joy)588 GLFWAPI const char* glfwGetJoystickName(int joy)
589 {
590     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
591 
592     if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
593     {
594         _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
595         return NULL;
596     }
597 
598     return _glfwPlatformGetJoystickName(joy);
599 }
600 
glfwSetJoystickCallback(GLFWjoystickfun cbfun)601 GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
602 {
603     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
604     _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
605     return cbfun;
606 }
607 
glfwSetClipboardString(GLFWwindow * handle,const char * string)608 GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
609 {
610     _GLFWwindow* window = (_GLFWwindow*) handle;
611     assert(window != NULL);
612     assert(string != NULL);
613 
614     _GLFW_REQUIRE_INIT();
615     _glfwPlatformSetClipboardString(window, string);
616 }
617 
glfwGetClipboardString(GLFWwindow * handle)618 GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
619 {
620     _GLFWwindow* window = (_GLFWwindow*) handle;
621     assert(window != NULL);
622 
623     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
624     return _glfwPlatformGetClipboardString(window);
625 }
626 
glfwGetTime(void)627 GLFWAPI double glfwGetTime(void)
628 {
629     _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
630     return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
631         _glfwPlatformGetTimerFrequency();
632 }
633 
glfwSetTime(double time)634 GLFWAPI void glfwSetTime(double time)
635 {
636     _GLFW_REQUIRE_INIT();
637 
638     if (time != time || time < 0.0 || time > 18446744073.0)
639     {
640         _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
641         return;
642     }
643 
644     _glfw.timerOffset = _glfwPlatformGetTimerValue() -
645         (uint64_t) (time * _glfwPlatformGetTimerFrequency());
646 }
647 
glfwGetTimerValue(void)648 GLFWAPI uint64_t glfwGetTimerValue(void)
649 {
650     _GLFW_REQUIRE_INIT_OR_RETURN(0);
651     return _glfwPlatformGetTimerValue();
652 }
653 
glfwGetTimerFrequency(void)654 GLFWAPI uint64_t glfwGetTimerFrequency(void)
655 {
656     _GLFW_REQUIRE_INIT_OR_RETURN(0);
657     return _glfwPlatformGetTimerFrequency();
658 }
659 
660