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 | // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net> |
7 | // |
8 | // This software is provided 'as-is', without any express or implied |
9 | // warranty. In no event will the authors be held liable for any damages |
10 | // arising from the use of this software. |
11 | // |
12 | // Permission is granted to anyone to use this software for any purpose, |
13 | // including commercial applications, and to alter it and redistribute it |
14 | // freely, subject to the following restrictions: |
15 | // |
16 | // 1. The origin of this software must not be misrepresented; you must not |
17 | // claim that you wrote the original software. If you use this software |
18 | // in a product, an acknowledgment in the product documentation would |
19 | // be appreciated but is not required. |
20 | // |
21 | // 2. Altered source versions must be plainly marked as such, and must not |
22 | // be misrepresented as being the original software. |
23 | // |
24 | // 3. This notice may not be removed or altered from any source |
25 | // distribution. |
26 | // |
27 | //======================================================================== |
28 | |
29 | #include "internal.h" |
30 | |
31 | #include <assert.h> |
32 | #include <string.h> |
33 | #include <stdlib.h> |
34 | #include <float.h> |
35 | |
36 | |
37 | ////////////////////////////////////////////////////////////////////////// |
38 | ////// GLFW event API ////// |
39 | ////////////////////////////////////////////////////////////////////////// |
40 | |
41 | void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) |
42 | { |
43 | if (focused) |
44 | { |
45 | if (window->callbacks.focus) |
46 | window->callbacks.focus((GLFWwindow*) window, focused); |
47 | } |
48 | else |
49 | { |
50 | int i; |
51 | |
52 | if (window->callbacks.focus) |
53 | window->callbacks.focus((GLFWwindow*) window, focused); |
54 | |
55 | // Release all pressed keyboard keys |
56 | for (i = 0; i <= GLFW_KEY_LAST; i++) |
57 | { |
58 | if (window->keys[i] == GLFW_PRESS) |
59 | _glfwInputKey(window, i, 0, GLFW_RELEASE, 0); |
60 | } |
61 | |
62 | // Release all pressed mouse buttons |
63 | for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) |
64 | { |
65 | if (window->mouseButtons[i] == GLFW_PRESS) |
66 | _glfwInputMouseClick(window, i, GLFW_RELEASE, 0); |
67 | } |
68 | } |
69 | } |
70 | |
71 | void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) |
72 | { |
73 | if (window->callbacks.pos) |
74 | window->callbacks.pos((GLFWwindow*) window, x, y); |
75 | } |
76 | |
77 | void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) |
78 | { |
79 | if (window->callbacks.size) |
80 | window->callbacks.size((GLFWwindow*) window, width, height); |
81 | } |
82 | |
83 | void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) |
84 | { |
85 | if (window->callbacks.iconify) |
86 | window->callbacks.iconify((GLFWwindow*) window, iconified); |
87 | } |
88 | |
89 | void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) |
90 | { |
91 | if (window->callbacks.fbsize) |
92 | window->callbacks.fbsize((GLFWwindow*) window, width, height); |
93 | } |
94 | |
95 | void _glfwInputWindowDamage(_GLFWwindow* window) |
96 | { |
97 | if (window->callbacks.refresh) |
98 | window->callbacks.refresh((GLFWwindow*) window); |
99 | } |
100 | |
101 | void _glfwInputWindowCloseRequest(_GLFWwindow* window) |
102 | { |
103 | window->closed = GLFW_TRUE; |
104 | |
105 | if (window->callbacks.close) |
106 | window->callbacks.close((GLFWwindow*) window); |
107 | } |
108 | |
109 | void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor) |
110 | { |
111 | window->monitor = monitor; |
112 | } |
113 | |
114 | |
115 | ////////////////////////////////////////////////////////////////////////// |
116 | ////// GLFW public API ////// |
117 | ////////////////////////////////////////////////////////////////////////// |
118 | |
119 | GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, |
120 | const char* title, |
121 | GLFWmonitor* monitor, |
122 | GLFWwindow* share) |
123 | { |
124 | _GLFWfbconfig fbconfig; |
125 | _GLFWctxconfig ctxconfig; |
126 | _GLFWwndconfig wndconfig; |
127 | _GLFWwindow* window; |
128 | _GLFWwindow* previous; |
129 | |
130 | assert(title != NULL); |
131 | |
132 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
133 | |
134 | if (width <= 0 || height <= 0) |
135 | { |
136 | _glfwInputError(GLFW_INVALID_VALUE, |
137 | "Invalid window size %ix%i" , |
138 | width, height); |
139 | |
140 | return NULL; |
141 | } |
142 | |
143 | fbconfig = _glfw.hints.framebuffer; |
144 | ctxconfig = _glfw.hints.context; |
145 | wndconfig = _glfw.hints.window; |
146 | |
147 | wndconfig.width = width; |
148 | wndconfig.height = height; |
149 | wndconfig.title = title; |
150 | ctxconfig.share = (_GLFWwindow*) share; |
151 | |
152 | if (ctxconfig.share) |
153 | { |
154 | if (ctxconfig.client == GLFW_NO_API || |
155 | ctxconfig.share->context.client == GLFW_NO_API) |
156 | { |
157 | _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); |
158 | return NULL; |
159 | } |
160 | } |
161 | |
162 | if (!_glfwIsValidContextConfig(&ctxconfig)) |
163 | return NULL; |
164 | |
165 | window = calloc(1, sizeof(_GLFWwindow)); |
166 | window->next = _glfw.windowListHead; |
167 | _glfw.windowListHead = window; |
168 | |
169 | window->videoMode.width = width; |
170 | window->videoMode.height = height; |
171 | window->videoMode.redBits = fbconfig.redBits; |
172 | window->videoMode.greenBits = fbconfig.greenBits; |
173 | window->videoMode.blueBits = fbconfig.blueBits; |
174 | window->videoMode.refreshRate = _glfw.hints.refreshRate; |
175 | |
176 | window->monitor = (_GLFWmonitor*) monitor; |
177 | window->resizable = wndconfig.resizable; |
178 | window->decorated = wndconfig.decorated; |
179 | window->autoIconify = wndconfig.autoIconify; |
180 | window->floating = wndconfig.floating; |
181 | window->cursorMode = GLFW_CURSOR_NORMAL; |
182 | |
183 | window->minwidth = GLFW_DONT_CARE; |
184 | window->minheight = GLFW_DONT_CARE; |
185 | window->maxwidth = GLFW_DONT_CARE; |
186 | window->maxheight = GLFW_DONT_CARE; |
187 | window->numer = GLFW_DONT_CARE; |
188 | window->denom = GLFW_DONT_CARE; |
189 | |
190 | // Save the currently current context so it can be restored later |
191 | previous = _glfwPlatformGetCurrentContext(); |
192 | if (ctxconfig.client != GLFW_NO_API) |
193 | glfwMakeContextCurrent(NULL); |
194 | |
195 | // Open the actual window and create its context |
196 | if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) |
197 | { |
198 | glfwMakeContextCurrent((GLFWwindow*) previous); |
199 | glfwDestroyWindow((GLFWwindow*) window); |
200 | return NULL; |
201 | } |
202 | |
203 | if (ctxconfig.client != GLFW_NO_API) |
204 | { |
205 | window->context.makeCurrent(window); |
206 | |
207 | // Retrieve the actual (as opposed to requested) context attributes |
208 | if (!_glfwRefreshContextAttribs(&ctxconfig)) |
209 | { |
210 | glfwMakeContextCurrent((GLFWwindow*) previous); |
211 | glfwDestroyWindow((GLFWwindow*) window); |
212 | return NULL; |
213 | } |
214 | |
215 | // Restore the previously current context (or NULL) |
216 | glfwMakeContextCurrent((GLFWwindow*) previous); |
217 | } |
218 | |
219 | if (!window->monitor) |
220 | { |
221 | if (wndconfig.visible) |
222 | { |
223 | _glfwPlatformShowWindow(window); |
224 | if (wndconfig.focused) |
225 | _glfwPlatformFocusWindow(window); |
226 | } |
227 | } |
228 | |
229 | return (GLFWwindow*) window; |
230 | } |
231 | |
232 | void glfwDefaultWindowHints(void) |
233 | { |
234 | _GLFW_REQUIRE_INIT(); |
235 | |
236 | memset(&_glfw.hints, 0, sizeof(_glfw.hints)); |
237 | |
238 | // The default is OpenGL with minimum version 1.0 |
239 | _glfw.hints.context.client = GLFW_OPENGL_API; |
240 | _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API; |
241 | _glfw.hints.context.major = 1; |
242 | _glfw.hints.context.minor = 0; |
243 | |
244 | // The default is a focused, visible, resizable window with decorations |
245 | _glfw.hints.window.resizable = GLFW_TRUE; |
246 | _glfw.hints.window.visible = GLFW_TRUE; |
247 | _glfw.hints.window.decorated = GLFW_TRUE; |
248 | _glfw.hints.window.focused = GLFW_TRUE; |
249 | _glfw.hints.window.autoIconify = GLFW_TRUE; |
250 | |
251 | // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, |
252 | // double buffered |
253 | _glfw.hints.framebuffer.redBits = 8; |
254 | _glfw.hints.framebuffer.greenBits = 8; |
255 | _glfw.hints.framebuffer.blueBits = 8; |
256 | _glfw.hints.framebuffer.alphaBits = 8; |
257 | _glfw.hints.framebuffer.depthBits = 24; |
258 | _glfw.hints.framebuffer.stencilBits = 8; |
259 | _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE; |
260 | |
261 | // The default is to select the highest available refresh rate |
262 | _glfw.hints.refreshRate = GLFW_DONT_CARE; |
263 | } |
264 | |
265 | GLFWAPI void glfwWindowHint(int hint, int value) |
266 | { |
267 | _GLFW_REQUIRE_INIT(); |
268 | |
269 | switch (hint) |
270 | { |
271 | case GLFW_RED_BITS: |
272 | _glfw.hints.framebuffer.redBits = value; |
273 | break; |
274 | case GLFW_GREEN_BITS: |
275 | _glfw.hints.framebuffer.greenBits = value; |
276 | break; |
277 | case GLFW_BLUE_BITS: |
278 | _glfw.hints.framebuffer.blueBits = value; |
279 | break; |
280 | case GLFW_ALPHA_BITS: |
281 | _glfw.hints.framebuffer.alphaBits = value; |
282 | break; |
283 | case GLFW_DEPTH_BITS: |
284 | _glfw.hints.framebuffer.depthBits = value; |
285 | break; |
286 | case GLFW_STENCIL_BITS: |
287 | _glfw.hints.framebuffer.stencilBits = value; |
288 | break; |
289 | case GLFW_ACCUM_RED_BITS: |
290 | _glfw.hints.framebuffer.accumRedBits = value; |
291 | break; |
292 | case GLFW_ACCUM_GREEN_BITS: |
293 | _glfw.hints.framebuffer.accumGreenBits = value; |
294 | break; |
295 | case GLFW_ACCUM_BLUE_BITS: |
296 | _glfw.hints.framebuffer.accumBlueBits = value; |
297 | break; |
298 | case GLFW_ACCUM_ALPHA_BITS: |
299 | _glfw.hints.framebuffer.accumAlphaBits = value; |
300 | break; |
301 | case GLFW_AUX_BUFFERS: |
302 | _glfw.hints.framebuffer.auxBuffers = value; |
303 | break; |
304 | case GLFW_STEREO: |
305 | _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; |
306 | break; |
307 | case GLFW_DOUBLEBUFFER: |
308 | _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; |
309 | break; |
310 | case GLFW_SAMPLES: |
311 | _glfw.hints.framebuffer.samples = value; |
312 | break; |
313 | case GLFW_SRGB_CAPABLE: |
314 | _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; |
315 | break; |
316 | case GLFW_RESIZABLE: |
317 | _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; |
318 | break; |
319 | case GLFW_DECORATED: |
320 | _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; |
321 | break; |
322 | case GLFW_FOCUSED: |
323 | _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; |
324 | break; |
325 | case GLFW_AUTO_ICONIFY: |
326 | _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; |
327 | break; |
328 | case GLFW_FLOATING: |
329 | _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; |
330 | break; |
331 | case GLFW_MAXIMIZED: |
332 | _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; |
333 | break; |
334 | case GLFW_VISIBLE: |
335 | _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; |
336 | break; |
337 | case GLFW_CLIENT_API: |
338 | _glfw.hints.context.client = value; |
339 | break; |
340 | case GLFW_CONTEXT_CREATION_API: |
341 | _glfw.hints.context.source = value; |
342 | break; |
343 | case GLFW_CONTEXT_VERSION_MAJOR: |
344 | _glfw.hints.context.major = value; |
345 | break; |
346 | case GLFW_CONTEXT_VERSION_MINOR: |
347 | _glfw.hints.context.minor = value; |
348 | break; |
349 | case GLFW_CONTEXT_ROBUSTNESS: |
350 | _glfw.hints.context.robustness = value; |
351 | break; |
352 | case GLFW_OPENGL_FORWARD_COMPAT: |
353 | _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; |
354 | break; |
355 | case GLFW_OPENGL_DEBUG_CONTEXT: |
356 | _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; |
357 | break; |
358 | case GLFW_CONTEXT_NO_ERROR: |
359 | _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE; |
360 | break; |
361 | case GLFW_OPENGL_PROFILE: |
362 | _glfw.hints.context.profile = value; |
363 | break; |
364 | case GLFW_CONTEXT_RELEASE_BEHAVIOR: |
365 | _glfw.hints.context.release = value; |
366 | break; |
367 | case GLFW_REFRESH_RATE: |
368 | _glfw.hints.refreshRate = value; |
369 | break; |
370 | default: |
371 | _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i" , hint); |
372 | break; |
373 | } |
374 | } |
375 | |
376 | GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) |
377 | { |
378 | _GLFWwindow* window = (_GLFWwindow*) handle; |
379 | |
380 | _GLFW_REQUIRE_INIT(); |
381 | |
382 | // Allow closing of NULL (to match the behavior of free) |
383 | if (window == NULL) |
384 | return; |
385 | |
386 | // Clear all callbacks to avoid exposing a half torn-down window object |
387 | memset(&window->callbacks, 0, sizeof(window->callbacks)); |
388 | |
389 | // The window's context must not be current on another thread when the |
390 | // window is destroyed |
391 | if (window == _glfwPlatformGetCurrentContext()) |
392 | glfwMakeContextCurrent(NULL); |
393 | |
394 | _glfwPlatformDestroyWindow(window); |
395 | |
396 | // Unlink window from global linked list |
397 | { |
398 | _GLFWwindow** prev = &_glfw.windowListHead; |
399 | |
400 | while (*prev != window) |
401 | prev = &((*prev)->next); |
402 | |
403 | *prev = window->next; |
404 | } |
405 | |
406 | free(window); |
407 | } |
408 | |
409 | GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) |
410 | { |
411 | _GLFWwindow* window = (_GLFWwindow*) handle; |
412 | assert(window != NULL); |
413 | |
414 | _GLFW_REQUIRE_INIT_OR_RETURN(0); |
415 | return window->closed; |
416 | } |
417 | |
418 | GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) |
419 | { |
420 | _GLFWwindow* window = (_GLFWwindow*) handle; |
421 | assert(window != NULL); |
422 | |
423 | _GLFW_REQUIRE_INIT(); |
424 | window->closed = value; |
425 | } |
426 | |
427 | GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) |
428 | { |
429 | _GLFWwindow* window = (_GLFWwindow*) handle; |
430 | assert(window != NULL); |
431 | |
432 | assert(title != NULL); |
433 | |
434 | _GLFW_REQUIRE_INIT(); |
435 | _glfwPlatformSetWindowTitle(window, title); |
436 | } |
437 | |
438 | GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, |
439 | int count, const GLFWimage* images) |
440 | { |
441 | _GLFWwindow* window = (_GLFWwindow*) handle; |
442 | assert(window != NULL); |
443 | assert(count >= 0); |
444 | assert(count == 0 || images != NULL); |
445 | |
446 | _GLFW_REQUIRE_INIT(); |
447 | _glfwPlatformSetWindowIcon(window, count, images); |
448 | } |
449 | |
450 | GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) |
451 | { |
452 | _GLFWwindow* window = (_GLFWwindow*) handle; |
453 | assert(window != NULL); |
454 | |
455 | if (xpos) |
456 | *xpos = 0; |
457 | if (ypos) |
458 | *ypos = 0; |
459 | |
460 | _GLFW_REQUIRE_INIT(); |
461 | _glfwPlatformGetWindowPos(window, xpos, ypos); |
462 | } |
463 | |
464 | GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) |
465 | { |
466 | _GLFWwindow* window = (_GLFWwindow*) handle; |
467 | assert(window != NULL); |
468 | |
469 | _GLFW_REQUIRE_INIT(); |
470 | |
471 | if (window->monitor) |
472 | return; |
473 | |
474 | _glfwPlatformSetWindowPos(window, xpos, ypos); |
475 | } |
476 | |
477 | GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) |
478 | { |
479 | _GLFWwindow* window = (_GLFWwindow*) handle; |
480 | assert(window != NULL); |
481 | |
482 | if (width) |
483 | *width = 0; |
484 | if (height) |
485 | *height = 0; |
486 | |
487 | _GLFW_REQUIRE_INIT(); |
488 | _glfwPlatformGetWindowSize(window, width, height); |
489 | } |
490 | |
491 | GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) |
492 | { |
493 | _GLFWwindow* window = (_GLFWwindow*) handle; |
494 | assert(window != NULL); |
495 | |
496 | _GLFW_REQUIRE_INIT(); |
497 | |
498 | window->videoMode.width = width; |
499 | window->videoMode.height = height; |
500 | |
501 | _glfwPlatformSetWindowSize(window, width, height); |
502 | } |
503 | |
504 | GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, |
505 | int minwidth, int minheight, |
506 | int maxwidth, int maxheight) |
507 | { |
508 | _GLFWwindow* window = (_GLFWwindow*) handle; |
509 | assert(window != NULL); |
510 | |
511 | _GLFW_REQUIRE_INIT(); |
512 | |
513 | if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) |
514 | { |
515 | if (minwidth < 0 || minheight < 0) |
516 | { |
517 | _glfwInputError(GLFW_INVALID_VALUE, |
518 | "Invalid window minimum size %ix%i" , |
519 | minwidth, minheight); |
520 | return; |
521 | } |
522 | } |
523 | |
524 | if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE) |
525 | { |
526 | if (maxwidth < 0 || maxheight < 0 || |
527 | maxwidth < minwidth || maxheight < minheight) |
528 | { |
529 | _glfwInputError(GLFW_INVALID_VALUE, |
530 | "Invalid window maximum size %ix%i" , |
531 | maxwidth, maxheight); |
532 | return; |
533 | } |
534 | } |
535 | |
536 | window->minwidth = minwidth; |
537 | window->minheight = minheight; |
538 | window->maxwidth = maxwidth; |
539 | window->maxheight = maxheight; |
540 | |
541 | if (window->monitor || !window->resizable) |
542 | return; |
543 | |
544 | _glfwPlatformSetWindowSizeLimits(window, |
545 | minwidth, minheight, |
546 | maxwidth, maxheight); |
547 | } |
548 | |
549 | GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) |
550 | { |
551 | _GLFWwindow* window = (_GLFWwindow*) handle; |
552 | assert(window != NULL); |
553 | |
554 | _GLFW_REQUIRE_INIT(); |
555 | |
556 | if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) |
557 | { |
558 | if (numer <= 0 || denom <= 0) |
559 | { |
560 | _glfwInputError(GLFW_INVALID_VALUE, |
561 | "Invalid window aspect ratio %i:%i" , |
562 | numer, denom); |
563 | return; |
564 | } |
565 | } |
566 | |
567 | window->numer = numer; |
568 | window->denom = denom; |
569 | |
570 | if (window->monitor || !window->resizable) |
571 | return; |
572 | |
573 | _glfwPlatformSetWindowAspectRatio(window, numer, denom); |
574 | } |
575 | |
576 | GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) |
577 | { |
578 | _GLFWwindow* window = (_GLFWwindow*) handle; |
579 | assert(window != NULL); |
580 | |
581 | if (width) |
582 | *width = 0; |
583 | if (height) |
584 | *height = 0; |
585 | |
586 | _GLFW_REQUIRE_INIT(); |
587 | _glfwPlatformGetFramebufferSize(window, width, height); |
588 | } |
589 | |
590 | GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, |
591 | int* left, int* top, |
592 | int* right, int* bottom) |
593 | { |
594 | _GLFWwindow* window = (_GLFWwindow*) handle; |
595 | assert(window != NULL); |
596 | |
597 | if (left) |
598 | *left = 0; |
599 | if (top) |
600 | *top = 0; |
601 | if (right) |
602 | *right = 0; |
603 | if (bottom) |
604 | *bottom = 0; |
605 | |
606 | _GLFW_REQUIRE_INIT(); |
607 | _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom); |
608 | } |
609 | |
610 | GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) |
611 | { |
612 | _GLFWwindow* window = (_GLFWwindow*) handle; |
613 | assert(window != NULL); |
614 | |
615 | _GLFW_REQUIRE_INIT(); |
616 | _glfwPlatformIconifyWindow(window); |
617 | } |
618 | |
619 | GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) |
620 | { |
621 | _GLFWwindow* window = (_GLFWwindow*) handle; |
622 | assert(window != NULL); |
623 | |
624 | _GLFW_REQUIRE_INIT(); |
625 | _glfwPlatformRestoreWindow(window); |
626 | } |
627 | |
628 | GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) |
629 | { |
630 | _GLFWwindow* window = (_GLFWwindow*) handle; |
631 | assert(window != NULL); |
632 | |
633 | _GLFW_REQUIRE_INIT(); |
634 | _glfwPlatformMaximizeWindow(window); |
635 | } |
636 | |
637 | GLFWAPI void glfwShowWindow(GLFWwindow* handle) |
638 | { |
639 | _GLFWwindow* window = (_GLFWwindow*) handle; |
640 | assert(window != NULL); |
641 | |
642 | _GLFW_REQUIRE_INIT(); |
643 | |
644 | if (window->monitor) |
645 | return; |
646 | |
647 | _glfwPlatformShowWindow(window); |
648 | _glfwPlatformFocusWindow(window); |
649 | } |
650 | |
651 | GLFWAPI void glfwHideWindow(GLFWwindow* handle) |
652 | { |
653 | _GLFWwindow* window = (_GLFWwindow*) handle; |
654 | assert(window != NULL); |
655 | |
656 | _GLFW_REQUIRE_INIT(); |
657 | |
658 | if (window->monitor) |
659 | return; |
660 | |
661 | _glfwPlatformHideWindow(window); |
662 | } |
663 | |
664 | GLFWAPI void glfwFocusWindow(GLFWwindow* handle) |
665 | { |
666 | _GLFWwindow* window = (_GLFWwindow*) handle; |
667 | assert(window != NULL); |
668 | |
669 | _GLFW_REQUIRE_INIT(); |
670 | |
671 | _glfwPlatformFocusWindow(window); |
672 | } |
673 | |
674 | GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) |
675 | { |
676 | _GLFWwindow* window = (_GLFWwindow*) handle; |
677 | assert(window != NULL); |
678 | |
679 | _GLFW_REQUIRE_INIT_OR_RETURN(0); |
680 | |
681 | switch (attrib) |
682 | { |
683 | case GLFW_FOCUSED: |
684 | return _glfwPlatformWindowFocused(window); |
685 | case GLFW_ICONIFIED: |
686 | return _glfwPlatformWindowIconified(window); |
687 | case GLFW_VISIBLE: |
688 | return _glfwPlatformWindowVisible(window); |
689 | case GLFW_MAXIMIZED: |
690 | return _glfwPlatformWindowMaximized(window); |
691 | case GLFW_RESIZABLE: |
692 | return window->resizable; |
693 | case GLFW_DECORATED: |
694 | return window->decorated; |
695 | case GLFW_FLOATING: |
696 | return window->floating; |
697 | case GLFW_CLIENT_API: |
698 | return window->context.client; |
699 | case GLFW_CONTEXT_CREATION_API: |
700 | return window->context.source; |
701 | case GLFW_CONTEXT_VERSION_MAJOR: |
702 | return window->context.major; |
703 | case GLFW_CONTEXT_VERSION_MINOR: |
704 | return window->context.minor; |
705 | case GLFW_CONTEXT_REVISION: |
706 | return window->context.revision; |
707 | case GLFW_CONTEXT_ROBUSTNESS: |
708 | return window->context.robustness; |
709 | case GLFW_OPENGL_FORWARD_COMPAT: |
710 | return window->context.forward; |
711 | case GLFW_OPENGL_DEBUG_CONTEXT: |
712 | return window->context.debug; |
713 | case GLFW_OPENGL_PROFILE: |
714 | return window->context.profile; |
715 | case GLFW_CONTEXT_RELEASE_BEHAVIOR: |
716 | return window->context.release; |
717 | case GLFW_CONTEXT_NO_ERROR: |
718 | return window->context.noerror; |
719 | } |
720 | |
721 | _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i" , attrib); |
722 | return 0; |
723 | } |
724 | |
725 | GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) |
726 | { |
727 | _GLFWwindow* window = (_GLFWwindow*) handle; |
728 | assert(window != NULL); |
729 | |
730 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
731 | return (GLFWmonitor*) window->monitor; |
732 | } |
733 | |
734 | GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, |
735 | GLFWmonitor* mh, |
736 | int xpos, int ypos, |
737 | int width, int height, |
738 | int refreshRate) |
739 | { |
740 | _GLFWwindow* window = (_GLFWwindow*) wh; |
741 | _GLFWmonitor* monitor = (_GLFWmonitor*) mh; |
742 | assert(window != NULL); |
743 | |
744 | _GLFW_REQUIRE_INIT(); |
745 | |
746 | if (width <= 0 || height <= 0) |
747 | { |
748 | _glfwInputError(GLFW_INVALID_VALUE, |
749 | "Invalid window size %ix%i" , |
750 | width, height); |
751 | return; |
752 | } |
753 | |
754 | if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE) |
755 | { |
756 | _glfwInputError(GLFW_INVALID_VALUE, |
757 | "Invalid refresh rate %i" , |
758 | refreshRate); |
759 | return; |
760 | } |
761 | |
762 | window->videoMode.width = width; |
763 | window->videoMode.height = height; |
764 | window->videoMode.refreshRate = refreshRate; |
765 | |
766 | _glfwPlatformSetWindowMonitor(window, monitor, |
767 | xpos, ypos, width, height, |
768 | refreshRate); |
769 | } |
770 | |
771 | GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) |
772 | { |
773 | _GLFWwindow* window = (_GLFWwindow*) handle; |
774 | assert(window != NULL); |
775 | |
776 | _GLFW_REQUIRE_INIT(); |
777 | window->userPointer = pointer; |
778 | } |
779 | |
780 | GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) |
781 | { |
782 | _GLFWwindow* window = (_GLFWwindow*) handle; |
783 | assert(window != NULL); |
784 | |
785 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
786 | return window->userPointer; |
787 | } |
788 | |
789 | GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, |
790 | GLFWwindowposfun cbfun) |
791 | { |
792 | _GLFWwindow* window = (_GLFWwindow*) handle; |
793 | assert(window != NULL); |
794 | |
795 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
796 | _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun); |
797 | return cbfun; |
798 | } |
799 | |
800 | GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, |
801 | GLFWwindowsizefun cbfun) |
802 | { |
803 | _GLFWwindow* window = (_GLFWwindow*) handle; |
804 | assert(window != NULL); |
805 | |
806 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
807 | _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun); |
808 | return cbfun; |
809 | } |
810 | |
811 | GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, |
812 | GLFWwindowclosefun cbfun) |
813 | { |
814 | _GLFWwindow* window = (_GLFWwindow*) handle; |
815 | assert(window != NULL); |
816 | |
817 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
818 | _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun); |
819 | return cbfun; |
820 | } |
821 | |
822 | GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, |
823 | GLFWwindowrefreshfun cbfun) |
824 | { |
825 | _GLFWwindow* window = (_GLFWwindow*) handle; |
826 | assert(window != NULL); |
827 | |
828 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
829 | _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun); |
830 | return cbfun; |
831 | } |
832 | |
833 | GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, |
834 | GLFWwindowfocusfun cbfun) |
835 | { |
836 | _GLFWwindow* window = (_GLFWwindow*) handle; |
837 | assert(window != NULL); |
838 | |
839 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
840 | _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun); |
841 | return cbfun; |
842 | } |
843 | |
844 | GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, |
845 | GLFWwindowiconifyfun cbfun) |
846 | { |
847 | _GLFWwindow* window = (_GLFWwindow*) handle; |
848 | assert(window != NULL); |
849 | |
850 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
851 | _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun); |
852 | return cbfun; |
853 | } |
854 | |
855 | GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, |
856 | GLFWframebuffersizefun cbfun) |
857 | { |
858 | _GLFWwindow* window = (_GLFWwindow*) handle; |
859 | assert(window != NULL); |
860 | |
861 | _GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
862 | _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun); |
863 | return cbfun; |
864 | } |
865 | |
866 | GLFWAPI void glfwPollEvents(void) |
867 | { |
868 | _GLFW_REQUIRE_INIT(); |
869 | _glfwPlatformPollEvents(); |
870 | } |
871 | |
872 | GLFWAPI void glfwWaitEvents(void) |
873 | { |
874 | _GLFW_REQUIRE_INIT(); |
875 | |
876 | if (!_glfw.windowListHead) |
877 | return; |
878 | |
879 | _glfwPlatformWaitEvents(); |
880 | } |
881 | |
882 | GLFWAPI void glfwWaitEventsTimeout(double timeout) |
883 | { |
884 | _GLFW_REQUIRE_INIT(); |
885 | |
886 | if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX) |
887 | { |
888 | _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f" , timeout); |
889 | return; |
890 | } |
891 | |
892 | _glfwPlatformWaitEventsTimeout(timeout); |
893 | } |
894 | |
895 | GLFWAPI void glfwPostEmptyEvent(void) |
896 | { |
897 | _GLFW_REQUIRE_INIT(); |
898 | |
899 | if (!_glfw.windowListHead) |
900 | return; |
901 | |
902 | _glfwPlatformPostEmptyEvent(); |
903 | } |
904 | |
905 | |