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