1//======================================================================== 2// GLFW 3.5 - 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// 43void _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// 75void _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// 86void _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// 98void _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// 109void _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// 121void _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// 134void _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// 148void _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// 158void _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// 170void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) 171{ 172 assert(window != NULL); 173 window->monitor = monitor; 174} 175 176////////////////////////////////////////////////////////////////////////// 177////// GLFW public API ////// 178////////////////////////////////////////////////////////////////////////// 179 180GLFWAPI 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 256void 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 295GLFWAPI 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 439GLFWAPI 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 468GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) 469{ 470 _GLFW_REQUIRE_INIT(); 471 472 _GLFWwindow* window = (_GLFWwindow*) handle; 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 502GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) 503{ 504 _GLFW_REQUIRE_INIT_OR_RETURN(0); 505 506 _GLFWwindow* window = (_GLFWwindow*) handle; 507 assert(window != NULL); 508 509 return window->shouldClose; 510} 511 512GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) 513{ 514 _GLFW_REQUIRE_INIT(); 515 516 _GLFWwindow* window = (_GLFWwindow*) handle; 517 assert(window != NULL); 518 519 window->shouldClose = value; 520} 521 522GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle) 523{ 524 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 525 526 _GLFWwindow* window = (_GLFWwindow*) handle; 527 assert(window != NULL); 528 529 return window->title; 530} 531 532GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) 533{ 534 assert(title != NULL); 535 536 _GLFW_REQUIRE_INIT(); 537 538 _GLFWwindow* window = (_GLFWwindow*) handle; 539 assert(window != NULL); 540 541 char* prev = window->title; 542 window->title = _glfw_strdup(title); 543 544 _glfw.platform.setWindowTitle(window, title); 545 _glfw_free(prev); 546} 547 548GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, 549 int count, const GLFWimage* images) 550{ 551 int i; 552 553 assert(count >= 0); 554 assert(count == 0 || images != NULL); 555 556 _GLFW_REQUIRE_INIT(); 557 558 _GLFWwindow* window = (_GLFWwindow*) handle; 559 assert(window != NULL); 560 561 if (count < 0) 562 { 563 _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon"); 564 return; 565 } 566 567 for (i = 0; i < count; i++) 568 { 569 assert(images[i].pixels != NULL); 570 571 if (images[i].width <= 0 || images[i].height <= 0) 572 { 573 _glfwInputError(GLFW_INVALID_VALUE, 574 "Invalid image dimensions for window icon"); 575 return; 576 } 577 } 578 579 _glfw.platform.setWindowIcon(window, count, images); 580} 581 582GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) 583{ 584 if (xpos) 585 *xpos = 0; 586 if (ypos) 587 *ypos = 0; 588 589 _GLFW_REQUIRE_INIT(); 590 591 _GLFWwindow* window = (_GLFWwindow*) handle; 592 assert(window != NULL); 593 594 _glfw.platform.getWindowPos(window, xpos, ypos); 595} 596 597GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) 598{ 599 _GLFW_REQUIRE_INIT(); 600 601 _GLFWwindow* window = (_GLFWwindow*) handle; 602 assert(window != NULL); 603 604 if (window->monitor) 605 return; 606 607 _glfw.platform.setWindowPos(window, xpos, ypos); 608} 609 610GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) 611{ 612 if (width) 613 *width = 0; 614 if (height) 615 *height = 0; 616 617 _GLFW_REQUIRE_INIT(); 618 619 _GLFWwindow* window = (_GLFWwindow*) handle; 620 assert(window != NULL); 621 622 _glfw.platform.getWindowSize(window, width, height); 623} 624 625GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) 626{ 627 assert(width >= 0); 628 assert(height >= 0); 629 630 _GLFW_REQUIRE_INIT(); 631 632 _GLFWwindow* window = (_GLFWwindow*) handle; 633 assert(window != NULL); 634 635 window->videoMode.width = width; 636 window->videoMode.height = height; 637 638 _glfw.platform.setWindowSize(window, width, height); 639} 640 641GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, 642 int minwidth, int minheight, 643 int maxwidth, int maxheight) 644{ 645 _GLFW_REQUIRE_INIT(); 646 647 _GLFWwindow* window = (_GLFWwindow*) handle; 648 assert(window != NULL); 649 650 if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) 651 { 652 if (minwidth < 0 || minheight < 0) 653 { 654 _glfwInputError(GLFW_INVALID_VALUE, 655 "Invalid window minimum size %ix%i", 656 minwidth, minheight); 657 return; 658 } 659 } 660 661 if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE) 662 { 663 if (maxwidth < 0 || maxheight < 0 || 664 maxwidth < minwidth || maxheight < minheight) 665 { 666 _glfwInputError(GLFW_INVALID_VALUE, 667 "Invalid window maximum size %ix%i", 668 maxwidth, maxheight); 669 return; 670 } 671 } 672 673 window->minwidth = minwidth; 674 window->minheight = minheight; 675 window->maxwidth = maxwidth; 676 window->maxheight = maxheight; 677 678 if (window->monitor || !window->resizable) 679 return; 680 681 _glfw.platform.setWindowSizeLimits(window, 682 minwidth, minheight, 683 maxwidth, maxheight); 684} 685 686GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) 687{ 688 assert(numer != 0); 689 assert(denom != 0); 690 691 _GLFW_REQUIRE_INIT(); 692 693 _GLFWwindow* window = (_GLFWwindow*) handle; 694 assert(window != NULL); 695 696 if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) 697 { 698 if (numer <= 0 || denom <= 0) 699 { 700 _glfwInputError(GLFW_INVALID_VALUE, 701 "Invalid window aspect ratio %i:%i", 702 numer, denom); 703 return; 704 } 705 } 706 707 window->numer = numer; 708 window->denom = denom; 709 710 if (window->monitor || !window->resizable) 711 return; 712 713 _glfw.platform.setWindowAspectRatio(window, numer, denom); 714} 715 716GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) 717{ 718 if (width) 719 *width = 0; 720 if (height) 721 *height = 0; 722 723 _GLFW_REQUIRE_INIT(); 724 725 _GLFWwindow* window = (_GLFWwindow*) handle; 726 assert(window != NULL); 727 728 _glfw.platform.getFramebufferSize(window, width, height); 729} 730 731GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, 732 int* left, int* top, 733 int* right, int* bottom) 734{ 735 if (left) 736 *left = 0; 737 if (top) 738 *top = 0; 739 if (right) 740 *right = 0; 741 if (bottom) 742 *bottom = 0; 743 744 _GLFW_REQUIRE_INIT(); 745 746 _GLFWwindow* window = (_GLFWwindow*) handle; 747 assert(window != NULL); 748 749 _glfw.platform.getWindowFrameSize(window, left, top, right, bottom); 750} 751 752GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, 753 float* xscale, float* yscale) 754{ 755 if (xscale) 756 *xscale = 0.f; 757 if (yscale) 758 *yscale = 0.f; 759 760 _GLFW_REQUIRE_INIT(); 761 762 _GLFWwindow* window = (_GLFWwindow*) handle; 763 assert(window != NULL); 764 765 _glfw.platform.getWindowContentScale(window, xscale, yscale); 766} 767 768GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle) 769{ 770 _GLFW_REQUIRE_INIT_OR_RETURN(0.f); 771 772 _GLFWwindow* window = (_GLFWwindow*) handle; 773 assert(window != NULL); 774 775 return _glfw.platform.getWindowOpacity(window); 776} 777 778GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) 779{ 780 assert(opacity == opacity); 781 assert(opacity >= 0.f); 782 assert(opacity <= 1.f); 783 784 _GLFW_REQUIRE_INIT(); 785 786 _GLFWwindow* window = (_GLFWwindow*) handle; 787 assert(window != NULL); 788 789 if (opacity != opacity || opacity < 0.f || opacity > 1.f) 790 { 791 _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity); 792 return; 793 } 794 795 _glfw.platform.setWindowOpacity(window, opacity); 796} 797 798GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) 799{ 800 _GLFW_REQUIRE_INIT(); 801 802 _GLFWwindow* window = (_GLFWwindow*) handle; 803 assert(window != NULL); 804 805 _glfw.platform.iconifyWindow(window); 806} 807 808GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) 809{ 810 _GLFW_REQUIRE_INIT(); 811 812 _GLFWwindow* window = (_GLFWwindow*) handle; 813 assert(window != NULL); 814 815 _glfw.platform.restoreWindow(window); 816} 817 818GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) 819{ 820 _GLFW_REQUIRE_INIT(); 821 822 _GLFWwindow* window = (_GLFWwindow*) handle; 823 assert(window != NULL); 824 825 if (window->monitor) 826 return; 827 828 _glfw.platform.maximizeWindow(window); 829} 830 831GLFWAPI void glfwShowWindow(GLFWwindow* handle) 832{ 833 _GLFW_REQUIRE_INIT(); 834 835 _GLFWwindow* window = (_GLFWwindow*) handle; 836 assert(window != NULL); 837 838 if (window->monitor) 839 return; 840 841 _glfw.platform.showWindow(window); 842 843 if (window->focusOnShow) 844 _glfw.platform.focusWindow(window); 845} 846 847GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) 848{ 849 _GLFW_REQUIRE_INIT(); 850 851 _GLFWwindow* window = (_GLFWwindow*) handle; 852 assert(window != NULL); 853 854 _glfw.platform.requestWindowAttention(window); 855} 856 857GLFWAPI void glfwHideWindow(GLFWwindow* handle) 858{ 859 _GLFW_REQUIRE_INIT(); 860 861 _GLFWwindow* window = (_GLFWwindow*) handle; 862 assert(window != NULL); 863 864 if (window->monitor) 865 return; 866 867 _glfw.platform.hideWindow(window); 868} 869 870GLFWAPI void glfwFocusWindow(GLFWwindow* handle) 871{ 872 _GLFW_REQUIRE_INIT(); 873 874 _GLFWwindow* window = (_GLFWwindow*) handle; 875 assert(window != NULL); 876 877 _glfw.platform.focusWindow(window); 878} 879 880GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) 881{ 882 _GLFW_REQUIRE_INIT_OR_RETURN(0); 883 884 _GLFWwindow* window = (_GLFWwindow*) handle; 885 assert(window != NULL); 886 887 switch (attrib) 888 { 889 case GLFW_FOCUSED: 890 return _glfw.platform.windowFocused(window); 891 case GLFW_ICONIFIED: 892 return _glfw.platform.windowIconified(window); 893 case GLFW_VISIBLE: 894 return _glfw.platform.windowVisible(window); 895 case GLFW_MAXIMIZED: 896 return _glfw.platform.windowMaximized(window); 897 case GLFW_HOVERED: 898 return _glfw.platform.windowHovered(window); 899 case GLFW_FOCUS_ON_SHOW: 900 return window->focusOnShow; 901 case GLFW_MOUSE_PASSTHROUGH: 902 return window->mousePassthrough; 903 case GLFW_TRANSPARENT_FRAMEBUFFER: 904 return _glfw.platform.framebufferTransparent(window); 905 case GLFW_RESIZABLE: 906 return window->resizable; 907 case GLFW_DECORATED: 908 return window->decorated; 909 case GLFW_FLOATING: 910 return window->floating; 911 case GLFW_AUTO_ICONIFY: 912 return window->autoIconify; 913 case GLFW_DOUBLEBUFFER: 914 return window->doublebuffer; 915 case GLFW_CLIENT_API: 916 return window->context.client; 917 case GLFW_CONTEXT_CREATION_API: 918 return window->context.source; 919 case GLFW_CONTEXT_VERSION_MAJOR: 920 return window->context.major; 921 case GLFW_CONTEXT_VERSION_MINOR: 922 return window->context.minor; 923 case GLFW_CONTEXT_REVISION: 924 return window->context.revision; 925 case GLFW_CONTEXT_ROBUSTNESS: 926 return window->context.robustness; 927 case GLFW_OPENGL_FORWARD_COMPAT: 928 return window->context.forward; 929 case GLFW_CONTEXT_DEBUG: 930 return window->context.debug; 931 case GLFW_OPENGL_PROFILE: 932 return window->context.profile; 933 case GLFW_CONTEXT_RELEASE_BEHAVIOR: 934 return window->context.release; 935 case GLFW_CONTEXT_NO_ERROR: 936 return window->context.noerror; 937 } 938 939 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); 940 return 0; 941} 942 943GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) 944{ 945 _GLFW_REQUIRE_INIT(); 946 947 _GLFWwindow* window = (_GLFWwindow*) handle; 948 assert(window != NULL); 949 950 value = value ? GLFW_TRUE : GLFW_FALSE; 951 952 switch (attrib) 953 { 954 case GLFW_AUTO_ICONIFY: 955 window->autoIconify = value; 956 return; 957 958 case GLFW_RESIZABLE: 959 window->resizable = value; 960 if (!window->monitor) 961 _glfw.platform.setWindowResizable(window, value); 962 return; 963 964 case GLFW_DECORATED: 965 window->decorated = value; 966 if (!window->monitor) 967 _glfw.platform.setWindowDecorated(window, value); 968 return; 969 970 case GLFW_FLOATING: 971 window->floating = value; 972 if (!window->monitor) 973 _glfw.platform.setWindowFloating(window, value); 974 return; 975 976 case GLFW_FOCUS_ON_SHOW: 977 window->focusOnShow = value; 978 return; 979 980 case GLFW_MOUSE_PASSTHROUGH: 981 window->mousePassthrough = value; 982 _glfw.platform.setWindowMousePassthrough(window, value); 983 return; 984 } 985 986 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); 987} 988 989GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) 990{ 991 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 992 993 _GLFWwindow* window = (_GLFWwindow*) handle; 994 assert(window != NULL); 995 996 return (GLFWmonitor*) window->monitor; 997} 998 999GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, 1000 GLFWmonitor* mh, 1001 int xpos, int ypos, 1002 int width, int height, 1003 int refreshRate) 1004{ 1005 assert(width >= 0); 1006 assert(height >= 0); 1007 1008 _GLFW_REQUIRE_INIT(); 1009 1010 _GLFWwindow* window = (_GLFWwindow*) wh; 1011 _GLFWmonitor* monitor = (_GLFWmonitor*) mh; 1012 assert(window != NULL); 1013 1014 if (width <= 0 || height <= 0) 1015 { 1016 _glfwInputError(GLFW_INVALID_VALUE, 1017 "Invalid window size %ix%i", 1018 width, height); 1019 return; 1020 } 1021 1022 if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE) 1023 { 1024 _glfwInputError(GLFW_INVALID_VALUE, 1025 "Invalid refresh rate %i", 1026 refreshRate); 1027 return; 1028 } 1029 1030 window->videoMode.width = width; 1031 window->videoMode.height = height; 1032 window->videoMode.refreshRate = refreshRate; 1033 1034 _glfw.platform.setWindowMonitor(window, monitor, 1035 xpos, ypos, width, height, 1036 refreshRate); 1037} 1038 1039GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) 1040{ 1041 _GLFW_REQUIRE_INIT(); 1042 1043 _GLFWwindow* window = (_GLFWwindow*) handle; 1044 assert(window != NULL); 1045 1046 window->userPointer = pointer; 1047} 1048 1049GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) 1050{ 1051 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1052 1053 _GLFWwindow* window = (_GLFWwindow*) handle; 1054 assert(window != NULL); 1055 1056 return window->userPointer; 1057} 1058 1059GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, 1060 GLFWwindowposfun cbfun) 1061{ 1062 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1063 1064 _GLFWwindow* window = (_GLFWwindow*) handle; 1065 assert(window != NULL); 1066 1067 _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun); 1068 return cbfun; 1069} 1070 1071GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, 1072 GLFWwindowsizefun cbfun) 1073{ 1074 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1075 1076 _GLFWwindow* window = (_GLFWwindow*) handle; 1077 assert(window != NULL); 1078 1079 _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun); 1080 return cbfun; 1081} 1082 1083GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, 1084 GLFWwindowclosefun cbfun) 1085{ 1086 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1087 1088 _GLFWwindow* window = (_GLFWwindow*) handle; 1089 assert(window != NULL); 1090 1091 _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun); 1092 return cbfun; 1093} 1094 1095GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, 1096 GLFWwindowrefreshfun cbfun) 1097{ 1098 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1099 1100 _GLFWwindow* window = (_GLFWwindow*) handle; 1101 assert(window != NULL); 1102 1103 _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun); 1104 return cbfun; 1105} 1106 1107GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, 1108 GLFWwindowfocusfun cbfun) 1109{ 1110 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1111 1112 _GLFWwindow* window = (_GLFWwindow*) handle; 1113 assert(window != NULL); 1114 1115 _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun); 1116 return cbfun; 1117} 1118 1119GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, 1120 GLFWwindowiconifyfun cbfun) 1121{ 1122 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1123 1124 _GLFWwindow* window = (_GLFWwindow*) handle; 1125 assert(window != NULL); 1126 1127 _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun); 1128 return cbfun; 1129} 1130 1131GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, 1132 GLFWwindowmaximizefun cbfun) 1133{ 1134 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1135 1136 _GLFWwindow* window = (_GLFWwindow*) handle; 1137 assert(window != NULL); 1138 1139 _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun); 1140 return cbfun; 1141} 1142 1143GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, 1144 GLFWframebuffersizefun cbfun) 1145{ 1146 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1147 1148 _GLFWwindow* window = (_GLFWwindow*) handle; 1149 assert(window != NULL); 1150 1151 _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun); 1152 return cbfun; 1153} 1154 1155GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle, 1156 GLFWwindowcontentscalefun cbfun) 1157{ 1158 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1159 1160 _GLFWwindow* window = (_GLFWwindow*) handle; 1161 assert(window != NULL); 1162 1163 _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun); 1164 return cbfun; 1165} 1166 1167GLFWAPI void glfwPollEvents(void) 1168{ 1169 _GLFW_REQUIRE_INIT(); 1170 _glfw.platform.pollEvents(); 1171} 1172 1173GLFWAPI void glfwWaitEvents(void) 1174{ 1175 _GLFW_REQUIRE_INIT(); 1176 _glfw.platform.waitEvents(); 1177} 1178 1179GLFWAPI void glfwWaitEventsTimeout(double timeout) 1180{ 1181 _GLFW_REQUIRE_INIT(); 1182 assert(timeout == timeout); 1183 assert(timeout >= 0.0); 1184 assert(timeout <= DBL_MAX); 1185 1186 if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX) 1187 { 1188 _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout); 1189 return; 1190 } 1191 1192 _glfw.platform.waitEventsTimeout(timeout); 1193} 1194 1195GLFWAPI void glfwPostEmptyEvent(void) 1196{ 1197 _GLFW_REQUIRE_INIT(); 1198 _glfw.platform.postEmptyEvent(); 1199} 1200 1201