From 9bfa4f4092f62f8ba6f9300deae3e6dff5db9bac Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sat, 2 May 2026 02:00:51 +0900 Subject: [PATCH] some fix --- examples/basic/periodic.c | 2 +- examples/basic/subwindow.c | 49 ++++++++++++++++ include/Mw/Widget/SubWindow.h | 11 ++++ pl/rules.pl | 1 + src/backend/x11.c | 52 +++++++++++++++-- src/widget/subwindow.c | 103 ++++++++++++++++++++++++++-------- 6 files changed, 189 insertions(+), 29 deletions(-) create mode 100644 examples/basic/subwindow.c diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 2fd4e4b..a1c36b2 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -317,7 +317,7 @@ int main() { NULL); add(f); MwVaCreateWidget(MwSubWindowClass, "swnd", MwViewportGetViewport(w), 64, 64, 256, 128, - MwNtitle, "Sub window", + MwNtitle, "Sub window 2", NULL); add(f); #endif diff --git a/examples/basic/subwindow.c b/examples/basic/subwindow.c new file mode 100644 index 0000000..1225f41 --- /dev/null +++ b/examples/basic/subwindow.c @@ -0,0 +1,49 @@ +#include + +static void resize(MwWidget handle, void* user, void* client) { + MwWidget f = MwSubWindowGetFrame(handle); + MwVaApply(user, + MwNwidth, MwGetInteger(f, MwNwidth), + MwNheight, MwGetInteger(f, MwNheight), + NULL); +} + +int main() { + MwWidget w; + int i; + MwLLPixmap px[6]; + + MwLibraryInit(); + + w = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 800, 600, + MwNtitle, "subwindow", + NULL); + + px[0] = MwLoadIcon(w, MwIconClock); + px[1] = MwLoadIcon(w, MwIconError); + px[2] = MwLoadIcon(w, MwIconInfo); + px[3] = MwLoadIcon(w, MwIconNews); + px[4] = MwLoadIcon(w, MwIconNote); + px[5] = MwLoadIcon(w, MwIconWarning); + + for(i = 0; i < 16; i++) { + char buf[32]; + MwWidget sw, f, img; + + sprintf(buf, "Sub window %d", i); + + sw = MwVaCreateWidget(MwSubWindowClass, "swnd", w, i * 32, i * 32, 128, 128, + MwNtitle, buf, + NULL); + + f = MwSubWindowGetFrame(sw); + + img = MwVaCreateWidget(MwImageClass, "img", f, 0, 0, MwGetInteger(f, MwNwidth), MwGetInteger(f, MwNheight), + MwNpixmap, px[rand() % 6], + NULL); + + MwAddUserHandler(sw, MwNresizeHandler, resize, img); + } + + MwLoop(w); +} diff --git a/include/Mw/Widget/SubWindow.h b/include/Mw/Widget/SubWindow.h index 38a1cdd..c7ce2e1 100644 --- a/include/Mw/Widget/SubWindow.h +++ b/include/Mw/Widget/SubWindow.h @@ -18,6 +18,17 @@ extern "C" { */ MWDECL MwClass MwSubWindowClass; +/*! + * @brief Get parent widget where widgets should be placed + * @param handle Widget + * @return Widget + */ +MwInline MwWidget MwSubWindowGetFrame(MwWidget handle) { + MwWidget out; + MwVaWidgetExecute(handle, "mwSubWindowGetFrame", &out); + return out; +} + #ifdef __cplusplus } #endif diff --git a/pl/rules.pl b/pl/rules.pl index 8534000..04f7ba5 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -195,6 +195,7 @@ new_example("examples/basic/sevensegment"); new_example("examples/basic/calculator"); new_example("examples/basic/filechooser"); new_example("examples/basic/periodic"); +new_example("examples/basic/subwindow"); if (param_get("opengl")) { new_example("examples/gldemos/boing", $gl_libs); diff --git a/src/backend/x11.c b/src/backend/x11.c index f3cf986..e9e24bd 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -4,6 +4,10 @@ #define ClipboardTimeout 100 +#ifdef USE_XRENDER +// #undef USE_XRENDER +#endif + static struct symtbl { void* lib_xlib; void* lib_xrender; @@ -75,6 +79,7 @@ static struct symtbl { XIC (*XCreateIC)(XIM, ...); void (*XDestroyIC)(XIC); void (*XSetICFocus)(XIC); + XImage* (*XGetImage)(Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int); XSizeHints* (*XAllocSizeHints)(void); XVisualInfo* (*XGetVisualInfo)(Display*, long, XVisualInfo*, int*); @@ -176,6 +181,7 @@ static struct symtbl { #define XQueryTree xsymtbl.XQueryTree #define XPending xsymtbl.XPending #define XChangeWindowAttributes xsymtbl.XChangeWindowAttributes +#define XGetImage xsymtbl.XGetImage #if USE_XRENDER #define XRenderFindStandardFormat xsymtbl.XRenderFindStandardFormat @@ -919,7 +925,7 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid #endif r->x11.image = XCreateImage(handle->x11.display, DefaultVisual(handle->x11.display, DefaultScreen(handle->x11.display)), r->x11.depth, ZPixmap, 0, NULL, width, height, 32, 0); - r->x11.mask = XCreateImage(handle->x11.display, DefaultVisual(handle->x11.display, DefaultScreen(handle->x11.display)), 1, ZPixmap, 0, NULL, width, height, 32, 0); + r->x11.mask = XCreateImage(handle->x11.display, DefaultVisual(handle->x11.display, DefaultScreen(handle->x11.display)), 8, ZPixmap, 0, NULL, width, height, 32, 0); r->x11.image->data = malloc(r->x11.image->bytes_per_line * height); r->x11.mask->data = malloc(r->x11.mask->bytes_per_line * height); @@ -948,7 +954,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { for(y = 0; y < r->common.height; y++) { for(x = 0; x < r->common.width; x++) { if(r->common.raw[(y * r->common.width + x) * 4 + 3]) { - XPutPixel(r->x11.mask, x, y, 1); + XPutPixel(r->x11.mask, x, y, 255); } else { XPutPixel(r->x11.mask, x, y, 0); } @@ -976,8 +982,8 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { \ XPutImage(handle->x11.display, src_px, gc, src, 0, 0, 0, 0, pixmap->common.width, pixmap->common.height); \ \ - src_pic = XRenderCreatePicture(handle->x11.display, src_px, fmt, 0, &attr); \ - dest_pic = XRenderCreatePicture(handle->x11.display, dest_px, fmt, 0, &attr); \ + src_pic = XRenderCreatePicture(handle->x11.display, src_px, fmt, render_mask, &attr); \ + dest_pic = XRenderCreatePicture(handle->x11.display, dest_px, fmt, render_mask, &attr); \ \ XRenderSetPictureTransform(handle->x11.display, src_pic, &m); \ XRenderComposite(handle->x11.display, PictOpSrc, src_pic, 0, dest_pic, 0, 0, 0, 0, 0, 0, rect->width, rect->height); \ @@ -996,11 +1002,16 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { #ifdef USE_XRENDER if(pixmap->x11.image != NULL && pixmap->x11.use_xrender) { Pixmap px; - Pixmap mask; + Pixmap mask, mask_tmp; XRenderPictureAttributes attr; XTransform m; double xsc; double ysc; + unsigned long render_mask = 0; + XImage* mask_tmp_img; + XImage* mask_img; + int y, x; + GC mask_gc; memset(&attr, 0, sizeof(attr)); @@ -1020,13 +1031,41 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { m.matrix[2][2] = XDoubleToFixed(1.0); DO_XRENDER(px, pixmap->x11.image, PictStandardRGB24, pixmap->x11.depth); - DO_XRENDER(mask, pixmap->x11.mask, PictStandardA1, 1); + DO_XRENDER(mask_tmp, pixmap->x11.mask, PictStandardA8, 8); + + /* FIXME: this is terrible way to do this... i hope someone who knows xrender better than me + * gives me better solution + */ + mask_tmp_img = XGetImage(handle->x11.display, mask_tmp, 0, 0, rect->width, rect->height, 0xff, ZPixmap); + mask_img = XCreateImage(handle->x11.display, DefaultVisual(handle->x11.display, DefaultScreen(handle->x11.display)), 1, ZPixmap, 0, NULL, rect->width, rect->height, 32, 0); + mask = XCreatePixmap(handle->x11.display, handle->x11.window, rect->width, rect->height, 1); + mask_gc = XCreateGC(handle->x11.display, mask, 0, NULL); + + mask_img->data = malloc(mask_img->bytes_per_line * rect->height); + + for(y = 0; y < rect->height; y++) { + for(x = 0; x < rect->width; x++) { + unsigned long p = XGetPixel(mask_tmp_img, x, y); + if(p == 255) { + p = 1; + } else { + p = 0; + } + XPutPixel(mask_img, x, y, p); + } + } + XPutImage(handle->x11.display, mask, mask_gc, mask_img, 0, 0, 0, 0, rect->width, rect->height); + XFreeGC(handle->x11.display, mask_gc); + XDestroyImage(mask_img); + XDestroyImage(mask_tmp_img); + /* end terrible hack */ XSetClipMask(handle->x11.display, handle->x11.gc, mask); XSetClipOrigin(handle->x11.display, handle->x11.gc, rect->x, rect->y); XCopyArea(handle->x11.display, px, handle->x11.pixmap, handle->x11.gc, 0, 0, rect->width, rect->height, rect->x, rect->y); XSetClipMask(handle->x11.display, handle->x11.gc, None); + XFreePixmap(handle->x11.display, mask_tmp); XFreePixmap(handle->x11.display, mask); XFreePixmap(handle->x11.display, px); } else @@ -1424,6 +1463,7 @@ static int MwLLX11CallInitImpl(void) { X11_FUNC_LOAD(XCreateIC); X11_FUNC_LOAD(XDestroyIC); X11_FUNC_LOAD(XSetICFocus); + X11_FUNC_LOAD(XGetImage); X11_FUNC_LOAD(XAllocSizeHints); X11_FUNC_LOAD(XGetVisualInfo); diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index 662cf62..d4294e4 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -20,18 +20,29 @@ static void close_draw(MwWidget handle) { p[1].y = h - bw * 2 - 1; MwLLLine(handle->lowlevel, p, c); + p[0].x++; + p[1].x--; + MwLLLine(handle->lowlevel, p, c); + p[0].x = w - bw * 2 - 1; p[0].y = bw * 2; p[1].x = bw * 2; p[1].y = h - bw * 2 - 1; MwLLLine(handle->lowlevel, p, c); + p[0].x--; + p[1].x++; + MwLLLine(handle->lowlevel, p, c); + MwLLFreeColor(c); } static void MWAPI close_activate(MwWidget handle, void* user, void* client) { MwWidget w = user; + (void)handle; + (void)client; + MwDispatchUserHandler(w, MwNcloseHandler, NULL); } @@ -51,6 +62,9 @@ static void maximize_draw(MwWidget handle) { p[0].y = p[1].y = h - bw * 2 - 1; MwLLLine(handle->lowlevel, p, c); + p[0].y = p[1].y = bw * 2 + 1; + MwLLLine(handle->lowlevel, p, c); + p[0].x = bw * 2; p[0].y = bw * 2; p[1].x = bw * 2; @@ -67,6 +81,9 @@ static void MWAPI maximize_activate(MwWidget handle, void* user, void* client) { MwWidget w = user; MwSubWindow sw = w->internal; + (void)handle; + (void)client; + if(sw->minimized) return; if(sw->maximized) { @@ -90,7 +107,6 @@ static void MWAPI maximize_activate(MwWidget handle, void* user, void* client) { NULL); } sw->maximized = !sw->maximized; - resize(user); } static void minimize_draw(MwWidget handle) { @@ -106,6 +122,10 @@ static void minimize_draw(MwWidget handle) { p[1].y = h - bw * 2 - 1; MwLLLine(handle->lowlevel, p, c); + p[0].y--; + p[1].y--; + MwLLLine(handle->lowlevel, p, c); + MwLLFreeColor(c); } @@ -124,6 +144,9 @@ static void MWAPI minimize_activate(MwWidget handle, void* user, void* client) { MwWidget w = user; MwSubWindow sw = w->internal; + (void)handle; + (void)client; + if(sw->maximized) return; if(sw->minimized) { @@ -132,7 +155,14 @@ static void MWAPI minimize_activate(MwWidget handle, void* user, void* client) { int p = 0; for(i = 0; i < arrlen(w->parent->children); i++) { - arrput(ws, w->parent->children[i]); + MwWidget c = w->parent->children[i]; + if(c->widget_class == MwSubWindowClass) { + MwSubWindow csw = c->internal; + + if(!csw->minimized) continue; + + arrput(ws, c); + } } if(ws != NULL) { @@ -177,7 +207,6 @@ static void MWAPI minimize_activate(MwWidget handle, void* user, void* client) { NULL); } sw->minimized = !sw->minimized; - resize(user); } static void resize(MwWidget handle) { @@ -228,6 +257,8 @@ static void resize(MwWidget handle) { BUTTON(close); BUTTON(maximize); BUTTON(minimize); + + MwDispatchUserHandler(handle, MwNresizeHandler, NULL); } static int wcreate(MwWidget handle) { @@ -246,7 +277,6 @@ static int wcreate(MwWidget handle) { } static void destroy(MwWidget handle) { - MwSubWindow sw = handle->internal; free(handle->internal); } @@ -278,6 +308,10 @@ static void draw(MwWidget handle) { handle->bgcolor = NULL; } + r2.width = ButtonSize * 3 + (TitleHeight - ButtonSize) / 2 * 4; + r2.x = r.width - r2.width; + MwDrawRect(handle, &r2, tb); + r.y += TitleHeight; r.height -= TitleHeight; MwDrawFrame(handle, &r, c, 1); @@ -287,32 +321,57 @@ static void draw(MwWidget handle) { MwLLFreeColor(c); } +static void parent_resize(MwWidget handle) { + MwSubWindow sw = handle->internal; + + if(sw->maximized) { + MwVaApply(handle, + MwNwidth, MwGetInteger(handle->parent, MwNwidth), + MwNheight, MwGetInteger(handle->parent, MwNheight), + NULL); + } else if(sw->minimized) { + MwVaApply(handle, + MwNy, MwGetInteger(handle->parent, MwNheight) - TitleHeight - MwDefaultBorderWidth(handle), + NULL); + } +} + static void prop_change(MwWidget handle, const char* key) { if(strcmp(key, MwNtitle) == 0) MwForceRender(handle); } +static MwWidget mwSubWindowGetFrameImpl(MwWidget handle) { + MwSubWindow sw = handle->internal; + + return sw->frame; +} + static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { - (void)out; + (void)va; + + if(strcmp(name, "mwSubWindowGetFrame") == 0) { + *(MwWidget*)out = mwSubWindowGetFrameImpl(handle); + } } MwClassRec MwSubWindowClassRec = { - wcreate, /* create */ - destroy, /* destroy */ - draw, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - prop_change, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + destroy, /* destroy */ + draw, /* draw */ + NULL, /* click */ + parent_resize, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + resize, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL};