From 4a7e919ad1885cb764e9067e889e6d01f0cdbb75 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sun, 5 Oct 2025 01:51:38 +0000 Subject: [PATCH] gdi fix and etc git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@176 b9cfdab3-6d41-4d17-bbe4-086880011989 --- include/Mw/TypeDefs.h | 2 ++ src/backend/gdi.c | 2 ++ src/core.c | 51 +++++++++++++++++++++++++------------------ src/widget/submenu.c | 46 ++++++++++++++++++++------------------ 4 files changed, 59 insertions(+), 42 deletions(-) diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 5fb244c..e64fc45 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -85,6 +85,8 @@ struct _MwWidget { MwTextKeyValue* text; MwUserHandlerKeyValue* handler; MwVoidKeyValue* data; + + MwWidget* destroy_queue; }; struct _MwMenu { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 70e7eb0..25a136e 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -134,6 +134,8 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { void MwLLDestroy(MwLL handle) { MwLLDestroyCommon(handle); + /* for safety */ + SetWindowLongPtr(handle->hWnd, GWLP_USERDATA, (LONG_PTR)NULL); DestroyWindow(handle->hWnd); free(handle); diff --git a/src/core.c b/src/core.c index f540db8..c16c954 100644 --- a/src/core.c +++ b/src/core.c @@ -77,9 +77,10 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, free(h); return NULL; } - h->widget_class = widget_class; - h->pressed = 0; - h->close = 0; + h->widget_class = widget_class; + h->pressed = 0; + h->close = 0; + h->destroy_queue = NULL; h->lowlevel->user = h; h->lowlevel->handler->draw = lldrawhandler; @@ -130,29 +131,17 @@ MwWidget MwVaListCreateWidget(MwClass widget_class, const char* name, MwWidget p return h; } -void MwDestroyWidget(MwWidget handle) { +static void MwFreeWidget(MwWidget handle) { int i; MwDispatch(handle, destroy); + for(i = 0; i < arrlen(handle->children); i++) { + MwFreeWidget(handle->children[i]); + } + free(handle->name); - if(handle->children != NULL) { - for(i = 0; i < arrlen(handle->children); i++) { - MwDestroyWidget(handle->children[i]); - break; - } - arrfree(handle->children); - } - - if(handle->parent != NULL) { - for(i = 0; i < arrlen(handle->parent->children); i++) { - if(handle->parent->children[i] == handle) { - arrdel(handle->parent->children, i); - break; - } - } - } MwLLDestroy(handle->lowlevel); shfree(handle->integer); @@ -165,14 +154,34 @@ void MwDestroyWidget(MwWidget handle) { shfree(handle->handler); shfree(handle->data); + arrfree(handle->destroy_queue); + free(handle); } +void MwDestroyWidget(MwWidget handle) { + arrput(handle->parent->destroy_queue, handle); +} + void MwStep(MwWidget handle) { - int i; + int i, j; if(setjmp(handle->before_step)) return; for(i = 0; i < arrlen(handle->children); i++) MwStep(handle->children[i]); MwLLNextEvent(handle->lowlevel); + for(i = 0; i < arrlen(handle->destroy_queue); i++) { + MwWidget w = handle->destroy_queue[i]; + + MwFreeWidget(w); + } + for(i = 0; i < arrlen(handle->destroy_queue); i++) { + for(j = 0; j < arrlen(handle->children); j++) { + if(handle->children[j] == handle->destroy_queue[i]) { + arrdel(handle->children, j); + break; + } + } + } + arrfree(handle->destroy_queue); } int MwPending(MwWidget handle) { diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 6ad61fa..823be17 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -25,6 +25,7 @@ static void null_all(MwMenu menu) { static void destroy(MwWidget handle) { MwMenu menu = handle->internal; + menu->wsub = NULL; null_all(menu); } @@ -122,27 +123,24 @@ static void click(MwWidget handle) { MwSubMenuAppear(menu->sub[i]->wsub, menu->sub[i], &p); i = -1; } else if(menu->sub[i]->wsub != NULL && arrlen(menu->sub[i]->sub) > 0) { + while(w->parent->widget_class != MwMenuClass) w = w->parent; + MwDestroyWidget(menu->sub[i]->wsub); menu->sub[i]->wsub = NULL; + MwForceRender(w->parent); + MwForceRender(handle); } else if(arrlen(menu->sub[i]->sub) == 0) { - MwWidget p; - while(w->parent->widget_class != MwMenuClass) w = w->parent; MwGetBeforeStep(w, &jmp); - p = w->parent; - MwDestroyWidget(w); + ((MwMenu)w->internal)->wsub = NULL; - MwForceRender(p); + MwForceRender(w->parent); - MwDispatchUserHandler(p, MwNmenuHandler, menu->sub[i]); - - longjmp(jmp, 1); - - break; + MwDispatchUserHandler(w->parent, MwNmenuHandler, menu->sub[i]); } } @@ -166,9 +164,23 @@ MwClass MwSubMenuClass = &MwSubMenuClassRec; void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point) { int i, w = 0, h = 0; #ifdef _WIN32 - RECT rc; + RECT rc; + LONG_PTR ex = GetWindowLongPtr(handle->lowlevel->hWnd, GWL_EXSTYLE); +#else + Atom wndtype = XInternAtom(handle->lowlevel->display, "_NET_WM_WINDOW_TYPE", False); + Atom wndmenu = XInternAtom(handle->lowlevel->display, "_NET_WM_WINDOW_TYPE_MENU", False); + int x = 0, y = 0; + Window child; + XSetWindowAttributes xswa; +#endif - SetWindowLongPtr(handle->lowlevel->hWnd, GWL_STYLE, (LONG_PTR)WS_POPUP); + handle->internal = menu; + +#ifdef _WIN32 + ex |= WS_EX_TOOLWINDOW; + + SetWindowLongPtr(handle->lowlevel->hWnd, GWL_STYLE, (LONG_PTR)0); + SetWindowLongPtr(handle->lowlevel->hWnd, GWL_EXSTYLE, ex); GetWindowRect(handle->parent->lowlevel->hWnd, &rc); @@ -177,18 +189,12 @@ void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point) { rc.left += point->x; rc.top += point->y; - SetWindowPos(handle->lowlevel->hWnd, NULL, rc.left, rc.top, 1, 1, SWP_NOREDRAW); + SetWindowPos(handle->lowlevel->hWnd, HWND_TOPMOST, rc.left, rc.top, 1, 1, SWP_NOREDRAW); ShowWindow(handle->lowlevel->hWnd, SW_NORMAL); - UpdateWindow(handle->lowlevel->hWnd); SetFocus(handle->lowlevel->hWnd); #else - Atom wndtype = XInternAtom(handle->lowlevel->display, "_NET_WM_WINDOW_TYPE", False); - Atom wndmenu = XInternAtom(handle->lowlevel->display, "_NET_WM_WINDOW_TYPE_MENU", False); - int x = 0, y = 0; - Window child; - XSetWindowAttributes xswa; xswa.override_redirect = True; @@ -203,8 +209,6 @@ void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point) { XSetInputFocus(handle->lowlevel->display, handle->lowlevel->window, RevertToNone, CurrentTime); #endif - handle->internal = menu; - for(i = 0; i < arrlen(menu->sub); i++) { int tw = MwTextWidth(handle, menu->sub[i]->name); h += MwTextHeight(handle, menu->sub[i]->name) + 3;