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