window.c (35148B)
1 //======================================================================== 2 // GLFW 3.4 - www.glfw.org 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2002-2006 Marcus Geelnard 5 // Copyright (c) 2006-2019 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 // Notifies shared code that a window has lost or received input focus 42 // 43 void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) 44 { 45 assert(window != NULL); 46 assert(focused == GLFW_TRUE || focused == GLFW_FALSE); 47 48 if (window->callbacks.focus) 49 window->callbacks.focus((GLFWwindow*) window, focused); 50 51 if (!focused) 52 { 53 int key, button; 54 55 for (key = 0; key <= GLFW_KEY_LAST; key++) 56 { 57 if (window->keys[key] == GLFW_PRESS) 58 { 59 const int scancode = _glfw.platform.getKeyScancode(key); 60 _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0); 61 } 62 } 63 64 for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++) 65 { 66 if (window->mouseButtons[button] == GLFW_PRESS) 67 _glfwInputMouseClick(window, button, GLFW_RELEASE, 0); 68 } 69 } 70 } 71 72 // Notifies shared code that a window has moved 73 // The position is specified in content area relative screen coordinates 74 // 75 void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) 76 { 77 assert(window != NULL); 78 79 if (window->callbacks.pos) 80 window->callbacks.pos((GLFWwindow*) window, x, y); 81 } 82 83 // Notifies shared code that a window has been resized 84 // The size is specified in screen coordinates 85 // 86 void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) 87 { 88 assert(window != NULL); 89 assert(width >= 0); 90 assert(height >= 0); 91 92 if (window->callbacks.size) 93 window->callbacks.size((GLFWwindow*) window, width, height); 94 } 95 96 // Notifies shared code that a window has been iconified or restored 97 // 98 void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) 99 { 100 assert(window != NULL); 101 assert(iconified == GLFW_TRUE || iconified == GLFW_FALSE); 102 103 if (window->callbacks.iconify) 104 window->callbacks.iconify((GLFWwindow*) window, iconified); 105 } 106 107 // Notifies shared code that a window has been maximized or restored 108 // 109 void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized) 110 { 111 assert(window != NULL); 112 assert(maximized == GLFW_TRUE || maximized == GLFW_FALSE); 113 114 if (window->callbacks.maximize) 115 window->callbacks.maximize((GLFWwindow*) window, maximized); 116 } 117 118 // Notifies shared code that a window framebuffer has been resized 119 // The size is specified in pixels 120 // 121 void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) 122 { 123 assert(window != NULL); 124 assert(width >= 0); 125 assert(height >= 0); 126 127 if (window->callbacks.fbsize) 128 window->callbacks.fbsize((GLFWwindow*) window, width, height); 129 } 130 131 // Notifies shared code that a window content scale has changed 132 // The scale is specified as the ratio between the current and default DPI 133 // 134 void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale) 135 { 136 assert(window != NULL); 137 assert(xscale > 0.f); 138 assert(xscale < FLT_MAX); 139 assert(yscale > 0.f); 140 assert(yscale < FLT_MAX); 141 142 if (window->callbacks.scale) 143 window->callbacks.scale((GLFWwindow*) window, xscale, yscale); 144 } 145 146 // Notifies shared code that the window contents needs updating 147 // 148 void _glfwInputWindowDamage(_GLFWwindow* window) 149 { 150 assert(window != NULL); 151 152 if (window->callbacks.refresh) 153 window->callbacks.refresh((GLFWwindow*) window); 154 } 155 156 // Notifies shared code that the user wishes to close a window 157 // 158 void _glfwInputWindowCloseRequest(_GLFWwindow* window) 159 { 160 assert(window != NULL); 161 162 window->shouldClose = GLFW_TRUE; 163 164 if (window->callbacks.close) 165 window->callbacks.close((GLFWwindow*) window); 166 } 167 168 // Notifies shared code that a window has changed its desired monitor 169 // 170 void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) 171 { 172 assert(window != NULL); 173 window->monitor = monitor; 174 } 175 176 ////////////////////////////////////////////////////////////////////////// 177 ////// GLFW public API ////// 178 ////////////////////////////////////////////////////////////////////////// 179 180 GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, 181 const char* title, 182 GLFWmonitor* monitor, 183 GLFWwindow* share) 184 { 185 _GLFWfbconfig fbconfig; 186 _GLFWctxconfig ctxconfig; 187 _GLFWwndconfig wndconfig; 188 _GLFWwindow* window; 189 190 assert(title != NULL); 191 assert(width >= 0); 192 assert(height >= 0); 193 194 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 195 196 if (width <= 0 || height <= 0) 197 { 198 _glfwInputError(GLFW_INVALID_VALUE, 199 "Invalid window size %ix%i", 200 width, height); 201 202 return NULL; 203 } 204 205 fbconfig = _glfw.hints.framebuffer; 206 ctxconfig = _glfw.hints.context; 207 wndconfig = _glfw.hints.window; 208 209 wndconfig.width = width; 210 wndconfig.height = height; 211 wndconfig.title = title; 212 ctxconfig.share = (_GLFWwindow*) share; 213 214 if (!_glfwIsValidContextConfig(&ctxconfig)) 215 return NULL; 216 217 window = _glfw_calloc(1, sizeof(_GLFWwindow)); 218 window->next = _glfw.windowListHead; 219 _glfw.windowListHead = window; 220 221 window->videoMode.width = width; 222 window->videoMode.height = height; 223 window->videoMode.redBits = fbconfig.redBits; 224 window->videoMode.greenBits = fbconfig.greenBits; 225 window->videoMode.blueBits = fbconfig.blueBits; 226 window->videoMode.refreshRate = _glfw.hints.refreshRate; 227 228 window->monitor = (_GLFWmonitor*) monitor; 229 window->resizable = wndconfig.resizable; 230 window->decorated = wndconfig.decorated; 231 window->autoIconify = wndconfig.autoIconify; 232 window->floating = wndconfig.floating; 233 window->focusOnShow = wndconfig.focusOnShow; 234 window->mousePassthrough = wndconfig.mousePassthrough; 235 window->cursorMode = GLFW_CURSOR_NORMAL; 236 237 window->doublebuffer = fbconfig.doublebuffer; 238 239 window->minwidth = GLFW_DONT_CARE; 240 window->minheight = GLFW_DONT_CARE; 241 window->maxwidth = GLFW_DONT_CARE; 242 window->maxheight = GLFW_DONT_CARE; 243 window->numer = GLFW_DONT_CARE; 244 window->denom = GLFW_DONT_CARE; 245 window->title = _glfw_strdup(title); 246 247 if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig)) 248 { 249 glfwDestroyWindow((GLFWwindow*) window); 250 return NULL; 251 } 252 253 return (GLFWwindow*) window; 254 } 255 256 void glfwDefaultWindowHints(void) 257 { 258 _GLFW_REQUIRE_INIT(); 259 260 // The default is OpenGL with minimum version 1.0 261 memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context)); 262 _glfw.hints.context.client = GLFW_OPENGL_API; 263 _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API; 264 _glfw.hints.context.major = 1; 265 _glfw.hints.context.minor = 0; 266 267 // The default is a focused, visible, resizable window with decorations 268 memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window)); 269 _glfw.hints.window.resizable = GLFW_TRUE; 270 _glfw.hints.window.visible = GLFW_TRUE; 271 _glfw.hints.window.decorated = GLFW_TRUE; 272 _glfw.hints.window.focused = GLFW_TRUE; 273 _glfw.hints.window.autoIconify = GLFW_TRUE; 274 _glfw.hints.window.centerCursor = GLFW_TRUE; 275 _glfw.hints.window.focusOnShow = GLFW_TRUE; 276 _glfw.hints.window.xpos = GLFW_ANY_POSITION; 277 _glfw.hints.window.ypos = GLFW_ANY_POSITION; 278 _glfw.hints.window.scaleFramebuffer = GLFW_TRUE; 279 280 // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, 281 // double buffered 282 memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer)); 283 _glfw.hints.framebuffer.redBits = 8; 284 _glfw.hints.framebuffer.greenBits = 8; 285 _glfw.hints.framebuffer.blueBits = 8; 286 _glfw.hints.framebuffer.alphaBits = 8; 287 _glfw.hints.framebuffer.depthBits = 24; 288 _glfw.hints.framebuffer.stencilBits = 8; 289 _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE; 290 291 // The default is to select the highest available refresh rate 292 _glfw.hints.refreshRate = GLFW_DONT_CARE; 293 } 294 295 GLFWAPI void glfwWindowHint(int hint, int value) 296 { 297 _GLFW_REQUIRE_INIT(); 298 299 switch (hint) 300 { 301 case GLFW_RED_BITS: 302 _glfw.hints.framebuffer.redBits = value; 303 return; 304 case GLFW_GREEN_BITS: 305 _glfw.hints.framebuffer.greenBits = value; 306 return; 307 case GLFW_BLUE_BITS: 308 _glfw.hints.framebuffer.blueBits = value; 309 return; 310 case GLFW_ALPHA_BITS: 311 _glfw.hints.framebuffer.alphaBits = value; 312 return; 313 case GLFW_DEPTH_BITS: 314 _glfw.hints.framebuffer.depthBits = value; 315 return; 316 case GLFW_STENCIL_BITS: 317 _glfw.hints.framebuffer.stencilBits = value; 318 return; 319 case GLFW_ACCUM_RED_BITS: 320 _glfw.hints.framebuffer.accumRedBits = value; 321 return; 322 case GLFW_ACCUM_GREEN_BITS: 323 _glfw.hints.framebuffer.accumGreenBits = value; 324 return; 325 case GLFW_ACCUM_BLUE_BITS: 326 _glfw.hints.framebuffer.accumBlueBits = value; 327 return; 328 case GLFW_ACCUM_ALPHA_BITS: 329 _glfw.hints.framebuffer.accumAlphaBits = value; 330 return; 331 case GLFW_AUX_BUFFERS: 332 _glfw.hints.framebuffer.auxBuffers = value; 333 return; 334 case GLFW_STEREO: 335 _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; 336 return; 337 case GLFW_DOUBLEBUFFER: 338 _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; 339 return; 340 case GLFW_TRANSPARENT_FRAMEBUFFER: 341 _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE; 342 return; 343 case GLFW_SAMPLES: 344 _glfw.hints.framebuffer.samples = value; 345 return; 346 case GLFW_SRGB_CAPABLE: 347 _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; 348 return; 349 case GLFW_RESIZABLE: 350 _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; 351 return; 352 case GLFW_DECORATED: 353 _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; 354 return; 355 case GLFW_FOCUSED: 356 _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; 357 return; 358 case GLFW_AUTO_ICONIFY: 359 _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; 360 return; 361 case GLFW_FLOATING: 362 _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; 363 return; 364 case GLFW_MAXIMIZED: 365 _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; 366 return; 367 case GLFW_VISIBLE: 368 _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; 369 return; 370 case GLFW_POSITION_X: 371 _glfw.hints.window.xpos = value; 372 return; 373 case GLFW_POSITION_Y: 374 _glfw.hints.window.ypos = value; 375 return; 376 case GLFW_WIN32_KEYBOARD_MENU: 377 _glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE; 378 return; 379 case GLFW_WIN32_SHOWDEFAULT: 380 _glfw.hints.window.win32.showDefault = value ? GLFW_TRUE : GLFW_FALSE; 381 return; 382 case GLFW_COCOA_GRAPHICS_SWITCHING: 383 _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE; 384 return; 385 case GLFW_SCALE_TO_MONITOR: 386 _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE; 387 return; 388 case GLFW_SCALE_FRAMEBUFFER: 389 case GLFW_COCOA_RETINA_FRAMEBUFFER: 390 _glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE; 391 return; 392 case GLFW_CENTER_CURSOR: 393 _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; 394 return; 395 case GLFW_FOCUS_ON_SHOW: 396 _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; 397 return; 398 case GLFW_MOUSE_PASSTHROUGH: 399 _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; 400 return; 401 case GLFW_CLIENT_API: 402 _glfw.hints.context.client = value; 403 return; 404 case GLFW_CONTEXT_CREATION_API: 405 _glfw.hints.context.source = value; 406 return; 407 case GLFW_CONTEXT_VERSION_MAJOR: 408 _glfw.hints.context.major = value; 409 return; 410 case GLFW_CONTEXT_VERSION_MINOR: 411 _glfw.hints.context.minor = value; 412 return; 413 case GLFW_CONTEXT_ROBUSTNESS: 414 _glfw.hints.context.robustness = value; 415 return; 416 case GLFW_OPENGL_FORWARD_COMPAT: 417 _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; 418 return; 419 case GLFW_CONTEXT_DEBUG: 420 _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; 421 return; 422 case GLFW_CONTEXT_NO_ERROR: 423 _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE; 424 return; 425 case GLFW_OPENGL_PROFILE: 426 _glfw.hints.context.profile = value; 427 return; 428 case GLFW_CONTEXT_RELEASE_BEHAVIOR: 429 _glfw.hints.context.release = value; 430 return; 431 case GLFW_REFRESH_RATE: 432 _glfw.hints.refreshRate = value; 433 return; 434 } 435 436 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); 437 } 438 439 GLFWAPI void glfwWindowHintString(int hint, const char* value) 440 { 441 assert(value != NULL); 442 443 _GLFW_REQUIRE_INIT(); 444 445 switch (hint) 446 { 447 case GLFW_COCOA_FRAME_NAME: 448 strncpy(_glfw.hints.window.ns.frameName, value, 449 sizeof(_glfw.hints.window.ns.frameName) - 1); 450 return; 451 case GLFW_X11_CLASS_NAME: 452 strncpy(_glfw.hints.window.x11.className, value, 453 sizeof(_glfw.hints.window.x11.className) - 1); 454 return; 455 case GLFW_X11_INSTANCE_NAME: 456 strncpy(_glfw.hints.window.x11.instanceName, value, 457 sizeof(_glfw.hints.window.x11.instanceName) - 1); 458 return; 459 case GLFW_WAYLAND_APP_ID: 460 strncpy(_glfw.hints.window.wl.appId, value, 461 sizeof(_glfw.hints.window.wl.appId) - 1); 462 return; 463 } 464 465 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint); 466 } 467 468 GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) 469 { 470 _GLFWwindow* window = (_GLFWwindow*) handle; 471 472 _GLFW_REQUIRE_INIT(); 473 474 // Allow closing of NULL (to match the behavior of free) 475 if (window == NULL) 476 return; 477 478 // Clear all callbacks to avoid exposing a half torn-down window object 479 memset(&window->callbacks, 0, sizeof(window->callbacks)); 480 481 // The window's context must not be current on another thread when the 482 // window is destroyed 483 if (window == _glfwPlatformGetTls(&_glfw.contextSlot)) 484 glfwMakeContextCurrent(NULL); 485 486 _glfw.platform.destroyWindow(window); 487 488 // Unlink window from global linked list 489 { 490 _GLFWwindow** prev = &_glfw.windowListHead; 491 492 while (*prev != window) 493 prev = &((*prev)->next); 494 495 *prev = window->next; 496 } 497 498 _glfw_free(window->title); 499 _glfw_free(window); 500 } 501 502 GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) 503 { 504 _GLFWwindow* window = (_GLFWwindow*) handle; 505 assert(window != NULL); 506 507 _GLFW_REQUIRE_INIT_OR_RETURN(0); 508 return window->shouldClose; 509 } 510 511 GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) 512 { 513 _GLFWwindow* window = (_GLFWwindow*) handle; 514 assert(window != NULL); 515 516 _GLFW_REQUIRE_INIT(); 517 window->shouldClose = value; 518 } 519 520 GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle) 521 { 522 _GLFWwindow* window = (_GLFWwindow*) handle; 523 assert(window != NULL); 524 525 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 526 527 return window->title; 528 } 529 530 GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) 531 { 532 _GLFWwindow* window = (_GLFWwindow*) handle; 533 assert(window != NULL); 534 assert(title != NULL); 535 536 _GLFW_REQUIRE_INIT(); 537 538 char* prev = window->title; 539 window->title = _glfw_strdup(title); 540 541 _glfw.platform.setWindowTitle(window, title); 542 _glfw_free(prev); 543 } 544 545 GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, 546 int count, const GLFWimage* images) 547 { 548 int i; 549 _GLFWwindow* window = (_GLFWwindow*) handle; 550 551 assert(window != NULL); 552 assert(count >= 0); 553 assert(count == 0 || images != NULL); 554 555 _GLFW_REQUIRE_INIT(); 556 557 if (count < 0) 558 { 559 _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon"); 560 return; 561 } 562 563 for (i = 0; i < count; i++) 564 { 565 assert(images[i].pixels != NULL); 566 567 if (images[i].width <= 0 || images[i].height <= 0) 568 { 569 _glfwInputError(GLFW_INVALID_VALUE, 570 "Invalid image dimensions for window icon"); 571 return; 572 } 573 } 574 575 _glfw.platform.setWindowIcon(window, count, images); 576 } 577 578 GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) 579 { 580 _GLFWwindow* window = (_GLFWwindow*) handle; 581 assert(window != NULL); 582 583 if (xpos) 584 *xpos = 0; 585 if (ypos) 586 *ypos = 0; 587 588 _GLFW_REQUIRE_INIT(); 589 _glfw.platform.getWindowPos(window, xpos, ypos); 590 } 591 592 GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) 593 { 594 _GLFWwindow* window = (_GLFWwindow*) handle; 595 assert(window != NULL); 596 597 _GLFW_REQUIRE_INIT(); 598 599 if (window->monitor) 600 return; 601 602 _glfw.platform.setWindowPos(window, xpos, ypos); 603 } 604 605 GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) 606 { 607 _GLFWwindow* window = (_GLFWwindow*) handle; 608 assert(window != NULL); 609 610 if (width) 611 *width = 0; 612 if (height) 613 *height = 0; 614 615 _GLFW_REQUIRE_INIT(); 616 _glfw.platform.getWindowSize(window, width, height); 617 } 618 619 GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) 620 { 621 _GLFWwindow* window = (_GLFWwindow*) handle; 622 assert(window != NULL); 623 assert(width >= 0); 624 assert(height >= 0); 625 626 _GLFW_REQUIRE_INIT(); 627 628 window->videoMode.width = width; 629 window->videoMode.height = height; 630 631 _glfw.platform.setWindowSize(window, width, height); 632 } 633 634 GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, 635 int minwidth, int minheight, 636 int maxwidth, int maxheight) 637 { 638 _GLFWwindow* window = (_GLFWwindow*) handle; 639 assert(window != NULL); 640 641 _GLFW_REQUIRE_INIT(); 642 643 if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) 644 { 645 if (minwidth < 0 || minheight < 0) 646 { 647 _glfwInputError(GLFW_INVALID_VALUE, 648 "Invalid window minimum size %ix%i", 649 minwidth, minheight); 650 return; 651 } 652 } 653 654 if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE) 655 { 656 if (maxwidth < 0 || maxheight < 0 || 657 maxwidth < minwidth || maxheight < minheight) 658 { 659 _glfwInputError(GLFW_INVALID_VALUE, 660 "Invalid window maximum size %ix%i", 661 maxwidth, maxheight); 662 return; 663 } 664 } 665 666 window->minwidth = minwidth; 667 window->minheight = minheight; 668 window->maxwidth = maxwidth; 669 window->maxheight = maxheight; 670 671 if (window->monitor || !window->resizable) 672 return; 673 674 _glfw.platform.setWindowSizeLimits(window, 675 minwidth, minheight, 676 maxwidth, maxheight); 677 } 678 679 GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) 680 { 681 _GLFWwindow* window = (_GLFWwindow*) handle; 682 assert(window != NULL); 683 assert(numer != 0); 684 assert(denom != 0); 685 686 _GLFW_REQUIRE_INIT(); 687 688 if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) 689 { 690 if (numer <= 0 || denom <= 0) 691 { 692 _glfwInputError(GLFW_INVALID_VALUE, 693 "Invalid window aspect ratio %i:%i", 694 numer, denom); 695 return; 696 } 697 } 698 699 window->numer = numer; 700 window->denom = denom; 701 702 if (window->monitor || !window->resizable) 703 return; 704 705 _glfw.platform.setWindowAspectRatio(window, numer, denom); 706 } 707 708 GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) 709 { 710 _GLFWwindow* window = (_GLFWwindow*) handle; 711 assert(window != NULL); 712 713 if (width) 714 *width = 0; 715 if (height) 716 *height = 0; 717 718 _GLFW_REQUIRE_INIT(); 719 _glfw.platform.getFramebufferSize(window, width, height); 720 } 721 722 GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, 723 int* left, int* top, 724 int* right, int* bottom) 725 { 726 _GLFWwindow* window = (_GLFWwindow*) handle; 727 assert(window != NULL); 728 729 if (left) 730 *left = 0; 731 if (top) 732 *top = 0; 733 if (right) 734 *right = 0; 735 if (bottom) 736 *bottom = 0; 737 738 _GLFW_REQUIRE_INIT(); 739 _glfw.platform.getWindowFrameSize(window, left, top, right, bottom); 740 } 741 742 GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, 743 float* xscale, float* yscale) 744 { 745 _GLFWwindow* window = (_GLFWwindow*) handle; 746 assert(window != NULL); 747 748 if (xscale) 749 *xscale = 0.f; 750 if (yscale) 751 *yscale = 0.f; 752 753 _GLFW_REQUIRE_INIT(); 754 _glfw.platform.getWindowContentScale(window, xscale, yscale); 755 } 756 757 GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle) 758 { 759 _GLFWwindow* window = (_GLFWwindow*) handle; 760 assert(window != NULL); 761 762 _GLFW_REQUIRE_INIT_OR_RETURN(0.f); 763 return _glfw.platform.getWindowOpacity(window); 764 } 765 766 GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) 767 { 768 _GLFWwindow* window = (_GLFWwindow*) handle; 769 assert(window != NULL); 770 assert(opacity == opacity); 771 assert(opacity >= 0.f); 772 assert(opacity <= 1.f); 773 774 _GLFW_REQUIRE_INIT(); 775 776 if (opacity != opacity || opacity < 0.f || opacity > 1.f) 777 { 778 _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity); 779 return; 780 } 781 782 _glfw.platform.setWindowOpacity(window, opacity); 783 } 784 785 GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) 786 { 787 _GLFWwindow* window = (_GLFWwindow*) handle; 788 assert(window != NULL); 789 790 _GLFW_REQUIRE_INIT(); 791 _glfw.platform.iconifyWindow(window); 792 } 793 794 GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) 795 { 796 _GLFWwindow* window = (_GLFWwindow*) handle; 797 assert(window != NULL); 798 799 _GLFW_REQUIRE_INIT(); 800 _glfw.platform.restoreWindow(window); 801 } 802 803 GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) 804 { 805 _GLFWwindow* window = (_GLFWwindow*) handle; 806 assert(window != NULL); 807 808 _GLFW_REQUIRE_INIT(); 809 810 if (window->monitor) 811 return; 812 813 _glfw.platform.maximizeWindow(window); 814 } 815 816 GLFWAPI void glfwShowWindow(GLFWwindow* handle) 817 { 818 _GLFWwindow* window = (_GLFWwindow*) handle; 819 assert(window != NULL); 820 821 _GLFW_REQUIRE_INIT(); 822 823 if (window->monitor) 824 return; 825 826 _glfw.platform.showWindow(window); 827 828 if (window->focusOnShow) 829 _glfw.platform.focusWindow(window); 830 } 831 832 GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) 833 { 834 _GLFWwindow* window = (_GLFWwindow*) handle; 835 assert(window != NULL); 836 837 _GLFW_REQUIRE_INIT(); 838 839 _glfw.platform.requestWindowAttention(window); 840 } 841 842 GLFWAPI void glfwHideWindow(GLFWwindow* handle) 843 { 844 _GLFWwindow* window = (_GLFWwindow*) handle; 845 assert(window != NULL); 846 847 _GLFW_REQUIRE_INIT(); 848 849 if (window->monitor) 850 return; 851 852 _glfw.platform.hideWindow(window); 853 } 854 855 GLFWAPI void glfwFocusWindow(GLFWwindow* handle) 856 { 857 _GLFWwindow* window = (_GLFWwindow*) handle; 858 assert(window != NULL); 859 860 _GLFW_REQUIRE_INIT(); 861 862 _glfw.platform.focusWindow(window); 863 } 864 865 GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) 866 { 867 _GLFWwindow* window = (_GLFWwindow*) handle; 868 assert(window != NULL); 869 870 _GLFW_REQUIRE_INIT_OR_RETURN(0); 871 872 switch (attrib) 873 { 874 case GLFW_FOCUSED: 875 return _glfw.platform.windowFocused(window); 876 case GLFW_ICONIFIED: 877 return _glfw.platform.windowIconified(window); 878 case GLFW_VISIBLE: 879 return _glfw.platform.windowVisible(window); 880 case GLFW_MAXIMIZED: 881 return _glfw.platform.windowMaximized(window); 882 case GLFW_HOVERED: 883 return _glfw.platform.windowHovered(window); 884 case GLFW_FOCUS_ON_SHOW: 885 return window->focusOnShow; 886 case GLFW_MOUSE_PASSTHROUGH: 887 return window->mousePassthrough; 888 case GLFW_TRANSPARENT_FRAMEBUFFER: 889 return _glfw.platform.framebufferTransparent(window); 890 case GLFW_RESIZABLE: 891 return window->resizable; 892 case GLFW_DECORATED: 893 return window->decorated; 894 case GLFW_FLOATING: 895 return window->floating; 896 case GLFW_AUTO_ICONIFY: 897 return window->autoIconify; 898 case GLFW_DOUBLEBUFFER: 899 return window->doublebuffer; 900 case GLFW_CLIENT_API: 901 return window->context.client; 902 case GLFW_CONTEXT_CREATION_API: 903 return window->context.source; 904 case GLFW_CONTEXT_VERSION_MAJOR: 905 return window->context.major; 906 case GLFW_CONTEXT_VERSION_MINOR: 907 return window->context.minor; 908 case GLFW_CONTEXT_REVISION: 909 return window->context.revision; 910 case GLFW_CONTEXT_ROBUSTNESS: 911 return window->context.robustness; 912 case GLFW_OPENGL_FORWARD_COMPAT: 913 return window->context.forward; 914 case GLFW_CONTEXT_DEBUG: 915 return window->context.debug; 916 case GLFW_OPENGL_PROFILE: 917 return window->context.profile; 918 case GLFW_CONTEXT_RELEASE_BEHAVIOR: 919 return window->context.release; 920 case GLFW_CONTEXT_NO_ERROR: 921 return window->context.noerror; 922 } 923 924 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); 925 return 0; 926 } 927 928 GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) 929 { 930 _GLFWwindow* window = (_GLFWwindow*) handle; 931 assert(window != NULL); 932 933 _GLFW_REQUIRE_INIT(); 934 935 value = value ? GLFW_TRUE : GLFW_FALSE; 936 937 switch (attrib) 938 { 939 case GLFW_AUTO_ICONIFY: 940 window->autoIconify = value; 941 return; 942 943 case GLFW_RESIZABLE: 944 window->resizable = value; 945 if (!window->monitor) 946 _glfw.platform.setWindowResizable(window, value); 947 return; 948 949 case GLFW_DECORATED: 950 window->decorated = value; 951 if (!window->monitor) 952 _glfw.platform.setWindowDecorated(window, value); 953 return; 954 955 case GLFW_FLOATING: 956 window->floating = value; 957 if (!window->monitor) 958 _glfw.platform.setWindowFloating(window, value); 959 return; 960 961 case GLFW_FOCUS_ON_SHOW: 962 window->focusOnShow = value; 963 return; 964 965 case GLFW_MOUSE_PASSTHROUGH: 966 window->mousePassthrough = value; 967 _glfw.platform.setWindowMousePassthrough(window, value); 968 return; 969 } 970 971 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); 972 } 973 974 GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) 975 { 976 _GLFWwindow* window = (_GLFWwindow*) handle; 977 assert(window != NULL); 978 979 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 980 return (GLFWmonitor*) window->monitor; 981 } 982 983 GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, 984 GLFWmonitor* mh, 985 int xpos, int ypos, 986 int width, int height, 987 int refreshRate) 988 { 989 _GLFWwindow* window = (_GLFWwindow*) wh; 990 _GLFWmonitor* monitor = (_GLFWmonitor*) mh; 991 assert(window != NULL); 992 assert(width >= 0); 993 assert(height >= 0); 994 995 _GLFW_REQUIRE_INIT(); 996 997 if (width <= 0 || height <= 0) 998 { 999 _glfwInputError(GLFW_INVALID_VALUE, 1000 "Invalid window size %ix%i", 1001 width, height); 1002 return; 1003 } 1004 1005 if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE) 1006 { 1007 _glfwInputError(GLFW_INVALID_VALUE, 1008 "Invalid refresh rate %i", 1009 refreshRate); 1010 return; 1011 } 1012 1013 window->videoMode.width = width; 1014 window->videoMode.height = height; 1015 window->videoMode.refreshRate = refreshRate; 1016 1017 _glfw.platform.setWindowMonitor(window, monitor, 1018 xpos, ypos, width, height, 1019 refreshRate); 1020 } 1021 1022 GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) 1023 { 1024 _GLFWwindow* window = (_GLFWwindow*) handle; 1025 assert(window != NULL); 1026 1027 _GLFW_REQUIRE_INIT(); 1028 window->userPointer = pointer; 1029 } 1030 1031 GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) 1032 { 1033 _GLFWwindow* window = (_GLFWwindow*) handle; 1034 assert(window != NULL); 1035 1036 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1037 return window->userPointer; 1038 } 1039 1040 GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, 1041 GLFWwindowposfun cbfun) 1042 { 1043 _GLFWwindow* window = (_GLFWwindow*) handle; 1044 assert(window != NULL); 1045 1046 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1047 _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun); 1048 return cbfun; 1049 } 1050 1051 GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, 1052 GLFWwindowsizefun cbfun) 1053 { 1054 _GLFWwindow* window = (_GLFWwindow*) handle; 1055 assert(window != NULL); 1056 1057 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1058 _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun); 1059 return cbfun; 1060 } 1061 1062 GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, 1063 GLFWwindowclosefun cbfun) 1064 { 1065 _GLFWwindow* window = (_GLFWwindow*) handle; 1066 assert(window != NULL); 1067 1068 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1069 _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun); 1070 return cbfun; 1071 } 1072 1073 GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, 1074 GLFWwindowrefreshfun cbfun) 1075 { 1076 _GLFWwindow* window = (_GLFWwindow*) handle; 1077 assert(window != NULL); 1078 1079 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1080 _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun); 1081 return cbfun; 1082 } 1083 1084 GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, 1085 GLFWwindowfocusfun cbfun) 1086 { 1087 _GLFWwindow* window = (_GLFWwindow*) handle; 1088 assert(window != NULL); 1089 1090 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1091 _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun); 1092 return cbfun; 1093 } 1094 1095 GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, 1096 GLFWwindowiconifyfun cbfun) 1097 { 1098 _GLFWwindow* window = (_GLFWwindow*) handle; 1099 assert(window != NULL); 1100 1101 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1102 _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun); 1103 return cbfun; 1104 } 1105 1106 GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, 1107 GLFWwindowmaximizefun cbfun) 1108 { 1109 _GLFWwindow* window = (_GLFWwindow*) handle; 1110 assert(window != NULL); 1111 1112 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1113 _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun); 1114 return cbfun; 1115 } 1116 1117 GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, 1118 GLFWframebuffersizefun cbfun) 1119 { 1120 _GLFWwindow* window = (_GLFWwindow*) handle; 1121 assert(window != NULL); 1122 1123 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1124 _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun); 1125 return cbfun; 1126 } 1127 1128 GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle, 1129 GLFWwindowcontentscalefun cbfun) 1130 { 1131 _GLFWwindow* window = (_GLFWwindow*) handle; 1132 assert(window != NULL); 1133 1134 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1135 _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun); 1136 return cbfun; 1137 } 1138 1139 GLFWAPI void glfwPollEvents(void) 1140 { 1141 _GLFW_REQUIRE_INIT(); 1142 _glfw.platform.pollEvents(); 1143 } 1144 1145 GLFWAPI void glfwWaitEvents(void) 1146 { 1147 _GLFW_REQUIRE_INIT(); 1148 _glfw.platform.waitEvents(); 1149 } 1150 1151 GLFWAPI void glfwWaitEventsTimeout(double timeout) 1152 { 1153 _GLFW_REQUIRE_INIT(); 1154 assert(timeout == timeout); 1155 assert(timeout >= 0.0); 1156 assert(timeout <= DBL_MAX); 1157 1158 if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX) 1159 { 1160 _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout); 1161 return; 1162 } 1163 1164 _glfw.platform.waitEventsTimeout(timeout); 1165 } 1166 1167 GLFWAPI void glfwPostEmptyEvent(void) 1168 { 1169 _GLFW_REQUIRE_INIT(); 1170 _glfw.platform.postEmptyEvent(); 1171 } 1172