1 /*
2  * Nuklear - 1.32.0 - public domain
3  * no warrenty implied; use at your own risk.
4  * authored from 2015-2016 by Micha Mettke
5  */
6 /*
7  * ==============================================================
8  *
9  *                              API
10  *
11  * ===============================================================
12  */
13 #ifndef NK_GLFW_GL3_H_
14 #define NK_GLFW_GL3_H_
15 
16 #include <GLFW/glfw3.h>
17 
18 enum nk_glfw_init_state{
19     NK_GLFW3_DEFAULT=0,
20     NK_GLFW3_INSTALL_CALLBACKS
21 };
22 
23 NK_API struct nk_context*   nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
24 NK_API void                 nk_glfw3_shutdown(void);
25 NK_API void                 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
26 NK_API void                 nk_glfw3_font_stash_end(void);
27 NK_API void                 nk_glfw3_new_frame(void);
28 NK_API void                 nk_glfw3_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
29 
30 NK_API void                 nk_glfw3_device_destroy(void);
31 NK_API void                 nk_glfw3_device_create(void);
32 
33 NK_API void                 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
34 NK_API void                 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
35 NK_API void                 nk_glfw3_mouse_button_callback(GLFWwindow *win, int button, int action, int mods);
36 
37 #endif
38 /*
39  * ==============================================================
40  *
41  *                          IMPLEMENTATION
42  *
43  * ===============================================================
44  */
45 #ifdef NK_GLFW_GL3_IMPLEMENTATION
46 
47 #ifndef NK_GLFW_TEXT_MAX
48 #define NK_GLFW_TEXT_MAX 256
49 #endif
50 #ifndef NK_GLFW_DOUBLE_CLICK_LO
51 #define NK_GLFW_DOUBLE_CLICK_LO 0.02
52 #endif
53 #ifndef NK_GLFW_DOUBLE_CLICK_HI
54 #define NK_GLFW_DOUBLE_CLICK_HI 0.2
55 #endif
56 
57 struct nk_glfw_device {
58     struct nk_buffer cmds;
59     struct nk_draw_null_texture null;
60     GLuint vbo, vao, ebo;
61     GLuint prog;
62     GLuint vert_shdr;
63     GLuint frag_shdr;
64     GLint attrib_pos;
65     GLint attrib_uv;
66     GLint attrib_col;
67     GLint uniform_tex;
68     GLint uniform_proj;
69     GLuint font_tex;
70 };
71 
72 struct nk_glfw_vertex {
73     float position[2];
74     float uv[2];
75     nk_byte col[4];
76 };
77 
78 static struct nk_glfw {
79     GLFWwindow *win;
80     int width, height;
81     int display_width, display_height;
82     struct nk_glfw_device ogl;
83     struct nk_context ctx;
84     struct nk_font_atlas atlas;
85     struct nk_vec2 fb_scale;
86     unsigned int text[NK_GLFW_TEXT_MAX];
87     int text_len;
88     struct nk_vec2 scroll;
89     double last_button_click;
90     int is_double_click_down;
91     struct nk_vec2 double_click_pos;
92 } glfw;
93 
94 #ifdef __APPLE__
95   #define NK_SHADER_VERSION "#version 150\n"
96 #else
97   #define NK_SHADER_VERSION "#version 300 es\n"
98 #endif
99 
100 NK_API void
nk_glfw3_device_create(void)101 nk_glfw3_device_create(void)
102 {
103     GLint status;
104     static const GLchar *vertex_shader =
105         NK_SHADER_VERSION
106         "uniform mat4 ProjMtx;\n"
107         "in vec2 Position;\n"
108         "in vec2 TexCoord;\n"
109         "in vec4 Color;\n"
110         "out vec2 Frag_UV;\n"
111         "out vec4 Frag_Color;\n"
112         "void main() {\n"
113         "   Frag_UV = TexCoord;\n"
114         "   Frag_Color = Color;\n"
115         "   gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
116         "}\n";
117     static const GLchar *fragment_shader =
118         NK_SHADER_VERSION
119         "precision mediump float;\n"
120         "uniform sampler2D Texture;\n"
121         "in vec2 Frag_UV;\n"
122         "in vec4 Frag_Color;\n"
123         "out vec4 Out_Color;\n"
124         "void main(){\n"
125         "   Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
126         "}\n";
127 
128     struct nk_glfw_device *dev = &glfw.ogl;
129     nk_buffer_init_default(&dev->cmds);
130     dev->prog = glCreateProgram();
131     dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
132     dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
133     glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
134     glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
135     glCompileShader(dev->vert_shdr);
136     glCompileShader(dev->frag_shdr);
137     glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
138     assert(status == GL_TRUE);
139     glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
140     assert(status == GL_TRUE);
141     glAttachShader(dev->prog, dev->vert_shdr);
142     glAttachShader(dev->prog, dev->frag_shdr);
143     glLinkProgram(dev->prog);
144     glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
145     assert(status == GL_TRUE);
146 
147     dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
148     dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
149     dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
150     dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
151     dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
152 
153     {
154         /* buffer setup */
155         GLsizei vs = sizeof(struct nk_glfw_vertex);
156         size_t vp = offsetof(struct nk_glfw_vertex, position);
157         size_t vt = offsetof(struct nk_glfw_vertex, uv);
158         size_t vc = offsetof(struct nk_glfw_vertex, col);
159 
160         glGenBuffers(1, &dev->vbo);
161         glGenBuffers(1, &dev->ebo);
162         glGenVertexArrays(1, &dev->vao);
163 
164         glBindVertexArray(dev->vao);
165         glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
166         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
167 
168         glEnableVertexAttribArray((GLuint)dev->attrib_pos);
169         glEnableVertexAttribArray((GLuint)dev->attrib_uv);
170         glEnableVertexAttribArray((GLuint)dev->attrib_col);
171 
172         glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
173         glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
174         glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
175     }
176 
177     glBindTexture(GL_TEXTURE_2D, 0);
178     glBindBuffer(GL_ARRAY_BUFFER, 0);
179     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
180     glBindVertexArray(0);
181 }
182 
183 NK_INTERN void
nk_glfw3_device_upload_atlas(const void * image,int width,int height)184 nk_glfw3_device_upload_atlas(const void *image, int width, int height)
185 {
186     struct nk_glfw_device *dev = &glfw.ogl;
187     glGenTextures(1, &dev->font_tex);
188     glBindTexture(GL_TEXTURE_2D, dev->font_tex);
189     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
190     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
191     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
192                 GL_RGBA, GL_UNSIGNED_BYTE, image);
193 }
194 
195 NK_API void
nk_glfw3_device_destroy(void)196 nk_glfw3_device_destroy(void)
197 {
198     struct nk_glfw_device *dev = &glfw.ogl;
199     glDetachShader(dev->prog, dev->vert_shdr);
200     glDetachShader(dev->prog, dev->frag_shdr);
201     glDeleteShader(dev->vert_shdr);
202     glDeleteShader(dev->frag_shdr);
203     glDeleteProgram(dev->prog);
204     glDeleteTextures(1, &dev->font_tex);
205     glDeleteBuffers(1, &dev->vbo);
206     glDeleteBuffers(1, &dev->ebo);
207     nk_buffer_free(&dev->cmds);
208 }
209 
210 NK_API void
nk_glfw3_render(enum nk_anti_aliasing AA,int max_vertex_buffer,int max_element_buffer)211 nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
212 {
213     struct nk_glfw_device *dev = &glfw.ogl;
214     struct nk_buffer vbuf, ebuf;
215     GLfloat ortho[4][4] = {
216         {2.0f, 0.0f, 0.0f, 0.0f},
217         {0.0f,-2.0f, 0.0f, 0.0f},
218         {0.0f, 0.0f,-1.0f, 0.0f},
219         {-1.0f,1.0f, 0.0f, 1.0f},
220     };
221     ortho[0][0] /= (GLfloat)glfw.width;
222     ortho[1][1] /= (GLfloat)glfw.height;
223 
224     /* setup global state */
225     glEnable(GL_BLEND);
226     glBlendEquation(GL_FUNC_ADD);
227     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
228     glDisable(GL_CULL_FACE);
229     glDisable(GL_DEPTH_TEST);
230     glEnable(GL_SCISSOR_TEST);
231     glActiveTexture(GL_TEXTURE0);
232 
233     /* setup program */
234     glUseProgram(dev->prog);
235     glUniform1i(dev->uniform_tex, 0);
236     glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
237     glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
238     {
239         /* convert from command queue into draw list and draw to screen */
240         const struct nk_draw_command *cmd;
241         void *vertices, *elements;
242         const nk_draw_index *offset = NULL;
243 
244         /* allocate vertex and element buffer */
245         glBindVertexArray(dev->vao);
246         glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
247         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
248 
249         glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW);
250         glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW);
251 
252         /* load draw vertices & elements directly into vertex + element buffer */
253         vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
254         elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
255         {
256             /* fill convert configuration */
257             struct nk_convert_config config;
258             static const struct nk_draw_vertex_layout_element vertex_layout[] = {
259                 {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
260                 {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
261                 {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
262                 {NK_VERTEX_LAYOUT_END}
263             };
264             NK_MEMSET(&config, 0, sizeof(config));
265             config.vertex_layout = vertex_layout;
266             config.vertex_size = sizeof(struct nk_glfw_vertex);
267             config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
268             config.null = dev->null;
269             config.circle_segment_count = 22;
270             config.curve_segment_count = 22;
271             config.arc_segment_count = 22;
272             config.global_alpha = 1.0f;
273             config.shape_AA = AA;
274             config.line_AA = AA;
275 
276             /* setup buffers to load vertices and elements */
277             nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer);
278             nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer);
279             nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
280         }
281         glUnmapBuffer(GL_ARRAY_BUFFER);
282         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
283 
284         /* iterate over and execute each draw command */
285         nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
286         {
287             if (!cmd->elem_count) continue;
288             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
289             glScissor(
290                 (GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
291                 (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
292                 (GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
293                 (GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
294             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
295             offset += cmd->elem_count;
296         }
297         nk_clear(&glfw.ctx);
298     }
299 
300     /* default OpenGL state */
301     glUseProgram(0);
302     glBindBuffer(GL_ARRAY_BUFFER, 0);
303     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
304     glBindVertexArray(0);
305     glDisable(GL_BLEND);
306     glDisable(GL_SCISSOR_TEST);
307 }
308 
309 NK_API void
nk_glfw3_char_callback(GLFWwindow * win,unsigned int codepoint)310 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
311 {
312     (void)win;
313     if (glfw.text_len < NK_GLFW_TEXT_MAX)
314         glfw.text[glfw.text_len++] = codepoint;
315 }
316 
317 NK_API void
nk_gflw3_scroll_callback(GLFWwindow * win,double xoff,double yoff)318 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
319 {
320     (void)win; (void)xoff;
321     glfw.scroll.x += (float)xoff;
322     glfw.scroll.y += (float)yoff;
323 }
324 
325 NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow * window,int button,int action,int mods)326 nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
327 {
328     double x, y;
329     if (button != GLFW_MOUSE_BUTTON_LEFT) return;
330     glfwGetCursorPos(window, &x, &y);
331     if (action == GLFW_PRESS)  {
332         double dt = glfwGetTime() - glfw.last_button_click;
333         if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
334             glfw.is_double_click_down = nk_true;
335             glfw.double_click_pos = nk_vec2((float)x, (float)y);
336         }
337         glfw.last_button_click = glfwGetTime();
338     } else glfw.is_double_click_down = nk_false;
339 }
340 
341 NK_INTERN void
nk_glfw3_clipbard_paste(nk_handle usr,struct nk_text_edit * edit)342 nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
343 {
344     const char *text = glfwGetClipboardString(glfw.win);
345     if (text) nk_textedit_paste(edit, text, nk_strlen(text));
346     (void)usr;
347 }
348 
349 NK_INTERN void
nk_glfw3_clipbard_copy(nk_handle usr,const char * text,int len)350 nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len)
351 {
352     char *str = 0;
353     (void)usr;
354     if (!len) return;
355     str = (char*)malloc((size_t)len+1);
356     if (!str) return;
357     memcpy(str, text, (size_t)len);
358     str[len] = '\0';
359     glfwSetClipboardString(glfw.win, str);
360     free(str);
361 }
362 
363 NK_API struct nk_context*
nk_glfw3_init(GLFWwindow * win,enum nk_glfw_init_state init_state)364 nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
365 {
366     glfw.win = win;
367     if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
368         glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
369         glfwSetCharCallback(win, nk_glfw3_char_callback);
370         glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
371     }
372     nk_init_default(&glfw.ctx, 0);
373     glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
374     glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
375     glfw.ctx.clip.userdata = nk_handle_ptr(0);
376     glfw.last_button_click = 0;
377     nk_glfw3_device_create();
378 
379     glfw.is_double_click_down = nk_false;
380     glfw.double_click_pos = nk_vec2(0, 0);
381 
382     return &glfw.ctx;
383 }
384 
385 NK_API void
nk_glfw3_font_stash_begin(struct nk_font_atlas ** atlas)386 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
387 {
388     nk_font_atlas_init_default(&glfw.atlas);
389     nk_font_atlas_begin(&glfw.atlas);
390     *atlas = &glfw.atlas;
391 }
392 
393 NK_API void
nk_glfw3_font_stash_end(void)394 nk_glfw3_font_stash_end(void)
395 {
396     const void *image; int w, h;
397     image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
398     nk_glfw3_device_upload_atlas(image, w, h);
399     nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
400     if (glfw.atlas.default_font)
401         nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
402 }
403 
404 NK_API void
nk_glfw3_new_frame(void)405 nk_glfw3_new_frame(void)
406 {
407     int i;
408     double x, y;
409     struct nk_context *ctx = &glfw.ctx;
410     struct GLFWwindow *win = glfw.win;
411 
412     glfwGetWindowSize(win, &glfw.width, &glfw.height);
413     glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
414     glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
415     glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
416 
417     nk_input_begin(ctx);
418     for (i = 0; i < glfw.text_len; ++i)
419         nk_input_unicode(ctx, glfw.text[i]);
420 
421 #ifdef NK_GLFW_GL3_MOUSE_GRABBING
422     /* optional grabbing behavior */
423     if (ctx->input.mouse.grab)
424         glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
425     else if (ctx->input.mouse.ungrab)
426         glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
427 #endif
428 
429     nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
430     nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
431     nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
432     nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
433     nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
434     nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
435     nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
436     nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
437     nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
438     nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
439     nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
440     nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
441     nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
442                                     glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
443 
444     if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
445         glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
446         nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
447         nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
448         nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
449         nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
450         nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
451         nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
452         nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
453         nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
454         nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
455     } else {
456         nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
457         nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
458         nk_input_key(ctx, NK_KEY_COPY, 0);
459         nk_input_key(ctx, NK_KEY_PASTE, 0);
460         nk_input_key(ctx, NK_KEY_CUT, 0);
461         nk_input_key(ctx, NK_KEY_SHIFT, 0);
462     }
463 
464     glfwGetCursorPos(win, &x, &y);
465     nk_input_motion(ctx, (int)x, (int)y);
466 #ifdef NK_GLFW_GL3_MOUSE_GRABBING
467     if (ctx->input.mouse.grabbed) {
468         glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
469         ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
470         ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
471     }
472 #endif
473     nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
474     nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
475     nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
476     nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw.double_click_pos.x, (int)glfw.double_click_pos.y, glfw.is_double_click_down);
477     nk_input_scroll(ctx, glfw.scroll);
478     nk_input_end(&glfw.ctx);
479     glfw.text_len = 0;
480     glfw.scroll = nk_vec2(0,0);
481 }
482 
483 NK_API
nk_glfw3_shutdown(void)484 void nk_glfw3_shutdown(void)
485 {
486     nk_font_atlas_clear(&glfw.atlas);
487     nk_free(&glfw.ctx);
488     nk_glfw3_device_destroy();
489     memset(&glfw, 0, sizeof(glfw));
490 }
491 
492 #endif
493