window.c 37 KB

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