| @@ -74,11 +74,13 @@ | |||||
| // OpenGL includes | // OpenGL includes | ||||
| #ifdef DISTRHO_OS_MAC | #ifdef DISTRHO_OS_MAC | ||||
| # include "OpenGL/gl.h" | |||||
| # include <OpenGL/gl.h> | |||||
| #else | #else | ||||
| # define GL_GLEXT_PROTOTYPES | |||||
| # include "GL/gl.h" | |||||
| # include "GL/glext.h" | |||||
| # ifndef DISTRHO_OS_WINDOWS | |||||
| # define GL_GLEXT_PROTOTYPES | |||||
| # endif | |||||
| # include <GL/gl.h> | |||||
| # include <GL/glext.h> | |||||
| #endif | #endif | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -18,26 +18,38 @@ | |||||
| #include "WidgetPrivateData.hpp" | #include "WidgetPrivateData.hpp" | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // Ignore some warnings if debugging | |||||
| #if 0 //def DEBUG | |||||
| # define NANOVG_GL3 0 | |||||
| # define NANOVG_GLES2 0 | |||||
| # define NANOVG_GLES3 0 | |||||
| # define NANOVG_GL_USE_UNIFORMBUFFER 0 | |||||
| # if defined(__clang__) | |||||
| # pragma clang diagnostic push | |||||
| # pragma clang diagnostic ignored "-Weverything" | |||||
| # elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||||
| # pragma GCC diagnostic push | |||||
| # pragma GCC diagnostic ignored "-Wall" | |||||
| # pragma GCC diagnostic ignored "-Wextra" | |||||
| # pragma GCC diagnostic ignored "-Wconversion" | |||||
| # pragma GCC diagnostic ignored "-Weffc++" | |||||
| # pragma GCC diagnostic ignored "-Wsign-conversion" | |||||
| # pragma GCC diagnostic ignored "-Wundef" | |||||
| # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" | |||||
| # endif | |||||
| #if defined(DISTRHO_OS_WINDOWS) | |||||
| # include <windows.h> | |||||
| # define DGL_EXT(PROC, func) static PROC func; | |||||
| DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) | |||||
| DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) | |||||
| DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) | |||||
| DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer) | |||||
| DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData) | |||||
| DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader) | |||||
| DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) | |||||
| DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader) | |||||
| DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) | |||||
| DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) | |||||
| DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader) | |||||
| DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) | |||||
| DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) | |||||
| DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers) | |||||
| DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) | |||||
| DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) | |||||
| DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv) | |||||
| DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) | |||||
| DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) | |||||
| DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram) | |||||
| DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource) | |||||
| DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) | |||||
| DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i) | |||||
| DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv) | |||||
| DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) | |||||
| DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) | |||||
| DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) | |||||
| # undef DGL_EXT | |||||
| #endif | #endif | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -61,16 +73,48 @@ | |||||
| # define nvgDeleteGL nvgDeleteGLES3 | # define nvgDeleteGL nvgDeleteGLES3 | ||||
| #endif | #endif | ||||
| // ----------------------------------------------------------------------- | |||||
| // Restore normal state if debugging | |||||
| #if 0//def DEBUG | |||||
| # if defined(__clang__) | |||||
| # pragma clang diagnostic pop | |||||
| # elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||||
| # pragma GCC diagnostic pop | |||||
| # endif | |||||
| static NVGcontext* nvgCreateGL_helper(int flags) | |||||
| { | |||||
| #if defined(DISTRHO_OS_WINDOWS) | |||||
| static bool needsInit = true; | |||||
| if (needsInit) | |||||
| { | |||||
| needsInit = false; | |||||
| # define DGL_EXT(PROC, func) \ | |||||
| func = (PROC) wglGetProcAddress ( #func ); \ | |||||
| DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr); | |||||
| DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) | |||||
| DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) | |||||
| DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) | |||||
| DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer) | |||||
| DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData) | |||||
| DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader) | |||||
| DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) | |||||
| DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader) | |||||
| DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) | |||||
| DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) | |||||
| DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader) | |||||
| DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) | |||||
| DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) | |||||
| DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers) | |||||
| DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) | |||||
| DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) | |||||
| DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv) | |||||
| DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) | |||||
| DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) | |||||
| DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram) | |||||
| DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource) | |||||
| DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) | |||||
| DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i) | |||||
| DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv) | |||||
| DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) | |||||
| DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) | |||||
| DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) | |||||
| # undef DGL_EXT | |||||
| } | |||||
| #endif | #endif | ||||
| return nvgCreateGL(flags); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -172,19 +216,14 @@ NanoVG::Paint::operator NVGpaint() const noexcept | |||||
| // NanoVG | // NanoVG | ||||
| NanoVG::NanoVG(int flags) | NanoVG::NanoVG(int flags) | ||||
| : fContext(nvgCreateGL(flags)), | |||||
| : fContext(nvgCreateGL_helper(flags)), | |||||
| fInFrame(false), | fInFrame(false), | ||||
| fIsSubWidget(false) | |||||
| { | |||||
| DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr,); | |||||
| } | |||||
| fIsSubWidget(false) {} | |||||
| NanoVG::NanoVG(NanoWidget* groupWidget) | NanoVG::NanoVG(NanoWidget* groupWidget) | ||||
| : fContext(groupWidget->fContext), | : fContext(groupWidget->fContext), | ||||
| fInFrame(false), | fInFrame(false), | ||||
| fIsSubWidget(true) | |||||
| { | |||||
| } | |||||
| fIsSubWidget(true) {} | |||||
| NanoVG::~NanoVG() | NanoVG::~NanoVG() | ||||
| { | { | ||||
| @@ -208,13 +247,15 @@ void NanoVG::beginFrame(const uint width, const uint height, const float scaleFa | |||||
| void NanoVG::beginFrame(Widget* const widget) | void NanoVG::beginFrame(Widget* const widget) | ||||
| { | { | ||||
| if (fContext == nullptr) return; | |||||
| DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,); | ||||
| DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); | DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); | ||||
| Window& window(widget->getParentWindow()); | |||||
| fInFrame = true; | fInFrame = true; | ||||
| if (fContext == nullptr) | |||||
| return; | |||||
| Window& window(widget->getParentWindow()); | |||||
| nvgBeginFrame(fContext, static_cast<int>(window.getWidth()), static_cast<int>(window.getHeight()), 1.0f); | nvgBeginFrame(fContext, static_cast<int>(window.getWidth()), static_cast<int>(window.getHeight()), 1.0f); | ||||
| } | } | ||||
| @@ -264,6 +264,12 @@ struct Window::PrivateData { | |||||
| fView = nullptr; | fView = nullptr; | ||||
| } | } | ||||
| if (fTitle != nullptr) | |||||
| { | |||||
| std::free(fTitle); | |||||
| fTitle = nullptr; | |||||
| } | |||||
| #if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
| hwnd = 0; | hwnd = 0; | ||||
| #elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
| @@ -677,12 +683,15 @@ struct Window::PrivateData { | |||||
| fSelf->onDisplayAfter(); | fSelf->onDisplayAfter(); | ||||
| } | } | ||||
| void onPuglKeyboard(const bool press, const uint key) | |||||
| int onPuglKeyboard(const bool press, const uint key) | |||||
| { | { | ||||
| DBGp("PUGL: onKeyboard : %i %i\n", press, key); | DBGp("PUGL: onKeyboard : %i %i\n", press, key); | ||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return fModal.childFocus->focus(); | |||||
| { | |||||
| fModal.childFocus->focus(); | |||||
| return 0; | |||||
| } | |||||
| Widget::KeyboardEvent ev; | Widget::KeyboardEvent ev; | ||||
| ev.press = press; | ev.press = press; | ||||
| @@ -695,16 +704,21 @@ struct Window::PrivateData { | |||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onKeyboard(ev)) | if (widget->isVisible() && widget->onKeyboard(ev)) | ||||
| break; | |||||
| return 0; | |||||
| } | } | ||||
| return 1; | |||||
| } | } | ||||
| void onPuglSpecial(const bool press, const Key key) | |||||
| int onPuglSpecial(const bool press, const Key key) | |||||
| { | { | ||||
| DBGp("PUGL: onSpecial : %i %i\n", press, key); | DBGp("PUGL: onSpecial : %i %i\n", press, key); | ||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return fModal.childFocus->focus(); | |||||
| { | |||||
| fModal.childFocus->focus(); | |||||
| return 0; | |||||
| } | |||||
| Widget::SpecialEvent ev; | Widget::SpecialEvent ev; | ||||
| ev.press = press; | ev.press = press; | ||||
| @@ -717,8 +731,10 @@ struct Window::PrivateData { | |||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onSpecial(ev)) | if (widget->isVisible() && widget->onSpecial(ev)) | ||||
| break; | |||||
| return 0; | |||||
| } | } | ||||
| return 1; | |||||
| } | } | ||||
| void onPuglMouse(const int button, const bool press, const int x, const int y) | void onPuglMouse(const int button, const bool press, const int x, const int y) | ||||
| @@ -889,14 +905,14 @@ struct Window::PrivateData { | |||||
| handlePtr->onPuglDisplay(); | handlePtr->onPuglDisplay(); | ||||
| } | } | ||||
| static void onKeyboardCallback(PuglView* view, bool press, uint32_t key) | |||||
| static int onKeyboardCallback(PuglView* view, bool press, uint32_t key) | |||||
| { | { | ||||
| handlePtr->onPuglKeyboard(press, key); | |||||
| return handlePtr->onPuglKeyboard(press, key); | |||||
| } | } | ||||
| static void onSpecialCallback(PuglView* view, bool press, PuglKey key) | |||||
| static int onSpecialCallback(PuglView* view, bool press, PuglKey key) | |||||
| { | { | ||||
| handlePtr->onPuglSpecial(press, static_cast<Key>(key)); | |||||
| return handlePtr->onPuglSpecial(press, static_cast<Key>(key)); | |||||
| } | } | ||||
| static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) | static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) | ||||
| @@ -2280,13 +2280,13 @@ static void stbi__init_zdefaults(void) | |||||
| static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) | static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) | ||||
| { | { | ||||
| int final, type; | |||||
| int final_, type; | |||||
| if (parse_header) | if (parse_header) | ||||
| if (!stbi__parse_zlib_header(a)) return 0; | if (!stbi__parse_zlib_header(a)) return 0; | ||||
| a->num_bits = 0; | a->num_bits = 0; | ||||
| a->code_buffer = 0; | a->code_buffer = 0; | ||||
| do { | do { | ||||
| final = stbi__zreceive(a,1); | |||||
| final_ = stbi__zreceive(a,1); | |||||
| type = stbi__zreceive(a,2); | type = stbi__zreceive(a,2); | ||||
| if (type == 0) { | if (type == 0) { | ||||
| if (!stbi__parse_uncomperssed_block(a)) return 0; | if (!stbi__parse_uncomperssed_block(a)) return 0; | ||||
| @@ -2303,7 +2303,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) | |||||
| } | } | ||||
| if (!stbi__parse_huffman_block(a)) return 0; | if (!stbi__parse_huffman_block(a)) return 0; | ||||
| } | } | ||||
| } while (!final); | |||||
| } while (!final_); | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| @@ -2535,13 +2535,13 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r | |||||
| static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int interlaced) | static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int interlaced) | ||||
| { | { | ||||
| stbi_uc *final; | |||||
| stbi_uc *final_; | |||||
| int p; | int p; | ||||
| if (!interlaced) | if (!interlaced) | ||||
| return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y); | return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y); | ||||
| // de-interlacing | // de-interlacing | ||||
| final = (stbi_uc *) malloc(a->s->img_x * a->s->img_y * out_n); | |||||
| final_ = (stbi_uc *) malloc(a->s->img_x * a->s->img_y * out_n); | |||||
| for (p=0; p < 7; ++p) { | for (p=0; p < 7; ++p) { | ||||
| int xorig[] = { 0,4,0,2,0,1,0 }; | int xorig[] = { 0,4,0,2,0,1,0 }; | ||||
| int yorig[] = { 0,0,4,0,2,0,1 }; | int yorig[] = { 0,0,4,0,2,0,1 }; | ||||
| @@ -2553,19 +2553,19 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_l | |||||
| y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; | y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; | ||||
| if (x && y) { | if (x && y) { | ||||
| if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, x, y)) { | if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, x, y)) { | ||||
| free(final); | |||||
| free(final_); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| for (j=0; j < y; ++j) | for (j=0; j < y; ++j) | ||||
| for (i=0; i < x; ++i) | for (i=0; i < x; ++i) | ||||
| memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, | |||||
| memcpy(final_ + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, | |||||
| a->out + (j*x+i)*out_n, out_n); | a->out + (j*x+i)*out_n, out_n); | ||||
| free(a->out); | free(a->out); | ||||
| raw += (x*out_n+1)*y; | raw += (x*out_n+1)*y; | ||||
| raw_len -= (x*out_n+1)*y; | raw_len -= (x*out_n+1)*y; | ||||
| } | } | ||||
| } | } | ||||
| a->out = final; | |||||
| a->out = final_; | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| @@ -74,8 +74,9 @@ typedef void (*PuglDisplayFunc)(PuglView* view); | |||||
| @param view The view the event occured in. | @param view The view the event occured in. | ||||
| @param press True if the key was pressed, false if released. | @param press True if the key was pressed, false if released. | ||||
| @param key Unicode point of the key pressed. | @param key Unicode point of the key pressed. | ||||
| @return 0 if event was handled, otherwise send event to parent window. | |||||
| */ | */ | ||||
| typedef void (*PuglKeyboardFunc)(PuglView* view, bool press, uint32_t key); | |||||
| typedef int (*PuglKeyboardFunc)(PuglView* view, bool press, uint32_t key); | |||||
| /** | /** | ||||
| A function called when the pointer moves. | A function called when the pointer moves. | ||||
| @@ -129,8 +130,9 @@ typedef void (*PuglScrollFunc)(PuglView* view, int x, int y, float dx, float dy) | |||||
| @param view The view the event occured in. | @param view The view the event occured in. | ||||
| @param press True if the key was pressed, false if released. | @param press True if the key was pressed, false if released. | ||||
| @param key The key pressed. | @param key The key pressed. | ||||
| @return 0 if event was handled, otherwise send event to parent window. | |||||
| */ | */ | ||||
| typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key); | |||||
| typedef int (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key); | |||||
| /** | /** | ||||
| A function called when a filename is selected via file-browser. | A function called when a filename is selected via file-browser. | ||||
| @@ -430,6 +430,7 @@ dispatchKey(PuglView* view, XEvent* event, bool press) | |||||
| { | { | ||||
| KeySym sym; | KeySym sym; | ||||
| char str[5]; | char str[5]; | ||||
| PuglKey special; | |||||
| const int n = XLookupString(&event->xkey, str, 4, &sym, NULL); | const int n = XLookupString(&event->xkey, str, 4, &sym, NULL); | ||||
| if (sym == XK_Escape && view->closeFunc && !press && !view->parent) { | if (sym == XK_Escape && view->closeFunc && !press && !view->parent) { | ||||
| @@ -438,18 +439,31 @@ dispatchKey(PuglView* view, XEvent* event, bool press) | |||||
| return; | return; | ||||
| } | } | ||||
| if (n == 0) { | if (n == 0) { | ||||
| goto send_event; | |||||
| return; | return; | ||||
| } | } | ||||
| if (n > 1) { | if (n > 1) { | ||||
| fprintf(stderr, "warning: Unsupported multi-byte key %X\n", (int)sym); | fprintf(stderr, "warning: Unsupported multi-byte key %X\n", (int)sym); | ||||
| goto send_event; | |||||
| return; | return; | ||||
| } | } | ||||
| const PuglKey special = keySymToSpecial(sym); | |||||
| special = keySymToSpecial(sym); | |||||
| if (special && view->specialFunc) { | if (special && view->specialFunc) { | ||||
| view->specialFunc(view, press, special); | |||||
| if (view->specialFunc(view, press, special) == 0) { | |||||
| return; | |||||
| } | |||||
| } else if (!special && view->keyboardFunc) { | } else if (!special && view->keyboardFunc) { | ||||
| view->keyboardFunc(view, press, str[0]); | |||||
| if (view->keyboardFunc(view, press, str[0]) == 0) { | |||||
| return; | |||||
| } | |||||
| } | |||||
| send_event: | |||||
| if (view->parent != 0) { | |||||
| event->xkey.time = 0; // purposefully set an invalid time, used for feedback detection on bad hosts | |||||
| event->xany.window = view->parent; | |||||
| XSendEvent(view->impl->display, view->parent, False, NoEventMask, event); | |||||
| } | } | ||||
| } | } | ||||
| @@ -479,7 +493,11 @@ puglProcessEvents(PuglView* view) | |||||
| break; | break; | ||||
| } | } | ||||
| if (event.xany.window != view->impl->win) { | |||||
| if (event.xany.window != view->impl->win && | |||||
| (view->parent == 0 || event.xany.window != (Window)view->parent)) { | |||||
| continue; | |||||
| } | |||||
| if ((event.type == KeyPress || event.type == KeyRelease) && event.xkey.time == 0) { | |||||
| continue; | continue; | ||||
| } | } | ||||