window.c 36 KB

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