Added platform double click support #412

This commit is contained in:
vurtun 2017-05-06 18:49:09 +02:00
parent 012170b308
commit 9dc7323b74
12 changed files with 232 additions and 93 deletions

View File

@ -11,6 +11,7 @@
Changes:
--------
- 2017/05/06 (1.38.0) - Added platform double-click support
- 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends
- 2017/04/20 (1.37.0) - Extended properties with selection and clipbard support
- 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing

View File

@ -44,6 +44,12 @@ NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xof
#ifndef NK_GLFW_TEXT_MAX
#define NK_GLFW_TEXT_MAX 256
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_LO
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_HI
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
#endif
struct nk_glfw_device {
struct nk_buffer cmds;
@ -68,6 +74,7 @@ static struct nk_glfw {
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
double last_button_click;
} glfw;
NK_INTERN void
@ -204,6 +211,20 @@ nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
glfw.scroll.y += (float)yoff;
}
NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
double x, y;
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw.last_button_click;
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI)
nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_true);
glfw.last_button_click = glfwGetTime();
} else nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_false);
}
NK_INTERN void
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
{
@ -233,8 +254,8 @@ nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
glfwSetCharCallback(win, nk_glfw3_char_callback);
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
}
nk_init_default(&glfw.ctx, 0);
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;

View File

@ -32,6 +32,7 @@ NK_API void nk_glfw3_device_create(void);
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
NK_API void nk_glfw3_mouse_button_callback(GLFWwindow *win, int button, int action, int mods);
#endif
/*
@ -46,6 +47,12 @@ NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xof
#ifndef NK_GLFW_TEXT_MAX
#define NK_GLFW_TEXT_MAX 256
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_LO
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_HI
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
#endif
struct nk_glfw_device {
struct nk_buffer cmds;
@ -79,6 +86,7 @@ static struct nk_glfw {
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
double last_button_click;
} glfw;
#ifdef __APPLE__
@ -312,6 +320,20 @@ nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
glfw.scroll.y += (float)yoff;
}
NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
double x, y;
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw.last_button_click;
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI)
nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_true);
glfw.last_button_click = glfwGetTime();
} else nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_false);
}
NK_INTERN void
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
{
@ -341,12 +363,13 @@ nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
glfwSetCharCallback(win, nk_glfw3_char_callback);
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
}
nk_init_default(&glfw.ctx, 0);
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
glfw.ctx.clip.userdata = nk_handle_ptr(0);
glfw.last_button_click = 0;
nk_glfw3_device_create();
return &glfw.ctx;
}
@ -387,11 +410,13 @@ nk_glfw3_new_frame(void)
for (i = 0; i < glfw.text_len; ++i)
nk_input_unicode(ctx, glfw.text[i]);
#if NK_GLFW_GL3_MOUSE_GRABBING
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
else if (ctx->input.mouse.ungrab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
@ -430,12 +455,13 @@ nk_glfw3_new_frame(void)
glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
#if NK_GLFW_GL3_MOUSE_GRABBING
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
#endif
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);

View File

@ -302,26 +302,31 @@ nk_sdl_handle_event(SDL_Event *evt)
/* mouse button */
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
if (evt->button.button == SDL_BUTTON_LEFT)
if (evt->button.button == SDL_BUTTON_LEFT) {
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
if (evt->button.button == SDL_BUTTON_MIDDLE)
} else if (evt->button.button == SDL_BUTTON_MIDDLE)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
if (evt->button.button == SDL_BUTTON_RIGHT)
else if (evt->button.button == SDL_BUTTON_RIGHT)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
else return 0;
return 1;
} else if (evt->type == SDL_MOUSEMOTION) {
/* mouse motion */
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
} else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
} else if (evt->type == SDL_TEXTINPUT) {
/* text input */
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
return 1;
} else if (evt->type == SDL_MOUSEWHEEL) {
/* mouse wheel */
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}

View File

