window.c 17 KB

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