From 1531f89ef00658ff7c3a7072a03bee2b1247f671 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 7 Apr 2026 22:42:19 +0900 Subject: [PATCH] better rendering --- include/Mw/TypeDefs.h | 3 ++ src/backend/x11.c | 5 +++ src/core.c | 98 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 7 deletions(-) diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index d1c0e88..62380f0 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -107,6 +107,9 @@ struct _MwWidget { void* root_monofont; void* root_boldmonofont; + int top_step; + MwWidget* draw_queue; + int berserk; }; #endif diff --git a/src/backend/x11.c b/src/backend/x11.c index 5e2843f..0b9c1da 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -9,6 +9,7 @@ static struct { void* lib_xrender; MwBool has_xrender; + int (*XClearWindow)(Display* display, Window w); XImage* (*XCreateImage)(Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int); Display* (*XOpenDisplay)(_Xconst char*); char* (*XKeysymToString)(KeySym); @@ -101,6 +102,7 @@ static struct { #endif } xsymtbl; +#define XClearWindow xsymtbl.XClearWindow #define XCreateIC xsymtbl.XCreateIC #define XFree xsymtbl.XFree #define XFreeCursor xsymtbl.XFreeCursor @@ -452,6 +454,8 @@ static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) { (void)handle; + + XClearWindow(handle->x11.display, handle->x11.window); } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { @@ -1283,6 +1287,7 @@ static int MwLLX11CallInitImpl(void) { #define X11_FUNC_LOAD(x) x = MwDynamicSymbol(xsymtbl.lib_xlib, #x) + X11_FUNC_LOAD(XClearWindow); X11_FUNC_LOAD(XCreateImage); X11_FUNC_LOAD(XOpenDisplay); X11_FUNC_LOAD(XKeysymToString); diff --git a/src/core.c b/src/core.c index 2c9d646..db90d61 100644 --- a/src/core.c +++ b/src/core.c @@ -2,18 +2,51 @@ #include "../external/stb_ds.h" +#define PERIODIC + +#define DRAW(handle) \ + { \ + MwLLBeginDraw(handle->lowlevel); \ +\ + handle->bgcolor = NULL; \ + MwDispatch(handle, draw); \ + if(handle->draw_inject != NULL) handle->draw_inject(handle); \ + MwDispatchUserHandler(handle, MwNdrawHandler, NULL); \ +\ + MwLLEndDraw(handle->lowlevel); \ + } + static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; +#ifdef PERIODIC + MwWidget top; +#endif (void)data; - MwLLBeginDraw(handle); - h->bgcolor = NULL; - MwDispatch(h, draw); - if(h->draw_inject != NULL) h->draw_inject(h); - MwDispatchUserHandler(h, MwNdrawHandler, NULL); +#ifdef PERIODIC + top = h; + while(top != NULL) { + if(top->top_step) { + break; + } - MwLLEndDraw(handle); + top = top->parent; + } + + if(top == NULL) { + DRAW(h); /* fallback */ + } else { + int i; + + for(i = 0; i < arrlen(top->draw_queue); i++) { + if(top->draw_queue[i] == h) break; + } + if(i == arrlen(top->draw_queue)) arrput(top->draw_queue, h); + } +#else + DRAW(h); +#endif } static void lluphandler(MwLL handle, void* data) { @@ -169,6 +202,9 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, h->bgcolor = NULL; h->berserk = 0; + h->top_step = 0; + h->draw_queue = NULL; + if(parent == NULL) arrput(h->tick_list, h); if(h->lowlevel != NULL) { @@ -255,6 +291,22 @@ MwWidget MwVaListCreateWidget(MwClass widget_class, const char* name, MwWidget p static void MwFreeWidget(MwWidget handle) { int i; MwWidget root = handle; + MwWidget w; + + w = handle; + while(w != NULL) { + if(w->top_step) break; + w = w->parent; + } + + if(w != NULL) { + for(i = 0; i < arrlen(w->draw_queue); i++) { + if(w->draw_queue[i] == handle) { + arrdel(w->draw_queue, i); + i--; + } + } + } handle->destroyed = 0; MwDispatch(handle, destroy); @@ -291,6 +343,8 @@ static void MwFreeWidget(MwWidget handle) { arrfree(handle->destroy_queue); arrfree(handle->tick_list); + arrfree(handle->draw_queue); + if(handle->root_font != NULL) MwFontFree(handle->root_font); if(handle->root_boldfont != NULL) MwFontFree(handle->root_boldfont); @@ -355,6 +409,9 @@ static void clean_destroy_queue(MwWidget handle) { int MwStep(MwWidget handle) { int i; MwWidget* widgets = NULL; +#ifdef PERIODIC + MwWidget w; +#endif if(setjmp(handle->before_step)) return 0; for(i = 0; i < arrlen(handle->children); i++) { arrput(widgets, handle->children[i]); @@ -365,9 +422,36 @@ int MwStep(MwWidget handle) { handle->prop_event = 0; +#ifdef PERIODIC + handle->top_step = 1; + w = handle->parent; + while(w != NULL) { + if(w->top_step) { + handle->top_step = 0; + + break; + } + + w = w->parent; + } +#endif + while(handle->lowlevel != NULL && MwLLPending(handle->lowlevel)) MwLLNextEvent(handle->lowlevel); +#ifdef PERIODIC + if(handle->top_step) { + int i; + + for(i = 0; i < arrlen(handle->draw_queue); i++) { + DRAW(handle->draw_queue[i]); + } + + arrfree(handle->draw_queue); + } +#endif + + handle->top_step = 0; handle->prop_event = 1; clean_destroy_queue(handle); @@ -383,7 +467,7 @@ int MwPending(MwWidget handle) { for(i = 0; i < arrlen(handle->children); i++) { if(MwPending(handle->children[i])) return 1; } - return (arrlen(handle->destroy_queue) > 0 ? 1 : 0) || (handle->widget_class == NULL ? 0 : MwLLPending(handle->lowlevel)); + return (arrlen(handle->draw_queue) > 0) || (arrlen(handle->destroy_queue) > 0) || (handle->widget_class == NULL ? 0 : MwLLPending(handle->lowlevel)); } void MwLoop(MwWidget handle) {