@ -47,8 +47,8 @@
* and the corresponding function. */
/*#include "../style.c"*/
/*#include "../calculator.c"*/
/*#include "../overview.c" */
/*#include "../node_editor.c" */
/*#include "../overview.c"*/
/*#include "../node_editor.c"*/
/* ===============================================================
*

View File

@ -400,25 +400,30 @@ nk_sdl_handle_event(SDL_Event *evt)
/* mouse button */
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
if (evt->button.button == SDL_BUTTON_LEFT)
if (evt->button.button == SDL_BUTTON_LEFT) {
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
if (evt->button.button == SDL_BUTTON_MIDDLE)
} else if (evt->button.button == SDL_BUTTON_MIDDLE)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
if (evt->button.button == SDL_BUTTON_RIGHT)
else if (evt->button.button == SDL_BUTTON_RIGHT)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
return 1;
} else if (evt->type == SDL_MOUSEMOTION) {
/* mouse motion */
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
} else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
} else if (evt->type == SDL_TEXTINPUT) {
/* text input */
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
return 1;
} else if (evt->type == SDL_MOUSEWHEEL) {
/* mouse wheel */
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}

View File

@ -44,6 +44,17 @@ NK_API void nk_xfont_del(Display *dpy, XFont *font);
#include <X11/Xlocale.h>
#include <X11/Xatom.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#ifndef NK_X11_DOUBLE_CLICK_LO
#define NK_X11_DOUBLE_CLICK_LO 20
#endif
#ifndef NK_X11_DOUBLE_CLICK_HI
#define NK_X11_DOUBLE_CLICK_HI 200
#endif
typedef struct XSurface XSurface;
struct XFont {
int ascent;
@ -76,16 +87,18 @@ static struct {
Cursor cursor;
Display *dpy;
Window root;
long last_button_click;
} xlib;
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#endif
NK_INTERN long
nk_timestamp(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) return 0;
return (long)((long)tv.tv_sec * 1000 + (long)tv.tv_usec/1000);
}
static unsigned long
NK_INTERN unsigned long
nk_color_from_byte(const nk_byte *c)
{
unsigned long res = 0;
@ -95,7 +108,7 @@ nk_color_from_byte(const nk_byte *c)
return (res);
}
static XSurface*
NK_INTERN XSurface*
nk_xsurf_create(int screen, unsigned int w, unsigned int h)
{
XSurface *surface = (XSurface*)calloc(1, sizeof(XSurface));
@ -111,7 +124,7 @@ nk_xsurf_create(int screen, unsigned int w, unsigned int h)
return surface;
}
static void
NK_INTERN void
nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h)
{
if(!surf) return;
@ -122,7 +135,7 @@ nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h)
(unsigned int)DefaultDepth(surf->dpy, surf->screen));
}
static void
NK_INTERN void
nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h)
{
XRectangle clip_rect;
@ -133,7 +146,7 @@ nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h)
XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted);
}
static void
NK_INTERN void
nk_xsurf_stroke_line(XSurface *surf, short x0, short y0, short x1,
short y1, unsigned int line_thickness, struct nk_color col)
{
@ -144,7 +157,7 @@ nk_xsurf_stroke_line(XSurface *surf, short x0, short y0, short x1,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_stroke_rect(XSurface* surf, short x, short y, unsigned short w,
unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
{
@ -174,7 +187,7 @@ nk_xsurf_stroke_rect(XSurface* surf, short x, short y, unsigned short w,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_fill_rect(XSurface* surf, short x, short y, unsigned short w,
unsigned short h, unsigned short r, struct nk_color col)
{
@ -227,7 +240,7 @@ nk_xsurf_fill_rect(XSurface* surf, short x, short y, unsigned short w,
(unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);}
}
static void
NK_INTERN void
nk_xsurf_fill_triangle(XSurface *surf, short x0, short y0, short x1,
short y1, short x2, short y2, struct nk_color col)
{
@ -243,7 +256,7 @@ nk_xsurf_fill_triangle(XSurface *surf, short x0, short y0, short x1,
XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin);
}
static void
NK_INTERN void
nk_xsurf_stroke_triangle(XSurface *surf, short x0, short y0, short x1,
short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
{
@ -257,7 +270,7 @@ nk_xsurf_stroke_triangle(XSurface *surf, short x0, short y0, short x1,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_fill_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count,
struct nk_color col)
{
@ -274,7 +287,7 @@ nk_xsurf_fill_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count,
#undef MAX_POINTS
}
static void
NK_INTERN void
nk_xsurf_stroke_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count,
unsigned short line_thickness, struct nk_color col)
{
@ -288,7 +301,7 @@ nk_xsurf_stroke_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_stroke_polyline(XSurface *surf, const struct nk_vec2i *pnts,
int count, unsigned short line_thickness, struct nk_color col)
{
@ -301,7 +314,7 @@ nk_xsurf_stroke_polyline(XSurface *surf, const struct nk_vec2i *pnts,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_fill_circle(XSurface *surf, short x, short y, unsigned short w,
unsigned short h, struct nk_color col)
{
@ -311,7 +324,7 @@ nk_xsurf_fill_circle(XSurface *surf, short x, short y, unsigned short w,
(unsigned)w, (unsigned)h, 0, 360 * 64);
}
static void
NK_INTERN void
nk_xsurf_stroke_circle(XSurface *surf, short x, short y, unsigned short w,
unsigned short h, unsigned short line_thickness, struct nk_color col)
{
@ -323,7 +336,7 @@ nk_xsurf_stroke_circle(XSurface *surf, short x, short y, unsigned short w,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_stroke_curve(XSurface *surf, struct nk_vec2i p1,
struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
unsigned int num_segments, unsigned short line_thickness, struct nk_color col)
@ -333,7 +346,7 @@ nk_xsurf_stroke_curve(XSurface *surf, struct nk_vec2i p1,
struct nk_vec2i last = p1;
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
num_segments = MAX(num_segments, 1);
num_segments = NK_MAX(num_segments, 1);
t_step = 1.0f/(float)num_segments;
for (i_step = 1; i_step <= num_segments; ++i_step) {
float t = t_step * (float)i_step;
@ -350,7 +363,7 @@ nk_xsurf_stroke_curve(XSurface *surf, struct nk_vec2i p1,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
static void
NK_INTERN void
nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h,
const char *text, int len, XFont *font, struct nk_color cbg, struct nk_color cfg)
{
@ -370,20 +383,20 @@ nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned
else XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len);
}
static void
NK_INTERN void
nk_xsurf_clear(XSurface *surf, unsigned long color)
{
XSetForeground(surf->dpy, surf->gc, color);
XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h);
}
static void
NK_INTERN void
nk_xsurf_blit(Drawable target, XSurface *surf, unsigned int w, unsigned int h)
{
XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, w, h, 0, 0);
}
static void
NK_INTERN void
nk_xsurf_del(XSurface *surf)
{
XFreePixmap(surf->dpy, surf->drawable);
@ -391,7 +404,7 @@ nk_xsurf_del(XSurface *surf)
free(surf);
}
XFont*
NK_API XFont*
nk_xfont_create(Display *dpy, const char *name)
{
int n;
@ -409,8 +422,8 @@ nk_xfont_create(Display *dpy, const char *name)
XExtentsOfFontSet(font->set);
n = XFontsOfFontSet(font->set, &xfonts, &font_names);
while(n--) {
font->ascent = MAX(font->ascent, (*xfonts)->ascent);
font->descent = MAX(font->descent,(*xfonts)->descent);
font->ascent = NK_MAX(font->ascent, (*xfonts)->ascent);
font->descent = NK_MAX(font->descent,(*xfonts)->descent);
xfonts++;
}
} else {
@ -426,7 +439,7 @@ nk_xfont_create(Display *dpy, const char *name)
return font;
}
static float
NK_INTERN float
nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int len)
{
XFont *font = (XFont*)handle.ptr;
@ -443,7 +456,7 @@ nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int le
}
}
void
NK_API void
nk_xfont_del(Display *dpy, XFont *font)
{
if(!font) return;
@ -609,9 +622,15 @@ nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt)
/* Button handler */
int down = (evt->type == ButtonPress);
const int x = evt->xbutton.x, y = evt->xbutton.y;
if (evt->xbutton.button == Button1)
if (evt->xbutton.button == Button1) {
if (down) { /* Double-Click Button handler */
long dt = nk_timestamp() - xlib.last_button_click;
if (dt > NK_X11_DOUBLE_CLICK_LO && dt < NK_X11_DOUBLE_CLICK_HI)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_true);
xlib.last_button_click = nk_timestamp();
} else nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_false);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
if (evt->xbutton.button == Button2)
} else if (evt->xbutton.button == Button2)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
else if (evt->xbutton.button == Button3)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);

View File

@ -65,9 +65,9 @@ struct XWindow {
Atom wm_delete_window;
int width, height;
};
static int gl_err = FALSE;
static int gl_err = nk_false;
static int gl_error_handler(Display *dpy, XErrorEvent *ev)
{UNUSED((dpy, ev)); gl_err = TRUE;return 0;}
{UNUSED((dpy, ev)); gl_err = nk_true; return 0;}
static void
die(const char *fmt, ...)
@ -86,7 +86,7 @@ has_extension(const char *string, const char *ext)
const char *start, *where, *term;
where = strchr(ext, ' ');
if (where || *ext == '\0')
return FALSE;
return nk_false;
for (start = string;;) {
where = strstr((const char*)start, ext);
@ -94,11 +94,11 @@ has_extension(const char *string, const char *ext)
term = where + strlen(ext);
if (where == start || *(where - 1) == ' ') {
if (*term == ' ' || *term == '\0')
return TRUE;
return nk_true;
}
start = term;
}
return FALSE;
return nk_false;
}
int main(int argc, char **argv)
@ -189,7 +189,7 @@ int main(int argc, char **argv)
glxCreateContext create_context = (glxCreateContext)
glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");
gl_err = FALSE;
gl_err = nk_false;
if (!has_extension(extensions_str, "GLX_ARB_create_context") || !create_context) {
fprintf(stdout, "[X11]: glXCreateContextAttribARB() not found...\n");
fprintf(stdout, "[X11]: ... using old-style GLX context\n");
@ -208,7 +208,7 @@ int main(int argc, char **argv)
* return the newest context version compatible with OpenGL
* version less than version 3.0.*/
attr[1] = 1; attr[3] = 0;
gl_err = FALSE;
gl_err = nk_false;
fprintf(stdout, "[X11] Failed to create OpenGL 3.0 context\n");
fprintf(stdout, "[X11] ... using old-style GLX context!\n");
glContext = create_context(win.dpy, win.fbc, 0, True, attr);

View File

@ -34,6 +34,10 @@ NK_API void nk_x11_shutdown(void);
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
@ -41,11 +45,11 @@ NK_API void nk_x11_shutdown(void);
#include <GL/gl.h>
#ifndef FALSE
#define FALSE 0
#ifndef NK_X11_DOUBLE_CLICK_LO
#define NK_X11_DOUBLE_CLICK_LO 20
#endif
#ifndef TRUE
#define TRUE 1
#ifndef NK_X11_DOUBLE_CLICK_HI
#define NK_X11_DOUBLE_CLICK_HI 200
#endif
struct nk_x11_vertex {
@ -67,8 +71,17 @@ static struct nk_x11 {
Cursor cursor;
Display *dpy;
Window win;
long last_button_click;
} x11;
NK_INTERN long
nk_timestamp(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) return 0;
return (long)((long)tv.tv_sec * 1000 + (long)tv.tv_usec/1000);
}
NK_INTERN void
nk_x11_device_upload_atlas(const void *image, int width, int height)
{
@ -291,9 +304,15 @@ nk_x11_handle_event(XEvent *evt)
/* Button handler */
int down = (evt->type == ButtonPress);
const int x = evt->xbutton.x, y = evt->xbutton.y;
if (evt->xbutton.button == Button1)
if (evt->xbutton.button == Button1) {
if (down) { /* Double-Click Button handler */
long dt = nk_timestamp() - x11.last_button_click;
if (dt > NK_X11_DOUBLE_CLICK_LO && dt < NK_X11_DOUBLE_CLICK_HI)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_true);
x11.last_button_click = nk_timestamp();
} else nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_false);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
if (evt->xbutton.button == Button2)
} else if (evt->xbutton.button == Button2)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
else if (evt->xbutton.button == Button3)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);

View File

@ -63,9 +63,9 @@ struct XWindow {
Atom wm_delete_window;
int width, height;
};
static int gl_err = FALSE;
static int gl_err = nk_false;
static int gl_error_handler(Display *dpy, XErrorEvent *ev)
{UNUSED((dpy, ev)); gl_err = TRUE;return 0;}
{UNUSED((dpy, ev)); gl_err = nk_true;return 0;}
static void
die(const char *fmt, ...)
@ -84,7 +84,7 @@ has_extension(const char *string, const char *ext)
const char *start, *where, *term;
where = strchr(ext, ' ');
if (where || *ext == '\0')
return FALSE;
return nk_false;
for (start = string;;) {
where = strstr((const char*)start, ext);
@ -92,11 +92,11 @@ has_extension(const char *string, const char *ext)
term = where + strlen(ext);
if (where == start || *(where - 1) == ' ') {
if (*term == ' ' || *term == '\0')
return TRUE;
return nk_true;
}
start = term;
}
return FALSE;
return nk_false;
}
int main(int argc, char **argv)
@ -187,7 +187,7 @@ int main(int argc, char **argv)
glxCreateContext create_context = (glxCreateContext)
glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");
gl_err = FALSE;
gl_err = nk_false;
if (!has_extension(extensions_str, "GLX_ARB_create_context") || !create_context) {
fprintf(stdout, "[X11]: glXCreateContextAttribARB() not found...\n");
fprintf(stdout, "[X11]: ... using old-style GLX context\n");
@ -206,7 +206,7 @@ int main(int argc, char **argv)
* return the newest context version compatible with OpenGL
* version less than version 3.0.*/
attr[1] = 1; attr[3] = 0;
gl_err = FALSE;
gl_err = nk_false;
fprintf(stdout, "[X11] Failed to create OpenGL 3.0 context\n");
fprintf(stdout, "[X11] ... using old-style GLX context!\n");
glContext = create_context(win.dpy, win.fbc, 0, True, attr);

View File

@ -36,6 +36,10 @@ NK_API void nk_x11_device_destroy(void);
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
@ -44,11 +48,11 @@ NK_API void nk_x11_device_destroy(void);
#include <GL/gl.h>
#include <GL/glx.h>
#ifndef FALSE
#define FALSE 0
#ifndef NK_X11_DOUBLE_CLICK_LO
#define NK_X11_DOUBLE_CLICK_LO 20
#endif
#ifndef TRUE
#define TRUE 1
#ifndef NK_X11_DOUBLE_CLICK_HI
#define NK_X11_DOUBLE_CLICK_HI 200
#endif
#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS
@ -189,6 +193,7 @@ static struct nk_x11 {
Cursor cursor;
Display *dpy;
Window win;
long last_button_click;
} x11;
#ifdef __APPLE__
@ -200,6 +205,14 @@ static struct nk_x11 {
#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS
#include <GL/glx.h>
NK_INTERN long
nk_timestamp(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) return 0;
return (long)((long)tv.tv_sec * 1000 + (long)tv.tv_usec/1000);
}
NK_INTERN int
nk_x11_stricmpn(const char *a, const char *b, int len)
{
@ -216,7 +229,7 @@ nk_x11_check_extension(struct opengl_info *GL, const char *ext)
const char *start, *where, *term;
where = strchr(ext, ' ');
if (where || *ext == '\0')
return FALSE;
return nk_false;
for (start = GL->extensions_str;;) {
where = strstr((const char*)start, ext);
@ -224,11 +237,11 @@ nk_x11_check_extension(struct opengl_info *GL, const char *ext)
term = where + strlen(ext);
if (where == start || *(where - 1) == ' ') {
if (*term == ' ' || *term == '\0')
return TRUE;
return nk_true;
}
start = term;
}
return FALSE;
return nk_false;
}
#define GL_EXT(name) (nk##name)nk_gl_ext(#name)
@ -247,7 +260,7 @@ nk_gl_ext(const char *name)
NK_INTERN int
nk_load_opengl(struct opengl_info *gl)
{
int failed = FALSE;
int failed = nk_false;
gl->version_str = (const char*)glGetString(GL_VERSION);
glGetIntegerv(GL_MAJOR_VERSION, &gl->major_version);
glGetIntegerv(GL_MINOR_VERSION, &gl->minor_version);
@ -255,7 +268,6 @@ nk_load_opengl(struct opengl_info *gl)
fprintf(stderr, "[GL]: Graphics card does not fullfill minimum OpenGL 2.0 support\n");
return 0;
}
gl->version = (float)gl->major_version + (float)gl->minor_version * 0.1f;
gl->renderer_str = (const char*)glGetString(GL_RENDERER);
gl->extensions_str = (const char*)glGetString(GL_EXTENSIONS);
@ -327,19 +339,19 @@ nk_load_opengl(struct opengl_info *gl)
}
if (!gl->vertex_buffer_obj_available) {
fprintf(stdout, "[GL] Error: GL_ARB_vertex_buffer_object is not available!\n");
failed = TRUE;
failed = nk_true;
}
if (!gl->fragment_program_available) {
fprintf(stdout, "[GL] Error: GL_ARB_fragment_program is not available!\n");
failed = TRUE;
failed = nk_true;
}
if (!gl->vertex_array_obj_available) {
fprintf(stdout, "[GL] Error: GL_ARB_vertex_array_object is not available!\n");
failed = TRUE;
failed = nk_true;
}
if (!gl->frame_buffer_object_available) {
fprintf(stdout, "[GL] Error: GL_ARB_framebuffer_object is not available!\n");
failed = TRUE;
failed = nk_true;
}
return !failed;
}
@ -661,9 +673,15 @@ nk_x11_handle_event(XEvent *evt)
/* Button handler */
int down = (evt->type == ButtonPress);
const int x = evt->xbutton.x, y = evt->xbutton.y;
if (evt->xbutton.button == Button1)
if (evt->xbutton.button == Button1) {
if (down) { /* Double-Click Button handler */
long dt = nk_timestamp() - x11.last_button_click;
if (dt > NK_X11_DOUBLE_CLICK_LO && dt < NK_X11_DOUBLE_CLICK_HI)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_true);
x11.last_button_click = nk_timestamp();
} else nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_false);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
if (evt->xbutton.button == Button2)
} else if (evt->xbutton.button == Button2)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
else if (evt->xbutton.button == Button3)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);

