From 64ba544fae0a7e9ca1de482a5a71684735a55821 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Mon, 17 Feb 2025 17:02:40 +0000 Subject: [PATCH] Build the X11 and XFT demos from the same sources --- .github/workflows/ccpp.yml | 2 - demo/x11/Makefile | 17 +- demo/x11/main.c | 6 + demo/x11/nuklear_xlib.h | 84 +++ demo/x11_xft/Makefile | 21 - demo/x11_xft/main.c | 242 -------- demo/x11_xft/nuklear_xlib.h | 1086 ----------------------------------- 7 files changed, 105 insertions(+), 1353 deletions(-) delete mode 100644 demo/x11_xft/Makefile delete mode 100644 demo/x11_xft/main.c delete mode 100644 demo/x11_xft/nuklear_xlib.h diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index be1e5422e..6e14e5d5d 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -43,7 +43,5 @@ jobs: run: make -C demo/x11_opengl3 - name: build x11_rawfb run: make -C demo/rawfb/x11 - - name: build x11_xft - run: make -C demo/x11_xft - name: build example run: make -C example diff --git a/demo/x11/Makefile b/demo/x11/Makefile index 10b7b6580..17d85305c 100644 --- a/demo/x11/Makefile +++ b/demo/x11/Makefile @@ -2,12 +2,25 @@ BIN = demo # Flags -CFLAGS += -std=c89 -Wall -Wextra -pedantic -Wno-unused-function +CFLAGS += -std=c89 -Wall -Wextra -pedantic -Wno-unused-function -D_POSIX_C_SOURCE=200809L SRC = main.c OBJ = $(SRC:.c=.o) +X11_CFLAGS += ${shell pkg-config --cflags x11} +X11_LDFLAGS += ${shell pkg-config --libs x11} -lm + +XFT_CFLAGS += ${shell pkg-config --cflags xft x11} -DNK_XLIB_USE_XFT +XFT_LDFLAGS += ${shell pkg-config --libs xft x11} -lm + +all: $(BIN) $(BIN)-xft + $(BIN): @mkdir -p bin rm -f bin/$(BIN) $(OBJS) - $(CC) $(SRC) $(CFLAGS) -D_POSIX_C_SOURCE=200809L -o bin/$(BIN) -lX11 -lm + $(CC) $(SRC) $(CFLAGS) $(X11_CFLAGS) -o bin/$(BIN) ${LDFLAGS} ${X11_LDFLAGS} + +$(BIN)-xft: + @mkdir -p bin + rm -f bin/$(BIN)-xft $(OBJS) + $(CC) $(SRC) $(CFLAGS) $(XFT_CFLAGS) -o bin/$(BIN)-xft ${LDFLAGS} ${LDFLAGS} ${XFT_LDFLAGS} diff --git a/demo/x11/main.c b/demo/x11/main.c index 6a99f83a8..e5d69002d 100644 --- a/demo/x11/main.c +++ b/demo/x11/main.c @@ -159,8 +159,14 @@ main(void) xw.height = (unsigned int)xw.attr.height; /* GUI */ +#ifdef NK_XLIB_USE_XFT + xw.font = nk_xfont_create(xw.dpy, "Arial"); + ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, + xw.vis, xw.cmap, xw.width, xw.height); +#else xw.font = nk_xfont_create(xw.dpy, "fixed"); ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, xw.width, xw.height); +#endif while (running) { diff --git a/demo/x11/nuklear_xlib.h b/demo/x11/nuklear_xlib.h index a11c88403..fe8a7a8ef 100644 --- a/demo/x11/nuklear_xlib.h +++ b/demo/x11/nuklear_xlib.h @@ -16,7 +16,11 @@ #include typedef struct XFont XFont; +#ifdef NK_XLIB_USE_XFT +NK_API struct nk_context* nk_xlib_init(XFont*, Display*, int scrn, Window root, Visual *vis, Colormap cmap, unsigned w, unsigned h); +#else NK_API struct nk_context* nk_xlib_init(XFont*, Display*, int scrn, Window root, unsigned w, unsigned h); +#endif NK_API int nk_xlib_handle_event(Display*, int scrn, Window, XEvent*); NK_API void nk_xlib_render(Drawable screen, struct nk_color clear); NK_API void nk_xlib_shutdown(void); @@ -53,6 +57,10 @@ NK_API void nk_xfont_del(Display *dpy, XFont *font); #include #include +#ifdef NK_XLIB_USE_XFT +#include +#endif + #include #include #include @@ -80,8 +88,12 @@ struct XFont { int ascent; int descent; int height; +#ifdef NK_XLIB_USE_XFT + XftFont * ft; +#else XFontSet set; XFontStruct *xfont; +#endif struct nk_user_font handle; }; struct XSurface { @@ -91,6 +103,9 @@ struct XSurface { Window root; Drawable drawable; unsigned int w, h; +#ifdef NK_XLIB_USE_XFT + XftDraw * ftdraw; +#endif }; struct XImageWithAlpha { XImage* ximage; @@ -112,6 +127,10 @@ static struct { Cursor cursor; Display *dpy; Window root; +#ifdef NK_XLIB_USE_XFT + Visual *vis; + Colormap cmap; +#endif double last_button_click; double time_of_last_frame; } xlib; @@ -147,6 +166,10 @@ nk_xsurf_create(int screen, unsigned int w, unsigned int h) XSetLineAttributes(xlib.dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter); surface->drawable = XCreatePixmap(xlib.dpy, xlib.root, w, h, (unsigned int)DefaultDepth(xlib.dpy, screen)); +#ifdef NK_XLIB_USE_XFT + surface->ftdraw = XftDrawCreate(xlib.dpy, surface->drawable, + xlib.vis, xlib.cmap); +#endif return surface; } @@ -159,6 +182,9 @@ nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h) if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable); surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h, (unsigned int)DefaultDepth(surf->dpy, surf->screen)); +#ifdef NK_XLIB_USE_XFT + XftDrawChange(surf->ftdraw, surf->drawable); +#endif } NK_INTERN void @@ -170,6 +196,10 @@ nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h) clip_rect.width = (unsigned short)(w+2); clip_rect.height = (unsigned short)(h+2); XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted); + +#ifdef NK_XLIB_USE_XFT + XftDrawSetClipRectangles(surf->ftdraw, 0, 0, &clip_rect, 1); +#endif } NK_INTERN void @@ -416,16 +446,31 @@ nk_xsurf_draw_text(XSurface *surf, short x, short y, const char *text, int len, XFont *font, struct nk_color cfg) { int tx, ty; +#ifdef NK_XLIB_USE_XFT + XRenderColor xrc; + XftColor color; +#else unsigned long fg = nk_color_from_byte(&cfg.r); +#endif if(!text || !font || !len) return; tx = (int)x; ty = (int)y + font->ascent; +#ifdef NK_XLIB_USE_XFT + xrc.red = cfg.r * 257; + xrc.green = cfg.g * 257; + xrc.blue = cfg.b * 257; + xrc.alpha = cfg.a * 257; + XftColorAllocValue(surf->dpy, xlib.vis, xlib.cmap, &xrc, &color); + XftDrawStringUtf8(surf->ftdraw, &color, font->ft, tx, ty, (FcChar8*)text, len); + XftColorFree(surf->dpy, xlib.vis, xlib.cmap, &color); +#else XSetForeground(surf->dpy, surf->gc, fg); if(font->set) XmbDrawString(surf->dpy,surf->drawable,font->set,surf->gc,tx,ty,(const char*)text,(int)len); else XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len); +#endif } @@ -563,6 +608,9 @@ nk_xsurf_blit(Drawable target, XSurface *surf, unsigned int w, unsigned int h) NK_INTERN void nk_xsurf_del(XSurface *surf) { +#ifdef NK_XLIB_USE_XFT + XftDrawDestroy(surf->ftdraw); +#endif XFreePixmap(surf->dpy, surf->drawable); XFreeGC(surf->dpy, surf->gc); free(surf); @@ -571,6 +619,17 @@ nk_xsurf_del(XSurface *surf) NK_API XFont* nk_xfont_create(Display *dpy, const char *name) { +#ifdef NK_XLIB_USE_XFT + XFont *font = (XFont*)calloc(1, sizeof(XFont)); + font->ft = XftFontOpenName(dpy, XDefaultScreen(dpy), name); + if (!font->ft) { + fprintf(stderr, "missing font: %s\n", name); + return font; + } + font->ascent = font->ft->ascent; + font->descent = font->ft->descent; + font->height = font->ft->height; +#else int n; char *def, **missing; XFont *font = (XFont*)calloc(1, sizeof(XFont)); @@ -600,6 +659,7 @@ nk_xfont_create(Display *dpy, const char *name) font->descent = font->xfont->descent; } font->height = font->ascent + font->descent; +#endif return font; } @@ -607,6 +667,18 @@ NK_INTERN float nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int len) { XFont *font = (XFont*)handle.ptr; + +#ifdef NK_XLIB_USE_XFT + XGlyphInfo g; + + NK_UNUSED(height); + + if(!font || !text) + return 0; + + XftTextExtentsUtf8(xlib.dpy, font->ft, (FcChar8*)text, len, &g); + return g.xOff; +#else XRectangle r; NK_UNUSED(height); @@ -621,21 +693,29 @@ nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int le int w = XTextWidth(font->xfont, (const char*)text, len); return (float)w; } +#endif } NK_API void nk_xfont_del(Display *dpy, XFont *font) { if(!font) return; +#ifdef NK_XLIB_USE_XFT + XftFontClose(dpy, font->ft); +#else if(font->set) XFreeFontSet(dpy, font->set); else XFreeFont(dpy, font->xfont); +#endif free(font); } NK_API struct nk_context* nk_xlib_init(XFont *xfont, Display *dpy, int screen, Window root, +#ifdef NK_XLIB_USE_XFT + Visual *vis, Colormap cmap, +#endif unsigned int w, unsigned int h) { struct nk_user_font *font = &xfont->handle; @@ -644,6 +724,10 @@ nk_xlib_init(XFont *xfont, Display *dpy, int screen, Window root, font->width = nk_xfont_get_text_width; xlib.dpy = dpy; xlib.root = root; +#ifdef NK_XLIB_USE_XFT + xlib.vis = vis; + xlib.cmap = cmap; +#endif if (!setlocale(LC_ALL,"")) return 0; if (!XSupportsLocale()) return 0; diff --git a/demo/x11_xft/Makefile b/demo/x11_xft/Makefile deleted file mode 100644 index 96b306755..000000000 --- a/demo/x11_xft/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Install -BIN = demo - -# Flags -CFLAGS += -std=c89 -Wall -Wextra -pedantic -Wno-unused-function - -SRC = main.c -OBJ = $(SRC:.c=.o) - -LDFLAGS += -lX11 -lm - -CFLAGS += ${shell pkg-config --cflags xft} -DNK_XLIB_USE_XFT -LDFLAGS += ${shell pkg-config --libs xft} - -SRC = ${wildcard *.c} -OBJ = $(SRC:.c=.o) - -$(BIN): - @mkdir -p bin - rm -f bin/$(BIN) $(OBJS) - $(CC) $(SRC) $(CFLAGS) -D_POSIX_C_SOURCE=200809L -o bin/$(BIN) -lX11 ${LDFLAGS} diff --git a/demo/x11_xft/main.c b/demo/x11_xft/main.c deleted file mode 100644 index 490357dce..000000000 --- a/demo/x11_xft/main.c +++ /dev/null @@ -1,242 +0,0 @@ -/* nuklear - v1.32.0 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_IMPLEMENTATION -#define NK_XLIB_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_xlib.h" - -#define DTIME 20 -#define WINDOW_WIDTH 800 -#define WINDOW_HEIGHT 600 - -typedef struct XWindow XWindow; -struct XWindow { - Display *dpy; - Window root; - Visual *vis; - Colormap cmap; - XWindowAttributes attr; - XSetWindowAttributes swa; - Window win; - int screen; - XFont *font; - unsigned int width; - unsigned int height; - Atom wm_delete_window; -}; - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static long -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 void -sleep_for(long t) -{ - struct timespec req; - const time_t sec = (int)(t/1000); - const long ms = t - (sec * 1000); - req.tv_sec = sec; - req.tv_nsec = ms * 1000000L; - while(-1 == nanosleep(&req, &req)); -} - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the defines */ -/*#define INCLUDE_ALL */ -/*#define INCLUDE_STYLE */ -/*#define INCLUDE_CALCULATOR */ -/*#define INCLUDE_CANVAS */ -#define INCLUDE_OVERVIEW -/*#define INCLUDE_CONFIGURATOR */ -/*#define INCLUDE_NODE_EDITOR */ - -#ifdef INCLUDE_ALL - #define INCLUDE_STYLE - #define INCLUDE_CALCULATOR - #define INCLUDE_CANVAS - #define INCLUDE_OVERVIEW - #define INCLUDE_CONFIGURATOR - #define INCLUDE_NODE_EDITOR -#endif - -#ifdef INCLUDE_STYLE - #include "../../demo/common/style.c" -#endif -#ifdef INCLUDE_CALCULATOR - #include "../../demo/common/calculator.c" -#endif -#ifdef INCLUDE_CANVAS - #include "../../demo/common/canvas.c" -#endif -#ifdef INCLUDE_OVERVIEW - #include "../../demo/common/overview.c" -#endif -#ifdef INCLUDE_CONFIGURATOR - #include "../../demo/common/style_configurator.c" -#endif -#ifdef INCLUDE_NODE_EDITOR - #include "../../demo/common/node_editor.c" -#endif - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -int -main(void) -{ - long dt; - long started; - int running = 1; - XWindow xw; - struct nk_context *ctx; - - #ifdef INCLUDE_CONFIGURATOR - static struct nk_color color_table[NK_COLOR_COUNT]; - memcpy(color_table, nk_default_color_style, sizeof(color_table)); - #endif - - /* X11 */ - memset(&xw, 0, sizeof xw); - xw.dpy = XOpenDisplay(NULL); - if (!xw.dpy) die("Could not open a display; perhaps $DISPLAY is not set?"); - xw.root = DefaultRootWindow(xw.dpy); - xw.screen = XDefaultScreen(xw.dpy); - xw.vis = XDefaultVisual(xw.dpy, xw.screen); - xw.cmap = XCreateColormap(xw.dpy,xw.root,xw.vis,AllocNone); - - xw.swa.colormap = xw.cmap; - xw.swa.event_mask = - ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPress | ButtonReleaseMask| ButtonMotionMask | - Button1MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask| - PointerMotionMask | KeymapStateMask; - xw.win = XCreateWindow(xw.dpy, xw.root, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, - XDefaultDepth(xw.dpy, xw.screen), InputOutput, - xw.vis, CWEventMask | CWColormap, &xw.swa); - - XStoreName(xw.dpy, xw.win, "X11"); - XMapWindow(xw.dpy, xw.win); - xw.wm_delete_window = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wm_delete_window, 1); - XGetWindowAttributes(xw.dpy, xw.win, &xw.attr); - xw.width = (unsigned int)xw.attr.width; - xw.height = (unsigned int)xw.attr.height; - - /* GUI */ - xw.font = nk_xfont_create(xw.dpy, "Arial"); - ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, -#ifdef NK_XLIB_USE_XFT - xw.vis, xw.cmap, -#endif - xw.width, xw.height); - - while (running) - { - /* Input */ - XEvent evt; - started = timestamp(); - nk_input_begin(ctx); - while (XPending(xw.dpy)) { - XNextEvent(xw.dpy, &evt); - if (evt.type == ClientMessage) goto cleanup; - if (XFilterEvent(&evt, xw.win)) continue; - nk_xlib_handle_event(xw.dpy, xw.screen, xw.win, &evt); - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - } - nk_end(ctx); - if (nk_window_is_hidden(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - #ifdef INCLUDE_CALCULATOR - calculator(ctx); - #endif - #ifdef INCLUDE_CANVAS - canvas(ctx); - #endif - #ifdef INCLUDE_OVERVIEW - overview(ctx); - #endif - #ifdef INCLUDE_CONFIGURATOR - style_configurator(ctx, color_table); - #endif - #ifdef INCLUDE_NODE_EDITOR - node_editor(ctx); - #endif - /* ----------------------------------------- */ - - /* Draw */ - XClearWindow(xw.dpy, xw.win); - nk_xlib_render(xw.win, nk_rgb(30,30,30)); - XFlush(xw.dpy); - - /* Timing */ - dt = timestamp() - started; - if (dt < DTIME) - sleep_for(DTIME - dt); - } - -cleanup: - nk_xfont_del(xw.dpy, xw.font); - nk_xlib_shutdown(); - XUnmapWindow(xw.dpy, xw.win); - XFreeColormap(xw.dpy, xw.cmap); - XDestroyWindow(xw.dpy, xw.win); - XCloseDisplay(xw.dpy); - return 0; -} - diff --git a/demo/x11_xft/nuklear_xlib.h b/demo/x11_xft/nuklear_xlib.h deleted file mode 100644 index 7fcd98f49..000000000 --- a/demo/x11_xft/nuklear_xlib.h +++ /dev/null @@ -1,1086 +0,0 @@ -/* - * Nuklear - v1.40.8 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2017 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_XLIB_H_ -#define NK_XLIB_H_ - -#include - -typedef struct XFont XFont; -#ifdef NK_XLIB_USE_XFT -NK_API struct nk_context* nk_xlib_init(XFont*, Display*, int scrn, Window root, Visual *vis, Colormap cmap, unsigned w, unsigned h); -#else -NK_API struct nk_context* nk_xlib_init(XFont*, Display*, int scrn, Window root, unsigned w, unsigned h); -#endif -NK_API int nk_xlib_handle_event(Display*, int scrn, Window, XEvent*); -NK_API void nk_xlib_render(Drawable screen, struct nk_color clear); -NK_API void nk_xlib_shutdown(void); -NK_API void nk_xlib_set_font(XFont*); -NK_API void nk_xlib_push_font(XFont*); -NK_API void nk_xlib_paste(nk_handle, struct nk_text_edit*); -NK_API void nk_xlib_copy(nk_handle, const char*, int len); - -/* Image */ -#ifdef NK_XLIB_INCLUDE_STB_IMAGE -NK_API struct nk_image nk_xsurf_load_image_from_file(char const *filename); -NK_API struct nk_image nk_xsurf_load_image_from_memory(const void *membuf, nk_uint membufSize); -#endif - -/* Font */ -NK_API XFont* nk_xfont_create(Display *dpy, const char *name); -NK_API void nk_xfont_del(Display *dpy, XFont *font); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_XLIB_IMPLEMENTATION -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef NK_XLIB_USE_XFT -#include -#endif - -#include -#include -#include - - -#ifdef NK_XLIB_IMPLEMENT_STB_IMAGE -#define STB_IMAGE_IMPLEMENTATION -#endif - -#ifdef NK_XLIB_INCLUDE_STB_IMAGE -#include "../../example/stb_image.h" -#endif - - -#ifndef NK_X11_DOUBLE_CLICK_LO -#define NK_X11_DOUBLE_CLICK_LO 0.02 -#endif -#ifndef NK_X11_DOUBLE_CLICK_HI -#define NK_X11_DOUBLE_CLICK_HI 0.20 -#endif - -typedef struct XSurface XSurface; -typedef struct XImageWithAlpha XImageWithAlpha; -struct XFont { - int ascent; - int descent; - int height; -#ifdef NK_XLIB_USE_XFT - XftFont * ft; -#else - XFontSet set; - XFontStruct *xfont; -#endif - struct nk_user_font handle; -}; -struct XSurface { - GC gc; - Display *dpy; - int screen; - Window root; - Drawable drawable; - unsigned int w, h; -#ifdef NK_XLIB_USE_XFT - XftDraw * ftdraw; -#endif -}; -struct XImageWithAlpha { - XImage* ximage; - GC clipMaskGC; - Pixmap clipMask; -}; -static struct { - char *clipboard_data; - int clipboard_len; - struct nk_text_edit* clipboard_target; - - Atom xa_clipboard; - Atom xa_targets; - Atom xa_text; - Atom xa_utf8_string; - - struct nk_context ctx; - struct XSurface *surf; - Cursor cursor; - Display *dpy; - Window root; -#ifdef NK_XLIB_USE_XFT - Visual *vis; - Colormap cmap; -#endif - double last_button_click; - double time_of_last_frame; -} xlib; - -NK_INTERN double -nk_get_time(void) -{ - struct timeval tv; - if (gettimeofday(&tv, NULL) < 0) return 0; - return ((double)tv.tv_sec + (double)tv.tv_usec/1000000); -} - -NK_INTERN unsigned long -nk_color_from_byte(const nk_byte *c) -{ - unsigned long res = 0; - res |= (unsigned long)c[0] << 16; - res |= (unsigned long)c[1] << 8; - res |= (unsigned long)c[2] << 0; - return (res); -} - -NK_INTERN XSurface* -nk_xsurf_create(int screen, unsigned int w, unsigned int h) -{ - XSurface *surface = (XSurface*)calloc(1, sizeof(XSurface)); - surface->w = w; - surface->h = h; - surface->dpy = xlib.dpy; - surface->screen = screen; - surface->root = xlib.root; - surface->gc = XCreateGC(xlib.dpy, xlib.root, 0, NULL); - XSetLineAttributes(xlib.dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter); - surface->drawable = XCreatePixmap(xlib.dpy, xlib.root, w, h, - (unsigned int)DefaultDepth(xlib.dpy, screen)); -#ifdef NK_XLIB_USE_XFT - surface->ftdraw = XftDrawCreate(xlib.dpy, surface->drawable, - xlib.vis, xlib.cmap); -#endif - return surface; -} - -NK_INTERN void -nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h) -{ - if(!surf) return; - if (surf->w == w && surf->h == h) return; - surf->w = w; surf->h = h; - if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable); - surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h, - (unsigned int)DefaultDepth(surf->dpy, surf->screen)); -#ifdef NK_XLIB_USE_XFT - XftDrawChange(surf->ftdraw, surf->drawable); -#endif - return; -} - -NK_INTERN void -nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h) -{ - XRectangle clip_rect; - clip_rect.x = (short)(x-1); - clip_rect.y = (short)(y-1); - clip_rect.width = (unsigned short)(w+2); - clip_rect.height = (unsigned short)(h+2); - XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted); - -#ifdef NK_XLIB_USE_XFT - XftDrawSetClipRectangles(surf->ftdraw, 0, 0, &clip_rect, 1); -#endif - return; -} - -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) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -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) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - if (r == 0) {XDrawRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);return;} - - {short xc = x + r; - short yc = y + r; - short wc = (short)(w - 2 * r); - short hc = (short)(h - 2 * r); - - XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y, xc+wc, y); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x+w, yc, x+w, yc+hc); - XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y+h, xc+wc, y+h); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x, yc, x, yc+hc); - - XDrawArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y, - (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64); - XDrawArc(surf->dpy, surf->drawable, surf->gc, x, y, - (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64); - XDrawArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64); - XDrawArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);} - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -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) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - if (r == 0) {XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h); return;} - - {short xc = x + r; - short yc = y + r; - short wc = (short)(w - 2 * r); - short hc = (short)(h - 2 * r); - - XPoint pnts[12]; - pnts[0].x = x; - pnts[0].y = yc; - pnts[1].x = xc; - pnts[1].y = yc; - pnts[2].x = xc; - pnts[2].y = y; - - pnts[3].x = xc + wc; - pnts[3].y = y; - pnts[4].x = xc + wc; - pnts[4].y = yc; - pnts[5].x = x + w; - pnts[5].y = yc; - - pnts[6].x = x + w; - pnts[6].y = yc + hc; - pnts[7].x = xc + wc; - pnts[7].y = yc + hc; - pnts[8].x = xc + wc; - pnts[8].y = y + h; - - pnts[9].x = xc; - pnts[9].y = y + h; - pnts[10].x = xc; - pnts[10].y = yc + hc; - pnts[11].x = x; - pnts[11].y = yc + hc; - - XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 12, Convex, CoordModeOrigin); - XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y, - (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64); - XFillArc(surf->dpy, surf->drawable, surf->gc, x, y, - (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64); - XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64); - XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);} -} - -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) -{ - XPoint pnts[3]; - unsigned long c = nk_color_from_byte(&col.r); - pnts[0].x = (short)x0; - pnts[0].y = (short)y0; - pnts[1].x = (short)x1; - pnts[1].y = (short)y1; - pnts[2].x = (short)x2; - pnts[2].y = (short)y2; - XSetForeground(surf->dpy, surf->gc, c); - XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin); -} - -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) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x1, y1, x2, y2); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x2, y2, x0, y0); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -NK_INTERN void -nk_xsurf_fill_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count, - struct nk_color col) -{ - int i = 0; - #define MAX_POINTS 128 - XPoint xpnts[MAX_POINTS]; - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - for (i = 0; i < count && i < MAX_POINTS; ++i) { - xpnts[i].x = pnts[i].x; - xpnts[i].y = pnts[i].y; - } - XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin); - #undef MAX_POINTS -} - -NK_INTERN void -nk_xsurf_stroke_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count, - unsigned short line_thickness, struct nk_color col) -{ - int i = 0; - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - for (i = 1; i < count; ++i) - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y); - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -NK_INTERN void -nk_xsurf_stroke_polyline(XSurface *surf, const struct nk_vec2i *pnts, - int count, unsigned short line_thickness, struct nk_color col) -{ - int i = 0; - unsigned long c = nk_color_from_byte(&col.r); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XSetForeground(surf->dpy, surf->gc, c); - for (i = 0; i < count-1; ++i) - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i].x, pnts[i].y, pnts[i+1].x, pnts[i+1].y); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -NK_INTERN void -nk_xsurf_fill_circle(XSurface *surf, short x, short y, unsigned short w, - unsigned short h, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XFillArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, - (unsigned)w, (unsigned)h, 0, 360 * 64); -} - -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) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XSetForeground(surf->dpy, surf->gc, c); - XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, - (unsigned)w, (unsigned)h, 0, 360 * 64); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -NK_INTERN void -nk_xsurf_stroke_arc(XSurface *surf, short cx, short cy, unsigned short radius, - float a_min, float a_max, unsigned short line_thickness, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XSetForeground(surf->dpy, surf->gc, c); - XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)(cx - radius), (int)(cy - radius), - (unsigned)(radius * 2), (unsigned)(radius * 2), - (int)(a_min * 180 * 64 / NK_PI), (int)(a_max * 180 * 64 / NK_PI)); -} - -NK_INTERN void -nk_xsurf_fill_arc(XSurface *surf, short cx, short cy, unsigned short radius, - float a_min, float a_max, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XFillArc(surf->dpy, surf->drawable, surf->gc, (int)(cx - radius), (int)(cy - radius), - (unsigned)(radius * 2), (unsigned)(radius * 2), - (int)(a_min * 180 * 64 / NK_PI), (int)(a_max * 180 * 64 / NK_PI)); -} - -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) -{ - unsigned int i_step; - float t_step; - struct nk_vec2i last = p1; - - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - 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; - float u = 1.0f - t; - float w1 = u*u*u; - float w2 = 3*u*u*t; - float w3 = 3*u*t*t; - float w4 = t * t *t; - float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; - float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; - nk_xsurf_stroke_line(surf, last.x, last.y, (short)x, (short)y, line_thickness,col); - last.x = (short)x; last.y = (short)y; - } - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -NK_INTERN void -nk_xsurf_draw_text(XSurface *surf, short x, short y, const char *text, int len, - XFont *font, struct nk_color cfg) -{ -#ifdef NK_XLIB_USE_XFT - XRenderColor xrc; - XftColor color; -#else - unsigned long fg = nk_color_from_byte(&cfg.r); -#endif - int tx, ty; - - if(!text || !font || !len) return; - - tx = (int)x; - ty = (int)y + font->ascent; -#ifdef NK_XLIB_USE_XFT - xrc.red = cfg.r * 257; - xrc.green = cfg.g * 257; - xrc.blue = cfg.b * 257; - xrc.alpha = cfg.a * 257; - XftColorAllocValue(surf->dpy, xlib.vis, xlib.cmap, &xrc, &color); - XftDrawStringUtf8(surf->ftdraw, &color, font->ft, tx, ty, (FcChar8*)text, len); - XftColorFree(surf->dpy, xlib.vis, xlib.cmap, &color); -#else - XSetForeground(surf->dpy, surf->gc, fg); - if(font->set) XmbDrawString(surf->dpy,surf->drawable, font->set, surf->gc, tx, ty, (const char*)text, (int)len); - else XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len); -#endif - return; -} - - -#ifdef NK_XLIB_INCLUDE_STB_IMAGE -NK_INTERN struct nk_image -nk_stbi_image_to_xsurf(unsigned char *data, int width, int height, int channels) { - XSurface *surf = xlib.surf; - struct nk_image img; - int bpl = channels; - long i, isize = width*height*channels; - XImageWithAlpha *aimage = (XImageWithAlpha*)calloc( 1, sizeof(XImageWithAlpha) ); - int depth = DefaultDepth(surf->dpy, surf->screen); - if (data == NULL) return nk_image_id(0); - if (aimage == NULL) return nk_image_id(0); - - switch (depth){ - case 24: - bpl = 4; - break; - case 16: - case 15: - bpl = 2; - break; - default: - bpl = 1; - break; - } - - /* rgba to bgra */ - if (channels >= 3){ - for (i=0; i < isize; i += channels) { - unsigned char red = data[i+2]; - unsigned char blue = data[i]; - data[i] = red; - data[i+2] = blue; - } - } - - if (channels == 4){ - const unsigned alpha_treshold = 127; - aimage->clipMask = XCreatePixmap(surf->dpy, surf->drawable, width, height, 1); - - if( aimage->clipMask ){ - aimage->clipMaskGC = XCreateGC(surf->dpy, aimage->clipMask, 0, 0); - XSetForeground(surf->dpy, aimage->clipMaskGC, BlackPixel(surf->dpy, surf->screen)); - XFillRectangle(surf->dpy, aimage->clipMask, aimage->clipMaskGC, 0, 0, width, height); - - XSetForeground(surf->dpy, aimage->clipMaskGC, WhitePixel(surf->dpy, surf->screen)); - for (i=0; i < isize; i += channels){ - unsigned char alpha = data[i+3]; - int div = i / channels; - int x = div % width; - int y = div / width; - if( alpha > alpha_treshold ) - XDrawPoint(surf->dpy, aimage->clipMask, aimage->clipMaskGC, x, y); - } - } - } - - aimage->ximage = XCreateImage(surf->dpy, - CopyFromParent, depth, - ZPixmap, 0, - (char*)data, - width, height, - bpl*8, bpl * width); - img = nk_image_ptr( (void*)aimage); - img.h = height; - img.w = width; - return img; -} - -NK_API struct nk_image -nk_xsurf_load_image_from_memory(const void *membuf, nk_uint membufSize) -{ - int x,y,n; - unsigned char *data; - data = stbi_load_from_memory(membuf, membufSize, &x, &y, &n, 0); - return nk_stbi_image_to_xsurf(data, x, y, n); -} - -NK_API struct nk_image -nk_xsurf_load_image_from_file(char const *filename) -{ - int x,y,n; - unsigned char *data; - data = stbi_load(filename, &x, &y, &n, 0); - return nk_stbi_image_to_xsurf(data, x, y, n); -} -#endif /* NK_XLIB_INCLUDE_STB_IMAGE */ - -NK_INTERN void -nk_xsurf_draw_image(XSurface *surf, short x, short y, unsigned short w, unsigned short h, - struct nk_image img, struct nk_color col) -{ - XImageWithAlpha *aimage = img.handle.ptr; - - NK_UNUSED(col); - - if (aimage){ - if (aimage->clipMask){ - XSetClipMask(surf->dpy, surf->gc, aimage->clipMask); - XSetClipOrigin(surf->dpy, surf->gc, x, y); - } - XPutImage(surf->dpy, surf->drawable, surf->gc, aimage->ximage, 0, 0, x, y, w, h); - XSetClipMask(surf->dpy, surf->gc, None); - } -} - -void -nk_xsurf_image_free(struct nk_image* image) -{ - XSurface *surf = xlib.surf; - XImageWithAlpha *aimage = image->handle.ptr; - if (!aimage) return; - XDestroyImage(aimage->ximage); - XFreePixmap(surf->dpy, aimage->clipMask); - XFreeGC(surf->dpy, aimage->clipMaskGC); - free(aimage); -} - - -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); -} - -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); -} - -NK_INTERN void -nk_xsurf_del(XSurface *surf) -{ -#ifdef NK_XLIB_USE_XFT - XftDrawDestroy(surf->ftdraw); -#endif - XFreePixmap(surf->dpy, surf->drawable); - XFreeGC(surf->dpy, surf->gc); - free(surf); -} - -NK_API XFont* -nk_xfont_create(Display *dpy, const char *name) -{ -#ifdef NK_XLIB_USE_XFT - XFont *font = (XFont*)calloc(1, sizeof(XFont)); - font->ft = XftFontOpenName(dpy, XDefaultScreen(dpy), name); - if (!font->ft) { - fprintf(stderr, "missing font: %s\n", name); - return font; - } - font->ascent = font->ft->ascent; - font->descent = font->ft->descent; - font->height = font->ft->height; -#else - int n; - char *def, **missing; - XFont *font = (XFont*)calloc(1, sizeof(XFont)); - font->set = XCreateFontSet(dpy, name, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - if(font->set) { - XFontStruct **xfonts; - char **font_names; - XExtentsOfFontSet(font->set); - n = XFontsOfFontSet(font->set, &xfonts, &font_names); - while(n--) { - font->ascent = NK_MAX(font->ascent, (*xfonts)->ascent); - font->descent = NK_MAX(font->descent,(*xfonts)->descent); - xfonts++; - } - } else { - if(!(font->xfont = XLoadQueryFont(dpy, name)) - && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) { - free(font); - return 0; - } - font->ascent = font->xfont->ascent; - font->descent = font->xfont->descent; - } - font->height = font->ascent + font->descent; -#endif - return font; -} - -NK_INTERN float -nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int len) -{ - XFont *font = (XFont*)handle.ptr; - -#ifdef NK_XLIB_USE_XFT - XGlyphInfo g; - - NK_UNUSED(height); - - if(!font || !text) - return 0; - - XftTextExtentsUtf8(xlib.dpy, font->ft, (FcChar8*)text, len, &g); - return g.xOff; -#else - XRectangle r; - - NK_UNUSED(height); - - if(!font || !text) - return 0; - - if(font->set) { - XmbTextExtents(font->set, (const char*)text, len, NULL, &r); - return (float)r.width; - } else{ - int w = XTextWidth(font->xfont, (const char*)text, len); - return (float)w; - } -#endif -} - -NK_API void -nk_xfont_del(Display *dpy, XFont *font) -{ - if(!font) return; -#ifdef NK_XLIB_USE_XFT - XftFontClose(dpy, font->ft); -#else - if(font->set) - XFreeFontSet(dpy, font->set); - else - XFreeFont(dpy, font->xfont); -#endif - free(font); -} - -NK_API struct nk_context* -nk_xlib_init(XFont *xfont, Display *dpy, int screen, Window root, -#ifdef NK_XLIB_USE_XFT - Visual *vis, Colormap cmap, -#endif - unsigned int w, unsigned int h) -{ - struct nk_user_font *font = &xfont->handle; - font->userdata = nk_handle_ptr(xfont); - font->height = (float)xfont->height; - font->width = nk_xfont_get_text_width; - xlib.dpy = dpy; - xlib.root = root; -#ifdef NK_XLIB_USE_XFT - xlib.vis = vis; - xlib.cmap = cmap; -#endif - - if (!setlocale(LC_ALL,"")) return 0; - if (!XSupportsLocale()) return 0; - if (!XSetLocaleModifiers("@im=none")) return 0; - - xlib.xa_clipboard = XInternAtom(dpy, "CLIPBOARD", False); - xlib.xa_targets = XInternAtom(dpy, "TARGETS", False); - xlib.xa_text = XInternAtom(dpy, "TEXT", False); - xlib.xa_utf8_string = XInternAtom(dpy, "UTF8_STRING", False); - - /* create invisible cursor */ - {static XColor dummy; char data[1] = {0}; - Pixmap blank = XCreateBitmapFromData(dpy, root, data, 1, 1); - if (blank == None) return 0; - xlib.cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0); - XFreePixmap(dpy, blank);} - xlib.surf = nk_xsurf_create(screen, w, h); - nk_init_default(&xlib.ctx, font); - xlib.time_of_last_frame = nk_get_time(); - return &xlib.ctx; -} - -NK_API void -nk_xlib_set_font(XFont *xfont) -{ - struct nk_user_font *font = &xfont->handle; - font->userdata = nk_handle_ptr(xfont); - font->height = (float)xfont->height; - font->width = nk_xfont_get_text_width; - nk_style_set_font(&xlib.ctx, font); -} - -NK_API void -nk_xlib_push_font(XFont *xfont) -{ - struct nk_user_font *font = &xfont->handle; - font->userdata = nk_handle_ptr(xfont); - font->height = (float)xfont->height; - font->width = nk_xfont_get_text_width; - nk_style_push_font(&xlib.ctx, font); -} - -NK_API void -nk_xlib_paste(nk_handle handle, struct nk_text_edit* edit) -{ - NK_UNUSED(handle); - /* Paste in X is asynchronous, so can not use a temporary text edit */ - NK_ASSERT(edit != &xlib.ctx.text_edit && "Paste not supported for temporary editors"); - xlib.clipboard_target = edit; - /* Request the contents of the primary buffer */ - XConvertSelection(xlib.dpy, XA_PRIMARY, XA_STRING, XA_PRIMARY, xlib.root, CurrentTime); -} - -NK_API void -nk_xlib_copy(nk_handle handle, const char* str, int len) -{ - NK_UNUSED(handle); - free(xlib.clipboard_data); - xlib.clipboard_len = 0; - xlib.clipboard_data = malloc((size_t)len); - if (xlib.clipboard_data) { - memcpy(xlib.clipboard_data, str, (size_t)len); - xlib.clipboard_len = len; - XSetSelectionOwner(xlib.dpy, XA_PRIMARY, xlib.root, CurrentTime); - XSetSelectionOwner(xlib.dpy, xlib.xa_clipboard, xlib.root, CurrentTime); - } -} - -NK_API int -nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt) -{ - struct nk_context *ctx = &xlib.ctx; - - NK_UNUSED(screen); - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) { - XDefineCursor(xlib.dpy, xlib.root, xlib.cursor); - ctx->input.mouse.grab = 0; - } else if (ctx->input.mouse.ungrab) { - XWarpPointer(xlib.dpy, None, xlib.root, 0, 0, 0, 0, - (int)ctx->input.mouse.prev.x, (int)ctx->input.mouse.prev.y); - XUndefineCursor(xlib.dpy, xlib.root); - ctx->input.mouse.ungrab = 0; - } - - if (evt->type == KeyPress || evt->type == KeyRelease) - { - /* Key handler */ - int ret, down = (evt->type == KeyPress); - KeySym *code = XGetKeyboardMapping(xlib.surf->dpy, (KeyCode)evt->xkey.keycode, 1, &ret); - if (*code == XK_Shift_L || *code == XK_Shift_R) nk_input_key(ctx, NK_KEY_SHIFT, down); - else if (*code == XK_Control_L || *code == XK_Control_R) nk_input_key(ctx, NK_KEY_CTRL, down); - else if (*code == XK_Delete) nk_input_key(ctx, NK_KEY_DEL, down); - else if (*code == XK_Return) nk_input_key(ctx, NK_KEY_ENTER, down); - else if (*code == XK_Tab) nk_input_key(ctx, NK_KEY_TAB, down); - else if (*code == XK_Left) nk_input_key(ctx, NK_KEY_LEFT, down); - else if (*code == XK_Right) nk_input_key(ctx, NK_KEY_RIGHT, down); - else if (*code == XK_Up) nk_input_key(ctx, NK_KEY_UP, down); - else if (*code == XK_Down) nk_input_key(ctx, NK_KEY_DOWN, down); - else if (*code == XK_BackSpace) nk_input_key(ctx, NK_KEY_BACKSPACE, down); - else if (*code == XK_Escape) nk_input_key(ctx, NK_KEY_TEXT_RESET_MODE, down); - else if (*code == XK_Page_Up) nk_input_key(ctx, NK_KEY_SCROLL_UP, down); - else if (*code == XK_Page_Down) nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); - else if (*code == XK_Home) { - nk_input_key(ctx, NK_KEY_TEXT_START, down); - nk_input_key(ctx, NK_KEY_SCROLL_START, down); - } else if (*code == XK_End) { - nk_input_key(ctx, NK_KEY_TEXT_END, down); - nk_input_key(ctx, NK_KEY_SCROLL_END, down); - } else { - if (*code == 'c' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_COPY, down); - else if (*code == 'v' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_PASTE, down); - else if (*code == 'x' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_CUT, down); - else if (*code == 'z' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_UNDO, down); - else if (*code == 'r' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_REDO, down); - else if (*code == XK_Left && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down); - else if (*code == XK_Right && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else if (*code == 'b' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down); - else if (*code == 'e' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down); - else if (*code == 'a' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx,NK_KEY_TEXT_SELECT_ALL, down); - else { - if (*code == 'i') - nk_input_key(ctx, NK_KEY_TEXT_INSERT_MODE, down); - else if (*code == 'r') - nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, down); - if (down) { - char buf[32]; - KeySym keysym = 0; - if (XLookupString((XKeyEvent*)evt, buf, 32, &keysym, NULL) != NoSymbol) - nk_input_glyph(ctx, buf); - } - } - } - XFree(code); - return 1; - } else if (evt->type == ButtonPress || evt->type == ButtonRelease) { - /* Button handler */ - int down = (evt->type == ButtonPress); - const int x = evt->xbutton.x, y = evt->xbutton.y; - if (evt->xbutton.button == Button1) { - if (down) { /* Double-Click Button handler */ - float dt = nk_get_time() - 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_get_time(); - } else nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, nk_false); - nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); - } 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); - else if (evt->xbutton.button == Button4) - nk_input_scroll(ctx, nk_vec2(0, 1.0f)); - else if (evt->xbutton.button == Button5) - nk_input_scroll(ctx, nk_vec2(0, -1.0f)); - else return 0; - return 1; - } else if (evt->type == MotionNotify) { - /* Mouse motion handler */ - const int x = evt->xmotion.x, y = evt->xmotion.y; - nk_input_motion(ctx, x, y); - if (ctx->input.mouse.grabbed) { - ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; - ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; - XWarpPointer(xlib.dpy, None, xlib.surf->root, 0, 0, 0, 0, (int)ctx->input.mouse.pos.x, (int)ctx->input.mouse.pos.y); - } - return 1; - } else if (evt->type == Expose || evt->type == ConfigureNotify) { - /* Window resize handler */ - unsigned int width, height; - XWindowAttributes attr; - XGetWindowAttributes(dpy, win, &attr); - width = (unsigned int)attr.width; - height = (unsigned int)attr.height; - nk_xsurf_resize(xlib.surf, width, height); - return 1; - } else if (evt->type == KeymapNotify) { - XRefreshKeyboardMapping(&evt->xmapping); - return 1; - } else if (evt->type == SelectionClear) { - free(xlib.clipboard_data); - xlib.clipboard_data = NULL; - xlib.clipboard_len = 0; - return 1; - } else if (evt->type == SelectionRequest) { - XEvent reply; - reply.xselection.type = SelectionNotify; - reply.xselection.requestor = evt->xselectionrequest.requestor; - reply.xselection.selection = evt->xselectionrequest.selection; - reply.xselection.target = evt->xselectionrequest.target; - reply.xselection.property = None; /* Default refuse */ - reply.xselection.time = evt->xselectionrequest.time; - - if (reply.xselection.target == xlib.xa_targets) { - Atom target_list[4]; - target_list[0] = xlib.xa_targets; - target_list[1] = xlib.xa_text; - target_list[2] = xlib.xa_utf8_string; - target_list[3] = XA_STRING; - - reply.xselection.property = evt->xselectionrequest.property; - XChangeProperty(evt->xselection.display,evt->xselectionrequest.requestor, - reply.xselection.property, XA_ATOM, 32, PropModeReplace, - (unsigned char*)&target_list, 4); - } else if (xlib.clipboard_data && (reply.xselection.target == xlib.xa_text || - reply.xselection.target == xlib.xa_utf8_string || reply.xselection.target == XA_STRING)) { - reply.xselection.property = evt->xselectionrequest.property; - XChangeProperty(evt->xselection.display,evt->xselectionrequest.requestor, - reply.xselection.property, reply.xselection.target, 8, PropModeReplace, - (unsigned char*)xlib.clipboard_data, xlib.clipboard_len); - } - XSendEvent(evt->xselection.display, evt->xselectionrequest.requestor, True, 0, &reply); - XFlush(evt->xselection.display); - return 1; - } else if (evt->type == SelectionNotify && xlib.clipboard_target) { - if ((evt->xselection.target != XA_STRING) && - (evt->xselection.target != xlib.xa_utf8_string) && - (evt->xselection.target != xlib.xa_text)) - return 1; - - {Atom actual_type; - int actual_format; - unsigned long pos = 0, len, remain; - unsigned char* data = 0; - do { - XGetWindowProperty(dpy, win, XA_PRIMARY, (int)pos, 1024, False, - AnyPropertyType, &actual_type, &actual_format, &len, &remain, &data); - if (len && data) - nk_textedit_text(xlib.clipboard_target, (char*)data, (int)len); - if (data != 0) XFree(data); - pos += (len * (unsigned long)actual_format) / 32; - } while (remain != 0);} - return 1; - } - return 0; -} - -NK_API void -nk_xlib_shutdown(void) -{ - nk_xsurf_del(xlib.surf); - nk_free(&xlib.ctx); - XFreeCursor(xlib.dpy, xlib.cursor); - memset(&xlib, 0, sizeof(xlib)); -} - -NK_API void -nk_xlib_render(Drawable screen, struct nk_color clear) -{ - const struct nk_command *cmd; - struct nk_context *ctx = &xlib.ctx; - XSurface *surf = xlib.surf; - - double now = nk_get_time(); - xlib.ctx.delta_time_seconds = now - xlib.time_of_last_frame; - xlib.time_of_last_frame = now; - - nk_xsurf_clear(xlib.surf, nk_color_from_byte(&clear.r)); - nk_foreach(cmd, &xlib.ctx) - { - switch (cmd->type) { - case NK_COMMAND_NOP: break; - case NK_COMMAND_SCISSOR: { - const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd; - nk_xsurf_scissor(surf, s->x, s->y, s->w, s->h); - } break; - case NK_COMMAND_LINE: { - const struct nk_command_line *l = (const struct nk_command_line *)cmd; - nk_xsurf_stroke_line(surf, l->begin.x, l->begin.y, l->end.x, - l->end.y, l->line_thickness, l->color); - } break; - case NK_COMMAND_RECT: { - const struct nk_command_rect *r = (const struct nk_command_rect *)cmd; - nk_xsurf_stroke_rect(surf, r->x, r->y, NK_MAX(r->w -r->line_thickness, 0), - NK_MAX(r->h - r->line_thickness, 0), (unsigned short)r->rounding, - r->line_thickness, r->color); - } break; - case NK_COMMAND_RECT_FILLED: { - const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd; - nk_xsurf_fill_rect(surf, r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->color); - } break; - case NK_COMMAND_CIRCLE: { - const struct nk_command_circle *c = (const struct nk_command_circle *)cmd; - nk_xsurf_stroke_circle(surf, c->x, c->y, c->w, c->h, c->line_thickness, c->color); - } break; - case NK_COMMAND_CIRCLE_FILLED: { - const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; - nk_xsurf_fill_circle(surf, c->x, c->y, c->w, c->h, c->color); - } break; - case NK_COMMAND_ARC: { - const struct nk_command_arc *a = (const struct nk_command_arc *)cmd; - nk_xsurf_stroke_arc(surf, a->cx, a->cy, a->r, a->a[0], a->a[1], a->line_thickness, a->color); - } break; - case NK_COMMAND_ARC_FILLED: { - const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled *)cmd; - nk_xsurf_fill_arc(surf, a->cx, a->cy, a->r, a->a[0], a->a[1], a->color); - } break; - case NK_COMMAND_TRIANGLE: { - const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd; - nk_xsurf_stroke_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->line_thickness, t->color); - } break; - case NK_COMMAND_TRIANGLE_FILLED: { - const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd; - nk_xsurf_fill_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->color); - } break; - case NK_COMMAND_POLYGON: { - const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd; - nk_xsurf_stroke_polygon(surf, p->points, p->point_count, p->line_thickness,p->color); - } break; - case NK_COMMAND_POLYGON_FILLED: { - const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd; - nk_xsurf_fill_polygon(surf, p->points, p->point_count, p->color); - } break; - case NK_COMMAND_POLYLINE: { - const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd; - nk_xsurf_stroke_polyline(surf, p->points, p->point_count, p->line_thickness, p->color); - } break; - case NK_COMMAND_TEXT: { - const struct nk_command_text *t = (const struct nk_command_text*)cmd; - nk_xsurf_draw_text(surf, t->x, t->y, (const char*)t->string, t->length, - (XFont*)t->font->userdata.ptr, t->foreground); - } break; - case NK_COMMAND_CURVE: { - const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; - nk_xsurf_stroke_curve(surf, q->begin, q->ctrl[0], q->ctrl[1], - q->end, 22, q->line_thickness, q->color); - } break; - case NK_COMMAND_IMAGE: { - const struct nk_command_image *i = (const struct nk_command_image *)cmd; - nk_xsurf_draw_image(surf, i->x, i->y, i->w, i->h, i->img, i->col); - } break; - case NK_COMMAND_RECT_MULTI_COLOR: - case NK_COMMAND_CUSTOM: - default: break; - } - } - nk_clear(ctx); - nk_xsurf_blit(screen, surf, surf->w, surf->h); -} -#endif