window.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //========================================================================
  2. // Window properties test
  3. // Copyright (c) Camilla Löwy <[email protected]>
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would
  16. // be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not
  19. // be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. //
  24. //========================================================================
  25. #define GLAD_GL_IMPLEMENTATION
  26. #include <glad/gl.h>
  27. #define GLFW_INCLUDE_NONE
  28. #include <GLFW/glfw3.h>
  29. #include <stdarg.h>
  30. #define NK_IMPLEMENTATION
  31. #define NK_INCLUDE_FIXED_TYPES
  32. #define NK_INCLUDE_FONT_BAKING
  33. #define NK_INCLUDE_DEFAULT_FONT
  34. #define NK_INCLUDE_DEFAULT_ALLOCATOR
  35. #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  36. #define NK_INCLUDE_STANDARD_VARARGS
  37. #define NK_BUTTON_TRIGGER_ON_RELEASE
  38. #include <nuklear.h>
  39. #define NK_GLFW_GL2_IMPLEMENTATION
  40. #include <nuklear_glfw_gl2.h>
  41. #include <stdbool.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <limits.h>
  45. int main(int argc, char** argv)
  46. {
  47. int windowed_x, windowed_y, windowed_width, windowed_height;
  48. int last_xpos = INT_MIN, last_ypos = INT_MIN;
  49. int last_width = INT_MIN, last_height = INT_MIN;
  50. int limit_aspect_ratio = false, aspect_numer = 1, aspect_denom = 1;
  51. int limit_min_size = false, min_width = 400, min_height = 400;
  52. int limit_max_size = false, max_width = 400, max_height = 400;
  53. char width_buffer[12] = "", height_buffer[12] = "";
  54. char xpos_buffer[12] = "", ypos_buffer[12] = "";
  55. char numer_buffer[12] = "", denom_buffer[12] = "";
  56. char min_width_buffer[12] = "", min_height_buffer[12] = "";
  57. char max_width_buffer[12] = "", max_height_buffer[12] = "";
  58. int may_close = true;
  59. char window_title[64] = "";
  60. if (!glfwInit())
  61. exit(EXIT_FAILURE);
  62. glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
  63. glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
  64. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  65. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
  66. GLFWwindow* window = glfwCreateWindow(600, 660, "Window Features", NULL, NULL);
  67. if (!window)
  68. {
  69. glfwTerminate();
  70. exit(EXIT_FAILURE);
  71. }
  72. glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE);
  73. glfwMakeContextCurrent(window);
  74. gladLoadGL(glfwGetProcAddress);
  75. glfwSwapInterval(0);
  76. bool position_supported = true;
  77. glfwGetError(NULL);
  78. glfwGetWindowPos(window, &last_xpos, &last_ypos);
  79. sprintf(xpos_buffer, "%i", last_xpos);
  80. sprintf(ypos_buffer, "%i", last_ypos);
  81. if (glfwGetError(NULL) == GLFW_FEATURE_UNAVAILABLE)
  82. position_supported = false;
  83. glfwGetWindowSize(window, &last_width, &last_height);
  84. sprintf(width_buffer, "%i", last_width);
  85. sprintf(height_buffer, "%i", last_height);
  86. sprintf(numer_buffer, "%i", aspect_numer);
  87. sprintf(denom_buffer, "%i", aspect_denom);
  88. sprintf(min_width_buffer, "%i", min_width);
  89. sprintf(min_height_buffer, "%i", min_height);
  90. sprintf(max_width_buffer, "%i", max_width);
  91. sprintf(max_height_buffer, "%i", max_height);
  92. struct nk_context* nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
  93. struct nk_font_atlas* atlas;
  94. nk_glfw3_font_stash_begin(&atlas);
  95. nk_glfw3_font_stash_end();
  96. strncpy(window_title, glfwGetWindowTitle(window), sizeof(window_title));
  97. while (!(may_close && glfwWindowShouldClose(window)))
  98. {
  99. int width, height;
  100. glfwGetWindowSize(window, &width, &height);
  101. struct nk_rect area = nk_rect(0.f, 0.f, (float) width, (float) height);
  102. nk_window_set_bounds(nk, "main", area);
  103. nk_glfw3_new_frame();
  104. if (nk_begin(nk, "main", area, 0))
  105. {
  106. nk_layout_row_dynamic(nk, 30, 4);
  107. if (glfwGetWindowMonitor(window))
  108. {
  109. if (nk_button_label(nk, "Make Windowed"))
  110. {
  111. glfwSetWindowMonitor(window, NULL,
  112. windowed_x, windowed_y,
  113. windowed_width, windowed_height, 0);
  114. }
  115. }
  116. else
  117. {
  118. if (nk_button_label(nk, "Make Fullscreen"))
  119. {
  120. GLFWmonitor* monitor = glfwGetPrimaryMonitor();
  121. const GLFWvidmode* mode = glfwGetVideoMode(monitor);
  122. glfwGetWindowPos(window, &windowed_x, &windowed_y);
  123. glfwGetWindowSize(window, &windowed_width, &windowed_height);
  124. glfwSetWindowMonitor(window, monitor,
  125. 0, 0, mode->width, mode->height,
  126. mode->refreshRate);
  127. }
  128. }
  129. if (nk_button_label(nk, "Maximize"))
  130. glfwMaximizeWindow(window);
  131. if (nk_button_label(nk, "Iconify"))
  132. glfwIconifyWindow(window);
  133. if (nk_button_label(nk, "Restore"))
  134. glfwRestoreWindow(window);
  135. nk_layout_row_dynamic(nk, 30, 2);
  136. if (nk_button_label(nk, "Hide (for 3s)"))
  137. {
  138. glfwHideWindow(window);
  139. const double time = glfwGetTime() + 3.0;
  140. while (glfwGetTime() < time)
  141. glfwWaitEventsTimeout(1.0);
  142. glfwShowWindow(window);
  143. }
  144. if (nk_button_label(nk, "Request Attention (after 3s)"))
  145. {
  146. glfwIconifyWindow(window);
  147. const double time = glfwGetTime() + 3.0;
  148. while (glfwGetTime() < time)
  149. glfwWaitEventsTimeout(1.0);
  150. glfwRequestWindowAttention(window);
  151. }
  152. nk_layout_row_dynamic(nk, 30, 1);
  153. if (glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH))
  154. {
  155. nk_label(nk, "Press H to disable mouse passthrough", NK_TEXT_CENTERED);
  156. if (glfwGetKey(window, GLFW_KEY_H))
  157. glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, false);
  158. }
  159. nk_label(nk, "Press Enter in a text field to set value", NK_TEXT_CENTERED);
  160. nk_flags events;
  161. const nk_flags flags = NK_EDIT_FIELD |
  162. NK_EDIT_SIG_ENTER |
  163. NK_EDIT_GOTO_END_ON_ACTIVATE;
  164. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
  165. nk_layout_row_push(nk, 1.f / 3.f);
  166. nk_label(nk, "Title", NK_TEXT_LEFT);
  167. nk_layout_row_push(nk, 2.f / 3.f);
  168. events = nk_edit_string_zero_terminated(nk, flags, window_title,
  169. sizeof(window_title), NULL);
  170. if (events & NK_EDIT_COMMITED)
  171. glfwSetWindowTitle(window, window_title);
  172. nk_layout_row_end(nk);
  173. if (position_supported)
  174. {
  175. int xpos, ypos;
  176. glfwGetWindowPos(window, &xpos, &ypos);
  177. nk_layout_row_dynamic(nk, 30, 3);
  178. nk_label(nk, "Position", NK_TEXT_LEFT);
  179. events = nk_edit_string_zero_terminated(nk, flags, xpos_buffer,
  180. sizeof(xpos_buffer),
  181. nk_filter_decimal);
  182. if (events & NK_EDIT_COMMITED)
  183. {
  184. xpos = atoi(xpos_buffer);
  185. glfwSetWindowPos(window, xpos, ypos);
  186. }
  187. else if (xpos != last_xpos || (events & NK_EDIT_DEACTIVATED))
  188. sprintf(xpos_buffer, "%i", xpos);
  189. events = nk_edit_string_zero_terminated(nk, flags, ypos_buffer,
  190. sizeof(ypos_buffer),
  191. nk_filter_decimal);
  192. if (events & NK_EDIT_COMMITED)
  193. {
  194. ypos = atoi(ypos_buffer);
  195. glfwSetWindowPos(window, xpos, ypos);
  196. }
  197. else if (ypos != last_ypos || (events & NK_EDIT_DEACTIVATED))
  198. sprintf(ypos_buffer, "%i", ypos);
  199. last_xpos = xpos;
  200. last_ypos = ypos;
  201. }
  202. else
  203. nk_label(nk, "Platform does not support window position", NK_TEXT_LEFT);
  204. nk_layout_row_dynamic(nk, 30, 3);
  205. nk_label(nk, "Size", NK_TEXT_LEFT);
  206. events = nk_edit_string_zero_terminated(nk, flags, width_buffer,
  207. sizeof(width_buffer),
  208. nk_filter_decimal);
  209. if (events & NK_EDIT_COMMITED)
  210. {
  211. width = atoi(width_buffer);
  212. glfwSetWindowSize(window, width, height);
  213. }
  214. else if (width != last_width || (events & NK_EDIT_DEACTIVATED))
  215. sprintf(width_buffer, "%i", width);
  216. events = nk_edit_string_zero_terminated(nk, flags, height_buffer,
  217. sizeof(height_buffer),
  218. nk_filter_decimal);
  219. if (events & NK_EDIT_COMMITED)
  220. {
  221. height = atoi(height_buffer);
  222. glfwSetWindowSize(window, width, height);
  223. }
  224. else if (height != last_height || (events & NK_EDIT_DEACTIVATED))
  225. sprintf(height_buffer, "%i", height);
  226. last_width = width;
  227. last_height = height;
  228. bool update_ratio_limit = false;
  229. if (nk_checkbox_label(nk, "Aspect Ratio", &limit_aspect_ratio))
  230. update_ratio_limit = true;
  231. events = nk_edit_string_zero_terminated(nk, flags, numer_buffer,
  232. sizeof(numer_buffer),
  233. nk_filter_decimal);
  234. if (events & NK_EDIT_COMMITED)
  235. {
  236. aspect_numer = abs(atoi(numer_buffer));
  237. update_ratio_limit = true;
  238. }
  239. else if (events & NK_EDIT_DEACTIVATED)
  240. sprintf(numer_buffer, "%i", aspect_numer);
  241. events = nk_edit_string_zero_terminated(nk, flags, denom_buffer,
  242. sizeof(denom_buffer),
  243. nk_filter_decimal);
  244. if (events & NK_EDIT_COMMITED)
  245. {
  246. aspect_denom = abs(atoi(denom_buffer));
  247. update_ratio_limit = true;
  248. }
  249. else if (events & NK_EDIT_DEACTIVATED)
  250. sprintf(denom_buffer, "%i", aspect_denom);
  251. if (update_ratio_limit)
  252. {
  253. if (limit_aspect_ratio)
  254. glfwSetWindowAspectRatio(window, aspect_numer, aspect_denom);
  255. else
  256. glfwSetWindowAspectRatio(window, GLFW_DONT_CARE, GLFW_DONT_CARE);
  257. }
  258. bool update_size_limit = false;
  259. if (nk_checkbox_label(nk, "Minimum Size", &limit_min_size))
  260. update_size_limit = true;
  261. events = nk_edit_string_zero_terminated(nk, flags, min_width_buffer,
  262. sizeof(min_width_buffer),
  263. nk_filter_decimal);
  264. if (events & NK_EDIT_COMMITED)
  265. {
  266. min_width = abs(atoi(min_width_buffer));
  267. update_size_limit = true;
  268. }
  269. else if (events & NK_EDIT_DEACTIVATED)
  270. sprintf(min_width_buffer, "%i", min_width);
  271. events = nk_edit_string_zero_terminated(nk, flags, min_height_buffer,
  272. sizeof(min_height_buffer),
  273. nk_filter_decimal);
  274. if (events & NK_EDIT_COMMITED)
  275. {
  276. min_height = abs(atoi(min_height_buffer));
  277. update_size_limit = true;
  278. }
  279. else if (events & NK_EDIT_DEACTIVATED)
  280. sprintf(min_height_buffer, "%i", min_height);
  281. if (nk_checkbox_label(nk, "Maximum Size", &limit_max_size))
  282. update_size_limit = true;
  283. events = nk_edit_string_zero_terminated(nk, flags, max_width_buffer,
  284. sizeof(max_width_buffer),
  285. nk_filter_decimal);
  286. if (events & NK_EDIT_COMMITED)
  287. {
  288. max_width = abs(atoi(max_width_buffer));
  289. update_size_limit = true;
  290. }
  291. else if (events & NK_EDIT_DEACTIVATED)
  292. sprintf(max_width_buffer, "%i", max_width);
  293. events = nk_edit_string_zero_terminated(nk, flags, max_height_buffer,
  294. sizeof(max_height_buffer),
  295. nk_filter_decimal);
  296. if (events & NK_EDIT_COMMITED)
  297. {
  298. max_height = abs(atoi(max_height_buffer));
  299. update_size_limit = true;
  300. }
  301. else if (events & NK_EDIT_DEACTIVATED)
  302. sprintf(max_height_buffer, "%i", max_height);
  303. if (update_size_limit)
  304. {
  305. glfwSetWindowSizeLimits(window,
  306. limit_min_size ? min_width : GLFW_DONT_CARE,
  307. limit_min_size ? min_height : GLFW_DONT_CARE,
  308. limit_max_size ? max_width : GLFW_DONT_CARE,
  309. limit_max_size ? max_height : GLFW_DONT_CARE);
  310. }
  311. int fb_width, fb_height;
  312. glfwGetFramebufferSize(window, &fb_width, &fb_height);
  313. nk_label(nk, "Framebuffer Size", NK_TEXT_LEFT);
  314. nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_width);
  315. nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_height);
  316. float xscale, yscale;
  317. glfwGetWindowContentScale(window, &xscale, &yscale);
  318. nk_label(nk, "Content Scale", NK_TEXT_LEFT);
  319. nk_labelf(nk, NK_TEXT_LEFT, "%f", xscale);
  320. nk_labelf(nk, NK_TEXT_LEFT, "%f", yscale);
  321. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 5);
  322. int frame_left, frame_top, frame_right, frame_bottom;
  323. glfwGetWindowFrameSize(window, &frame_left, &frame_top, &frame_right, &frame_bottom);
  324. nk_layout_row_push(nk, 1.f / 3.f);
  325. nk_label(nk, "Frame Size:", NK_TEXT_LEFT);
  326. nk_layout_row_push(nk, 1.f / 6.f);
  327. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_left);
  328. nk_layout_row_push(nk, 1.f / 6.f);
  329. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_top);
  330. nk_layout_row_push(nk, 1.f / 6.f);
  331. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_right);
  332. nk_layout_row_push(nk, 1.f / 6.f);
  333. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_bottom);
  334. nk_layout_row_end(nk);
  335. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
  336. float opacity = glfwGetWindowOpacity(window);
  337. nk_layout_row_push(nk, 1.f / 3.f);
  338. nk_labelf(nk, NK_TEXT_LEFT, "Opacity: %0.3f", opacity);
  339. nk_layout_row_push(nk, 2.f / 3.f);
  340. if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f))
  341. glfwSetWindowOpacity(window, opacity);
  342. nk_layout_row_end(nk);
  343. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
  344. int should_close = glfwWindowShouldClose(window);
  345. nk_layout_row_push(nk, 1.f / 3.f);
  346. if (nk_checkbox_label(nk, "Should Close", &should_close))
  347. glfwSetWindowShouldClose(window, should_close);
  348. nk_layout_row_push(nk, 2.f / 3.f);
  349. nk_checkbox_label(nk, "May Close", &may_close);
  350. nk_layout_row_end(nk);
  351. nk_layout_row_dynamic(nk, 30, 1);
  352. nk_label(nk, "Attributes", NK_TEXT_CENTERED);
  353. nk_layout_row_dynamic(nk, 30, width > 200 ? width / 200 : 1);
  354. int decorated = glfwGetWindowAttrib(window, GLFW_DECORATED);
  355. if (nk_checkbox_label(nk, "Decorated", &decorated))
  356. glfwSetWindowAttrib(window, GLFW_DECORATED, decorated);
  357. int resizable = glfwGetWindowAttrib(window, GLFW_RESIZABLE);
  358. if (nk_checkbox_label(nk, "Resizable", &resizable))
  359. glfwSetWindowAttrib(window, GLFW_RESIZABLE, resizable);
  360. int floating = glfwGetWindowAttrib(window, GLFW_FLOATING);
  361. if (nk_checkbox_label(nk, "Floating", &floating))
  362. glfwSetWindowAttrib(window, GLFW_FLOATING, floating);
  363. int passthrough = glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH);
  364. if (nk_checkbox_label(nk, "Mouse Passthrough", &passthrough))
  365. glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, passthrough);
  366. int auto_iconify = glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY);
  367. if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify))
  368. glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify);
  369. nk_value_bool(nk, "Focused", glfwGetWindowAttrib(window, GLFW_FOCUSED));
  370. nk_value_bool(nk, "Hovered", glfwGetWindowAttrib(window, GLFW_HOVERED));
  371. nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE));
  372. nk_value_bool(nk, "Iconified", glfwGetWindowAttrib(window, GLFW_ICONIFIED));
  373. nk_value_bool(nk, "Maximized", glfwGetWindowAttrib(window, GLFW_MAXIMIZED));
  374. }
  375. nk_end(nk);
  376. glClear(GL_COLOR_BUFFER_BIT);
  377. nk_glfw3_render(NK_ANTI_ALIASING_ON);
  378. glfwSwapBuffers(window);
  379. glfwWaitEvents();
  380. }
  381. nk_glfw3_shutdown();
  382. glfwTerminate();
  383. exit(EXIT_SUCCESS);
  384. }