View File

@ -696,6 +696,7 @@ enum nk_buttons {
NK_BUTTON_LEFT,
NK_BUTTON_MIDDLE,
NK_BUTTON_RIGHT,
NK_BUTTON_DOUBLE,
NK_BUTTON_MAX
};
/* nk_input_begin - Begins the input mirroring process by resetting text, scroll
@ -837,9 +838,9 @@ NK_API void nk_input_end(struct nk_context*);
* quite wasteful. While the actual UI updating loop is quite fast rendering
* without actually needing it is not. So there are multiple things you could do.
*
* First is only update on input. This ofcourse is only an option if your
* First is only update on input. This of course is only an option if your
* application only depends on the UI and does not require any outside calculations.
* If you actually only update on input make sure to update the UI to times each
* If you actually only update on input make sure to update the UI two times each
* frame and call `nk_clear` directly after the first pass and only draw in
* the second pass.
*
@ -1170,7 +1171,7 @@ NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*
* nk_window_show_if - hides/shows a window depending on condition
*/
enum nk_panel_flags {
NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate the window from the background */
NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */
NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */
NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */
NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */
@ -1545,7 +1546,7 @@ NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show
* is provided.
*
* if (nk_begin_xxx(...) {
* // two rows with height: 30 composed of two widgets with width 60 and 40
* // two rows with height: 30 composed of three widgets
* nk_layout_row_template_begin(ctx, 30);
* nk_layout_row_template_push_dynamic(ctx);
* nk_layout_row_template_push_variable(ctx, 80);
@ -1587,12 +1588,12 @@ NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show
*
* Reference
* -------------------
* nk_layout_row_dynamic
* nk_layout_row_static
* nk_layout_row_begin
* nk_layout_row_push
* nk_layout_row_end
* nk_layout_row
* nk_layout_row_dynamic - current layout is divided into n same sized gowing columns
* nk_layout_row_static - current layout is divided into n same fixed sized columns
* nk_layout_row_begin - starts a new row with given height and number of columns
* nk_layout_row_push - pushes another column with given size or window ratio
* nk_layout_row_end - finished previously started row
* nk_layout_row - specifies row columns in array as either window ratio or size
*
* nk_layout_row_template_begin
* nk_layout_row_template_push_dynamic
@ -1611,10 +1612,34 @@ NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show
* nk_layout_space_rect_to_local
* nk_layout_ratio_from_pixel
*/
NK_API void nk_layout_row_dynamic(struct nk_context*, float height, int cols);
NK_API void nk_layout_row_static(struct nk_context*, float height, int item_width, int cols);
NK_API void nk_layout_row_begin(struct nk_context*, enum nk_layout_format, float row_height, int cols);
/* nk_layout_row_dynamic - Sets current row layout to share horizontal space
* between @cols number of widgets evenly. Once called all subsequent widget
* calls greater than @cols will allocate a new row with same layout.
* Parameters:
* @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
* @height holds row height to allocate from panel for widget height
* @cols number of widget inside row */
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
/* nk_layout_row_static - Sets current row layout to fill @cols number of widgets
* in row with same @item_width horizontal size. Once called all subsequent widget
* calls greater than @cols will allocate a new row with same layout.
* Parameters:
* @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
* @height holds row height to allocate from panel for widget height
* @item_width holds width of each widget in row
* @cols number of widget inside row */
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
/* nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns.
* Parameters:
* @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
* @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
* @row_height holds width of each widget in row
* @cols number of widget inside row */
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
/* nk_layout_row_push - Specifies either window ratio or width of a single column
* Parameters:
* @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin`
* @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */
NK_API void nk_layout_row_push(struct nk_context*, float value);
NK_API void nk_layout_row_end(struct nk_context*);
NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);