window.c 32 KB

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