window.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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. glfwMakeContextCurrent(window);
  73. gladLoadGL(glfwGetProcAddress);
  74. glfwSwapInterval(0);
  75. bool position_supported = true;
  76. glfwGetError(NULL);
  77. glfwGetWindowPos(window, &last_xpos, &last_ypos);
  78. sprintf(xpos_buffer, "%i", last_xpos);
  79. sprintf(ypos_buffer, "%i", last_ypos);
  80. if (glfwGetError(NULL) == GLFW_FEATURE_UNAVAILABLE)
  81. position_supported = false;
  82. glfwGetWindowSize(window, &last_width, &last_height);
  83. sprintf(width_buffer, "%i", last_width);
  84. sprintf(height_buffer, "%i", last_height);
  85. sprintf(numer_buffer, "%i", aspect_numer);
  86. sprintf(denom_buffer, "%i", aspect_denom);
  87. sprintf(min_width_buffer, "%i", min_width);
  88. sprintf(min_height_buffer, "%i", min_height);
  89. sprintf(max_width_buffer, "%i", max_width);
  90. sprintf(max_height_buffer, "%i", max_height);
  91. struct nk_context* nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
  92. struct nk_font_atlas* atlas;
  93. nk_glfw3_font_stash_begin(&atlas);
  94. nk_glfw3_font_stash_end();
  95. strncpy(window_title, glfwGetWindowTitle(window), sizeof(window_title));
  96. while (!(may_close && glfwWindowShouldClose(window)))
  97. {
  98. int width, height;
  99. glfwGetWindowSize(window, &width, &height);
  100. struct nk_rect area = nk_rect(0.f, 0.f, (float) width, (float) height);
  101. nk_window_set_bounds(nk, "main", area);
  102. nk_glfw3_new_frame();
  103. if (nk_begin(nk, "main", area, 0))
  104. {
  105. nk_layout_row_dynamic(nk, 30, 4);
  106. if (glfwGetWindowMonitor(window))
  107. {
  108. if (nk_button_label(nk, "Make Windowed"))
  109. {
  110. glfwSetWindowMonitor(window, NULL,
  111. windowed_x, windowed_y,
  112. windowed_width, windowed_height, 0);
  113. }
  114. }
  115. else
  116. {
  117. if (nk_button_label(nk, "Make Fullscreen"))
  118. {
  119. GLFWmonitor* monitor = glfwGetPrimaryMonitor();
  120. const GLFWvidmode* mode = glfwGetVideoMode(monitor);
  121. glfwGetWindowPos(window, &windowed_x, &windowed_y);
  122. glfwGetWindowSize(window, &windowed_width, &windowed_height);
  123. glfwSetWindowMonitor(window, monitor,
  124. 0, 0, mode->width, mode->height,
  125. mode->refreshRate);
  126. }
  127. }
  128. if (nk_button_label(nk, "Maximize"))
  129. glfwMaximizeWindow(window);
  130. if (nk_button_label(nk, "Iconify"))
  131. glfwIconifyWindow(window);
  132. if (nk_button_label(nk, "Restore"))
  133. glfwRestoreWindow(window);
  134. nk_layout_row_dynamic(nk, 30, 2);
  135. if (nk_button_label(nk, "Hide (for 3s)"))
  136. {
  137. glfwHideWindow(window);
  138. const double time = glfwGetTime() + 3.0;
  139. while (glfwGetTime() < time)
  140. glfwWaitEventsTimeout(1.0);
  141. glfwShowWindow(window);
  142. }
  143. if (nk_button_label(nk, "Request Attention (after 3s)"))
  144. {
  145. glfwIconifyWindow(window);
  146. const double time = glfwGetTime() + 3.0;
  147. while (glfwGetTime() < time)
  148. glfwWaitEventsTimeout(1.0);
  149. glfwRequestWindowAttention(window);
  150. }
  151. nk_layout_row_dynamic(nk, 30, 1);
  152. if (glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH))
  153. {
  154. nk_label(nk, "Press H to disable mouse passthrough", NK_TEXT_CENTERED);
  155. if (glfwGetKey(window, GLFW_KEY_H))
  156. glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, false);
  157. }
  158. nk_label(nk, "Press Enter in a text field to set value", NK_TEXT_CENTERED);
  159. nk_flags events;
  160. const nk_flags flags = NK_EDIT_FIELD |
  161. NK_EDIT_SIG_ENTER |
  162. NK_EDIT_GOTO_END_ON_ACTIVATE;
  163. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
  164. nk_layout_row_push(nk, 1.f / 3.f);
  165. nk_label(nk, "Title", NK_TEXT_LEFT);
  166. nk_layout_row_push(nk, 2.f / 3.f);
  167. events = nk_edit_string_zero_terminated(nk, flags, window_title,
  168. sizeof(window_title), NULL);
  169. if (events & NK_EDIT_COMMITED)
  170. glfwSetWindowTitle(window, window_title);
  171. nk_layout_row_end(nk);
  172. if (position_supported)
  173. {
  174. int xpos, ypos;
  175. glfwGetWindowPos(window, &xpos, &ypos);
  176. nk_layout_row_dynamic(nk, 30, 3);
  177. nk_label(nk, "Position", NK_TEXT_LEFT);
  178. events = nk_edit_string_zero_terminated(nk, flags, xpos_buffer,
  179. sizeof(xpos_buffer),
  180. nk_filter_decimal);
  181. if (events & NK_EDIT_COMMITED)
  182. {
  183. xpos = atoi(xpos_buffer);
  184. glfwSetWindowPos(window, xpos, ypos);
  185. }
  186. else if (xpos != last_xpos || (events & NK_EDIT_DEACTIVATED))
  187. sprintf(xpos_buffer, "%i", xpos);
  188. events = nk_edit_string_zero_terminated(nk, flags, ypos_buffer,
  189. sizeof(ypos_buffer),
  190. nk_filter_decimal);
  191. if (events & NK_EDIT_COMMITED)
  192. {
  193. ypos = atoi(ypos_buffer);
  194. glfwSetWindowPos(window, xpos, ypos);
  195. }
  196. else if (ypos != last_ypos || (events & NK_EDIT_DEACTIVATED))
  197. sprintf(ypos_buffer, "%i", ypos);
  198. last_xpos = xpos;
  199. last_ypos = ypos;
  200. }
  201. else
  202. nk_label(nk, "Platform does not support window position", NK_TEXT_LEFT);
  203. nk_layout_row_dynamic(nk, 30, 3);
  204. nk_label(nk, "Size", NK_TEXT_LEFT);
  205. events = nk_edit_string_zero_terminated(nk, flags, width_buffer,
  206. sizeof(width_buffer),
  207. nk_filter_decimal);
  208. if (events & NK_EDIT_COMMITED)
  209. {
  210. width = atoi(width_buffer);
  211. glfwSetWindowSize(window, width, height);
  212. }
  213. else if (width != last_width || (events & NK_EDIT_DEACTIVATED))
  214. sprintf(width_buffer, "%i", width);
  215. events = nk_edit_string_zero_terminated(nk, flags, height_buffer,
  216. sizeof(height_buffer),
  217. nk_filter_decimal);
  218. if (events & NK_EDIT_COMMITED)
  219. {
  220. height = atoi(height_buffer);
  221. glfwSetWindowSize(window, width, height);
  222. }
  223. else if (height != last_height || (events & NK_EDIT_DEACTIVATED))
  224. sprintf(height_buffer, "%i", height);
  225. last_width = width;
  226. last_height = height;
  227. bool update_ratio_limit = false;
  228. if (nk_checkbox_label(nk, "Aspect Ratio", &limit_aspect_ratio))
  229. update_ratio_limit = true;
  230. events = nk_edit_string_zero_terminated(nk, flags, numer_buffer,
  231. sizeof(numer_buffer),
  232. nk_filter_decimal);
  233. if (events & NK_EDIT_COMMITED)
  234. {
  235. aspect_numer = abs(atoi(numer_buffer));
  236. update_ratio_limit = true;
  237. }
  238. else if (events & NK_EDIT_DEACTIVATED)
  239. sprintf(numer_buffer, "%i", aspect_numer);
  240. events = nk_edit_string_zero_terminated(nk, flags, denom_buffer,
  241. sizeof(denom_buffer),
  242. nk_filter_decimal);
  243. if (events & NK_EDIT_COMMITED)
  244. {
  245. aspect_denom = abs(atoi(denom_buffer));
  246. update_ratio_limit = true;
  247. }
  248. else if (events & NK_EDIT_DEACTIVATED)
  249. sprintf(denom_buffer, "%i", aspect_denom);
  250. if (update_ratio_limit)
  251. {
  252. if (limit_aspect_ratio)
  253. glfwSetWindowAspectRatio(window, aspect_numer, aspect_denom);
  254. else
  255. glfwSetWindowAspectRatio(window, GLFW_DONT_CARE, GLFW_DONT_CARE);
  256. }
  257. bool update_size_limit = false;
  258. if (nk_checkbox_label(nk, "Minimum Size", &limit_min_size))
  259. update_size_limit = true;
  260. events = nk_edit_string_zero_terminated(nk, flags, min_width_buffer,
  261. sizeof(min_width_buffer),
  262. nk_filter_decimal);
  263. if (events & NK_EDIT_COMMITED)
  264. {
  265. min_width = abs(atoi(min_width_buffer));
  266. update_size_limit = true;
  267. }
  268. else if (events & NK_EDIT_DEACTIVATED)
  269. sprintf(min_width_buffer, "%i", min_width);
  270. events = nk_edit_string_zero_terminated(nk, flags, min_height_buffer,
  271. sizeof(min_height_buffer),
  272. nk_filter_decimal);
  273. if (events & NK_EDIT_COMMITED)
  274. {
  275. min_height = abs(atoi(min_height_buffer));
  276. update_size_limit = true;
  277. }
  278. else if (events & NK_EDIT_DEACTIVATED)
  279. sprintf(min_height_buffer, "%i", min_height);
  280. if (nk_checkbox_label(nk, "Maximum Size", &limit_max_size))
  281. update_size_limit = true;
  282. events = nk_edit_string_zero_terminated(nk, flags, max_width_buffer,
  283. sizeof(max_width_buffer),
  284. nk_filter_decimal);
  285. if (events & NK_EDIT_COMMITED)
  286. {
  287. max_width = abs(atoi(max_width_buffer));
  288. update_size_limit = true;
  289. }
  290. else if (events & NK_EDIT_DEACTIVATED)
  291. sprintf(max_width_buffer, "%i", max_width);
  292. events = nk_edit_string_zero_terminated(nk, flags, max_height_buffer,
  293. sizeof(max_height_buffer),
  294. nk_filter_decimal);
  295. if (events & NK_EDIT_COMMITED)
  296. {
  297. max_height = abs(atoi(max_height_buffer));
  298. update_size_limit = true;
  299. }
  300. else if (events & NK_EDIT_DEACTIVATED)
  301. sprintf(max_height_buffer, "%i", max_height);
  302. if (update_size_limit)
  303. {
  304. glfwSetWindowSizeLimits(window,
  305. limit_min_size ? min_width : GLFW_DONT_CARE,
  306. limit_min_size ? min_height : GLFW_DONT_CARE,
  307. limit_max_size ? max_width : GLFW_DONT_CARE,
  308. limit_max_size ? max_height : GLFW_DONT_CARE);
  309. }
  310. int fb_width, fb_height;
  311. glfwGetFramebufferSize(window, &fb_width, &fb_height);
  312. nk_label(nk, "Framebuffer Size", NK_TEXT_LEFT);
  313. nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_width);
  314. nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_height);
  315. float xscale, yscale;
  316. glfwGetWindowContentScale(window, &xscale, &yscale);
  317. nk_label(nk, "Content Scale", NK_TEXT_LEFT);
  318. nk_labelf(nk, NK_TEXT_LEFT, "%f", xscale);
  319. nk_labelf(nk, NK_TEXT_LEFT, "%f", yscale);
  320. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 5);
  321. int frame_left, frame_top, frame_right, frame_bottom;
  322. glfwGetWindowFrameSize(window, &frame_left, &frame_top, &frame_right, &frame_bottom);
  323. nk_layout_row_push(nk, 1.f / 3.f);
  324. nk_label(nk, "Frame Size:", NK_TEXT_LEFT);
  325. nk_layout_row_push(nk, 1.f / 6.f);
  326. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_left);
  327. nk_layout_row_push(nk, 1.f / 6.f);
  328. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_top);
  329. nk_layout_row_push(nk, 1.f / 6.f);
  330. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_right);
  331. nk_layout_row_push(nk, 1.f / 6.f);
  332. nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_bottom);
  333. nk_layout_row_end(nk);
  334. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
  335. float opacity = glfwGetWindowOpacity(window);
  336. nk_layout_row_push(nk, 1.f / 3.f);
  337. nk_labelf(nk, NK_TEXT_LEFT, "Opacity: %0.3f", opacity);
  338. nk_layout_row_push(nk, 2.f / 3.f);
  339. if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f))
  340. glfwSetWindowOpacity(window, opacity);
  341. nk_layout_row_end(nk);
  342. nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
  343. int should_close = glfwWindowShouldClose(window);
  344. nk_layout_row_push(nk, 1.f / 3.f);
  345. if (nk_checkbox_label(nk, "Should Close", &should_close))
  346. glfwSetWindowShouldClose(window, should_close);
  347. nk_layout_row_push(nk, 2.f / 3.f);
  348. nk_checkbox_label(nk, "May Close", &may_close);
  349. nk_layout_row_end(nk);
  350. nk_layout_row_dynamic(nk, 30, 1);
  351. nk_label(nk, "Attributes", NK_TEXT_CENTERED);
  352. nk_layout_row_dynamic(nk, 30, width > 200 ? width / 200 : 1);
  353. int decorated = glfwGetWindowAttrib(window, GLFW_DECORATED);
  354. if (nk_checkbox_label(nk, "Decorated", &decorated))
  355. glfwSetWindowAttrib(window, GLFW_DECORATED, decorated);
  356. int resizable = glfwGetWindowAttrib(window, GLFW_RESIZABLE);
  357. if (nk_checkbox_label(nk, "Resizable", &resizable))
  358. glfwSetWindowAttrib(window, GLFW_RESIZABLE, resizable);
  359. int floating = glfwGetWindowAttrib(window, GLFW_FLOATING);
  360. if (nk_checkbox_label(nk, "Floating", &floating))
  361. glfwSetWindowAttrib(window, GLFW_FLOATING, floating);
  362. int passthrough = glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH);
  363. if (nk_checkbox_label(nk, "Mouse Passthrough", &passthrough))
  364. glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, passthrough);
  365. int auto_iconify = glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY);
  366. if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify))
  367. glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify);
  368. nk_value_bool(nk, "Focused", glfwGetWindowAttrib(window, GLFW_FOCUSED));
  369. nk_value_bool(nk, "Hovered", glfwGetWindowAttrib(window, GLFW_HOVERED));
  370. nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE));
  371. nk_value_bool(nk, "Iconified", glfwGetWindowAttrib(window, GLFW_ICONIFIED));
  372. nk_value_bool(nk, "Maximized", glfwGetWindowAttrib(window, GLFW_MAXIMIZED));
  373. }
  374. nk_end(nk);
  375. glClear(GL_COLOR_BUFFER_BIT);
  376. nk_glfw3_render(NK_ANTI_ALIASING_ON);
  377. glfwSwapBuffers(window);
  378. glfwWaitEvents();
  379. }
  380. nk_glfw3_shutdown();
  381. glfwTerminate();
  382. exit(EXIT_SUCCESS);
  383. }