From 1dda7934ce9665657c6b7235171b3422ca875358 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 07:25:52 +0900 Subject: [PATCH 001/102] wayland flickering/ghosting fix --- CMakeLists.txt | 1 + include/Mw/LowLevel/Cairo.h | 3 ++ include/Mw/LowLevel/Wayland.h | 6 ++++ pl/rules.pl | 1 + src/backend/cairo.c | 27 ++++++++------ src/backend/wayland/buffer.c | 11 ++++-- src/backend/wayland/interfaces.c | 17 +++++++++ src/backend/wayland/wayland.c | 62 +++++++++++++++----------------- 8 files changed, 82 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07f7bb9cf..f5bb78056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,7 @@ if(MW_USE_WAYLAND) scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") + scan_wayland_protocol("staging" "fifo" "-v1") scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml") target_sources( diff --git a/include/Mw/LowLevel/Cairo.h b/include/Mw/LowLevel/Cairo.h index 680c651fc..92304fa62 100644 --- a/include/Mw/LowLevel/Cairo.h +++ b/include/Mw/LowLevel/Cairo.h @@ -196,6 +196,9 @@ struct _MwLLCairo { /* The cairo to actually use for draw operations. Typically is front_cairo, but wayland's MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */ cairo_t* selected_cairo; + cairo_surface_t* frontbuffer_cs; + cairo_t* frontbuffer_cairo; + int x; int y; int width; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 3b7918426..e3b9ff997 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -207,6 +207,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/wlr-layer-shell-client-protocol.h" +#include "Wayland/fifo-client-protocol.h" #endif typedef struct wayland_protocol { @@ -265,6 +266,7 @@ struct _MwLLWaylandShmBuffer { struct wl_buffer* shm_buffer_back; struct wl_surface* surface; struct wl_output* output; + struct wp_fifo_v1* fifo; MwU8* buf; MwU8* buf_back; @@ -426,9 +428,13 @@ struct _MwLLWayland { MwBool force_render; MwBool did_event_loop_early; + MwBool do_cascading_draw; + int cascading_child_num; MwBool dispatching_resize; + MwBool is_toplevel_menu; + struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; diff --git a/pl/rules.pl b/pl/rules.pl index 551d39103..f12c0922f 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,6 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 3683ca885..9dab1c197 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -113,13 +113,16 @@ void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixm void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) { if(data) { - cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); + cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); + cairo->frontbuffer_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); } else { - cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->frontbuffer_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); } - cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo->front_cairo_back = cairo_create(cairo->front_cs_back); - cairo->front_cairo = cairo_create(cairo->front_cs); + cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->front_cairo_back = cairo_create(cairo->front_cs_back); + cairo->front_cairo = cairo_create(cairo->front_cs); + cairo->frontbuffer_cairo = cairo_create(cairo->frontbuffer_cs); } void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) { @@ -135,6 +138,8 @@ void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->front_cairo); cairo_destroy(cairo->front_cairo_back); cairo_surface_destroy(cairo->front_cs); + cairo_surface_destroy(cairo->frontbuffer_cs); + cairo_destroy(cairo->frontbuffer_cairo); }; void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->back_cairo); @@ -214,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -259,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 48071ec95..79ce72cad 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -10,6 +10,9 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); + if(wayland->framebuffer.fifo) + wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); + wl_surface_commit(wayland->framebuffer.surface); MwLLWaylandHangUntilConfigured((MwLL)wayland); @@ -38,6 +41,8 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); + // if(wayland->framebuffer.fifo) + // wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); wl_surface_commit(wayland->backbuffer.surface); MwLLWaylandHangUntilConfigured((MwLL)wayland); MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->backbuffer); @@ -119,9 +124,11 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); if(buffer->surface) { // Yes this is needed every time, it's how we fix weston. - if(self->wayland.configured) + if(self->wayland.configured) { wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - + } + if(buffer->fifo) + wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); } } diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index dd58f9aa9..3378d0d28 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -749,6 +749,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time if(self->wayland.backbuffer.surface) { wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); } + WAYLAND_EVENT_OP_END(self); }; @@ -1511,6 +1512,21 @@ static void zwlr_layer_shell_v1_interface_destroy(struct _MwLLWayland* wayland, free(data); } +static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + + proto->context = wl_registry_bind(wayland->registry, name, &wp_fifo_manager_v1_interface, version); + proto->listener = NULL; + + return proto; +} + +static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + + free(data); +} + /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { /* Convience macro for adding the interface functions to the setup map */ @@ -1553,6 +1569,7 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_seat); + WL_INTERFACE(wp_fifo_manager_v1); } else if(wayland->type == MwLL_WAYLAND_POPUP) { WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 9d8d634ab..ff8fb49db 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -265,6 +265,10 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); wl_subsurface_set_desync(r->wayland.toplevel->ssurface); + if(WAYLAND_GET_INTERFACE(r->wayland, wp_fifo_manager_v1) != NULL) { + r->wayland.framebuffer.fifo = wp_fifo_manager_v1_get_fifo(WAYLAND_GET_INTERFACE(r->wayland, wp_fifo_manager_v1)->context, r->wayland.framebuffer.surface); + } + r->wayland.toplevel->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.backbuffer.surface); r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); @@ -407,10 +411,13 @@ static void popup_configure(void* data, if(width < 50) width = 50; if(height < 50) height = 50; - self->wayland.x = x; - self->wayland.y = y; - self->wayland.ww = width; - self->wayland.wh = height; + self->wayland.x = x; + self->wayland.y = y; + + if(!self->wayland.setting_wh) { + self->wayland.ww = width; + self->wayland.wh = height; + } }; static void popup_done(void* data, @@ -439,10 +446,11 @@ struct xdg_popup_listener popup_listener = { static void setup_popup(MwLL r, int x, int y, MwLL parent) { char* mw_force_csd = getenv("MW_FORCE_CSD"); MwLL topmost_parent = r->wayland.parent; - r->wayland.type = MwLL_WAYLAND_POPUP; - r->wayland.x = x; - r->wayland.y = y; - r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); + + r->wayland.type = MwLL_WAYLAND_POPUP; + r->wayland.x = x; + r->wayland.y = y; + r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); if(parent) { MwWidget p = parent->common.user; @@ -908,13 +916,8 @@ static void draw_child(MwLL handle, MwLL child) { cairo_t* c; cairo_surface_t* cs; cairo_t* selected_cairo; - MwLL topmost_parent = handle; - if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { - while(topmost_parent->wayland.parent) { - topmost_parent = topmost_parent->wayland.parent; - } - } + draw_children(child); wl_surface_commit(child->wayland.framebuffer.surface); @@ -928,20 +931,18 @@ static void draw_child(MwLL handle, MwLL child) { cairo_paint(c); - // printf("%d %d\n", child->wayland.x, child->wayland.y); - cairo_set_source_surface(handle->wayland.cairo.front_cairo_back, cs, child->wayland.x, child->wayland.y); cairo_paint(handle->wayland.cairo.front_cairo_back); cairo_destroy(c); cairo_surface_destroy(cs); - - draw_children(child); } static void draw_children(MwLL handle) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + cairo_reset_clip(handle->wayland.cairo.front_cairo_back); + MwLLWaylandChildrenIterate(handle, draw_child); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); @@ -949,24 +950,13 @@ static void draw_children(MwLL handle) { } static void frontbuffer_draw(MwLL handle) { - cairo_t* c; - cairo_surface_t* cs; - - cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, handle->wayland.ww, handle->wayland.wh); - c = cairo_create(cs); + cairo_t* c = handle->wayland.cairo.frontbuffer_cairo; cairo_set_source_surface(c, handle->wayland.cairo.front_cs_back, 0, 0); cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER); cairo_paint(c); - - cairo_set_source_surface(handle->wayland.cairo.front_cairo, cs, 0, 0); - cairo_paint(handle->wayland.cairo.front_cairo); - - cairo_destroy(c); - cairo_surface_destroy(cs); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -1301,10 +1291,17 @@ static void MwLLBeginDrawImpl(MwLL handle) { } static void MwLLEndDrawImpl(MwLL handle) { + MwLL root = handle; + while(root->wayland.type == MwLL_WAYLAND_SUBLEVEL && root->wayland.parent) { + root = root->wayland.parent; + } + root->wayland.do_cascading_draw = MwTRUE; + if(handle->wayland.configured) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } + MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); } } @@ -1363,9 +1360,10 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.resizing = 0; - if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL) { + if(handle->wayland.do_cascading_draw) { draw_children(handle); frontbuffer_draw(handle); + handle->wayland.do_cascading_draw = MwFALSE; } if(handle->wayland.setting_wh) { @@ -1430,7 +1428,6 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - if(!MwWaylandVulkan) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; @@ -1450,7 +1447,6 @@ static void MwLLNextEventImpl(MwLL handle) { } static void MwLLSetTitleImpl(MwLL handle, const char* title) { - if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title); } From e81156708c8846f03d8100b231eb81784429daf2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 16 Sep 2026 15:30:37 -0700 Subject: [PATCH 002/102] fix key repeat --- include/Mw/LowLevel/Wayland.h | 5 +++-- src/backend/wayland/interfaces.c | 6 +++--- src/backend/wayland/wayland.c | 6 +----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index e3b9ff997..5c91ebf05 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -433,8 +433,6 @@ struct _MwLLWayland { MwBool dispatching_resize; - MwBool is_toplevel_menu; - struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; @@ -491,6 +489,9 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ /* Flush Wayland events */ void MwLLWaylandFlush(MwLL handle); +/* recursively dispatch the key event to focused widgets. */ +void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down); + /* Standard procedure before event callbacks in Wayland */ #define WAYLAND_EVENT_OP_START(self) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 3378d0d28..5f4d6ffb8 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1000,7 +1000,7 @@ static void keyboard_leave(void* data, WAYLAND_EVENT_OP_END(self); }; -static void key_dispatch(MwLL self, int* k, MwBool down) { +void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { if(self->common.user) { MwWidget w = self->common.user; int i, n; @@ -1019,7 +1019,7 @@ static void key_dispatch(MwLL self, int* k, MwBool down) { MwLLDispatch(child, key_released, k); } - key_dispatch(child, k, down); + MwLLRecursiveKeyDispatch(child, k, down); } } } @@ -1141,7 +1141,7 @@ static void keyboard_key(void* data, } else { self->wayland.holding_key = MwFALSE; } - key_dispatch(self, &key, state == WL_KEYBOARD_KEY_STATE_PRESSED); + MwLLRecursiveKeyDispatch(self, &key, state == WL_KEYBOARD_KEY_STATE_PRESSED); self->wayland.start_time = MwTimeGetTick(); self->wayland.next_elapsed = self->wayland.keyboard_delay; } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index ff8fb49db..c8544531c 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1376,11 +1376,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.holding_key) { float elapsed = ((float)(handle->wayland.end_time - (float)handle->wayland.start_time)); if(elapsed >= handle->wayland.next_elapsed) { - MwLL topmost_parent = handle; - while(topmost_parent->wayland.parent) { - MwLLDispatch(topmost_parent, key, &handle->wayland.last_pressed_key); - topmost_parent = topmost_parent->wayland.parent; - } + MwLLRecursiveKeyDispatch(handle, &handle->wayland.last_pressed_key, MwTRUE); handle->wayland.next_elapsed = elapsed + handle->wayland.keyboard_rate; } } From e6e69b9915f366f422ffe802b44c671f42f03c97 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 16 Sep 2026 15:32:45 -0700 Subject: [PATCH 003/102] remove unused fields in MwLLWayland --- include/Mw/LowLevel/Wayland.h | 6 +----- src/backend/wayland/interfaces.c | 16 ---------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 5c91ebf05..0d5a24f66 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -320,7 +320,6 @@ struct _MwLLWayland { enum _MwLLWaylandType type_to_be; MwRect clipping_rect; - MwBool no; MwBool changing; MwBool detatching; @@ -361,8 +360,6 @@ struct _MwLLWayland { struct wl_region* region; struct wl_output* output; - struct wp_viewport* vp; - MwBool do_lock_pointer; struct zwp_pointer_constraints_v1* pointer_constraints; struct zwp_relative_pointer_manager_v1* relative_pointer_manager; @@ -378,9 +375,8 @@ struct _MwLLWayland { MwBool dark_theme_detection; MwU32 dark_theme; - /* clipboard related stuff. + /* clipboard/ related stuff. * Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/ - struct { struct wl_data_device_manager* wl; struct zwp_primary_selection_device_manager_v1* zwp; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 5f4d6ffb8..50a58e465 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1431,20 +1431,6 @@ static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_ free(data); } -/* xdg_wm_base setup function */ -static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { - wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - (void)version; - proto->context = wl_registry_bind(wayland->registry, name, &wp_viewporter_interface, 1); - - return proto; -} - -static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; - (void)data; -} - /* zxdg_decoration_manager_v1 setup function */ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -1564,7 +1550,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { - WL_INTERFACE(wp_viewporter); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); @@ -1573,7 +1558,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { } else if(wayland->type == MwLL_WAYLAND_POPUP) { WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { - WL_INTERFACE(wp_viewporter); WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_seat); } else { From f3c9c8650540317e459a1724fcc545ef35929be4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 18:26:32 -0700 Subject: [PATCH 004/102] document bindings --- doc/BINDINGS.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 doc/BINDINGS.md diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md new file mode 100644 index 000000000..c5bcdd7a7 --- /dev/null +++ b/doc/BINDINGS.md @@ -0,0 +1,14 @@ +# Active Bindings + +| Language | Repo | Version | Notes | +| -------- | --------------------------------------------------------------------- | ------- | -------------- | +| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | | +| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 1.5* | Auto-generated | +| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 1.5* | Auto-generated | +| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 1.5* | Auto-generated | + +# Inactive Bindings + +| Language | Repo | Version | Notes | +| -------- | ---------------------------------------------------- | ----------- | ----- | +| Rust | [milsko-rs](https://github.com/pyrite-dev/milsko-rs) | **pre-1.0** | | From a27d914ba2938eaac6137526146b23a02e2f9c30 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 18:28:08 -0700 Subject: [PATCH 005/102] in bindings document what aestrick means --- doc/BINDINGS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index c5bcdd7a7..37821915d 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -1,3 +1,5 @@ +\* = in-dev version + # Active Bindings | Language | Repo | Version | Notes | From 3e9ffcee0bc12aedb52e88a2c768a9466e01bb0f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 18:31:09 -0700 Subject: [PATCH 006/102] node.js bindings are auto generated --- doc/BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index 37821915d..44014accc 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -4,7 +4,7 @@ | Language | Repo | Version | Notes | | -------- | --------------------------------------------------------------------- | ------- | -------------- | -| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | | +| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | Auto-generated | | C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 1.5* | Auto-generated | | Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 1.5* | Auto-generated | | Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 1.5* | Auto-generated | From 2b15e7e0a3a5aac4fff6af8ad7c26a7d73821108 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 13:11:34 +0900 Subject: [PATCH 007/102] introducde underline and strikethrough --- include/Mw/StringDefs.h | 2 ++ milsko.xml | 8 +++++--- src/core.c | 24 ++++++++++++++++-------- src/draw.c | 4 +++- src/text/text.c | 33 +++++++++++++++++++++++++++------ 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index cf0a7233a..8d00b409e 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -58,6 +58,8 @@ #define MwNminute "Iminute" #define MwNsecond "Isecond" #define MwNtype "Itype" +#define MwNstrikethrough "Istrikethrough" +#define MwNunderline "Iunderline" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/milsko.xml b/milsko.xml index 5b9041000..7a7410a9e 100644 --- a/milsko.xml +++ b/milsko.xml @@ -105,13 +105,15 @@ - - - + + + + + diff --git a/src/core.c b/src/core.c index 481fa340f..1403310f8 100644 --- a/src/core.c +++ b/src/core.c @@ -69,7 +69,8 @@ static void lldrawhandler(MwLL handle, void* data) { static void lluphandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; MwMouse* p = data; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; if(p->button == MwMOUSE_LEFT) h->pressed = 0; h->mouse_point.x = p->point.x; @@ -83,7 +84,8 @@ static void lluphandler(MwLL handle, void* data) { static void lldownhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; MwMouse* p = data; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; if(p->button == MwMOUSE_LEFT) h->pressed = 1; h->mouse_point.x = p->point.x; @@ -158,7 +160,8 @@ static void llmovehandler(MwLL handle, void* data) { static void llkeyhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; int key = *(int*)data; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatch3(h, key, key); MwDispatchUserHandler(h, MwNkeyHandler, data); @@ -166,28 +169,32 @@ static void llkeyhandler(MwLL handle, void* data) { static void llkeyrelhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNkeyReleaseHandler, data); } static void llfocusinhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNfocusInHandler, data); } static void llfocusouthandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNfocusOutHandler, data); } static void llclipboardhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatch3(h, clipboard, data); MwDispatchUserHandler(h, MwNclipboardHandler, data); @@ -195,7 +202,8 @@ static void llclipboardhandler(MwLL handle, void* data) { static void lldraganddrophandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNdragAndDropHandler, data); } diff --git a/src/draw.c b/src/draw.c index eb15c76ba..ab4c9cb2a 100644 --- a/src/draw.c +++ b/src/draw.c @@ -39,7 +39,9 @@ static int hex(const char* txt, int len) { } static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { - if(MwGetInteger(handle, MwNdisabled) == 1) { + int n; + + if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { diff --git a/src/text/text.c b/src/text/text.c index 45e588602..1c9f6e6de 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -82,8 +82,9 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, char* last = input; int cp; MwLLColor fadedColor = NULL; + int n; - if(MwGetInteger(handle, MwNdisabled) == 1) { + if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { @@ -107,8 +108,10 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, input += MwUTF8ToUTF32(input, &cp); if(*input == 0 || cp == '\n') { - char* line = malloc(input - last + 1); - int i; + char* line = malloc(input - last + 1); + int i; + MwPoint l[2]; + int tw, th; if(!line) { printf("Out Of Memory\n"); @@ -134,20 +137,38 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, continue; } + tw = MwTextWidth(handle, ttf, line); + th = MwTextHeight(handle, ttf, line); + p.x = point->x; if(align == MwALIGNMENT_CENTER) { - p.x -= MwTextWidth(handle, ttf, line) / 2; + p.x -= tw / 2; } else if(align == MwALIGNMENT_END) { - p.x -= MwTextWidth(handle, ttf, line); + p.x -= tw; } + l[0].x = p.x; + l[1].x = l[0].x + tw; + #ifdef TTF if(MwFLDrawText) if(is_bitmap(handle, ttf) || ttf == NULL || MwFLDrawText(handle, ttf, &p, line, fadedColor ? fadedColor : color)) #endif bitmap_MwDrawText(handle, &p, line, is_bold(handle, ttf), fadedColor ? fadedColor : color); - p.y += MwTextHeight(handle, ttf, line); + l[0].y = l[1].y = p.y; + + if((n = MwGetInteger(handle, MwNstrikethrough)) != MwDEFAULT && n) { + MwLLLine(handle->lowlevel, l, color); + } + + if((n = MwGetInteger(handle, MwNunderline)) != MwDEFAULT && n) { + l[0].y += th / 2; + l[1].y += th / 2; + MwLLLine(handle->lowlevel, l, color); + } + + p.y += th; free(line); From 39dd112f2bd9fc4ef1aa60a4e995dca51402b403 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 21 Sep 2026 11:47:44 +0900 Subject: [PATCH 008/102] improve callback --- examples/basic/document.c | 7 ++++--- milsko.xml | 28 ++++++++++++++++++---------- pl/rules.pl | 2 +- src/backend/cairo.c | 12 ++++++------ src/widget/document.c | 6 ++++-- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/examples/basic/document.c b/examples/basic/document.c index f9529fe04..cea017042 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -22,11 +22,12 @@ static void MWAPI resize_window(MwWidget handle, void* user, void* call) { } static void MWAPI layout_document(MwWidget handle, void* user, void* call) { - int height = *(int*)call; + MwRect size = *(MwRect*)call; - MwViewportSetSize(viewport, MwGetInteger(document, MwNwidth), height); + MwViewportSetSize(viewport, size.width, size.height); MwVaApply(document, - MwNheight, height, + MwNwidth, size.width, + MwNheight, size.height, NULL); } diff --git a/milsko.xml b/milsko.xml index 7a7410a9e..81d6e136e 100644 --- a/milsko.xml +++ b/milsko.xml @@ -105,15 +105,13 @@ - - - + + + - - @@ -206,7 +204,7 @@ - + @@ -1072,10 +1070,20 @@ - - - - + + + + + + + + + + + + + + diff --git a/pl/rules.pl b/pl/rules.pl index f12c0922f..7a58a9715 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,7 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - scan_wayland_protocol("staging", "fifo", "-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 9dab1c197..3f1e18c80 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -219,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -264,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/widget/document.c b/src/widget/document.c index 1f48cec66..d6aec38a4 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -498,6 +498,7 @@ static void layout(MwWidget handle) { MwFLFont* fontstack = NULL; MwRect clickable; char* c_title = NULL; + MwRect size; arrput(fontstack, NULL); @@ -612,8 +613,9 @@ static void layout(MwWidget handle) { l->font = TOPFONT; } - y += MwTextHeight(handle, TOPFONT, "M"); - MwDispatchUserHandler(handle, MwNlayoutHandler, &y); + size.width = w; + size.height = y + MwTextHeight(handle, TOPFONT, "M"); + MwDispatchUserHandler(handle, MwNlayoutHandler, &size); arrfree(fontstack); From 2858679cc4ef80c6c0bf679aa02e6e9326043488 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 21 Sep 2026 11:57:37 +0900 Subject: [PATCH 009/102] optimize --- src/widget/document.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/widget/document.c b/src/widget/document.c index d6aec38a4..f71e1bcad 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -59,6 +59,17 @@ static void draw(MwWidget handle) { MwFLFont font = NULL; MwPoint u_p, s_p, c_p; int u = 0, s = 0, c = 0; + int s_y = 0; + int s_h = MwGetInteger(handle, MwNheight); + MwWidget p = handle->parent; + + s_y = MwGetInteger(handle, MwNy); + while(p != NULL && p->widget_class != MwWindowClass) { + s_y += MwGetInteger(p, MwNy); + + p = p->parent; + } + s_y *= -1; u_p.x = s_p.x = c_p.x = 0; u_p.y = s_p.y = c_p.y = 0; @@ -80,6 +91,8 @@ static void draw(MwWidget handle) { p.x = l->x; p.y = l->y + MwTextHeight(handle, font, l->text) / 2; + if(p.y <= s_y || p.y >= s_y + s_h) break; + if(u || s || c) { MwPoint line[2]; int j; From f8c678ac53bee5be4005afb19317d2b192525c62 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 21 Sep 2026 12:41:56 +0900 Subject: [PATCH 010/102] ok --- include/Mw/Core.h | 7 +++++++ include/Mw/Draw.h | 7 +++++++ src/core.c | 27 +++++++++++++++++++++++++++ src/draw.c | 32 ++++++++++++++++++++++++++++++++ src/widget/document.c | 17 +++++------------ 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 61cb08550..318a8cab3 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -390,6 +390,13 @@ MWDECL void MWAPI MwFreeWidget(MwWidget handle); */ MWDECL void MWAPI MwGetFrame(MwWidget handle, MwRect* rect); +/*! + * @brief Gets the clipping frame of the widget + * @param handle Widget + * @param rect Frame + */ +MWDECL void MWAPI MwGetClipFrame(MwWidget handle, MwRect* rect); + #ifdef _MILSKO MWDECL void MwForceRender_Internal(MwWidget handle); MWDECL void MwForceRender2_Internal(MwWidget handle, void* ptr); diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index ad13c6032..12d3d4534 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -220,6 +220,13 @@ MWDECL void MWAPI MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, */ MWDECL void MWAPI MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor background, int filled); +/*! + * @brief Calculate intersect of 2 rectangles + * @param a 1st rectangle + * @param a 2nd rectangle + */ +MWDECL void MwIntersectRect(MwRect* a, const MwRect* b); + /* text.c */ /*! diff --git a/src/core.c b/src/core.c index 1403310f8..7bc706514 100644 --- a/src/core.c +++ b/src/core.c @@ -1241,4 +1241,31 @@ void MwGetFrame(MwWidget handle, MwRect* rect) { rect->height = MwGetInteger(handle, MwNheight); } +void MwGetClipFrame(MwWidget handle, MwRect* rect) { + MwWidget child = handle; + MwWidget p = handle->parent; + int o_x = 0, o_y = 0; + + rect->x = 0; + rect->y = 0; + rect->width = MwGetInteger(handle, MwNwidth); + rect->height = MwGetInteger(handle, MwNheight); + while(p != NULL && p->widget_class != MwWindowClass) { + MwRect pclip; + + o_x += MwGetInteger(child, MwNx); + o_y += MwGetInteger(child, MwNy); + + pclip.x = -o_x; + pclip.y = -o_y; + pclip.width = MwGetInteger(p, MwNwidth); + pclip.height = MwGetInteger(p, MwNheight); + MwIntersectRect(rect, &pclip); + if(rect->width == 0 || rect->height == 0) break; + + child = p; + p = p->parent; + } +} + const char* MwVersionString = MwVERSION; diff --git a/src/draw.c b/src/draw.c index ab4c9cb2a..b2ab8b148 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1125,3 +1125,35 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { return px; } + +static int _min(int a, int b) { + return a < b ? a : b; +} + +static int _max(int a, int b) { + return a > b ? a : b; +} + +void MwIntersectRect(MwRect* a, const MwRect* b) { + int x; + int y; + int right; + int bottom; + + x = _max(a->x, b->x); + y = _max(a->y, b->y); + right = _min(a->x + a->width, b->x + b->width); + bottom = _min(a->y + a->height, b->y + b->height); + + a->x = x; + a->y = y; + + if(right <= x || bottom <= x) { + a->width = 0; + a->height = 0; + return; + } + + a->width = right - x; + a->height = bottom - y; +} diff --git a/src/widget/document.c b/src/widget/document.c index f71e1bcad..eb5233d43 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -59,17 +59,9 @@ static void draw(MwWidget handle) { MwFLFont font = NULL; MwPoint u_p, s_p, c_p; int u = 0, s = 0, c = 0; - int s_y = 0; - int s_h = MwGetInteger(handle, MwNheight); - MwWidget p = handle->parent; + MwRect clip; - s_y = MwGetInteger(handle, MwNy); - while(p != NULL && p->widget_class != MwWindowClass) { - s_y += MwGetInteger(p, MwNy); - - p = p->parent; - } - s_y *= -1; + MwGetClipFrame(handle, &clip); u_p.x = s_p.x = c_p.x = 0; u_p.y = s_p.y = c_p.y = 0; @@ -87,11 +79,12 @@ static void draw(MwWidget handle) { case MwDOCUMENT_TEXT: { MwPoint p; + int th2; p.x = l->x; - p.y = l->y + MwTextHeight(handle, font, l->text) / 2; + p.y = l->y + (th2 = MwTextHeight(handle, font, l->text) / 2); - if(p.y <= s_y || p.y >= s_y + s_h) break; + if((p.y + th2) <= clip.y || (p.y - th2) >= clip.y + clip.height) break; if(u || s || c) { MwPoint line[2]; From b1a2d4d549229149a8f4af37c657ae84a52d429b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 11:36:08 -0700 Subject: [PATCH 011/102] wayland fixes --- src/backend/wayland/interfaces.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 50a58e465..2d6649318 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -17,9 +17,9 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat); static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); -static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); -static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); -static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos); +static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); +static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); +static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos); /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { @@ -398,7 +398,6 @@ static void wl_data_source_listener_target(void* data, (void)data; (void)wl_data_source; (void)mime_type; - printf("test\n"); }; static void wl_data_source_listener_send(void* data, struct wl_data_source* wl_data_source, @@ -591,6 +590,10 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria if(self->wayland.backbuffer.surface == surface) { curSurface = surface; } + + self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); + self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); + WAYLAND_EVENT_OP_END(self); }; @@ -780,7 +783,7 @@ static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { } }; -static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) { +static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) { MwLL topmost_parent = child; MwPoint point; MwPoint relative_mouse_pos; @@ -791,8 +794,15 @@ static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoi while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; if(topmost_parent) { - absolute_pos.x += topmost_parent->wayland.x; - absolute_pos.y += topmost_parent->wayland.y; + /* if the topmost parent is a popup then its x/y is irrelevant to us. + * it's gonna be the position of the popup itself, and we want our + * position to be relative to the popup itself. */ + if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { + if(topmost_parent->wayland.x > 0) + absolute_pos.x += topmost_parent->wayland.x; + if(topmost_parent->wayland.y > 0) + absolute_pos.y += topmost_parent->wayland.y; + } } } From 4cb88fdc05e74ddb3f1a4032dca53fcf64634bb7 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 11:40:51 -0700 Subject: [PATCH 012/102] wayland: remove our widget from parent's currently held widgets on destroy --- src/backend/wayland/wayland.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index c8544531c..d53451808 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -986,6 +986,9 @@ static void MwLLDestroyImpl(MwLL handle) { int i; struct timeval tv; int select_ret; + MwLL topmost_parent = handle; + + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; event_loop(handle); // wl_display_cancel_read(handle->wayland.display); @@ -1025,6 +1028,12 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } + for(i = 0; i < arrlen(topmost_parent->wayland.currentlyHeldWidgets); i++) { + if(topmost_parent->wayland.currentlyHeldWidgets[i] == handle) { + arrdel(topmost_parent->wayland.currentlyHeldWidgets, i); + } + } + // pthread_mutex_destroy(&handle->wayland.eventsMutex); free(handle); From e8d692f05a296064f2f37f6dc369a7219505b173 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 11:54:07 -0700 Subject: [PATCH 013/102] remove the unneeded 'wayland event start/end' macros --- include/Mw/LowLevel/Wayland.h | 6 --- src/backend/wayland/interfaces.c | 85 +++++--------------------------- src/backend/wayland/wayland.c | 3 +- 3 files changed, 14 insertions(+), 80 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0d5a24f66..83cd29990 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -488,12 +488,6 @@ void MwLLWaylandFlush(MwLL handle); /* recursively dispatch the key event to focused widgets. */ void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down); -/* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) - -/* Footer for WAYLAND_EVENT_OP_START */ -#define WAYLAND_EVENT_OP_END(self) - /* the two decoration manager constructs */ typedef struct zxdg_decoration_manager_v1_context { struct zxdg_decoration_manager_v1* manager; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 2d6649318..82146f600 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -72,8 +72,6 @@ static void new_protocol(void* data, struct wl_registry* registry, (void)version; (void)registry; - WAYLAND_EVENT_OP_START(self); - wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); if(cb != NULL) { shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); @@ -83,8 +81,6 @@ static void new_protocol(void* data, struct wl_registry* registry, } else { // printf("unknown interface %s\n", interface); } - - WAYLAND_EVENT_OP_END(self); }; /* `wl_registry.global_remove` callback */ @@ -154,11 +150,7 @@ static void wl_data_device_enter(void* data, (void)y; (void)id; - WAYLAND_EVENT_OP_START(self); - self->ll->wayland.clipboard_serial = serial; - - WAYLAND_EVENT_OP_END(self); }; static void wl_data_device_leave(void* data, struct wl_data_device* wl_data_device) { @@ -407,12 +399,10 @@ static void wl_data_source_listener_send(void* data, (void)wl_data_source; (void)mime_type; - WAYLAND_EVENT_OP_START(self); if(self->wayland.clipboard_buffer != NULL) { write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer)); close(fd); } - WAYLAND_EVENT_OP_END(self); }; static void wl_data_source_listener_cancelled(void* data, struct wl_data_source* wl_data_source); @@ -427,8 +417,6 @@ static void wl_data_source_listener_cancelled(void* data, struct wl_data_source* wl_data_source) { MwLL self = data; - WAYLAND_EVENT_OP_START(self); - if(wl_data_source) wl_data_source_destroy(wl_data_source); @@ -442,8 +430,6 @@ static void wl_data_source_listener_cancelled(void* data, wl_data_source_offer(self->wayland.clipboard_source.wl, "text/uri-list"); wl_data_source_add_listener(self->wayland.clipboard_source.wl, &wl_data_source_listener, self); - - WAYLAND_EVENT_OP_END(self); }; static void zwp_primary_selection_source_v1_send(void* data, @@ -454,22 +440,16 @@ static void zwp_primary_selection_source_v1_send(void* data, (void)wl_data_source; (void)mime_type; - WAYLAND_EVENT_OP_START(self); - if(self->wayland.clipboard_buffer != NULL) { write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer)); close(fd); } - - WAYLAND_EVENT_OP_END(self); }; static void zwp_primary_selection_source_v1_cancelled(void* data, struct zwp_primary_selection_source_v1* wl_data_source) { MwLL self = data; (void)wl_data_source; - WAYLAND_EVENT_OP_START(self); - zwp_primary_selection_source_v1_destroy(self->wayland.clipboard_source.zwp); self->wayland.clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(self->wayland.clipboard_manager.zwp); @@ -479,8 +459,6 @@ static void zwp_primary_selection_source_v1_cancelled(void* data, zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "TEXT"); zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "STRING"); zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "UTF8_STRING"); - - WAYLAND_EVENT_OP_END(self); }; struct zwp_primary_selection_source_v1_listener zwp_primary_selection_source_v1_listener = { @@ -577,7 +555,6 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria (void)surface_y; (void)wl_pointer; - WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; if(self->wayland.framebuffer.surface == surface) { @@ -593,20 +570,15 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - - WAYLAND_EVENT_OP_END(self); }; /* `wl_pointer.leave` callback */ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface) { - MwLL self = data; + (void)data; (void)wl_pointer; (void)serial; (void)surface; - WAYLAND_EVENT_OP_START(self); - curSurface = NULL; - WAYLAND_EVENT_OP_END(self); }; static void xdg_borderless_step_mdown(MwLL self, MwMouse p, MwU32 serial) { @@ -676,15 +648,11 @@ static void relative_pointer_motion(void* data, (void)dx; (void)dy; - WAYLAND_EVENT_OP_START(self); - p.point.x = wl_fixed_to_int(dxUnaccel); p.point.y = wl_fixed_to_int(dyUnaccel); recursive_dispatch_move(self, &p); if(self->wayland.locked_pointer) zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP); - - WAYLAND_EVENT_OP_END(self); } struct zwp_relative_pointer_v1_listener MwLLWaylandRelativePointerListener = @@ -716,7 +684,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time (void)time; (void)wl_pointer; - WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; currentlyHeldWidgets = topmost_parent->wayland.currentlyHeldWidgets; @@ -752,8 +719,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time if(self->wayland.backbuffer.surface) { wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); } - - WAYLAND_EVENT_OP_END(self); }; static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { @@ -794,10 +759,8 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; if(topmost_parent) { - /* if the topmost parent is a popup then its x/y is irrelevant to us. - * it's gonna be the position of the popup itself, and we want our - * position to be relative to the popup itself. */ - if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { + /* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */ + if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { if(topmost_parent->wayland.x > 0) absolute_pos.x += topmost_parent->wayland.x; if(topmost_parent->wayland.y > 0) @@ -881,8 +844,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri (void)serial; (void)time; - WAYLAND_EVENT_OP_START(self); - if(self->wayland.type != MwLL_WAYLAND_POPUP) { while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; } @@ -909,19 +870,18 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri arrsetlen(self->wayland.currentlyHeldWidgets, 0); mouse_dispatch(self, p, state); - } - if(self->wayland.backbuffer.surface) { - if(!self->wayland.has_decorations && self->wayland.do_csd) { - if(state != WL_POINTER_BUTTON_STATE_RELEASED) - xdg_borderless_step_mdown(self, p, serial); - else - xdg_borderless_step_mup(self, p, serial); + + if(self->wayland.backbuffer.surface) { + if(!self->wayland.has_decorations && self->wayland.do_csd) { + if(state != WL_POINTER_BUTTON_STATE_RELEASED) + xdg_borderless_step_mdown(self, p, serial); + else + xdg_borderless_step_mup(self, p, serial); + } } } MwLLForceRender(self); - - WAYLAND_EVENT_OP_END(self); }; /* `wl_pointer.axis` callback */ @@ -984,13 +944,9 @@ static void keyboard_enter(void* data, (void)surface; (void)keys; - WAYLAND_EVENT_OP_START(self); - self->wayland.keyboard_serial = serial; MwLLDispatch(self, focus_in, NULL); - - WAYLAND_EVENT_OP_END(self); }; /* `wl_keyboard.leave` callback */ @@ -1003,11 +959,7 @@ static void keyboard_leave(void* data, (void)serial; (void)surface; - WAYLAND_EVENT_OP_START(self); - MwLLDispatch(self, focus_out, NULL); - - WAYLAND_EVENT_OP_END(self); }; void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { @@ -1053,8 +1005,6 @@ static void keyboard_key(void* data, while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - WAYLAND_EVENT_OP_START(self); - if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } @@ -1072,7 +1022,7 @@ static void keyboard_key(void* data, int i; if(!self->wayland.xkb_keymap) { - WAYLAND_EVENT_OP_END(self); + return; } @@ -1087,7 +1037,7 @@ static void keyboard_key(void* data, } syms_num = xkb_keymap_key_get_syms_by_level(self->wayland.xkb_keymap, keycode, layout, level, &syms_out); if(syms_out == NULL) { - WAYLAND_EVENT_OP_END(self); + return; } @@ -1161,8 +1111,6 @@ static void keyboard_key(void* data, if(!MwWaylandVulkan) { MwLLDispatch(self, draw, NULL); } - - WAYLAND_EVENT_OP_END(self); }; /* `wl_keyboard.modifiers` callback */ @@ -1179,13 +1127,9 @@ static void keyboard_modifiers(void* data, (void)group; (void)mods_latched; - WAYLAND_EVENT_OP_START(self); - self->wayland.mod_state = 0; self->wayland.mod_state |= mods_depressed; self->wayland.mod_state |= mods_locked; - - WAYLAND_EVENT_OP_END(self); }; static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat) { @@ -1256,8 +1200,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, MwU32 capabilities) { MwLL self = data; - WAYLAND_EVENT_OP_START(self); - /* Always remember the seat itself, regardless of which capabilities it has - this is * both what setup_clipboard()/setup_zwp_clipboard() below use, and what lets * wl_seat_interface_destroy() release it later even on a keyboard-only seat. */ @@ -1271,7 +1213,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, self->wayland.pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); } - WAYLAND_EVENT_OP_END(self); /* Only hooked up if this seat actually has a pointer: wl_data_device.get_data_device() * requires a non-null seat, and pointer_seat is only ever null before the first diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d53451808..a0645e79f 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -196,9 +196,8 @@ static void xdg_toplevel_close( void* data, struct xdg_toplevel* xdg_toplevel) { MwLL self = data; (void)xdg_toplevel; - WAYLAND_EVENT_OP_START(self); + MwLLDispatch(self, close, NULL); - WAYLAND_EVENT_OP_END(self); }; /* `xdg_surface.configure` callback */ From 9420878b93ea98cdd62ee416d968de2c60920a54 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 12:01:23 -0700 Subject: [PATCH 014/102] oops! fix csd not working --- src/backend/wayland/interfaces.c | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 82146f600..31a8219d8 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -692,9 +692,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time inArea |= self->wayland.framebuffer.surface == curSurface; } - // if(self->wayland.backbuffer.surface) { - // inArea |= self->wayland.backbuffer.surface == curSurface; - // } + if(self->wayland.backbuffer.surface) { + inArea |= self->wayland.backbuffer.surface == curSurface; + } self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); @@ -854,30 +854,30 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri inArea |= self->wayland.framebuffer.surface == curSurface; } - if(inArea) { - switch(button) { - case BTN_LEFT: - p.button = MwMOUSE_LEFT; - break; - case BTN_MIDDLE: - p.button = MwMOUSE_MIDDLE; - break; - case BTN_RIGHT: - p.button = MwMOUSE_RIGHT; - break; - } - self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; + switch(button) { + case BTN_LEFT: + p.button = MwMOUSE_LEFT; + break; + case BTN_MIDDLE: + p.button = MwMOUSE_MIDDLE; + break; + case BTN_RIGHT: + p.button = MwMOUSE_RIGHT; + break; + } + if(inArea) { + self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; arrsetlen(self->wayland.currentlyHeldWidgets, 0); mouse_dispatch(self, p, state); + } - if(self->wayland.backbuffer.surface) { - if(!self->wayland.has_decorations && self->wayland.do_csd) { - if(state != WL_POINTER_BUTTON_STATE_RELEASED) - xdg_borderless_step_mdown(self, p, serial); - else - xdg_borderless_step_mup(self, p, serial); - } + if(self->wayland.backbuffer.surface) { + if(!self->wayland.has_decorations && self->wayland.do_csd) { + if(state != WL_POINTER_BUTTON_STATE_RELEASED) + xdg_borderless_step_mdown(self, p, serial); + else + xdg_borderless_step_mup(self, p, serial); } } From 954a4a8e1562dea886070b733b40f218d1cafc42 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 14:27:03 -0700 Subject: [PATCH 015/102] disable dnd on X11 for now --- examples/basic/dnd.c | 2 +- src/backend/x11.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index 8d0f47d03..56e1c8e34 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -48,7 +48,7 @@ int main() { NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); - MwAddUserHandler(instructions, MwNdragAndDropHandler, dnd, NULL); + MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL); resize(window, NULL, NULL); diff --git a/src/backend/x11.c b/src/backend/x11.c index eaa64e0f6..b713821e3 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -978,6 +978,7 @@ static void MwLLNextEventImpl(MwLL handle) { }; case SelectionNotify: { +#if 0 handle->x11.clipboard_pending = 0; if(ev.xselection.property == handle->x11.xdnd_selection) { @@ -1066,6 +1067,7 @@ static void MwLLNextEventImpl(MwLL handle) { } XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection); } +#endif } break; } if(render) { From cb5efd9224d7e2a2648629276499b7e740f11a7c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 15:49:01 -0700 Subject: [PATCH 016/102] wayland: got resizing looking good enough --- include/Mw/LowLevel/Wayland.h | 7 ++++ src/backend/wayland/buffer.c | 65 +++++++++++++++++++++++++++++++---- src/backend/wayland/wayland.c | 10 ++---- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 83cd29990..91234588b 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -271,6 +271,7 @@ struct _MwLLWaylandShmBuffer { MwU8* buf; MwU8* buf_back; MwU64 buf_size; + MwU64 buf_capacity; int fd; int fd_back; MwBool setup; @@ -466,6 +467,12 @@ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* handle); void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); +/* Resize an already set-up shm buffer pair in place, growing the backing pool with + * wl_shm_pool_resize instead of tearing it down and recreating it from scratch. */ +void MwLLWaylandBufferResize(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); + +void MwLLWaylandFramebufferResize(struct _MwLLWayland* wayland); +void MwLLWaylandBackbufferResize(struct _MwLLWayland* wayland); void MwLLWaylandRegionSetup(MwLL handle); void MwLLWaylandRegionInvalidate(MwLL handle); diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 79ce72cad..3b6171658 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -7,7 +7,7 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh); - memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); + memset(wayland->framebuffer.buf_back, 255, wayland->framebuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); if(wayland->framebuffer.fifo) @@ -38,7 +38,7 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h); - memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); + memset(wayland->backbuffer.buf_back, 0, wayland->backbuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); // if(wayland->framebuffer.fifo) @@ -90,6 +90,8 @@ void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, M buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0); buffer->buf_back = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd_back, 0); + buffer->buf_capacity = buffer->buf_size; + fsync(buffer->fd); fsync(buffer->fd_back); @@ -108,8 +110,8 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { if(!buffer->setup) { return; } - if(buffer->buf) munmap(buffer->buf, buffer->buf_size); - if(buffer->buf_back) munmap(buffer->buf_back, buffer->buf_size); + if(buffer->buf) munmap(buffer->buf, buffer->buf_capacity); + if(buffer->buf_back) munmap(buffer->buf_back, buffer->buf_capacity); if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer); if(buffer->shm_buffer_back) wl_buffer_destroy(buffer->shm_buffer_back); if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool); @@ -119,14 +121,63 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { buffer->setup = MwFALSE; } +void MwLLWaylandBufferResize(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { + MwLLWaylandBufferDestroy(buffer); + MwLLWaylandBufferSetup(buffer, width, height); + memset(buffer->buf_back, 0, buffer->buf_size); + memset(buffer->buf, 0, buffer->buf_size); +} + +void MwLLWaylandFramebufferResize(struct _MwLLWayland* wayland) { + MwLLWaylandBufferResize(&wayland->framebuffer, wayland->ww, wayland->wh); + + MwLLCairoFrontDestroy(&wayland->cairo); + MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh); + + if(wayland->configured) + wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); + if(wayland->framebuffer.fifo) + wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); + + wl_surface_commit(wayland->framebuffer.surface); + + MwLLWaylandHangUntilConfigured((MwLL)wayland); + MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->framebuffer); +} + +void MwLLWaylandBackbufferResize(struct _MwLLWayland* wayland) { + MwU32 w = wayland->ww; + MwU32 h = wayland->wh; + + if(wayland->type != MwLL_WAYLAND_TOPLEVEL) { + return; + } + + if(!wayland->has_decorations && wayland->do_csd) { + w += (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); + h += (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + } + + MwLLWaylandBufferResize(&wayland->backbuffer, w, h); + + MwLLCairoBackDestroy(&wayland->cairo); + MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h); + + if(wayland->configured) + wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); + wl_surface_commit(wayland->backbuffer.surface); + MwLLWaylandHangUntilConfigured((MwLL)wayland); + MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->backbuffer); +} + void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { if(self->wayland.configured) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); if(buffer->surface) { // Yes this is needed every time, it's how we fix weston. - if(self->wayland.configured) { - wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - } + // if(self->wayland.configured) { + // wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + // } if(buffer->fifo) wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index a0645e79f..650e949da 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -173,10 +173,7 @@ static void xdg_toplevel_configure(void* data, if(self->wayland.resizing == 0) { xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); - MwLLWaylandBackbufferDestroy(&self->wayland); - MwLLWaylandBackbufferSetup(&self->wayland); - MwLLWaylandFramebufferDestroy(&self->wayland); - MwLLWaylandFramebufferSetup(&self->wayland); + MwLLWaylandFramebufferResize(&self->wayland); MwLLWaylandRegionSetup(self); MwLLDispatch(self, resize, NULL); @@ -1112,10 +1109,7 @@ static void actually_set_wh(MwLL handle) { MwLLWaylandRegionSetup(handle); if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) recursive_render(handle); - MwLLWaylandFramebufferDestroy(&handle->wayland); - MwLLWaylandFramebufferSetup(&handle->wayland); - MwLLWaylandBackbufferDestroy(&handle->wayland); - MwLLWaylandBackbufferSetup(&handle->wayland); + MwLLWaylandFramebufferResize(&handle->wayland); MwLLDispatch(handle, draw, NULL); } From 58027c095f51bd4f68e45b0bc21a7ed3edb8c747 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 16:51:46 -0700 Subject: [PATCH 017/102] snapshot previous buffer so that we don't have ghosting anymore on rotate (this also makes resizing A Bit better) --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland/wayland.c | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 91234588b..c176ee297 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -428,6 +428,8 @@ struct _MwLLWayland { MwBool do_cascading_draw; int cascading_child_num; + cairo_surface_t* snapshot; + MwBool dispatching_resize; struct _MwLLWaylandShmBuffer framebuffer; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 650e949da..24c6a1b31 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -939,6 +939,13 @@ static void draw_children(MwLL handle) { cairo_reset_clip(handle->wayland.cairo.front_cairo_back); + if(handle->wayland.snapshot) { + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(handle->wayland.cairo.front_cairo_back, handle->wayland.snapshot, 0, 0); + cairo_paint(handle->wayland.cairo.front_cairo_back); + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER); + } + MwLLWaylandChildrenIterate(handle, draw_child); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); @@ -1299,6 +1306,21 @@ static void MwLLEndDrawImpl(MwLL handle) { } root->wayland.do_cascading_draw = MwTRUE; + if(handle->wayland.snapshot) { + cairo_surface_destroy(handle->wayland.snapshot); + handle->wayland.snapshot = NULL; + } + if(handle->wayland.ww > 0 && handle->wayland.wh > 0) { + cairo_t* snap_cr; + + handle->wayland.snapshot = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, handle->wayland.ww, handle->wayland.wh); + snap_cr = cairo_create(handle->wayland.snapshot); + cairo_set_operator(snap_cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(snap_cr, handle->wayland.cairo.front_cs_back, 0, 0); + cairo_paint(snap_cr); + cairo_destroy(snap_cr); + } + if(handle->wayland.configured) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); From e43a5291f5d3ddb154e5e583b84e42c78ac97f49 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 16:55:27 -0700 Subject: [PATCH 018/102] combobox fix --- src/backend/wayland/buffer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 3b6171658..dec8564f9 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -175,9 +175,10 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); if(buffer->surface) { // Yes this is needed every time, it's how we fix weston. - // if(self->wayland.configured) { - // wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - // } + // it's also how we fix comboboxes. + if(self->wayland.configured) { + wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + } if(buffer->fifo) wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); From c2f8fb3f82ab64d24eba5f8772dd20b425153218 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 17:22:15 -0700 Subject: [PATCH 019/102] wayland: actual subsurface type for the one widget that needs it (vulkan) --- CMakeLists.txt | 2 +- examples/vkdemos/vulkan.c | 4 +- include/Mw/LowLevel/Wayland.h | 11 +++++ src/backend/wayland/interfaces.c | 15 +++---- src/backend/wayland/wayland.c | 69 ++++++++++++++++++++++++++++++++ src/widget/vulkan.c | 12 +++++- 6 files changed, 100 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5bb78056..21746498b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -467,7 +467,7 @@ if(MW_BUILD_VULKAN) ) endif() - check_include_files(vulkan/VULKAN.h HAS_VK_HEADER) + check_include_files(vulkan/vulkan.h HAS_VK_HEADER) if(HAS_VK_HEADER) target_compile_definitions( Mw diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 9060a970f..601541529 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c176ee297..607ff2cae 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -257,6 +257,14 @@ struct _MwLLWaylandLayerSurface { struct zwlr_layer_surface_v1* surface; }; +struct _MwLLWaylandSubsurface { + MwLL parent; + + struct xdg_surface* xdg_surface; + struct wl_subsurface* subsurface; + struct wl_subcompositor* subcompositor; +}; + /* Shared set of anything needed for a shm buffer. */ struct _MwLLWaylandShmBuffer { struct wl_shm* shm; @@ -283,6 +291,7 @@ enum _MwLLWaylandType { MwLL_WAYLAND_SUBLEVEL, MwLL_WAYLAND_POPUP, MwLL_WAYLAND_LAYER_SURFACE, + MwLL_WAYLAND_SUBSURFACE, }; typedef struct wl_clipboard_device_context { @@ -315,6 +324,8 @@ struct _MwLLWayland { struct _MwLLWaylandPopup* popup; /* Pointer for data that's only loaded if the widget is a layer surface */ struct _MwLLWaylandLayerSurface* layer_surface; + /* Pointer for data that's only loaded if the widget is a subsurface */ + struct _MwLLWaylandSubsurface* subsurface; }; enum _MwLLWaylandType type; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 31a8219d8..4aebb6192 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1350,6 +1350,8 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan (void)version; if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + } else if(wayland->type == MwLL_WAYLAND_SUBSURFACE) { + wayland->subsurface->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } return NULL; @@ -1360,6 +1362,9 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wl_subcompositor_destroy(wayland->toplevel->scompositor); } + if(wayland->type == MwLL_WAYLAND_SUBSURFACE) { + wl_subcompositor_destroy(wayland->subsurface->subcompositor); + } } /* xdg_wm_base setup function */ @@ -1500,19 +1505,11 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ + WL_INTERFACE(wl_subcompositor); if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); - WL_INTERFACE(wl_subcompositor); - WL_INTERFACE(wl_seat); WL_INTERFACE(wp_fifo_manager_v1); - } else if(wayland->type == MwLL_WAYLAND_POPUP) { - WL_INTERFACE(wl_seat); - } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { - WL_INTERFACE(wl_subcompositor); - WL_INTERFACE(wl_seat); - } else { - WL_INTERFACE(wl_subcompositor); } #undef WL_INTERFACE } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 24c6a1b31..67429f204 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -366,6 +366,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.sublevel->xdg_surface = parent->wayland.toplevel->xdg_surface; } else if(parent->wayland.type == MwLL_WAYLAND_SUBLEVEL) { r->wayland.sublevel->xdg_surface = parent->wayland.sublevel->xdg_surface; + } else if(parent->wayland.type == MwLL_WAYLAND_SUBSURFACE) { + r->wayland.sublevel->xdg_surface = parent->wayland.subsurface->xdg_surface; } else if(parent->wayland.type == MwLL_WAYLAND_POPUP) { r->wayland.sublevel->xdg_surface = parent->wayland.popup->xdg_surface; } @@ -396,6 +398,66 @@ static void destroy_sublevel(MwLL r) { r->wayland.configured = MwFALSE; } +/* Subsurface setup function */ +static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { + struct wl_compositor* compositor = parent->wayland.compositor; + struct wl_surface* parent_surface = parent->wayland.framebuffer.surface; + + r->wayland.subsurface = malloc(sizeof(struct _MwLLWaylandSubsurface)); + r->wayland.subsurface->parent = parent; + + r->wayland.type = MwLL_WAYLAND_SUBSURFACE; + + r->wayland.display = parent->wayland.display; + + MwLLWaylandSetupCallbacks(&r->wayland); + + r->wayland.registry = wl_display_get_registry(parent->wayland.display); + r->wayland.display = parent->wayland.display; + + if(parent->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + r->wayland.subsurface->xdg_surface = parent->wayland.toplevel->xdg_surface; + } else { + r->wayland.subsurface->xdg_surface = parent->wayland.subsurface->xdg_surface; + } + + wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed: %d\n", wl_display_get_error(r->wayland.display)); + raise(SIGTRAP); + return; + } + + r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); + + r->wayland.subsurface->subsurface = wl_subcompositor_get_subsurface(r->wayland.subsurface->subcompositor, r->wayland.framebuffer.surface, parent_surface); + + wl_subsurface_set_desync(r->wayland.subsurface->subsurface); + wl_subsurface_set_position(r->wayland.subsurface->subsurface, x, y); + + if(parent) { + wl_subsurface_place_above(r->wayland.subsurface->subsurface, parent->wayland.framebuffer.surface); + } + + r->wayland.xkb_keymap = parent->wayland.xkb_keymap; + r->wayland.xkb_state = parent->wayland.xkb_state; + + r->wayland.configured = MwTRUE; + + MwLLWaylandFramebufferSetup(&r->wayland); + MwLLWaylandBackbufferSetup(&r->wayland); +} + +/* Subsurface setup function */ +static void destroy_subsurface(MwLL r) { + MwLLWaylandBackbufferDestroy(&r->wayland); + MwLLWaylandFramebufferDestroy(&r->wayland); + + free(r->wayland.sublevel); + + r->wayland.configured = MwFALSE; +} + static void popup_configure(void* data, struct xdg_popup* xdg_popup, int32_t x, @@ -830,6 +892,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.parent = parent; r->wayland.valid = MwTRUE; + printf("type %d\n", ty); if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { setup_toplevel(r, x, y); @@ -862,6 +925,9 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh case MwLL_WAYLAND_LAYER_SURFACE: setup_layer_surface(r, x, y, width, height); break; + case MwLL_WAYLAND_SUBSURFACE: + setup_subsurface(parent, r, x, y); + break; } } @@ -1086,6 +1152,9 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { break; case MwLL_WAYLAND_UNKNOWN: break; + case MwLL_WAYLAND_SUBSURFACE: + wl_subsurface_set_position(handle->wayland.subsurface->subsurface, x, y); + break; } MwLLWaylandRegionSetup(handle); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index acffda3ad..0bc0703d9 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -351,13 +351,22 @@ static int vulkan_surface_setup(MwWidget handle, vulkan_t* o) { if(handle->lowlevel->common.type == MwLLBackendWayland) { LOAD_VK_FUNCTION(vkCreateWaylandSurfaceKHR); - VkWaylandSurfaceCreateInfoKHR createInfo = { + VkWaylandSurfaceCreateInfoKHR createInfo; + + /* transition to a subsurface */ + MwLLBeginStateChange(handle->lowlevel); + handle->lowlevel->wayland.changing = MwTRUE; + handle->lowlevel->wayland.type_to_be = MwLL_WAYLAND_SUBSURFACE; + MwLLEndStateChange(handle->lowlevel); + + createInfo = (VkWaylandSurfaceCreateInfoKHR){ .sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, .pNext = NULL, .flags = 0, .display = handle->lowlevel->wayland.display, .surface = handle->lowlevel->wayland.framebuffer.surface, }; + VK_CMD(_vkCreateWaylandSurfaceKHR(o->vkInstance, &createInfo, NULL, &o->vkSurface)); } #endif @@ -609,6 +618,7 @@ void MwVulkanConfigure(MwVulkanConfig* cfg) { } int MwVulkanSupported(void) { + printf("[vulkan support not copmiled]\n"); return 0; } #endif From 960db8d3e35ceefe6365266e17541f8a4c8ae884 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 10:13:08 +0900 Subject: [PATCH 020/102] some fix --- examples/basic/clipboard.c | 1 - examples/basic/dnd.c | 3 +-- examples/vkdemos/vulkan.c | 4 ++-- src/core.c | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index 9d060c31a..6c4a46e49 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -45,7 +45,6 @@ static void MWAPI tick(MwWidget handle, void* user_data, void* call_data) { MwGetClipboard(handle, MwCLIPBOARD_MAIN); cur_text = text2; MwGetClipboard(handle, MwCLIPBOARD_PRIMARY); - MwForceRender(window); } int main() { diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index 56e1c8e34..0ce9aeff7 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -44,11 +44,10 @@ int main() { NULL); text_listbox = MwVaCreateWidget(MwListBoxClass, "label", box, 25, 150, 750, 700, MwNtext, "", - MwNacceptsDnD, 1, NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); - MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL); + MwAddUserHandler(instructions, MwNdragAndDropHandler, dnd, NULL); resize(window, NULL, NULL); diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 601541529..9060a970f 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/src/core.c b/src/core.c index 7bc706514..0a5fd8bb3 100644 --- a/src/core.c +++ b/src/core.c @@ -679,7 +679,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { if(h->lowlevel != NULL) MwLLSetDarkTheme(h->lowlevel, n); } - if(strcmp(key, MwNacceptsDnD) == 0) { + if(strcmp(key, MwNacceptsDnD) == 0 && n) { if(handle->lowlevel != NULL) MwLLSetupDragAndDrop(handle->lowlevel); } } From bc326491b5d105cef5165a580013648c4565d78a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 20:58:41 -0700 Subject: [PATCH 021/102] dx9 --- CMakeLists.txt | 23 +++ Jenkinsfile | 8 +- NTMakefile | 21 ++- WatMakefile | 9 +- configure | 8 +- examples/CMakeLists.txt | 9 +- examples/dxdemos/CMakeLists.txt | 24 +++ examples/dxdemos/directx9.c | 93 +++++++++ include/Mw/Widget/DirectX.h | 53 ++++++ pl/rules.pl | 8 + resource/FindDirectX.cmake | 325 ++++++++++++++++++++++++++++++++ src/widget/directx.c | 96 ++++++++++ tools/genmk.pl | 36 +++- 13 files changed, 698 insertions(+), 15 deletions(-) create mode 100644 examples/dxdemos/CMakeLists.txt create mode 100644 examples/dxdemos/directx9.c create mode 100644 include/Mw/Widget/DirectX.h create mode 100644 resource/FindDirectX.cmake create mode 100644 src/widget/directx.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 21746498b..046f08c1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,10 @@ else() option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON) option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON) endif() +if(${CMAKE_SYSTEM_NAME} MATCHES Windows) + option(MW_TRY_DIRECTX "Try to compile DirectX widget or not" ON) +endif() + option(MW_INSTALL_HEADERS "Install headers" ON) @@ -90,6 +94,16 @@ if(MW_TRY_VULKAN) endif() endif() +if(MW_TRY_DIRECTX) + include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) + if(DIRECTX_FOUND) + set(MW_BUILD_DIRECTX ON) + message(STATUS "DirectX widget has been enabled") + else() + message(STATUS "DirectX widget has been disabled") + endif() +endif() + if(MW_BUILD_STATIC) message(STATUS "Building Milsko as a static library") add_library( @@ -477,6 +491,15 @@ if(MW_BUILD_VULKAN) endif() endif() +if(MW_BUILD_DIRECTX) + list(APPEND LIBRARIES ${DIRECTX_D3DX9_LIBRARIES}) + target_compile_definitions( + Mw + PRIVATE + MW_DIRECTX + ) +endif() + target_compile_definitions( Mw PRIVATE diff --git a/Jenkinsfile b/Jenkinsfile index 9b7d63979..6d93874c1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-directx --enable-vulkan --without-vulkan-string-helper") sh("make -j4") sh("mv src/libMw.so libMw64.so") archiveArtifacts("libMw64.so") @@ -42,7 +42,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -55,7 +55,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") @@ -80,7 +80,7 @@ pipeline { } environment { WATCOM = "/usr/watcom" - INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt" + INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt:/usr/watcom/h/nt/directx" PATH = "/usr/watcom/binl64:${env.PATH}" } steps { diff --git a/NTMakefile b/NTMakefile index b07f798ad..37b4a9507 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,7 +1,20 @@ CC = cl /TC /c /nologo LD = link /nologo -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL +!if [where d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!endif +!else +!if [echo DX9_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx9flags.mk") +!include "dx9flags.mk" +!else +DX9_FLAGS = +!endif + +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS) MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = @@ -86,6 +99,7 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj + del /f /q src\widget\directx.obj del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -108,6 +122,7 @@ clean: del /f /q src\widget\window.obj del /f /q src\Mw.dll del /f /q src\Mw.lib + del /f /q dx9flags.mk del /f /q examples\basic\box.obj del /f /q examples\basic\calculator.obj del /f /q examples\basic\checkbox.obj @@ -342,8 +357,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index fd9807901..09a942d0e 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt @@ -85,6 +85,7 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj + %erase src/widget/directx.obj %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -341,8 +342,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/directx.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/directx.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -498,6 +499,8 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c +src/widget/directx.obj: src/widget/directx.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/directx.c src/widget/document.obj: src/widget/document.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c diff --git a/configure b/configure index 44db66d80..f6ff13bc8 100755 --- a/configure +++ b/configure @@ -54,6 +54,9 @@ param_set("examples", 1); # (option that only makes sense on x11) param_set("allow-sloppy-focus", 0); +# (option that only makes sense on Windows) +param_set("directx", 0); + my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", @@ -69,7 +72,8 @@ my %features = ( "wayland" => "enable wayland backend", "gnustep" => "use gnustep", "dbus" => "use DBus on supported platform", - "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus" + "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", + "directx" => "(Windows only) build DirectX widget" ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -78,7 +82,7 @@ my @features_keys = ( "1vulkan", "2vulkan-string-helper", "1shared", "1static", "1wayland", "1gnustep", - "1dbus" + "1dbus", "1directx" ); sub def_platform { diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 5baed4a88..4ac6962b9 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,12 @@ add_subdirectory(basic) if(${MW_TRY_OPENGL}) -add_subdirectory(gldemos) + add_subdirectory(gldemos) endif() if(${MW_TRY_VULKAN}) -add_subdirectory(vkdemos) + add_subdirectory(vkdemos) +endif() +if(WIN32) + if(${MW_TRY_DIRECTX}) + add_subdirectory(dxdemos) + endif() endif() diff --git a/examples/dxdemos/CMakeLists.txt b/examples/dxdemos/CMakeLists.txt new file mode 100644 index 000000000..38265e1cc --- /dev/null +++ b/examples/dxdemos/CMakeLists.txt @@ -0,0 +1,24 @@ +file( + GLOB + EXAMPLES_DIRECTX_SOURCES + *.c +) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake) + +if(${DIRECTX_FOUND}) + foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) + target_include_directories( + ${TARGET} + PRIVATE + ${DIRECTX_INCLUDE_DIRS} + ) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ${DIRECTX_D3DX9_LIBRARIES} + ) + endforeach() +endif() diff --git a/examples/dxdemos/directx9.c b/examples/dxdemos/directx9.c new file mode 100644 index 000000000..6b28ac020 --- /dev/null +++ b/examples/dxdemos/directx9.c @@ -0,0 +1,93 @@ +/* + * Adapted from: + * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-1 + * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4 + */ +#include +#include + +MwWidget window, d3d9; +LPDIRECT3D9 d3d; +LPDIRECT3DDEVICE9 d3ddev; +LPDIRECT3DVERTEXBUFFER9 v_buffer; + +struct CUSTOMVERTEX { + FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag + DWORD color; // from the D3DFVF_DIFFUSE flag +}; +#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) + +static void MWAPI draw(MwWidget handle, void* user, void* client) { + // clear the window to a deep blue + d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); + + d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene + + // select which vertex format we are using + d3ddev->lpVtbl->SetFVF(d3ddev, CUSTOMFVF); + + // select the vertex buffer to display + d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, 0, sizeof(struct CUSTOMVERTEX)); + + // copy the vertex buffer to the back buffer + d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1); + + d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene + + d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame +} + +int main() { + MwLibraryInit(); + + window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); + + d3d9 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + + d3d = MwDirectXGetD3D9(d3d9); + d3ddev = MwDirectXGetD3Dev9(d3d9); + + // create three vertices using the CUSTOMVERTEX struct built earlier + struct CUSTOMVERTEX vertices[] = + { + { + 400.0f, + 0.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 0, 255), + }, + { + 800.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 255, 0), + }, + { + 0.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(255, 0, 0), + }, + }; + + d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, + 3 * sizeof(struct CUSTOMVERTEX), + 0, + CUSTOMFVF, + D3DPOOL_MANAGED, + &v_buffer, + NULL); + + VOID* pVoid; // the void pointer + + v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (void**)&pVoid, 0); // lock the vertex buffer + memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer + v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer + + MwAddUserHandler(window, MwNtickHandler, draw, NULL); + + MwLoop(window); +} diff --git a/include/Mw/Widget/DirectX.h b/include/Mw/Widget/DirectX.h new file mode 100644 index 000000000..a81b4aee7 --- /dev/null +++ b/include/Mw/Widget/DirectX.h @@ -0,0 +1,53 @@ +/*! + * @file Mw/Widget/DirectX.h + * @brief DirectX widget. + * @warning Only avaliable on Windows. + */ +#ifndef __MW_WIDGET_DIRECTX_H__ +#define __MW_WIDGET_DIRECTX_H__ + +#include +#include +#include + +#if !defined(MW_DIRECTX_NO_INCLUDE) + +/* https://github.com/microsoft/Windows-classic-samples/issues/317 */ +#if defined(__MINGW32__) || defined(__MINGW64__) +#define NTDDI_VERSION 0x07000000 +#define _WIN32_WINNT 0x0A00 + +#endif + +#include +#endif + +#ifndef _WIN32 +#error DirectX widget only avaliable for Win32 backends +#endif + +/*! + * @brief D3D9 widget class + */ +MWDECL MwClass MwD3D9Class; + +#ifdef __cplusplus +extern "C" { +#endif + +MwInline LPDIRECT3D9 MwDirectXGetD3D9(MwWidget handle) { + LPDIRECT3D9 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); + return out; +}; +MwInline LPDIRECT3DDEVICE9 MwDirectXGetD3Dev9(MwWidget handle) { + LPDIRECT3DDEVICE9 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); + return out; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pl/rules.pl b/pl/rules.pl index 7a58a9715..3f539eee7 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -178,6 +178,7 @@ new_object("src/widget/window.c"); new_object("src/widget/opengl.c"); new_object("src/widget/vulkan.c"); +new_object("src/widget/directx.c"); if (param_get("opengl")) { add_cflags("-DMW_OPENGL"); @@ -185,6 +186,9 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } +if (param_get("directx")) { + add_cflags("-DMW_DIRECTX"); +} new_object("src/dialog/*.c"); @@ -230,4 +234,8 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } +if (param_get("directx")) { + new_example("examples/dxdemos/directx9"); +} + 1; diff --git a/resource/FindDirectX.cmake b/resource/FindDirectX.cmake new file mode 100644 index 000000000..89b96ec03 --- /dev/null +++ b/resource/FindDirectX.cmake @@ -0,0 +1,325 @@ +# - try to find part of DirectX SDK +# +# Cache Variables: (probably not for direct use in your scripts) +# DIRECTX_INCLUDE_DIR +# +# Variables you should use in your CMakeLists.txt: +# DIRECTX_DXGUID_LIBRARY - deprecated, see below +# DIRECTX_DXERR_LIBRARY - deprecated, see http://blogs.msdn.com/b/chuckw/archive/2012/04/24/where-s-dxerr-lib.aspx +# DIRECTX_DINPUT_LIBRARY +# DIRECTX_DINPUT_INCLUDE_DIR +# DIRECTX_D3D9_LIBRARY +# DIRECTX_D3DXOF_LIBRARY +# DIRECTX_D3DX9_LIBRARIES +# DIRECTX_INCLUDE_DIRS +# DIRECTX_FOUND - if this is not true, do not attempt to use this library +# +# Defines these macros: +# find_directx_include - wrapper for find_path that provides PATHS, HINTS, and PATH_SUFFIXES. +# find_directx_library - wrapper for find_library that provides PATHS, HINTS, and PATH_SUFFIXES. +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# SelectLibraryConfigurations +# +# Original Author: +# 2012 Rylie Pavlik +# https://ryliepavlik.com/ +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright 2012, Iowa State University +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# SPDX-License-Identifier: BSL-1.0 + + +set(DIRECTX_ROOT_DIR + "${DIRECTX_ROOT_DIR}" + CACHE + PATH + "Root directory to search for DirectX") + +if(MSVC) + file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _PROG_FILES) + set(_PF86 "ProgramFiles(x86)") + file(TO_CMAKE_PATH "$ENV{${_PF86}}" _PROG_FILES_X86) + if(_PROG_FILES_X86) + set(_PROG_FILES "${_PROG_FILES_X86}") + endif() + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_dx_lib_suffixes lib/x64 lib) + else() + set(_dx_lib_suffixes lib/x86 lib) + endif() + set(DXSDK_DIRS) + + set(_dx_quiet) + if(DirectX_FIND_QUIETLY) + set(_dx_quiet QUIET) + endif() + find_package(WindowsSDK ${_dx_quiet}) + if(WINDOWSSDK_FOUND) + foreach(_dir ${WINDOWSSDK_DIRS}) + get_windowssdk_include_dirs(${_dir} _include_dirs) + if(_include_dirs) + list(APPEND DXSDK_DIRS ${_include_dirs}) + endif() + endforeach() + endif() + + macro(_append_dxsdk_in_inclusive_range _low _high) + if((NOT MSVC_VERSION LESS ${_low}) AND (NOT MSVC_VERSION GREATER ${_high})) + list(APPEND DXSDK_DIRS ${ARGN}) + endif() + endmacro() + _append_dxsdk_in_inclusive_range(1500 1600 "${_PROG_FILES}/Microsoft DirectX SDK (June 2010)") + _append_dxsdk_in_inclusive_range(1400 1600 + "${_PROG_FILES}/Microsoft DirectX SDK (February 2010)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2009)" + "${_PROG_FILES}/Microsoft DirectX SDK (March 2009)" + "${_PROG_FILES}/Microsoft DirectX SDK (November 2008)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2008)" + "${_PROG_FILES}/Microsoft DirectX SDK (June 2008)" + "${_PROG_FILES}/Microsoft DirectX SDK (March 2008)") + _append_dxsdk_in_inclusive_range(1310 1500 + "${_PROG_FILES}/Microsoft DirectX SDK (November 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (June 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (April 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (February 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (December 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (October 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (June 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (April 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (February 2006)") + + file(TO_CMAKE_PATH "$ENV{DXSDK_DIR}" ENV_DXSDK_DIR) + if(ENV_DXSDK_DIR) + list(APPEND DXSDK_DIRS ${ENV_DXSDK_DIR}) + endif() +else() + set(_dx_lib_suffixes lib) + set(DXSDK_DIRS /mingw) +endif() + +find_path(DIRECTX_INCLUDE_DIR + NAMES + dxdiag.h + dinput.h + dxerr8.h + PATHS + ${DXSDK_DIRS} + HINTS + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + include) +find_path(DIRECTX_DINPUT_INCLUDE_DIR + NAMES + dinput.h + PATHS + ${DXSDK_DIRS} + HINTS + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + include) + +set(DXLIB_HINTS) +if(WINDOWSSDK_FOUND AND DIRECTX_INCLUDE_DIR) + get_windowssdk_from_component("${DIRECTX_INCLUDE_DIR}" _winsdk) + if(_winsdk) + get_windowssdk_library_dirs("${_winsdk}" _libdirs) + if(_libdirs) + list(APPEND DXLIB_HINTS ${_libdirs}) + endif() + endif() +endif() + +if(WINDOWSSDK_FOUND AND DIRECTX_DINPUT_INCLUDE_DIR) + get_windowssdk_from_component("${DIRECTX_DINPUT_INCLUDE_DIR}" _winsdk) + if(_winsdk) + get_windowssdk_library_dirs("${_winsdk}" _includes) + if(_includes) + list(APPEND DXLIB_HINTS ${_includes}) + endif() + endif() +endif() + +find_library(DIRECTX_DXGUID_LIBRARY + NAMES + dxguid + PATHS + ${DXLIB_HINTS} + ${DXSDK_DIRS} + HINTS + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +if(DIRECTX_DXGUID_LIBRARY) + get_filename_component(_dxsdk_lib_dir ${DIRECTX_DXGUID_LIBRARY} PATH) + list(APPEND DXLIB_HINTS "${_dxsdk_lib_dir}") +endif() + +find_library(DIRECTX_DINPUT_LIBRARY + NAMES + dinput8 + dinput + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_DXERR_LIBRARY + NAMES + dxerr + dxerr9 + dxerr8 + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3D9_LIBRARY + NAMES + d3d9 + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3DXOF_LIBRARY + NAMES + d3dxof + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3DX9_LIBRARY_RELEASE + NAMES + d3dx9 + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3DX9_LIBRARY_DEBUG + NAMES + d3dx9d + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_XINPUT_LIBRARY + NAMES + Xinput9_1_0 + Xinput + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +include(SelectLibraryConfigurations) +select_library_configurations(DIRECTX_D3DX9) + +set(DIRECTX_EXTRA_CHECK) +if(DIRECTX_INCLUDE_DIR) + if(MSVC80) + set(DXSDK_DEPRECATION_BUILD 1962) + endif() + + if(DXSDK_DEPRECATION_BUILD) + include(CheckCSourceCompiles) + set(_dinput_old_includes ${CMAKE_REQUIRED_INCLUDES}) + set(CMAKE_REQUIRED_INCLUDES "${DIRECTX_INCLUDE_DIR}") + check_c_source_compiles(" + #include + #if _DXSDK_BUILD_MAJOR >= ${DXSDK_DEPRECATION_BUILD} + #error + #else + int main(int argc, char * argv[]) { + return 0; + } + #endif + " + DIRECTX_SDK_SUPPORTS_COMPILER) + set(DIRECTX_EXTRA_CHECK DIRECTX_SDK_SUPPORTS_COMPILER) + set(CMAKE_REQUIRED_INCLUDES "${_dinput_old_includes}") + else() + # Until proven otherwise. + set(DIRECTX_SDK_SUPPORTS_COMPILER TRUE) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(DirectX + DEFAULT_MSG + DIRECTX_DXGUID_LIBRARY + DIRECTX_DINPUT_LIBRARY + DIRECTX_INCLUDE_DIR + ${DIRECTX_EXTRA_CHECK}) + +if(DIRECTX_FOUND) + set(DIRECTX_LIBRARIES + "${DIRECTX_DXGUID_LIBRARY}" + "${DIRECTX_DINPUT_LIBRARY}") + + set(DIRECTX_INCLUDE_DIRS "${DIRECTX_INCLUDE_DIR}") + + mark_as_advanced(DIRECTX_ROOT_DIR) +endif() + +macro(find_directx_library) + find_library(${ARGN} + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) +endmacro() +macro(find_directx_include) + find_path(${ARGN} + PATHS + ${DXSDK_DIRS} + HINTS + ${DIRECTX_INCLUDE_DIR} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + include) +endmacro() + +mark_as_advanced(DIRECTX_DINPUT_LIBRARY + DIRECTX_DXGUID_LIBRARY + DIRECTX_DXERR_LIBRARY + DIRECTX_D3D9_LIBRARY + DIRECTX_D3DXOF_LIBRARY + DIRECTX_D3DX9_LIBRARY_RELEASE + DIRECTX_D3DX9_LIBRARY_DEBUG + DIRECTX_INCLUDE_DIR) diff --git a/src/widget/directx.c b/src/widget/directx.c new file mode 100644 index 000000000..7465d69d9 --- /dev/null +++ b/src/widget/directx.c @@ -0,0 +1,96 @@ +#include + +#ifndef MW_DIRECTX +#define MW_DIRECTX_NO_INCLUDE +MWDECL MwClass MwDX9Class; + +MwClass MwDX9Class = NULL; +#else +#include + +typedef struct gdid3d9 { + void* d3d9dll; + IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); + + LPDIRECT3D9 d3d; // the pointer to our Direct3D interface + LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class\ + +} gdid3d9_t; + +static int wcreate(MwWidget handle) { + void* r = NULL; + MwWidget w = handle; + gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); + + o->d3d9dll = LoadLibrary("d3d9.dll"); + if(!o->d3d9dll) { + MessageBox(NULL, "d3d9.dll not found! Is DirectX9 installed?", "Error", MB_OK); + ExitProcess(-1); + } + o->Direct3DCreate9 = (void*)GetProcAddress(o->d3d9dll, "Direct3DCreate9"); + + o->d3d = o->Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface + + D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information + + ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use + d3dpp.Windowed = TRUE; // program windowed, not fullscreen + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames + d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; // set the window to be used by Direct3D + + // create a device class using this information and information from the d3dpp stuct + o->d3d->lpVtbl->CreateDevice(o->d3d, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + handle->lowlevel->gdi.hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &d3dpp, + &o->d3ddev); + + handle->internal = o; + + return 0; +} + +static void destroy(MwWidget handle) { + MwWidget w = handle; + gdid3d9_t* o = handle->internal; + + o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device + o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D + + free(handle->internal); +} + +static void func_handler(MwWidget handle, const char* name, void* out, + va_list va) { + gdid3d9_t* o = handle->internal; + + if(strcmp(name, "mwDirectXGetD3D9") == 0) { + *(LPDIRECT3D9*)out = o->d3d; + } + if(strcmp(name, "mwDirectXGetD3Dev9") == 0) { + *(LPDIRECT3DDEVICE9*)out = o->d3ddev; + } +} + +MwClassRec MwDX9ClassRec = {wcreate, /* create */ + destroy, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* 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 */ + NULL, NULL, NULL}; +MwClass MwD3D9Class = &MwDX9ClassRec; +#endif diff --git a/tools/genmk.pl b/tools/genmk.pl index 26a7ebbbd..ad1495f43 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,6 +42,23 @@ sub cobjs { return $r; } +sub dx9_detect_block { + return <<'EOF'; +!if [where d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!endif +!else +!if [echo DX9_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx9flags.mk") +!include "dx9flags.mk" +!else +DX9_FLAGS = +!endif +EOF +} + sub generate { my ($output, $type) = @_; @@ -65,6 +82,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; + my $dx9_flags = ""; + my $dx9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -88,6 +107,12 @@ sub generate { $def = "/D"; $inc = "/I"; $dll = "/DLL"; + + # DX9 headers aren't part of every MSVC/Windows SDK install, so probe + # PATH for a d3d9.h at build time (on the machine actually running + # nmake) rather than baking in a yes/no here. + $dx9_flags = "\$(DX9_FLAGS)"; + $dx9_block = dx9_detect_block(); } elsif ($type eq "Watcom") { $cc = "wcc386 -bt=nt -q"; @@ -109,14 +134,20 @@ sub generate { $prefobj = "file "; $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; + + $dx9_flags = "${def}MW_DIRECTX"; } open(OUT, ">", $output); print(OUT "CC = $cc\n"); print(OUT "LD = $link\n"); print(OUT "\n"); + if ($dx9_block ne "") { + print(OUT $dx9_block); + print(OUT "\n"); + } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); @@ -152,6 +183,9 @@ sub generate { } print(OUT " $del src${dir}Mw.dll\n"); print(OUT " $del src${dir}Mw.lib\n"); + if ($dx9_block ne "") { + print(OUT " $del dx9flags.mk\n"); + } foreach my $f (@examples) { my $b = $f; $b =~ s/\.c$/.obj/; From 47c9f8df4e55741595ab61c3219ff6e6b3c6fb2d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 21:44:55 -0700 Subject: [PATCH 022/102] d3d8 too --- CMakeLists.txt | 37 +++++--- NTMakefile | 4 +- WatMakefile | 2 +- examples/CMakeLists.txt | 3 +- examples/dxdemos/CMakeLists.txt | 11 ++- examples/dxdemos/d3d8.c | 91 ++++++++++++++++++++ examples/dxdemos/{directx9.c => d3d9.c} | 14 ++-- include/Mw/Widget/D3D8.h | 55 ++++++++++++ include/Mw/Widget/{DirectX.h => D3D9.h} | 17 ++-- src/widget/d3d8.c | 107 ++++++++++++++++++++++++ src/widget/{directx.c => d3d9.c} | 48 +++++------ tools/genmk.pl | 32 +++++-- 12 files changed, 355 insertions(+), 66 deletions(-) create mode 100644 examples/dxdemos/d3d8.c rename examples/dxdemos/{directx9.c => d3d9.c} (90%) create mode 100644 include/Mw/Widget/D3D8.h rename include/Mw/Widget/{DirectX.h => D3D9.h} (83%) create mode 100644 src/widget/d3d8.c rename src/widget/{directx.c => d3d9.c} (68%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 046f08c1a..fa1644dcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,8 +32,10 @@ else() option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON) option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON) endif() + if(${CMAKE_SYSTEM_NAME} MATCHES Windows) - option(MW_TRY_DIRECTX "Try to compile DirectX widget or not" ON) + option(MW_TRY_D3D8 "Try to compile D3D8 widget or not" ON) + option(MW_TRY_D3D9 "Try to compile D3D9 widget or not" ON) endif() @@ -94,13 +96,19 @@ if(MW_TRY_VULKAN) endif() endif() -if(MW_TRY_DIRECTX) +if(MW_TRY_D3D8 OR MW_TRY_D3D9) include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) if(DIRECTX_FOUND) - set(MW_BUILD_DIRECTX ON) - message(STATUS "DirectX widget has been enabled") + if(MW_TRY_D3D8) + set(MW_BUILD_D3D8 ON) + message(STATUS "D3D8 widget has been enabled") + endif() + if(MW_TRY_D3D9) + set(MW_BUILD_D3D9 ON) + message(STATUS "D3D9 widget has been enabled") + endif() else() - message(STATUS "DirectX widget has been disabled") + message(STATUS "DirectX widgets have been disabled (DirectX not found)") endif() endif() @@ -491,13 +499,20 @@ if(MW_BUILD_VULKAN) endif() endif() -if(MW_BUILD_DIRECTX) - list(APPEND LIBRARIES ${DIRECTX_D3DX9_LIBRARIES}) +if(MW_BUILD_D3D8) target_compile_definitions( - Mw - PRIVATE - MW_DIRECTX - ) + Mw + PUBLIC + MW_DIRECTX8 + ) +endif() + +if(MW_BUILD_D3D9) + target_compile_definitions( + Mw + PUBLIC + MW_DIRECTX9 + ) endif() target_compile_definitions( diff --git a/NTMakefile b/NTMakefile index 37b4a9507..12b6446a5 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,7 +2,7 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -14,7 +14,7 @@ LD = link /nologo DX9_FLAGS = !endif -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS) +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = diff --git a/WatMakefile b/WatMakefile index 09a942d0e..9c7f08921 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX8 -dMW_DIRECTX9 MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4ac6962b9..87225f1ab 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,8 +5,9 @@ endif() if(${MW_TRY_VULKAN}) add_subdirectory(vkdemos) endif() + if(WIN32) - if(${MW_TRY_DIRECTX}) + if(${MW_TRY_D3D8} OR ${MW_BUILD_D3D8}) add_subdirectory(dxdemos) endif() endif() diff --git a/examples/dxdemos/CMakeLists.txt b/examples/dxdemos/CMakeLists.txt index 38265e1cc..aa09d6386 100644 --- a/examples/dxdemos/CMakeLists.txt +++ b/examples/dxdemos/CMakeLists.txt @@ -8,17 +8,16 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake) if(${DIRECTX_FOUND}) foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) + add_executable(${TARGET} ${PATH}) target_include_directories( ${TARGET} PRIVATE ${DIRECTX_INCLUDE_DIRS} ) target_link_libraries( - ${TARGET} - PRIVATE - Mw - ${DIRECTX_D3DX9_LIBRARIES} - ) +${TARGET} +PRIVATE +Mw +) endforeach() endif() diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c new file mode 100644 index 000000000..400adc6ca --- /dev/null +++ b/examples/dxdemos/d3d8.c @@ -0,0 +1,91 @@ +/* + * Adapted from: + * https://web.archive.org/web/20211126225651/https://www.codeguru.com/multimedia/using-direct3d8-the-basics/ + */ +#include +#include + +MwWidget window, d3d8; +LPDIRECT3D8 d3d; +LPDIRECT3DDEVICE8 d3ddev; +LPDIRECT3DVERTEXBUFFER8 v_buffer; + +struct CUSTOMVERTEX { + FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag + DWORD color; // from the D3DFVF_DIFFUSE flag +}; +#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) + +static void MWAPI draw(MwWidget handle, void* user, void* client) { + // clear the window to a deep blue + d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); + + d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene + + // select which vertex format we are using + d3ddev->lpVtbl->SetVertexShader(d3ddev, CUSTOMFVF); + + // select the vertex buffer to display + d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, sizeof(struct CUSTOMVERTEX)); + + // // copy the vertex buffer to the back buffer + d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1); + + d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene + + d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame +} + +int main() { + BYTE* pVoid; + + MwLibraryInit(); + + window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); + + d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + + d3d = MwDirectXGetD3D8(d3d8); + d3ddev = MwDirectXGetD3Dev8(d3d8); + + // create three vertices using the CUSTOMVERTEX struct built earlier + struct CUSTOMVERTEX vertices[] = + { + { + 400.0f, + 0.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 0, 255), + }, + { + 800.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 255, 0), + }, + { + 0.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(255, 0, 0), + }, + }; + + d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, + 3 * sizeof(struct CUSTOMVERTEX), + 0, + CUSTOMFVF, + D3DPOOL_MANAGED, + &v_buffer); + + v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (BYTE**)&pVoid, 0); // lock the vertex buffer + memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer + v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer + + MwAddUserHandler(window, MwNtickHandler, draw, NULL); + + MwLoop(window); +} diff --git a/examples/dxdemos/directx9.c b/examples/dxdemos/d3d9.c similarity index 90% rename from examples/dxdemos/directx9.c rename to examples/dxdemos/d3d9.c index 6b28ac020..5975739da 100644 --- a/examples/dxdemos/directx9.c +++ b/examples/dxdemos/d3d9.c @@ -4,9 +4,9 @@ * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4 */ #include -#include +#include -MwWidget window, d3d9; +MwWidget window, d3d8; LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; LPDIRECT3DVERTEXBUFFER9 v_buffer; @@ -38,14 +38,16 @@ static void MWAPI draw(MwWidget handle, void* user, void* client) { } int main() { + VOID* pVoid; + MwLibraryInit(); window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); - d3d9 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirectXGetD3D9(d3d9); - d3ddev = MwDirectXGetD3Dev9(d3d9); + d3d = MwDirectXGetD3D9(d3d8); + d3ddev = MwDirectXGetD3Dev9(d3d8); // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = @@ -81,8 +83,6 @@ int main() { &v_buffer, NULL); - VOID* pVoid; // the void pointer - v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (void**)&pVoid, 0); // lock the vertex buffer memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h new file mode 100644 index 000000000..022e7bc93 --- /dev/null +++ b/include/Mw/Widget/D3D8.h @@ -0,0 +1,55 @@ +/*! + * @file Mw/Widget/D3D8.h + * @brief D3D8 widget. + * @warning Only avaliable on Windows. + */ +#ifndef __MW_WIDGET_D3D8_H__ +#define __MW_WIDGET_D3D8_H__ + +#include +#include +#include + +#if !defined(MW_D3D8_NO_INCLUDE) + +/* https://github.com/microsoft/Windows-classic-samples/issues/317 */ +#if defined(__MINGW32__) || defined(__MINGW64__) +#define NTDDI_VERSION 0x07000000 +#define _WIN32_WINNT 0x0A00 + +#endif +#endif + +#ifndef _WIN32 +#error D3D8 widget only avaliable for Win32 backends +#else +#ifdef MW_DIRECTX8 +#include +#endif +#endif + +/*! + * @brief D3D8 widget class + */ +MWDECL MwClass MwD3D8Class; + +#ifdef __cplusplus +extern "C" { +#endif + +MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) { + LPDIRECT3D8 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); + return out; +}; +MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) { + LPDIRECT3DDEVICE8 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); + return out; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/Mw/Widget/DirectX.h b/include/Mw/Widget/D3D9.h similarity index 83% rename from include/Mw/Widget/DirectX.h rename to include/Mw/Widget/D3D9.h index a81b4aee7..2639e1756 100644 --- a/include/Mw/Widget/DirectX.h +++ b/include/Mw/Widget/D3D9.h @@ -3,27 +3,28 @@ * @brief DirectX widget. * @warning Only avaliable on Windows. */ -#ifndef __MW_WIDGET_DIRECTX_H__ -#define __MW_WIDGET_DIRECTX_H__ +#ifndef __MW_WIDGET_D3D9_H__ +#define __MW_WIDGET_D3D9_H__ #include #include #include -#if !defined(MW_DIRECTX_NO_INCLUDE) +#if !defined(MW_D3D9_NO_INCLUDE) /* https://github.com/microsoft/Windows-classic-samples/issues/317 */ #if defined(__MINGW32__) || defined(__MINGW64__) #define NTDDI_VERSION 0x07000000 #define _WIN32_WINNT 0x0A00 - -#endif - -#include #endif #ifndef _WIN32 -#error DirectX widget only avaliable for Win32 backends +#error D3D9 widget only avaliable for Win32 backends +#else +#ifdef MW_DIRECTX9 +#include +#endif +#endif #endif /*! diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c new file mode 100644 index 000000000..13e656d4a --- /dev/null +++ b/src/widget/d3d8.c @@ -0,0 +1,107 @@ +#include + +#ifndef MW_DIRECTX8 +#define MW_DIRECTX8_NO_INCLUDE +MWDECL MwClass MwDX8Class; + +MwClass MwDX8Class = NULL; +#else +#include + +typedef struct gdid3d8 { + void* d3d8dll; + IDirect3D8* (*Direct3DCreate8)(UINT sdk_version); + + LPDIRECT3D8 d3d; // the pointer to our Direct3D interface + LPDIRECT3DDEVICE8 d3ddev; // the pointer to the device class\ + +} gdid3d8_t; + +static int wcreate_d3d8(MwWidget handle) { + void* r = NULL; + MwWidget w = handle; + gdid3d8_t* o = malloc(sizeof(gdid3d8_t)); + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE dispMode; + + o->d3d8dll = LoadLibrary("d3d8.dll"); + if(!o->d3d8dll) { + MessageBox(NULL, "d3d8.dll not found! Is DirectX8 installed?", "Error", MB_OK); + ExitProcess(-1); + } + o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8"); + if(!o->Direct3DCreate8) { + MessageBox(NULL, "Direct3DCreate8 not found! Is DirectX8 installed properly?", "Error", MB_OK); + ExitProcess(-1); + } + + o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION); + + o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; + d3dpp.BackBufferFormat = dispMode.Format; + d3dpp.EnableAutoDepthStencil = TRUE; + d3dpp.AutoDepthStencilFormat = D3DFMT_D16; + + // create a device class using this information and information from the d3dpp stuct + o->d3d->lpVtbl->CreateDevice(o->d3d, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + handle->lowlevel->gdi.hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &d3dpp, + &o->d3ddev); + + o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE); + + handle->internal = o; + + return 0; +} + +static void destroy_d3d8(MwWidget handle) { + MwWidget w = handle; + gdid3d8_t* o = handle->internal; + + o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device + o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D + + free(handle->internal); +} + +static void func_handler_d3d8(MwWidget handle, const char* name, void* out, + va_list va) { + gdid3d8_t* o = handle->internal; + + if(strcmp(name, "mwDirectXGetD3D8") == 0) { + *(LPDIRECT3D8*)out = o->d3d; + } + if(strcmp(name, "mwDirectXGetD3Dev8") == 0) { + *(LPDIRECT3DDEVICE8*)out = o->d3ddev; + } +} + +MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */ + destroy_d3d8, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler_d3d8, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, NULL, NULL}; +MwClass MwD3D8Class = &MwDX8ClassRec; +#endif diff --git a/src/widget/directx.c b/src/widget/d3d9.c similarity index 68% rename from src/widget/directx.c rename to src/widget/d3d9.c index 7465d69d9..f6fc5d965 100644 --- a/src/widget/directx.c +++ b/src/widget/d3d9.c @@ -1,12 +1,12 @@ #include -#ifndef MW_DIRECTX -#define MW_DIRECTX_NO_INCLUDE +#ifndef MW_DIRECTX9 +#define MW_DIRECTX9_NO_INCLUDE MWDECL MwClass MwDX9Class; MwClass MwDX9Class = NULL; #else -#include +#include typedef struct gdid3d9 { void* d3d9dll; @@ -17,7 +17,7 @@ typedef struct gdid3d9 { } gdid3d9_t; -static int wcreate(MwWidget handle) { +static int wcreate_d3d9(MwWidget handle) { void* r = NULL; MwWidget w = handle; gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); @@ -52,7 +52,7 @@ static int wcreate(MwWidget handle) { return 0; } -static void destroy(MwWidget handle) { +static void destroy_d3d9(MwWidget handle) { MwWidget w = handle; gdid3d9_t* o = handle->internal; @@ -62,8 +62,8 @@ static void destroy(MwWidget handle) { free(handle->internal); } -static void func_handler(MwWidget handle, const char* name, void* out, - va_list va) { +static void func_handler_d3d9(MwWidget handle, const char* name, void* out, + va_list va) { gdid3d9_t* o = handle->internal; if(strcmp(name, "mwDirectXGetD3D9") == 0) { @@ -74,23 +74,23 @@ static void func_handler(MwWidget handle, const char* name, void* out, } } -MwClassRec MwDX9ClassRec = {wcreate, /* create */ - destroy, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* 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 */ +MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */ + destroy_d3d9, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler_d3d9, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; MwClass MwD3D9Class = &MwDX9ClassRec; #endif diff --git a/tools/genmk.pl b/tools/genmk.pl index ad1495f43..a249e24c2 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,10 +42,28 @@ sub cobjs { return $r; } + +sub dx8_detect_block { + return <<'EOF'; +!if [where d3d8.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d8.h 2^>nul') do @echo DX8_FLAGS = /DMW_DIRECTX8 /I"%~dpP">dx8flags.mk] +!endif +!else +!if [echo DX8_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx8flags.mk") +!include "dx8flags.mk" +!else +DX8_FLAGS = +!endif +EOF +} + sub dx9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -82,6 +100,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; + my $dx8_flags = ""; + my $dx8_block = ""; my $dx9_flags = ""; my $dx9_block = ""; @@ -108,9 +128,8 @@ sub generate { $inc = "/I"; $dll = "/DLL"; - # DX9 headers aren't part of every MSVC/Windows SDK install, so probe - # PATH for a d3d9.h at build time (on the machine actually running - # nmake) rather than baking in a yes/no here. + $dx8_flags = "\$(DX8_FLAGS)"; + $dx8_block = dx8_detect_block(); $dx9_flags = "\$(DX9_FLAGS)"; $dx9_block = dx9_detect_block(); } @@ -135,7 +154,8 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx9_flags = "${def}MW_DIRECTX"; + $dx8_flags = "${def}MW_DIRECTX8"; + $dx9_flags = "${def}MW_DIRECTX9"; } open(OUT, ">", $output); @@ -147,7 +167,7 @@ sub generate { print(OUT "\n"); } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx8_flags} ${dx9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); From 87cbb582f76c8aa9cecad228852b9aa86c37c7cf Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:02:27 -0700 Subject: [PATCH 023/102] perl --- configure | 8 +++++--- examples/dxdemos/d3d8.c | 4 ++++ examples/dxdemos/d3d9.c | 4 ++++ include/Mw/Widget/D3D8.h | 12 ++++++++++++ include/Mw/Widget/D3D9.h | 12 ++++++++++++ pl/rules.pl | 18 +++++++++++++----- src/widget/d3d8.c | 12 +++++------- src/widget/d3d9.c | 12 +++++------- tools/gendcl.pl | 2 ++ 9 files changed, 62 insertions(+), 22 deletions(-) diff --git a/configure b/configure index f6ff13bc8..a2d0ba61b 100755 --- a/configure +++ b/configure @@ -55,7 +55,8 @@ param_set("examples", 1); param_set("allow-sloppy-focus", 0); # (option that only makes sense on Windows) -param_set("directx", 0); +param_set("dxd8", 0); +param_set("dxd9", 0); my %features = ( "classic-theme" => "use classic theme", @@ -73,7 +74,8 @@ my %features = ( "gnustep" => "use gnustep", "dbus" => "use DBus on supported platform", "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", - "directx" => "(Windows only) build DirectX widget" + "directx8" => "(Windows only) build DXD8 widget", + "directx9" => "(Windows only) build DXD9 widget" ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -82,7 +84,7 @@ my @features_keys = ( "1vulkan", "2vulkan-string-helper", "1shared", "1static", "1wayland", "1gnustep", - "1dbus", "1directx" + "1dbus", "1direct8", "1directx9" ); sub def_platform { diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c index 400adc6ca..2ef08a389 100644 --- a/examples/dxdemos/d3d8.c +++ b/examples/dxdemos/d3d8.c @@ -5,6 +5,8 @@ #include #include +#ifdef MW_DIRECTX8 + MwWidget window, d3d8; LPDIRECT3D8 d3d; LPDIRECT3DDEVICE8 d3ddev; @@ -89,3 +91,5 @@ int main() { MwLoop(window); } + +#endif diff --git a/examples/dxdemos/d3d9.c b/examples/dxdemos/d3d9.c index 5975739da..9fe685c35 100644 --- a/examples/dxdemos/d3d9.c +++ b/examples/dxdemos/d3d9.c @@ -6,6 +6,8 @@ #include #include +#ifdef MW_DIRECTX9 + MwWidget window, d3d8; LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; @@ -91,3 +93,5 @@ int main() { MwLoop(window); } + +#endif diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h index 022e7bc93..ee1bf052d 100644 --- a/include/Mw/Widget/D3D8.h +++ b/include/Mw/Widget/D3D8.h @@ -22,6 +22,7 @@ #ifndef _WIN32 #error D3D8 widget only avaliable for Win32 backends +#undef MW_DIRECTX8 #else #ifdef MW_DIRECTX8 #include @@ -37,6 +38,7 @@ MWDECL MwClass MwD3D8Class; extern "C" { #endif +#ifdef MW_DIRECTX8 MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) { LPDIRECT3D8 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); @@ -47,6 +49,16 @@ MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) { MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); return out; }; +#else +MwInline void* MwDirectXGetD3D8(MwWidget handle) { + (void)handle; + return NULL; +}; +MwInline void* MwDirectXGetD3Dev8(MwWidget handle) { + (void)handle; + return NULL; +}; +#endif #ifdef __cplusplus } diff --git a/include/Mw/Widget/D3D9.h b/include/Mw/Widget/D3D9.h index 2639e1756..e7a7149b1 100644 --- a/include/Mw/Widget/D3D9.h +++ b/include/Mw/Widget/D3D9.h @@ -20,6 +20,7 @@ #ifndef _WIN32 #error D3D9 widget only avaliable for Win32 backends +#undef MW_DIRECTX9 #else #ifdef MW_DIRECTX9 #include @@ -36,6 +37,7 @@ MWDECL MwClass MwD3D9Class; extern "C" { #endif +#ifdef MW_DIRECTX9 MwInline LPDIRECT3D9 MwDirectXGetD3D9(MwWidget handle) { LPDIRECT3D9 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); @@ -46,6 +48,16 @@ MwInline LPDIRECT3DDEVICE9 MwDirectXGetD3Dev9(MwWidget handle) { MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); return out; }; +#else +MwInline void* MwDirectXGetD3D9(MwWidget handle) { + (void)handle; + return NULL; +}; +MwInline void* MwDirectXGetD3Dev9(MwWidget handle) { + (void)handle; + return NULL; +}; +#endif #ifdef __cplusplus } diff --git a/pl/rules.pl b/pl/rules.pl index 3f539eee7..76ab9b4c4 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -178,7 +178,8 @@ new_object("src/widget/window.c"); new_object("src/widget/opengl.c"); new_object("src/widget/vulkan.c"); -new_object("src/widget/directx.c"); +new_object("src/widget/d3d8.c"); +new_object("src/widget/d3d9.c"); if (param_get("opengl")) { add_cflags("-DMW_OPENGL"); @@ -186,8 +187,11 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } -if (param_get("directx")) { - add_cflags("-DMW_DIRECTX"); +if (param_get("directx8")) { + add_cflags("-DMW_DIRECTX8"); +} +if (param_get("directx9")) { + add_cflags("-DMW_DIRECTX9"); } new_object("src/dialog/*.c"); @@ -234,8 +238,12 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } -if (param_get("directx")) { - new_example("examples/dxdemos/directx9"); +if (param_get("directx8")) { + new_example("examples/dxdemos/d3d8"); +} + +if (param_get("directx9")) { + new_example("examples/dxdemos/d3d9"); } 1; diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c index 13e656d4a..066332101 100644 --- a/src/widget/d3d8.c +++ b/src/widget/d3d8.c @@ -1,13 +1,7 @@ #include -#ifndef MW_DIRECTX8 -#define MW_DIRECTX8_NO_INCLUDE -MWDECL MwClass MwDX8Class; - -MwClass MwDX8Class = NULL; -#else +#ifdef MW_DIRECTX8 #include - typedef struct gdid3d8 { void* d3d8dll; IDirect3D8* (*Direct3DCreate8)(UINT sdk_version); @@ -104,4 +98,8 @@ MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */ NULL, /* props_change */ NULL, NULL, NULL}; MwClass MwD3D8Class = &MwDX8ClassRec; +#else +MWDECL MwClass MwDX8Class; + +MwClass MwDX8Class = NULL; #endif diff --git a/src/widget/d3d9.c b/src/widget/d3d9.c index f6fc5d965..3246cafb7 100644 --- a/src/widget/d3d9.c +++ b/src/widget/d3d9.c @@ -1,13 +1,7 @@ #include -#ifndef MW_DIRECTX9 -#define MW_DIRECTX9_NO_INCLUDE -MWDECL MwClass MwDX9Class; - -MwClass MwDX9Class = NULL; -#else +#ifdef MW_DIRECTX9 #include - typedef struct gdid3d9 { void* d3d9dll; IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); @@ -93,4 +87,8 @@ MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */ NULL, /* props_change */ NULL, NULL, NULL}; MwClass MwD3D9Class = &MwDX9ClassRec; +#else +MWDECL MwClass MwDX9Class; + +MwClass MwDX9Class = NULL; #endif diff --git a/tools/gendcl.pl b/tools/gendcl.pl index f2e3399c3..ccc29dc86 100755 --- a/tools/gendcl.pl +++ b/tools/gendcl.pl @@ -59,6 +59,8 @@ sub scan { while (my $file = readdir($dh)) { if ( !(($dir . "/" . $file) eq "src/widget/opengl.c") && !(($dir . "/" . $file) eq "src/widget/vulkan.c") + && !(($dir . "/" . $file) eq "src/widget/d3d8.c") + && !(($dir . "/" . $file) eq "src/widget/d3d9.c") && !(($dir . "/" . $file) eq "external/stb_truetype.c") && !(($dir . "/" . $file) eq "external/stb_image.c") && ($file =~ /\.c$/)) From 2a19c5e5cf6bb61cab59b4f8c9e7a0695ee6c03e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:05:40 -0700 Subject: [PATCH 024/102] genmk --- NTMakefile | 7 ++++--- WatMakefile | 13 ++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/NTMakefile b/NTMakefile index 12b6446a5..f42873ba6 100644 --- a/NTMakefile +++ b/NTMakefile @@ -99,7 +99,8 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj - del /f /q src\widget\directx.obj + del /f /q src\widget\d3d8.obj + del /f /q src\widget\d3d9.obj del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -357,8 +358,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 9c7f08921..55bc6b8e5 100644 --- a/WatMakefile +++ b/WatMakefile @@ -85,7 +85,8 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj - %erase src/widget/directx.obj + %erase src/widget/d3d8.obj + %erase src/widget/d3d9.obj %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -342,8 +343,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/directx.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/directx.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/d3d8.obj src/widget/d3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/d3d8.obj file src/widget/d3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -499,8 +500,10 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c -src/widget/directx.obj: src/widget/directx.c - $(CC) $(MW_CFLAGS) -fo=$@ src/widget/directx.c +src/widget/d3d8.obj: src/widget/d3d8.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d8.c +src/widget/d3d9.obj: src/widget/d3d9.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d9.c src/widget/document.obj: src/widget/document.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c From 5872c43539471fb1bcc9b630c24d871392adbd46 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:11:17 -0700 Subject: [PATCH 025/102] have watcom check for d3d8.h/d3d9.h --- WatMakefile | 16 +++++++++++++++- tools/genmk.pl | 6 ++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/WatMakefile b/WatMakefile index 55bc6b8e5..02205a744 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,20 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX8 -dMW_DIRECTX9 +!if [where d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!endif +!else +!if [echo DX9_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx9flags.mk") +!include "dx9flags.mk" +!else +DX9_FLAGS = +!endif + +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt @@ -109,6 +122,7 @@ clean: .SYMBOLIC %erase src/widget/window.obj %erase src/Mw.dll %erase src/Mw.lib + %erase dx9flags.mk %erase examples/basic/box.obj %erase examples/basic/calculator.obj %erase examples/basic/checkbox.obj diff --git a/tools/genmk.pl b/tools/genmk.pl index a249e24c2..9f45add95 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -154,8 +154,10 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx8_flags = "${def}MW_DIRECTX8"; - $dx9_flags = "${def}MW_DIRECTX9"; + $dx8_flags = "\$(DX8_FLAGS)"; + $dx8_block = dx8_detect_block(); + $dx9_flags = "\$(DX9_FLAGS)"; + $dx9_block = dx9_detect_block(); } open(OUT, ">", $output); From 2f3b8f2417cb5375611460792c5ac392643a8447 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:16:16 -0700 Subject: [PATCH 026/102] error handling for d3d8 and d3d9 --- src/widget/d3d8.c | 32 +++++++++++++++++++++++++++----- src/widget/d3d9.c | 34 ++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c index 066332101..d569f5308 100644 --- a/src/widget/d3d8.c +++ b/src/widget/d3d8.c @@ -17,21 +17,33 @@ static int wcreate_d3d8(MwWidget handle) { gdid3d8_t* o = malloc(sizeof(gdid3d8_t)); D3DPRESENT_PARAMETERS d3dpp; D3DDISPLAYMODE dispMode; + HRESULT hr; + char errbuf[2048] = {0}; o->d3d8dll = LoadLibrary("d3d8.dll"); if(!o->d3d8dll) { - MessageBox(NULL, "d3d8.dll not found! Is DirectX8 installed?", "Error", MB_OK); - ExitProcess(-1); + MwDispatchError(1, "d3d8.dll not found! Is DirectX8 installed?"); + return 1; } o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8"); if(!o->Direct3DCreate8) { - MessageBox(NULL, "Direct3DCreate8 not found! Is DirectX8 installed properly?", "Error", MB_OK); - ExitProcess(-1); + MwDispatchError(1, "Direct3DCreate8 not found! Is DirectX8 installed properly?"); + return 1; } o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION); + if(!o->Direct3DCreate8) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "Direct3DCreate8 NULL: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } - o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); + hr = o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "GetAdapterDisplayMode ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; @@ -49,8 +61,18 @@ static int wcreate_d3d8(MwWidget handle) { D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &o->d3ddev); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "CreateDevice ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "SetRenderState ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } handle->internal = o; diff --git a/src/widget/d3d9.c b/src/widget/d3d9.c index 3246cafb7..7219e58a9 100644 --- a/src/widget/d3d9.c +++ b/src/widget/d3d9.c @@ -12,9 +12,12 @@ typedef struct gdid3d9 { } gdid3d9_t; static int wcreate_d3d9(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; - gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); + void* r = NULL; + MwWidget w = handle; + gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); + HRESULT hr; + char errbuf[2048]; + D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information o->d3d9dll = LoadLibrary("d3d9.dll"); if(!o->d3d9dll) { @@ -24,8 +27,10 @@ static int wcreate_d3d9(MwWidget handle) { o->Direct3DCreate9 = (void*)GetProcAddress(o->d3d9dll, "Direct3DCreate9"); o->d3d = o->Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface - - D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information + if(hr != D3D_OK) { + MwDispatchError(1, "Direct3DCreate9 NULL"); + return 1; + } ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use d3dpp.Windowed = TRUE; // program windowed, not fullscreen @@ -33,13 +38,18 @@ static int wcreate_d3d9(MwWidget handle) { d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; // set the window to be used by Direct3D // create a device class using this information and information from the d3dpp stuct - o->d3d->lpVtbl->CreateDevice(o->d3d, - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - handle->lowlevel->gdi.hWnd, - D3DCREATE_MIXED_VERTEXPROCESSING, - &d3dpp, - &o->d3ddev); + hr = o->d3d->lpVtbl->CreateDevice(o->d3d, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + handle->lowlevel->gdi.hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &d3dpp, + &o->d3ddev); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "CreateDevice ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } handle->internal = o; From f89eaf690139bcbf2aef9d4cd410b1cc829d662f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:16:43 -0700 Subject: [PATCH 027/102] put nul in gitignore for watcom cross compile --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3faccd358..ce6459a0f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ compile_flags.txt flamegraph.svg perf.* + +nul From a18ca58f1814dc29113c9bb6a2e5942fa09d75f3 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:21:25 -0700 Subject: [PATCH 028/102] xml --- examples/dxdemos/d3d8.c | 4 ++-- examples/dxdemos/d3d9.c | 4 ++-- include/Mw/Widget/D3D8.h | 8 ++++---- include/Mw/Widget/D3D9.h | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c index 2ef08a389..c5d65d909 100644 --- a/examples/dxdemos/d3d8.c +++ b/examples/dxdemos/d3d8.c @@ -47,8 +47,8 @@ int main() { d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirectXGetD3D8(d3d8); - d3ddev = MwDirectXGetD3Dev8(d3d8); + d3d = MwD3D8GetD3D(d3d8); + d3ddev = MwD3D8GetD3Dev(d3d8); // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = diff --git a/examples/dxdemos/d3d9.c b/examples/dxdemos/d3d9.c index 9fe685c35..86186ae89 100644 --- a/examples/dxdemos/d3d9.c +++ b/examples/dxdemos/d3d9.c @@ -48,8 +48,8 @@ int main() { d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirectXGetD3D9(d3d8); - d3ddev = MwDirectXGetD3Dev9(d3d8); + d3d = MwD3D9GetD3D(d3d8); + d3ddev = MwD3D9GetD3Dev(d3d8); // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h index ee1bf052d..9b0ae6eb0 100644 --- a/include/Mw/Widget/D3D8.h +++ b/include/Mw/Widget/D3D8.h @@ -39,22 +39,22 @@ extern "C" { #endif #ifdef MW_DIRECTX8 -MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) { +MwInline LPDIRECT3D8 MwD3D8GetD3D(MwWidget handle) { LPDIRECT3D8 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) { +MwInline LPDIRECT3DDEVICE8 MwD3D8GetD3Dev(MwWidget handle) { LPDIRECT3DDEVICE8 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); return out; }; #else -MwInline void* MwDirectXGetD3D8(MwWidget handle) { +MwInline void* MwD3D8GetD3D(MwWidget handle) { (void)handle; return NULL; }; -MwInline void* MwDirectXGetD3Dev8(MwWidget handle) { +MwInline void* MwD3D8GetD3Dev(MwWidget handle) { (void)handle; return NULL; }; diff --git a/include/Mw/Widget/D3D9.h b/include/Mw/Widget/D3D9.h index e7a7149b1..3831301d2 100644 --- a/include/Mw/Widget/D3D9.h +++ b/include/Mw/Widget/D3D9.h @@ -38,22 +38,22 @@ extern "C" { #endif #ifdef MW_DIRECTX9 -MwInline LPDIRECT3D9 MwDirectXGetD3D9(MwWidget handle) { +MwInline LPDIRECT3D9 MwD3D9GetD3D(MwWidget handle) { LPDIRECT3D9 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE9 MwDirectXGetD3Dev9(MwWidget handle) { +MwInline LPDIRECT3DDEVICE9 MwD3D9GetD3Dev(MwWidget handle) { LPDIRECT3DDEVICE9 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); return out; }; #else -MwInline void* MwDirectXGetD3D9(MwWidget handle) { +MwInline void* MwD3D9GetD3D(MwWidget handle) { (void)handle; return NULL; }; -MwInline void* MwDirectXGetD3Dev9(MwWidget handle) { +MwInline void* MwD3D9GetD3Dev(MwWidget handle) { (void)handle; return NULL; }; From fb9919de2a90b87a01a279a999a854d1ab4beef4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:24:48 -0700 Subject: [PATCH 029/102] oh wait the jenkinsfile can at least use enable-d3d --- Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6d93874c1..c688af01c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-directx --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --enable-vulkan --without-vulkan-string-helper") sh("make -j4") sh("mv src/libMw.so libMw64.so") archiveArtifacts("libMw64.so") @@ -42,7 +42,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -55,7 +55,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") From a0da41210a37ef1894715191bf3a95ab20a933f9 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:42:10 +0900 Subject: [PATCH 030/102] Update configure --- configure | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/configure b/configure index a2d0ba61b..c4fc7e9b0 100755 --- a/configure +++ b/configure @@ -54,10 +54,6 @@ param_set("examples", 1); # (option that only makes sense on x11) param_set("allow-sloppy-focus", 0); -# (option that only makes sense on Windows) -param_set("dxd8", 0); -param_set("dxd9", 0); - my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", @@ -91,6 +87,8 @@ sub def_platform { if($target eq "Windows") { param_set("freetype2", 0); param_set("stb-truetype", 0); + param_set("dxd8", 1); + param_set("dxd9", 1); } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); From aef5fe03a972e8ef7725d391f4cc273d2c5200ee Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:45:38 +0900 Subject: [PATCH 031/102] Update configure --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index c4fc7e9b0..5463444f7 100755 --- a/configure +++ b/configure @@ -87,8 +87,8 @@ sub def_platform { if($target eq "Windows") { param_set("freetype2", 0); param_set("stb-truetype", 0); - param_set("dxd8", 1); - param_set("dxd9", 1); + param_set("d3d8", 1); + param_set("d3d9", 1); } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); From e967523063f21726693ec780ddc94def22412090 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:46:57 +0900 Subject: [PATCH 032/102] Update pl/rules.pl --- pl/rules.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pl/rules.pl b/pl/rules.pl index 76ab9b4c4..2c1cd2473 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -187,10 +187,10 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } -if (param_get("directx8")) { +if (param_get("d3d8")) { add_cflags("-DMW_DIRECTX8"); } -if (param_get("directx9")) { +if (param_get("d3d9")) { add_cflags("-DMW_DIRECTX9"); } @@ -238,11 +238,11 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } -if (param_get("directx8")) { +if (param_get("d3d8")) { new_example("examples/dxdemos/d3d8"); } -if (param_get("directx9")) { +if (param_get("d3d9")) { new_example("examples/dxdemos/d3d9"); } From 12b89aab9b596cd340ca2822893c04795710f537 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:49:44 +0900 Subject: [PATCH 033/102] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index c688af01c..c506028dd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make -j4") sh("mv src/libMw.so libMw64.so") archiveArtifacts("libMw64.so") From c5330cc18419f2650050c325bf312522f4fd5228 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:43:15 +0900 Subject: [PATCH 034/102] direct3d9 --- CMakeLists.txt | 29 ++--- NTMakefile | 2 +- WatMakefile | 2 +- configure | 8 +- examples/CMakeLists.txt | 2 +- examples/dxdemos/d3d8.c | 95 ---------------- examples/dxdemos/{d3d9.c => direct3d9.c} | 27 ++--- include/Mw/Widget/D3D8.h | 67 ------------ include/Mw/Widget/{D3D9.h => Direct3D9.h} | 34 ++---- pl/rules.pl | 18 +-- src/widget/d3d8.c | 127 ---------------------- src/widget/{d3d9.c => direct3d9.c} | 59 +++++----- tools/genmk.pl | 30 +---- 13 files changed, 74 insertions(+), 426 deletions(-) delete mode 100644 examples/dxdemos/d3d8.c rename examples/dxdemos/{d3d9.c => direct3d9.c} (90%) delete mode 100644 include/Mw/Widget/D3D8.h rename include/Mw/Widget/{D3D9.h => Direct3D9.h} (53%) delete mode 100644 src/widget/d3d8.c rename src/widget/{d3d9.c => direct3d9.c} (65%) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa1644dcd..15cbb11c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,9 @@ else() endif() if(${CMAKE_SYSTEM_NAME} MATCHES Windows) - option(MW_TRY_D3D8 "Try to compile D3D8 widget or not" ON) - option(MW_TRY_D3D9 "Try to compile D3D9 widget or not" ON) + option(MW_TRY_DIRECT3D9 "Try to compile Direct3D9 widget or not" ON) +else() + option(MW_TRY_DIRECT3D9 "Try to compile Direct3D9 widget or not" OFF) endif() @@ -96,16 +97,12 @@ if(MW_TRY_VULKAN) endif() endif() -if(MW_TRY_D3D8 OR MW_TRY_D3D9) +if(MW_TRY_DIRECT3D9) include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) if(DIRECTX_FOUND) - if(MW_TRY_D3D8) - set(MW_BUILD_D3D8 ON) - message(STATUS "D3D8 widget has been enabled") - endif() - if(MW_TRY_D3D9) - set(MW_BUILD_D3D9 ON) - message(STATUS "D3D9 widget has been enabled") + if(MW_TRY_DIRECT3D9) + set(MW_BUILD_DIRECT3D9 ON) + message(STATUS "Direct3D9 widget has been enabled") endif() else() message(STATUS "DirectX widgets have been disabled (DirectX not found)") @@ -499,19 +496,11 @@ if(MW_BUILD_VULKAN) endif() endif() -if(MW_BUILD_D3D8) +if(MW_BUILD_DIRECT3D9) target_compile_definitions( Mw PUBLIC - MW_DIRECTX8 - ) -endif() - -if(MW_BUILD_D3D9) - target_compile_definitions( - Mw - PUBLIC - MW_DIRECTX9 + MW_DIRECT3D9 ) endif() diff --git a/NTMakefile b/NTMakefile index f42873ba6..a54901575 100644 --- a/NTMakefile +++ b/NTMakefile @@ -14,7 +14,7 @@ LD = link /nologo DX9_FLAGS = !endif -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS) MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = diff --git a/WatMakefile b/WatMakefile index 02205a744..99334e55d 100644 --- a/WatMakefile +++ b/WatMakefile @@ -14,7 +14,7 @@ LD = wlink option quiet DX9_FLAGS = !endif -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX9_FLAGS) MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt diff --git a/configure b/configure index 5463444f7..025b2656a 100755 --- a/configure +++ b/configure @@ -70,8 +70,7 @@ my %features = ( "gnustep" => "use gnustep", "dbus" => "use DBus on supported platform", "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", - "directx8" => "(Windows only) build DXD8 widget", - "directx9" => "(Windows only) build DXD9 widget" + "direct3d9" => "(Windows only) build Direct3D9 widget" ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -80,15 +79,14 @@ my @features_keys = ( "1vulkan", "2vulkan-string-helper", "1shared", "1static", "1wayland", "1gnustep", - "1dbus", "1direct8", "1directx9" + "1dbus", "1direct3d9" ); sub def_platform { if($target eq "Windows") { param_set("freetype2", 0); param_set("stb-truetype", 0); - param_set("d3d8", 1); - param_set("d3d9", 1); + param_set("direct3d9", 1); } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 87225f1ab..821516f8d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -7,7 +7,7 @@ if(${MW_TRY_VULKAN}) endif() if(WIN32) - if(${MW_TRY_D3D8} OR ${MW_BUILD_D3D8}) + if(${MW_TRY_DIRECT3D9}) add_subdirectory(dxdemos) endif() endif() diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c deleted file mode 100644 index c5d65d909..000000000 --- a/examples/dxdemos/d3d8.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Adapted from: - * https://web.archive.org/web/20211126225651/https://www.codeguru.com/multimedia/using-direct3d8-the-basics/ - */ -#include -#include - -#ifdef MW_DIRECTX8 - -MwWidget window, d3d8; -LPDIRECT3D8 d3d; -LPDIRECT3DDEVICE8 d3ddev; -LPDIRECT3DVERTEXBUFFER8 v_buffer; - -struct CUSTOMVERTEX { - FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag - DWORD color; // from the D3DFVF_DIFFUSE flag -}; -#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) - -static void MWAPI draw(MwWidget handle, void* user, void* client) { - // clear the window to a deep blue - d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); - - d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene - - // select which vertex format we are using - d3ddev->lpVtbl->SetVertexShader(d3ddev, CUSTOMFVF); - - // select the vertex buffer to display - d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, sizeof(struct CUSTOMVERTEX)); - - // // copy the vertex buffer to the back buffer - d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1); - - d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene - - d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame -} - -int main() { - BYTE* pVoid; - - MwLibraryInit(); - - window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); - - d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - - d3d = MwD3D8GetD3D(d3d8); - d3ddev = MwD3D8GetD3Dev(d3d8); - - // create three vertices using the CUSTOMVERTEX struct built earlier - struct CUSTOMVERTEX vertices[] = - { - { - 400.0f, - 0.0f, - 0.5f, - 1.0f, - D3DCOLOR_XRGB(0, 0, 255), - }, - { - 800.0f, - 600.0f, - 0.5f, - 1.0f, - D3DCOLOR_XRGB(0, 255, 0), - }, - { - 0.0f, - 600.0f, - 0.5f, - 1.0f, - D3DCOLOR_XRGB(255, 0, 0), - }, - }; - - d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, - 3 * sizeof(struct CUSTOMVERTEX), - 0, - CUSTOMFVF, - D3DPOOL_MANAGED, - &v_buffer); - - v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (BYTE**)&pVoid, 0); // lock the vertex buffer - memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer - v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer - - MwAddUserHandler(window, MwNtickHandler, draw, NULL); - - MwLoop(window); -} - -#endif diff --git a/examples/dxdemos/d3d9.c b/examples/dxdemos/direct3d9.c similarity index 90% rename from examples/dxdemos/d3d9.c rename to examples/dxdemos/direct3d9.c index 86186ae89..47a260929 100644 --- a/examples/dxdemos/d3d9.c +++ b/examples/dxdemos/direct3d9.c @@ -4,11 +4,9 @@ * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4 */ #include -#include +#include -#ifdef MW_DIRECTX9 - -MwWidget window, d3d8; +MwWidget window, d3d9; LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; LPDIRECT3DVERTEXBUFFER9 v_buffer; @@ -41,16 +39,6 @@ static void MWAPI draw(MwWidget handle, void* user, void* client) { int main() { VOID* pVoid; - - MwLibraryInit(); - - window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); - - d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - - d3d = MwD3D9GetD3D(d3d8); - d3ddev = MwD3D9GetD3Dev(d3d8); - // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = { @@ -77,6 +65,15 @@ int main() { }, }; + MwLibraryInit(); + + window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); + + d3d9 = MwCreateWidget(MwDirect3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + + d3d = MwDirect3D9GetD3D(d3d9); + d3ddev = MwDirect3D9GetD3DDevice(d3d9); + d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, 3 * sizeof(struct CUSTOMVERTEX), 0, @@ -93,5 +90,3 @@ int main() { MwLoop(window); } - -#endif diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h deleted file mode 100644 index 9b0ae6eb0..000000000 --- a/include/Mw/Widget/D3D8.h +++ /dev/null @@ -1,67 +0,0 @@ -/*! - * @file Mw/Widget/D3D8.h - * @brief D3D8 widget. - * @warning Only avaliable on Windows. - */ -#ifndef __MW_WIDGET_D3D8_H__ -#define __MW_WIDGET_D3D8_H__ - -#include -#include -#include - -#if !defined(MW_D3D8_NO_INCLUDE) - -/* https://github.com/microsoft/Windows-classic-samples/issues/317 */ -#if defined(__MINGW32__) || defined(__MINGW64__) -#define NTDDI_VERSION 0x07000000 -#define _WIN32_WINNT 0x0A00 - -#endif -#endif - -#ifndef _WIN32 -#error D3D8 widget only avaliable for Win32 backends -#undef MW_DIRECTX8 -#else -#ifdef MW_DIRECTX8 -#include -#endif -#endif - -/*! - * @brief D3D8 widget class - */ -MWDECL MwClass MwD3D8Class; - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef MW_DIRECTX8 -MwInline LPDIRECT3D8 MwD3D8GetD3D(MwWidget handle) { - LPDIRECT3D8 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); - return out; -}; -MwInline LPDIRECT3DDEVICE8 MwD3D8GetD3Dev(MwWidget handle) { - LPDIRECT3DDEVICE8 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); - return out; -}; -#else -MwInline void* MwD3D8GetD3D(MwWidget handle) { - (void)handle; - return NULL; -}; -MwInline void* MwD3D8GetD3Dev(MwWidget handle) { - (void)handle; - return NULL; -}; -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/Mw/Widget/D3D9.h b/include/Mw/Widget/Direct3D9.h similarity index 53% rename from include/Mw/Widget/D3D9.h rename to include/Mw/Widget/Direct3D9.h index 3831301d2..f31e24744 100644 --- a/include/Mw/Widget/D3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -3,61 +3,51 @@ * @brief DirectX widget. * @warning Only avaliable on Windows. */ -#ifndef __MW_WIDGET_D3D9_H__ -#define __MW_WIDGET_D3D9_H__ +#ifndef __MW_WIDGET_DIRECT3D9_H__ +#define __MW_WIDGET_DIRECT3D9_H__ #include #include #include -#if !defined(MW_D3D9_NO_INCLUDE) +#if !defined(MW_DIRECT3D9_NO_INCLUDE) /* https://github.com/microsoft/Windows-classic-samples/issues/317 */ #if defined(__MINGW32__) || defined(__MINGW64__) +#undef NTDDI_VERSION +#undef _WIN32_WINNT + #define NTDDI_VERSION 0x07000000 #define _WIN32_WINNT 0x0A00 #endif #ifndef _WIN32 #error D3D9 widget only avaliable for Win32 backends -#undef MW_DIRECTX9 +#undef MW_DIRECT3D9 #else -#ifdef MW_DIRECTX9 #include #endif #endif -#endif /*! * @brief D3D9 widget class */ -MWDECL MwClass MwD3D9Class; +MWDECL MwClass MwDirect3D9Class; #ifdef __cplusplus extern "C" { #endif -#ifdef MW_DIRECTX9 -MwInline LPDIRECT3D9 MwD3D9GetD3D(MwWidget handle) { +MwInline LPDIRECT3D9 MwDirect3D9GetD3D(MwWidget handle) { LPDIRECT3D9 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); + MwVaWidgetExecute(handle, "mwDirect3D9GetD3D9", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE9 MwD3D9GetD3Dev(MwWidget handle) { +MwInline LPDIRECT3DDEVICE9 MwDirect3D9GetD3DDevice(MwWidget handle) { LPDIRECT3DDEVICE9 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); + MwVaWidgetExecute(handle, "mwDirect3D9GetD3DDevice9", &out); return out; }; -#else -MwInline void* MwD3D9GetD3D(MwWidget handle) { - (void)handle; - return NULL; -}; -MwInline void* MwD3D9GetD3Dev(MwWidget handle) { - (void)handle; - return NULL; -}; -#endif #ifdef __cplusplus } diff --git a/pl/rules.pl b/pl/rules.pl index 2c1cd2473..276eb8871 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -178,8 +178,7 @@ new_object("src/widget/window.c"); new_object("src/widget/opengl.c"); new_object("src/widget/vulkan.c"); -new_object("src/widget/d3d8.c"); -new_object("src/widget/d3d9.c"); +new_object("src/widget/direct3d9.c"); if (param_get("opengl")) { add_cflags("-DMW_OPENGL"); @@ -187,11 +186,8 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } -if (param_get("d3d8")) { - add_cflags("-DMW_DIRECTX8"); -} -if (param_get("d3d9")) { - add_cflags("-DMW_DIRECTX9"); +if (param_get("direct3d9")) { + add_cflags("-DMW_DIRECT3D9"); } new_object("src/dialog/*.c"); @@ -238,12 +234,8 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } -if (param_get("d3d8")) { - new_example("examples/dxdemos/d3d8"); -} - -if (param_get("d3d9")) { - new_example("examples/dxdemos/d3d9"); +if (param_get("direct3d9")) { + new_example("examples/dxdemos/direct3d9"); } 1; diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c deleted file mode 100644 index d569f5308..000000000 --- a/src/widget/d3d8.c +++ /dev/null @@ -1,127 +0,0 @@ -#include - -#ifdef MW_DIRECTX8 -#include -typedef struct gdid3d8 { - void* d3d8dll; - IDirect3D8* (*Direct3DCreate8)(UINT sdk_version); - - LPDIRECT3D8 d3d; // the pointer to our Direct3D interface - LPDIRECT3DDEVICE8 d3ddev; // the pointer to the device class\ - -} gdid3d8_t; - -static int wcreate_d3d8(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; - gdid3d8_t* o = malloc(sizeof(gdid3d8_t)); - D3DPRESENT_PARAMETERS d3dpp; - D3DDISPLAYMODE dispMode; - HRESULT hr; - char errbuf[2048] = {0}; - - o->d3d8dll = LoadLibrary("d3d8.dll"); - if(!o->d3d8dll) { - MwDispatchError(1, "d3d8.dll not found! Is DirectX8 installed?"); - return 1; - } - o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8"); - if(!o->Direct3DCreate8) { - MwDispatchError(1, "Direct3DCreate8 not found! Is DirectX8 installed properly?"); - return 1; - } - - o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION); - if(!o->Direct3DCreate8) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "Direct3DCreate8 NULL: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - hr = o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); - if(hr != D3D_OK) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "GetAdapterDisplayMode ERROR: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - ZeroMemory(&d3dpp, sizeof(d3dpp)); - d3dpp.Windowed = TRUE; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; - d3dpp.BackBufferFormat = dispMode.Format; - d3dpp.EnableAutoDepthStencil = TRUE; - d3dpp.AutoDepthStencilFormat = D3DFMT_D16; - - // create a device class using this information and information from the d3dpp stuct - o->d3d->lpVtbl->CreateDevice(o->d3d, - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - handle->lowlevel->gdi.hWnd, - D3DCREATE_MIXED_VERTEXPROCESSING, - &d3dpp, - &o->d3ddev); - if(hr != D3D_OK) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "CreateDevice ERROR: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE); - if(hr != D3D_OK) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "SetRenderState ERROR: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - handle->internal = o; - - return 0; -} - -static void destroy_d3d8(MwWidget handle) { - MwWidget w = handle; - gdid3d8_t* o = handle->internal; - - o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device - o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D - - free(handle->internal); -} - -static void func_handler_d3d8(MwWidget handle, const char* name, void* out, - va_list va) { - gdid3d8_t* o = handle->internal; - - if(strcmp(name, "mwDirectXGetD3D8") == 0) { - *(LPDIRECT3D8*)out = o->d3d; - } - if(strcmp(name, "mwDirectXGetD3Dev8") == 0) { - *(LPDIRECT3DDEVICE8*)out = o->d3ddev; - } -} - -MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */ - destroy_d3d8, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler_d3d8, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ - NULL, NULL, NULL}; -MwClass MwD3D8Class = &MwDX8ClassRec; -#else -MWDECL MwClass MwDX8Class; - -MwClass MwDX8Class = NULL; -#endif diff --git a/src/widget/d3d9.c b/src/widget/direct3d9.c similarity index 65% rename from src/widget/d3d9.c rename to src/widget/direct3d9.c index 7219e58a9..da77041f5 100644 --- a/src/widget/d3d9.c +++ b/src/widget/direct3d9.c @@ -1,19 +1,17 @@ #include -#ifdef MW_DIRECTX9 -#include +#ifdef MW_DIRECT3D9 +#include typedef struct gdid3d9 { void* d3d9dll; IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); LPDIRECT3D9 d3d; // the pointer to our Direct3D interface - LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class\ + LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class } gdid3d9_t; static int wcreate_d3d9(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); HRESULT hr; char errbuf[2048]; @@ -27,7 +25,7 @@ static int wcreate_d3d9(MwWidget handle) { o->Direct3DCreate9 = (void*)GetProcAddress(o->d3d9dll, "Direct3DCreate9"); o->d3d = o->Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface - if(hr != D3D_OK) { + if(o->d3d == NULL) { MwDispatchError(1, "Direct3DCreate9 NULL"); return 1; } @@ -57,7 +55,6 @@ static int wcreate_d3d9(MwWidget handle) { } static void destroy_d3d9(MwWidget handle) { - MwWidget w = handle; gdid3d9_t* o = handle->internal; o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device @@ -70,35 +67,35 @@ static void func_handler_d3d9(MwWidget handle, const char* name, void* out, va_list va) { gdid3d9_t* o = handle->internal; - if(strcmp(name, "mwDirectXGetD3D9") == 0) { + (void)va; + + if(strcmp(name, "mwDirect3D9GetD3D9") == 0) { *(LPDIRECT3D9*)out = o->d3d; } - if(strcmp(name, "mwDirectXGetD3Dev9") == 0) { + if(strcmp(name, "mwDirect3D9GetD3DDevice9") == 0) { *(LPDIRECT3DDEVICE9*)out = o->d3ddev; } } -MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */ - destroy_d3d9, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler_d3d9, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ - NULL, NULL, NULL}; -MwClass MwD3D9Class = &MwDX9ClassRec; +MwClassRec MwDirect3D9ClassRec = {wcreate_d3d9, /* create */ + destroy_d3d9, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler_d3d9, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, NULL, NULL}; +MwClass MwDirect3D9Class = &MwDirect3D9ClassRec; #else -MWDECL MwClass MwDX9Class; - -MwClass MwDX9Class = NULL; +MwClass MwDirect3D9Class = NULL; #endif diff --git a/tools/genmk.pl b/tools/genmk.pl index 9f45add95..369ed5810 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,24 +42,6 @@ sub cobjs { return $r; } - -sub dx8_detect_block { - return <<'EOF'; -!if [where d3d8.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d8.h 2^>nul') do @echo DX8_FLAGS = /DMW_DIRECTX8 /I"%~dpP">dx8flags.mk] -!endif -!else -!if [echo DX8_FLAGS =>dx9flags.mk] -!endif -!endif -!if exist("dx8flags.mk") -!include "dx8flags.mk" -!else -DX8_FLAGS = -!endif -EOF -} - sub dx9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] @@ -100,10 +82,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; - my $dx8_flags = ""; - my $dx8_block = ""; - my $dx9_flags = ""; - my $dx9_block = ""; + my $dx9_flags = ""; + my $dx9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -128,8 +108,6 @@ sub generate { $inc = "/I"; $dll = "/DLL"; - $dx8_flags = "\$(DX8_FLAGS)"; - $dx8_block = dx8_detect_block(); $dx9_flags = "\$(DX9_FLAGS)"; $dx9_block = dx9_detect_block(); } @@ -154,8 +132,6 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx8_flags = "\$(DX8_FLAGS)"; - $dx8_block = dx8_detect_block(); $dx9_flags = "\$(DX9_FLAGS)"; $dx9_block = dx9_detect_block(); } @@ -169,7 +145,7 @@ sub generate { print(OUT "\n"); } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx8_flags} ${dx9_flags}\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); From 83eb8c8dc4291c5529e8654e857c230e53a5c0cf Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:43:56 +0900 Subject: [PATCH 035/102] ok --- NTMakefile | 9 ++++----- WatMakefile | 15 ++++++--------- tools/genmk.pl | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/NTMakefile b/NTMakefile index a54901575..9f8ffe798 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,7 +2,7 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -99,8 +99,7 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj - del /f /q src\widget\d3d8.obj - del /f /q src\widget\d3d9.obj + del /f /q src\widget\direct3d9.obj del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -358,8 +357,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 99334e55d..f8cc43065 100644 --- a/WatMakefile +++ b/WatMakefile @@ -2,7 +2,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -98,8 +98,7 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj - %erase src/widget/d3d8.obj - %erase src/widget/d3d9.obj + %erase src/widget/direct3d9.obj %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -357,8 +356,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/d3d8.obj src/widget/d3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/d3d8.obj file src/widget/d3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/direct3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/direct3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -514,10 +513,8 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c -src/widget/d3d8.obj: src/widget/d3d8.c - $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d8.c -src/widget/d3d9.obj: src/widget/d3d9.c - $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d9.c +src/widget/direct3d9.obj: src/widget/direct3d9.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/direct3d9.c src/widget/document.obj: src/widget/document.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c diff --git a/tools/genmk.pl b/tools/genmk.pl index 369ed5810..95297708b 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -45,7 +45,7 @@ sub cobjs { sub dx9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] From ec45c8828d8d6a7b6d42ce4e039149436cac5158 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:47:13 +0900 Subject: [PATCH 036/102] rename --- examples/dxdemos/direct3d9.c | 4 ++-- include/Mw/Widget/Direct3D9.h | 8 ++++---- src/widget/direct3d9.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/dxdemos/direct3d9.c b/examples/dxdemos/direct3d9.c index 47a260929..368d6186b 100644 --- a/examples/dxdemos/direct3d9.c +++ b/examples/dxdemos/direct3d9.c @@ -71,8 +71,8 @@ int main() { d3d9 = MwCreateWidget(MwDirect3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirect3D9GetD3D(d3d9); - d3ddev = MwDirect3D9GetD3DDevice(d3d9); + d3d = MwDirect3D9GetDirect3D9(d3d9); + d3ddev = MwDirect3D9GetDirect3DDevice9(d3d9); d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, 3 * sizeof(struct CUSTOMVERTEX), diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index f31e24744..b6904d4d2 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -38,14 +38,14 @@ MWDECL MwClass MwDirect3D9Class; extern "C" { #endif -MwInline LPDIRECT3D9 MwDirect3D9GetD3D(MwWidget handle) { +MwInline LPDIRECT3D9 MwDirect3D9GetDirect3D9(MwWidget handle) { LPDIRECT3D9 out = NULL; - MwVaWidgetExecute(handle, "mwDirect3D9GetD3D9", &out, NULL); + MwVaWidgetExecute(handle, "mwDirect3D9GetDirect3D9", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE9 MwDirect3D9GetD3DDevice(MwWidget handle) { +MwInline LPDIRECT3DDEVICE9 MwDirect3D9GetDirect3DDevice9(MwWidget handle) { LPDIRECT3DDEVICE9 out = NULL; - MwVaWidgetExecute(handle, "mwDirect3D9GetD3DDevice9", &out); + MwVaWidgetExecute(handle, "mwDirect3D9GetDirect3DDevice9", &out); return out; }; diff --git a/src/widget/direct3d9.c b/src/widget/direct3d9.c index da77041f5..41347861a 100644 --- a/src/widget/direct3d9.c +++ b/src/widget/direct3d9.c @@ -69,10 +69,10 @@ static void func_handler_d3d9(MwWidget handle, const char* name, void* out, (void)va; - if(strcmp(name, "mwDirect3D9GetD3D9") == 0) { + if(strcmp(name, "mwDirect3D9GetDirect3D9") == 0) { *(LPDIRECT3D9*)out = o->d3d; } - if(strcmp(name, "mwDirect3D9GetD3DDevice9") == 0) { + if(strcmp(name, "mwDirect3D9GetDirect3DDevice9") == 0) { *(LPDIRECT3DDEVICE9*)out = o->d3ddev; } } From 7f361b9d15919e07c4186d7e231b315977543b7f Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:49:06 +0900 Subject: [PATCH 037/102] correct names --- NTMakefile | 10 +++++----- WatMakefile | 10 +++++----- tools/genmk.pl | 32 ++++++++++++++++---------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/NTMakefile b/NTMakefile index 9f8ffe798..038397438 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,14 +2,14 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else -!if [echo DX9_FLAGS =>dx9flags.mk] +!if [echo DX9_FLAGS =>d3d9flags.mk] !endif !endif -!if exist("dx9flags.mk") -!include "dx9flags.mk" +!if exist("d3d9flags.mk") +!include "d3d9flags.mk" !else DX9_FLAGS = !endif @@ -122,7 +122,7 @@ clean: del /f /q src\widget\window.obj del /f /q src\Mw.dll del /f /q src\Mw.lib - del /f /q dx9flags.mk + del /f /q d3d9flags.mk del /f /q examples\basic\box.obj del /f /q examples\basic\calculator.obj del /f /q examples\basic\checkbox.obj diff --git a/WatMakefile b/WatMakefile index f8cc43065..070294770 100644 --- a/WatMakefile +++ b/WatMakefile @@ -2,14 +2,14 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else -!if [echo DX9_FLAGS =>dx9flags.mk] +!if [echo DX9_FLAGS =>d3d9flags.mk] !endif !endif -!if exist("dx9flags.mk") -!include "dx9flags.mk" +!if exist("d3d9flags.mk") +!include "d3d9flags.mk" !else DX9_FLAGS = !endif @@ -121,7 +121,7 @@ clean: .SYMBOLIC %erase src/widget/window.obj %erase src/Mw.dll %erase src/Mw.lib - %erase dx9flags.mk + %erase d3d9flags.mk %erase examples/basic/box.obj %erase examples/basic/calculator.obj %erase examples/basic/checkbox.obj diff --git a/tools/genmk.pl b/tools/genmk.pl index 95297708b..e8c769597 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,17 +42,17 @@ sub cobjs { return $r; } -sub dx9_detect_block { +sub d3d9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else -!if [echo DX9_FLAGS =>dx9flags.mk] +!if [echo DX9_FLAGS =>d3d9flags.mk] !endif !endif -!if exist("dx9flags.mk") -!include "dx9flags.mk" +!if exist("d3d9flags.mk") +!include "d3d9flags.mk" !else DX9_FLAGS = !endif @@ -82,8 +82,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; - my $dx9_flags = ""; - my $dx9_block = ""; + my $d3d9_flags = ""; + my $d3d9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -108,8 +108,8 @@ sub generate { $inc = "/I"; $dll = "/DLL"; - $dx9_flags = "\$(DX9_FLAGS)"; - $dx9_block = dx9_detect_block(); + $d3d9_flags = "\$(DX9_FLAGS)"; + $d3d9_block = d3d9_detect_block(); } elsif ($type eq "Watcom") { $cc = "wcc386 -bt=nt -q"; @@ -132,20 +132,20 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx9_flags = "\$(DX9_FLAGS)"; - $dx9_block = dx9_detect_block(); + $d3d9_flags = "\$(DX9_FLAGS)"; + $d3d9_block = d3d9_detect_block(); } open(OUT, ">", $output); print(OUT "CC = $cc\n"); print(OUT "LD = $link\n"); print(OUT "\n"); - if ($dx9_block ne "") { - print(OUT $dx9_block); + if ($d3d9_block ne "") { + print(OUT $d3d9_block); print(OUT "\n"); } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${d3d9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); @@ -181,8 +181,8 @@ sub generate { } print(OUT " $del src${dir}Mw.dll\n"); print(OUT " $del src${dir}Mw.lib\n"); - if ($dx9_block ne "") { - print(OUT " $del dx9flags.mk\n"); + if ($d3d9_block ne "") { + print(OUT " $del d3d9flags.mk\n"); } foreach my $f (@examples) { my $b = $f; From e7dc38175f2243848906b418ed42eea95d488f14 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 19 Sep 2026 01:58:40 +0900 Subject: [PATCH 038/102] experiment with cmake not trying to find directx --- CMakeLists.txt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15cbb11c7..82d8a0e8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,15 +98,8 @@ if(MW_TRY_VULKAN) endif() if(MW_TRY_DIRECT3D9) - include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) - if(DIRECTX_FOUND) - if(MW_TRY_DIRECT3D9) - set(MW_BUILD_DIRECT3D9 ON) - message(STATUS "Direct3D9 widget has been enabled") - endif() - else() - message(STATUS "DirectX widgets have been disabled (DirectX not found)") - endif() + set(MW_BUILD_DIRECT3D9 ON) + message(STATUS "Direct3D9 widget has been enabled") endif() if(MW_BUILD_STATIC) From 21911dd899e5450b71475b8dde64125ceccbb361 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 19 Sep 2026 02:00:27 +0900 Subject: [PATCH 039/102] Update examples/dxdemos/CMakeLists.txt --- examples/dxdemos/CMakeLists.txt | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/examples/dxdemos/CMakeLists.txt b/examples/dxdemos/CMakeLists.txt index aa09d6386..15316514c 100644 --- a/examples/dxdemos/CMakeLists.txt +++ b/examples/dxdemos/CMakeLists.txt @@ -3,21 +3,13 @@ file( EXAMPLES_DIRECTX_SOURCES *.c ) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake) -if(${DIRECTX_FOUND}) - foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) - get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} ${PATH}) - target_include_directories( - ${TARGET} - PRIVATE - ${DIRECTX_INCLUDE_DIRS} - ) - target_link_libraries( -${TARGET} -PRIVATE -Mw -) - endforeach() -endif() +foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + add_executable(${TARGET} ${PATH}) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ) +endforeach() From dfa8c22f1a4453e76e9ff966a49fcf0c10a16f65 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 10:27:37 +0900 Subject: [PATCH 040/102] fix --- NTMakefile | 4 ++-- WatMakefile | 16 +--------------- tools/genmk.pl | 7 ++----- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/NTMakefile b/NTMakefile index 038397438..6712a8b26 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,8 +1,8 @@ CC = cl /TC /c /nologo LD = link /nologo -!if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] diff --git a/WatMakefile b/WatMakefile index 070294770..04a48b8ec 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,20 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -!if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] -!endif -!else -!if [echo DX9_FLAGS =>d3d9flags.mk] -!endif -!endif -!if exist("d3d9flags.mk") -!include "d3d9flags.mk" -!else -DX9_FLAGS = -!endif - -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX9_FLAGS) +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt @@ -121,7 +108,6 @@ clean: .SYMBOLIC %erase src/widget/window.obj %erase src/Mw.dll %erase src/Mw.lib - %erase d3d9flags.mk %erase examples/basic/box.obj %erase examples/basic/calculator.obj %erase examples/basic/checkbox.obj diff --git a/tools/genmk.pl b/tools/genmk.pl index e8c769597..ee4822aba 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -44,8 +44,8 @@ sub cobjs { sub d3d9_detect_block { return <<'EOF'; -!if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] @@ -131,9 +131,6 @@ sub generate { $prefobj = "file "; $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - - $d3d9_flags = "\$(DX9_FLAGS)"; - $d3d9_block = d3d9_detect_block(); } open(OUT, ">", $output); From 9bdd80b42188ab22017ee077f50142a39329f082 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 10:57:31 +0900 Subject: [PATCH 041/102] fix watcom --- WatMakefile | 16 +++++++++++---- include/Mw/Widget/Direct3D9.h | 3 +++ src/widget/direct3d9.c | 6 +++++- tools/genmk.pl | 38 ++++++++++++++++++++++++++++++++--- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/WatMakefile b/WatMakefile index 04a48b8ec..8873675a7 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,13 +1,13 @@ -CC = wcc386 -bt=nt -q +CC = wcc386 -bt=nt -q -fr LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECT3D9 MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt -all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/dxdemos/direct3d9.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe lib: src/Mw.dll -examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/dxdemos/direct3d9.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe clean: .SYMBOLIC %erase external/libz/src/adler32.obj %erase external/libz/src/compress.obj @@ -131,6 +131,7 @@ clean: .SYMBOLIC %erase examples/basic/tab.obj %erase examples/basic/treeview.obj %erase examples/basic/viewport.obj + %erase examples/dxdemos/direct3d9.obj %erase examples/gldemos/boing.obj %erase examples/gldemos/clock.obj %erase examples/gldemos/cube.obj @@ -160,6 +161,7 @@ clean: .SYMBOLIC %erase examples/basic/tab.exe %erase examples/basic/treeview.exe %erase examples/basic/viewport.exe + %erase examples/dxdemos/direct3d9.exe %erase examples/gldemos/boing.exe %erase examples/gldemos/clock.exe %erase examples/gldemos/cube.exe @@ -305,6 +307,12 @@ examples/basic/viewport.exe: examples/basic/viewport.obj src/Mw.dll examples/basic/viewport.obj: examples/basic/viewport.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/viewport.c +examples/dxdemos/direct3d9.exe: examples/dxdemos/direct3d9.obj src/Mw.dll + $(LD) $(EXE_LDFLAGS) name $@ file examples/dxdemos/direct3d9.obj library clib3r.lib library src/Mw.lib + +examples/dxdemos/direct3d9.obj: examples/dxdemos/direct3d9.c + $(CC) $(EXE_CFLAGS) -fo=$@ examples/dxdemos/direct3d9.c + examples/gldemos/boing.exe: examples/gldemos/boing.obj src/Mw.dll $(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/boing.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index b6904d4d2..5715c1b03 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -25,6 +25,9 @@ #error D3D9 widget only avaliable for Win32 backends #undef MW_DIRECT3D9 #else +#ifdef __WATCOMC__ +#include +#endif #include #endif #endif diff --git a/src/widget/direct3d9.c b/src/widget/direct3d9.c index 41347861a..9c151e7fb 100644 --- a/src/widget/direct3d9.c +++ b/src/widget/direct3d9.c @@ -4,13 +4,17 @@ #include typedef struct gdid3d9 { void* d3d9dll; - IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); + IDirect3D9*(D3DAPI* Direct3DCreate9)(UINT sdk_version); LPDIRECT3D9 d3d; // the pointer to our Direct3D interface LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class } gdid3d9_t; +#ifndef D3D_SDK_VERSION +#define D3D_SDK_VERSION 32 +#endif + static int wcreate_d3d9(MwWidget handle) { gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); HRESULT hr; diff --git a/tools/genmk.pl b/tools/genmk.pl index ee4822aba..ba5d40d70 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -59,6 +59,17 @@ DX9_FLAGS = EOF } +sub skip_d3d9 { + my $f = $_[0]; + my $type = $_[1]; + + if (($f =~ /\/dxdemos\//) and not($type eq "Watcom")) { + return 1; + } + + return 0; +} + sub generate { my ($output, $type) = @_; @@ -82,8 +93,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; - my $d3d9_flags = ""; - my $d3d9_block = ""; + my $d3d9_flags = ""; + my $d3d9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -112,7 +123,7 @@ sub generate { $d3d9_block = d3d9_detect_block(); } elsif ($type eq "Watcom") { - $cc = "wcc386 -bt=nt -q"; + $cc = "wcc386 -bt=nt -q -fr"; $link = "wlink option quiet"; $out = "-fo="; $dllout = "name "; @@ -131,6 +142,8 @@ sub generate { $prefobj = "file "; $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; + + $d3d9_flags = "${def}MW_DIRECT3D9"; } open(OUT, ">", $output); @@ -154,6 +167,9 @@ sub generate { } print(OUT "all: src${dir}Mw.dll"); foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -163,6 +179,9 @@ sub generate { print(OUT "lib: src${dir}Mw.dll\n"); print(OUT "examples:"); foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -171,6 +190,9 @@ sub generate { print(OUT "\n"); print(OUT "clean: $symbolic\n"); foreach my $f (@cfiles) { + if (skip_d3d9($f, $type)) { + next; + } my $b = $f; $b =~ s/\.c$/.obj/; $b =~ s/\//$dir/g; @@ -182,12 +204,18 @@ sub generate { print(OUT " $del d3d9flags.mk\n"); } foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } my $b = $f; $b =~ s/\.c$/.obj/; $b =~ s/\//$dir/g; print(OUT " $del $b\n"); } foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -195,6 +223,9 @@ sub generate { } print(OUT "\n"); foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } my $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -256,6 +287,7 @@ push(@cfiles, "src/backend/gdi.c"); scan_examples("examples/basic"); scan_examples("examples/gldemos"); +scan_examples("examples/dxdemos"); @examples = sort(@examples); From 7d2b5a17a4e608f41fc05a6bc93f4ed95785ec3e Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:00:33 +0900 Subject: [PATCH 042/102] o --- Jenkinsfile | 4 ++-- src/widget/direct3d9.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c506028dd..593d08fcb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -42,7 +42,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -55,7 +55,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") diff --git a/src/widget/direct3d9.c b/src/widget/direct3d9.c index 9c151e7fb..5d8a93493 100644 --- a/src/widget/direct3d9.c +++ b/src/widget/direct3d9.c @@ -4,7 +4,7 @@ #include typedef struct gdid3d9 { void* d3d9dll; - IDirect3D9*(D3DAPI* Direct3DCreate9)(UINT sdk_version); + IDirect3D9*(WINAPI* Direct3DCreate9)(UINT sdk_version); LPDIRECT3D9 d3d; // the pointer to our Direct3D interface LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class From cdf7657b197f445e02e29c0c345f770585280b4b Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:06:13 +0900 Subject: [PATCH 043/102] ok --- NTMakefile | 2 +- configure | 2 +- tools/genmk.pl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NTMakefile b/NTMakefile index 6712a8b26..a0bc3d79e 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,7 +2,7 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] diff --git a/configure b/configure index 025b2656a..f84b1ea59 100755 --- a/configure +++ b/configure @@ -246,7 +246,7 @@ print(OUT " clang-format --verbose -i `find tools src include examples \"(\" -name \"*.c\" -or -name \"*.cc\" -or -name \"*.h\" -or -name \"*.m\" \")\" -and -not -name \"*ttf.c\"`\n" ); print(OUT -" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl configure -name \"*.pl\"`\n" +" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl -name \"*.pl\"` configure\n" ); print(OUT "\n"); print(OUT "lib:"); diff --git a/tools/genmk.pl b/tools/genmk.pl index ba5d40d70..b7993e39d 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -45,7 +45,7 @@ sub cobjs { sub d3d9_detect_block { return <<'EOF'; !if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] From 4e2c2709082a7f3791dbcd313d65f0c3f2f9eb3d Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:09:11 +0900 Subject: [PATCH 044/102] ok --- NTMakefile | 2 +- tools/genmk.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NTMakefile b/NTMakefile index a0bc3d79e..18fbbda78 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,7 +1,7 @@ CC = cl /TC /c /nologo LD = link /nologo -!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [where /R "%DXSDK_DIR%\\Include" /Q d3d9.h] == 0 !if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else diff --git a/tools/genmk.pl b/tools/genmk.pl index b7993e39d..bc97e84cf 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -44,7 +44,7 @@ sub cobjs { sub d3d9_detect_block { return <<'EOF'; -!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [where /R "%DXSDK_DIR%\\Include" /Q d3d9.h] == 0 !if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else From 75b42a2467f7e7d11b1d9c53c4943bff3208d5b9 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:18:15 +0900 Subject: [PATCH 045/102] add header --- doc/BINDINGS.md | 2 ++ doc/ENV.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index 44014accc..ef327be1e 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -1,3 +1,5 @@ +# Bindings + \* = in-dev version # Active Bindings diff --git a/doc/ENV.md b/doc/ENV.md index 001c30113..b6f572983 100644 --- a/doc/ENV.md +++ b/doc/ENV.md @@ -1,3 +1,5 @@ +# Environment vaiables + Platforms that support both X11 and Wayland (Linux, namely) support launching Milsko programs with following environment variables: - `MW_BACKEND`: set to either `wayland` or `x11` to force which display protocol Wayland uses From 61529b752052be33e3454fd6bc4c42373d7023d1 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:20:06 +0900 Subject: [PATCH 046/102] update header --- include/Mw/Widget/Direct3D9.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index 5715c1b03..8e7cb5b3f 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -1,6 +1,6 @@ /*! - * @file Mw/Widget/DirectX.h - * @brief DirectX widget. + * @file Mw/Widget/Direct3D9.h + * @brief Direct3D9 widget. * @warning Only avaliable on Windows. */ #ifndef __MW_WIDGET_DIRECT3D9_H__ From 941f7f0075b93cad68c081cfc3a7e51c1d93248e Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:41:23 +0900 Subject: [PATCH 047/102] fix line --- src/backend/cairo.c | 4 ++-- src/backend/wayland/wayland.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 3f1e18c80..49f315c7f 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -31,9 +31,9 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_move_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } else { - cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } } cairo_stroke(handle.front_cairo_back); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 67429f204..c944587cd 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1986,7 +1986,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - loadWayland = 0; + //loadWayland = 0; } #endif From 179853c6c874aa6a5bbe32f056a400fe06a2d9e5 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 19:45:06 -0700 Subject: [PATCH 048/102] hte w --- src/backend/cairo.c | 16 ++++++++-------- src/backend/wayland/interfaces.c | 10 +++++++++- src/backend/wayland/wayland.c | 3 +-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 49f315c7f..9dab1c197 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -31,9 +31,9 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); + cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); } else { - cairo_line_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); + cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); } } cairo_stroke(handle.front_cairo_back); @@ -219,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -264,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 4aebb6192..1b9fe1a5d 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1505,11 +1505,19 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ - WL_INTERFACE(wl_subcompositor); if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); + WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); WL_INTERFACE(wp_fifo_manager_v1); + } else if(wayland->type == MwLL_WAYLAND_POPUP) { + WL_INTERFACE(wl_seat); + } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { + WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); + } else { + WL_INTERFACE(wl_subcompositor); } #undef WL_INTERFACE } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index c944587cd..227ced43e 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -892,7 +892,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.parent = parent; r->wayland.valid = MwTRUE; - printf("type %d\n", ty); if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { setup_toplevel(r, x, y); @@ -1986,7 +1985,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - //loadWayland = 0; + // loadWayland = 0; } #endif From 46bc51076cc0a106bdf7e536418adf02e7fad618 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:47:44 +0900 Subject: [PATCH 049/102] fix line --- src/backend/cairo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 9dab1c197..237f6b574 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -31,9 +31,9 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_move_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } else { - cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } } cairo_stroke(handle.front_cairo_back); From bd97cc23da4dd488f69aae759177c34851f01873 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 23 Sep 2026 23:09:24 -0700 Subject: [PATCH 050/102] size hints fixes --- examples/basic/dnd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index 0ce9aeff7..6acc20af7 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -26,10 +26,11 @@ static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) { } int main() { - MwSizeHints hints; + MwSizeHints hints = {0}; MwLibraryInit(); hints.min_width = hints.min_height = 600; + // hints.max_width = hints.max_height = 600; window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 600, 600, MwNtitle, "dnd", From 6de65dfe8720deffb90d8b1b72f987b804c8a4dd Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 25 Sep 2026 13:02:34 -0700 Subject: [PATCH 051/102] show an actual error if we ever run out of FDs (thanks rob pike) --- src/backend/wayland/buffer.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index dec8564f9..a11bc3095 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -55,24 +55,28 @@ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* wayland) { void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { int stride = width * 4; - char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; - char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXX"; + char temp_name[] = "/tmp/milsko-wl-shm-XXXXXXXX"; + char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXXXX"; buffer->buf_size = width * height * 4; buffer->fd = mkstemp(temp_name); buffer->fd_back = mkstemp(temp_name_back); + if(buffer->fd >= FD_SETSIZE - 1) { + MwDispatchError(-1, "Amount of allocated buffers has reached FD_SETSIZE! Cannot continue.\n"); + return; + } unlink(temp_name); unlink(temp_name_back); if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) { - printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno)); + printf("failure setting up wl_shm (front buf): could not fallocate. %s.\n", strerror(errno)); close(buffer->fd); return; } if(posix_fallocate(buffer->fd_back, 0, buffer->buf_size) != 0) { - printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno)); + printf("failure setting up wl_shm (back buf): could not fallocate. %s.\n", strerror(errno)); close(buffer->fd_back); return; } From c9dbca2cc80737750c5511f0bd267f053fdd417c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 25 Sep 2026 13:06:02 -0700 Subject: [PATCH 052/102] go against modern advice and set RLIMIT_NOFILE to 65536. We're otherwise really leniant with our fd usage but since Wayland uses fds to allocate buffers, wanting to create more then 1024 widgets causes a crash, justifying this. --- src/backend/wayland/buffer.c | 4 ++-- src/backend/wayland/wayland.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index a11bc3095..2280bd7d2 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -62,8 +62,8 @@ void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, M buffer->fd = mkstemp(temp_name); buffer->fd_back = mkstemp(temp_name_back); - if(buffer->fd >= FD_SETSIZE - 1) { - MwDispatchError(-1, "Amount of allocated buffers has reached FD_SETSIZE! Cannot continue.\n"); + if(buffer->fd >= 65536) { + MwDispatchError(-1, "Amount of allocated buffers has gone above 65536! Cannot continue.\n"); return; } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 227ced43e..973b6f473 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -2,6 +2,7 @@ #include #include +#include #include "../../../external/stb_ds.h" @@ -1968,6 +1969,17 @@ static int MwLLWaylandCallInitImpl(void) { char* milsko_backend_env = getenv("MILSKO_BACKEND"); char* mw_backend_env = getenv("MW_BACKEND"); + struct rlimit rl; + + /* Set both soft and hard limit to 65536 file descriptors */ + rl.rlim_cur = 65536; /* soft limit */ + rl.rlim_max = 65536; /* hard limit */ + + if(setrlimit(RLIMIT_NOFILE, &rl) == -1) { + perror("setrlimit"); + return 1; + } + if(milsko_backend_env || mw_backend_env) { if(milsko_backend_env) { /* From e2da02f2c9ecae15738e973c96edcbfb648bdcb2 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 17:41:38 +0900 Subject: [PATCH 053/102] resizing works partly --- configure | 120 +++++++++++++++++++---------------- include/Mw/Resource/Cursor.h | 10 +++ include/Mw/TypeDefs.h | 2 + src/backend/cairo.c | 12 ++-- src/core.c | 4 +- src/cursor/bottomright.c | 43 +++++++++++++ src/widget/subwindow.c | 51 ++++++++++++--- 7 files changed, 171 insertions(+), 71 deletions(-) create mode 100644 src/cursor/bottomright.c diff --git a/configure b/configure index f84b1ea59..f06b38ab9 100755 --- a/configure +++ b/configure @@ -4,7 +4,7 @@ $target =~ s/\r?\n$//; # MSYS with MinGW gives us some other shit idk if (index($target, "MINGW") != -1) { - $target = "Windows"; + $target = "Windows"; } foreach my $l (@ARGV) { @@ -16,11 +16,11 @@ foreach my $l (@ARGV) { } our $prefix = "/usr/local"; -our $cc = defined($ENV{CC}) ? $ENV{CC} : "*host*gcc"; -our $cxx = defined($ENV{CXX}) ? $ENV{CXX} : "*host*g++"; -our $ar = defined($ENV{AR}) ? $ENV{AR} : "*host*ar"; +our $cc = defined($ENV{CC}) ? $ENV{CC} : "*host*gcc"; +our $cxx = defined($ENV{CXX}) ? $ENV{CXX} : "*host*g++"; +our $ar = defined($ENV{AR}) ? $ENV{AR} : "*host*ar"; our $incdir = "-I include"; -our $incdir2 = ""; +our $incdir2 = ""; our $cflags = "-fPIC -D_MILSKO -D_MILSKO_BUILD -fvisibility=hidden"; our $libdir = ""; our $ldflags = ""; @@ -68,46 +68,54 @@ my %features = ( "static" => "build static library", "wayland" => "enable wayland backend", "gnustep" => "use gnustep", - "dbus" => "use DBus on supported platform", - "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", + "dbus" => "use DBus on supported platform", + "allow-sloppy-focus" => +"prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", "direct3d9" => "(Windows only) build Direct3D9 widget" ); my @features_keys = ( - "1classic-theme", "1stb-image", - "1stb-truetype", "1freetype2", "1gdi-text", - "1opengl", "2xrender", - "1vulkan", "2vulkan-string-helper", - "1shared", "1static", - "1wayland", "1gnustep", - "1dbus", "1direct3d9" + "1classic-theme", "1stb-image", + "1stb-truetype", "1freetype2", + "1gdi-text", "1opengl", + "2xrender", "1vulkan", + "2vulkan-string-helper", "1shared", + "1static", "1wayland", + "1gnustep", "1dbus", + "1direct3d9" ); sub def_platform { - if($target eq "Windows") { - param_set("freetype2", 0); - param_set("stb-truetype", 0); - param_set("direct3d9", 1); - } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { - param_set("freetype2", 1); - param_set("stb-truetype", 0); - } else { - param_set("freetype2", 0); - param_set("stb-truetype", 1); - } - if($target eq "Linux" || $target eq "FreeBSD") { - param_set("x11", 1); + if ($target eq "Windows") { + param_set("freetype2", 0); + param_set("stb-truetype", 0); + param_set("direct3d9", 1); + } + elsif ( $target ne "Darwin" + and $target ne "ClassicMacOS" + and $target ne "Haiku") + { + param_set("freetype2", 1); + param_set("stb-truetype", 0); + } + else { + param_set("freetype2", 0); + param_set("stb-truetype", 1); + } + if ($target eq "Linux" || $target eq "FreeBSD") { + param_set("x11", 1); param_set("xrender", 1); - if(!param_get("tiny")){ + if (!param_get("tiny")) { param_set("wayland", 1); } param_set("dbus", 1); } - if($target eq "NetBSD" || $target eq "OpenBSD") { + if ($target eq "NetBSD" || $target eq "OpenBSD") { param_set("x11", 1); } - if($target eq "Windows") { + if ($target eq "Windows") { param_set("gdi-text", 1); - } else { + } + else { param_set("gdi-text", 0); } } @@ -120,7 +128,6 @@ foreach my $l (@ARGV) { def_platform(); - foreach my $l (@ARGV) { if ($l =~ /^--with-([^=]+)=(.+)$/) { param_set($1, $2); @@ -141,7 +148,7 @@ foreach my $l (@ARGV) { $cross = 1; } elsif ($l eq "--tiny") { - param_set("tiny",1); + param_set("tiny", 1); } elsif (($l eq "-h") or ($l eq "--help")) { print("Milsko Toolkit Configuration Utility\n"); @@ -154,7 +161,9 @@ foreach my $l (@ARGV) { print(" --host=TARGET Host for compiler/archiver\n"); print(" --target=TARGET Specify target\n"); print(" --cflags=CFLAGS Add cflags\n"); - print(" --tiny Build smallest possible library\n"); + print( +" --tiny Build smallest possible library\n" + ); print(" --cross Indicate cross compilation\n"); print("\n"); print("Features:\n"); @@ -211,9 +220,9 @@ foreach my $e (param_list()) { } print("Enabled: " . join(" ", @l) . "\n"); -$cc =~ s/\*host\*/$host/; +$cc =~ s/\*host\*/$host/; $cxx =~ s/\*host\*/$host/; -$ar =~ s/\*host\*/$host/; +$ar =~ s/\*host\*/$host/; open(OUT, ">", "Makefile"); print(OUT "PREFIX = ${prefix}\n"); @@ -261,9 +270,9 @@ print(OUT "\n"); print(OUT "\n"); if (param_get("shared")) { my $linker = "CC"; -if (grep(/^haiku$/, @backends)) { - $linker = "CXX"; -} + if (grep(/^haiku$/, @backends)) { + $linker = "CXX"; + } print( OUT "src/${library_prefix}Mw${library_suffix}: " . join(" ", @library_targets) . "\n"); @@ -279,18 +288,18 @@ if (param_get("static")) { } foreach my $l (@library_targets) { - my $warn = "-Wall -Wextra -Wno-sign-compare -Wno-unused-value"; - my $s = $l; + my $warn = "-Wall -Wextra -Wno-sign-compare -Wno-unused-value"; + my $s = $l; my $compiler = "CC"; - my $o = $object_suffix; + my $o = $object_suffix; $o =~ s/\./\\\./g; if ($l =~ /cocoa/) { $s =~ s/$o$/.m/; } elsif ($l =~ /haiku/) { - $s =~ s/$o$/.cc/; - $compiler = "CXX"; + $s =~ s/$o$/.cc/; + $compiler = "CXX"; } else { $s =~ s/$o$/.c/; @@ -321,13 +330,12 @@ if (param_get("examples")) { if (param_get("shared")) { print(OUT - "${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n" - ); - } else { - print(OUT - "${l}: ${s}${object_suffix} src/${library_prefix}Mw.a\n" +"${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n" ); } + else { + print(OUT "${l}: ${s}${object_suffix} src/${library_prefix}Mw.a\n"); + } if (grep(/^cocoa$/, @backends)) { print(OUT " \$(CC) -L./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" @@ -339,11 +347,15 @@ if (param_get("examples")) { ); } - if($target eq "ClassicMacOS") { - print(OUT -" ".$ENV{RETRO68_TOOLCHAIN_PATH}."/bin/MakePEF ${l} -o ${s}.pef\n"); - print(OUT -" Rez -I ".$ENV{RETRO68_TOOLCHAIN_PATH}."/RIncludes ".$ENV{RETRO68_TOOLCHAIN_PATH}."/RIncludes/Retro68APPL.r -DCFRAG_NAME=\"example\" --data ${l}.pef --cc ${l}.dsk -t APPL\n" + if ($target eq "ClassicMacOS") { + print( OUT " " + . $ENV{RETRO68_TOOLCHAIN_PATH} + . "/bin/MakePEF ${l} -o ${s}.pef\n"); + print( OUT " Rez -I " + . $ENV{RETRO68_TOOLCHAIN_PATH} + . "/RIncludes " + . $ENV{RETRO68_TOOLCHAIN_PATH} + . "/RIncludes/Retro68APPL.r -DCFRAG_NAME=\"example\" --data ${l}.pef --cc ${l}.dsk -t APPL\n" ); } diff --git a/include/Mw/Resource/Cursor.h b/include/Mw/Resource/Cursor.h index c9347b97a..d62321eb1 100644 --- a/include/Mw/Resource/Cursor.h +++ b/include/Mw/Resource/Cursor.h @@ -83,6 +83,16 @@ MWDECL MwCursor MwCursorCenter; */ MWDECL MwCursor MwCursorCenterMask; +/*! + * @brief Bottom right cursor + */ +MWDECL MwCursor MwCursorBottomRight; + +/*! + * @brief Bottom right cursor mask + */ +MWDECL MwCursor MwCursorBottomRightMask; + #ifdef __cplusplus } #endif diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 3463b37b8..7ac9417cd 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -244,7 +244,9 @@ struct _MwSubWindow { int width; int height; MwPoint cursor_start; + MwPoint local_start; MwPoint base; + int mouse_cache; }; struct _MwTab { diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 237f6b574..49f315c7f 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -219,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -264,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/core.c b/src/core.c index 0a5fd8bb3..9776c1844 100644 --- a/src/core.c +++ b/src/core.c @@ -23,11 +23,11 @@ #define RESIZE(handle) \ { \ int RESIZE_i; \ + MwDispatch(handle, resize); \ MwDispatchUserHandler(handle, MwNresizeHandler, NULL); \ for(RESIZE_i = 0; RESIZE_i < arrlen(handle->children); RESIZE_i++) { \ MwDispatch(handle->children[RESIZE_i], parent_resize); \ } \ - MwDispatch(handle, resize); \ } static void MWAPI MwVaListApply_Internal(MwWidget handle, va_list va, int only_early); @@ -590,7 +590,7 @@ int MwPending(MwWidget handle) { for(i = 0; i < arrlen(handle->children); i++) { if(MwPending(handle->children[i])) return 1; } - return (arrlen(handle->tick_list) > 0 && (MwTimeGetTick() - handle->last_tick) >= (MwGetInteger(handle, MwNwaitMS) == MwDEFAULT ? MwWaitMS : MwGetInteger(handle, MwNwaitMS))) || (arrlen(handle->destroy_queue) > 0) || (handle->widget_class == NULL ? 0 : MwLLPending(handle->lowlevel)); + return (arrlen(handle->tick_list) > 0 && (MwTimeGetTick() - handle->last_tick) >= (MwGetInteger(handle, MwNwaitMS) == MwDEFAULT ? MwWaitMS : MwGetInteger(handle, MwNwaitMS))) || (arrlen(handle->destroy_queue) > 0) || (arrlen(handle->resize_queue) > 0) || (handle->widget_class == NULL ? 0 : MwLLPending(handle->lowlevel)); } void MwLoop(MwWidget handle) { diff --git a/src/cursor/bottomright.c b/src/cursor/bottomright.c new file mode 100644 index 000000000..55c20a9df --- /dev/null +++ b/src/cursor/bottomright.c @@ -0,0 +1,43 @@ +#include + +/** + * Created by bitmaptobdf + * + * Copyright notice: + * These ""glyphs"" are unencumbered + */ +MwCursor MwCursorBottomRight = { + 14, 14, -13, -1, {3, /* ............## */ + 3, /* ............## */ + 2083, /* ..#.....#...## */ + 1059, /* ...#....#...## */ + 547, /* ....#...#...## */ + 291, /* .....#..#...## */ + 163, /* ......#.#...## */ + 99, /* .......##...## */ + 4067, /* ..#######...## */ + 3, /* ............## */ + 3, /* ............## */ + 3, /* ............## */ + 16383, /* ############## */ + 16383, /* ############## */ + 0, 0}}; +MwCursor MwCursorBottomRightMask = { + 16, 16, -14, -2, { + 15, /* ............#### */ + 15, /* ............#### */ + 12527, /* ..##....###.#### */ + 14575, /* ..###...###.#### */ + 7407, /* ...###..###.#### */ + 3823, /* ....###.###.#### */ + 2031, /* .....######.#### */ + 1007, /* ......#####.#### */ + 16367, /* ..#########.#### */ + 16367, /* ..#########.#### */ + 16367, /* ..#########.#### */ + 15, /* ............#### */ + 65535, /* ################ */ + 65535, /* ################ */ + 65535, /* ################ */ + 65535 /* ################ */ + }}; diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index 81b539218..e1d887140 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -359,10 +359,29 @@ static void prop_change(MwWidget handle, const char* key) { if(strcmp(key, MwNtitle) == 0 || strcmp(key, MwNiconPixmap) == 0) MwForceRender(handle); } -static MwWidget mwSubWindowGetFrameImpl(MwWidget handle) { +static int is_bottom_right(MwWidget handle, MwPoint* p) { + int w = MwGetInteger(handle, MwNwidth); + int h = MwGetInteger(handle, MwNheight); + + if(p->x >= (w - TitleHeight) && p->y >= (h - TitleHeight)) { + return 1; + } + + return 0; +} + +static void mouse_move(MwWidget handle) { MwSubWindow sw = handle->internal; - return sw->frame; + if(is_bottom_right(handle, &handle->mouse_point)) { + if(sw->mouse_cache == 0) MwLLSetCursor(handle->lowlevel, &MwCursorBottomRight, &MwCursorBottomRightMask); + + sw->mouse_cache = 1; + } else if(!handle->pressed && sw->mouse_cache != 0) { + sw->mouse_cache = 0; + + MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); + } } static void mouse_down(MwWidget handle, void* ptr) { @@ -371,13 +390,20 @@ static void mouse_down(MwWidget handle, void* ptr) { if(m->button == MwMOUSE_LEFT && !sw->minimized && !sw->maximized) { MwGetCursorCoord(handle, &sw->cursor_start); - sw->base.x = MwGetInteger(handle, MwNx); - sw->base.y = MwGetInteger(handle, MwNy); + sw->local_start = handle->mouse_point; + sw->base.x = MwGetInteger(handle, MwNx); + sw->base.y = MwGetInteger(handle, MwNy); } MwLLRaise(handle->lowlevel); } +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)va; @@ -394,10 +420,17 @@ static void tick(MwWidget handle) { MwGetCursorCoord(handle, &p); - MwVaApply(handle, - MwNx, sw->base.x + p.x - sw->cursor_start.x, - MwNy, sw->base.y + p.y - sw->cursor_start.y, - NULL); + if(sw->mouse_cache == 1) { + MwVaApply(handle, + MwNwidth, handle->mouse_point.x, + MwNheight, handle->mouse_point.y, + NULL); + } else { + MwVaApply(handle, + MwNx, sw->base.x + p.x - sw->cursor_start.x, + MwNy, sw->base.y + p.y - sw->cursor_start.y, + NULL); + } } } @@ -408,7 +441,7 @@ MwClassRec MwSubWindowClassRec = { NULL, /* click */ parent_resize, /* parent_resize */ prop_change, /* prop_change */ - NULL, /* mouse_move */ + mouse_move, /* mouse_move */ NULL, /* mouse_up */ mouse_down, /* mouse_down */ NULL, /* key */ From 0d27c78b02a8c98a3e507baf59308bd79f73f0f2 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 17:43:41 +0900 Subject: [PATCH 054/102] fix --- src/widget/subwindow.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index e1d887140..f20f7c926 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -373,11 +373,13 @@ static int is_bottom_right(MwWidget handle, MwPoint* p) { static void mouse_move(MwWidget handle) { MwSubWindow sw = handle->internal; + if(handle->pressed) return; + if(is_bottom_right(handle, &handle->mouse_point)) { if(sw->mouse_cache == 0) MwLLSetCursor(handle->lowlevel, &MwCursorBottomRight, &MwCursorBottomRightMask); sw->mouse_cache = 1; - } else if(!handle->pressed && sw->mouse_cache != 0) { + } else if(sw->mouse_cache != 0) { sw->mouse_cache = 0; MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); From 122fbd949dcf377a47f0a40cbf13c2d42a8c6f18 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 17:46:01 +0900 Subject: [PATCH 055/102] ok --- NTMakefile | 5 +++-- WatMakefile | 7 +++++-- src/draw.c | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/NTMakefile b/NTMakefile index 18fbbda78..fcc7c5ae9 100644 --- a/NTMakefile +++ b/NTMakefile @@ -50,6 +50,7 @@ clean: del /f /q src\color.obj del /f /q src\core.obj del /f /q src\cursor\arrow.obj + del /f /q src\cursor\bottomright.obj del /f /q src\cursor\center.obj del /f /q src\cursor\cross.obj del /f /q src\cursor\default.obj @@ -357,8 +358,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\bottomright.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\bottomright.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 8873675a7..9f98f8ba4 100644 --- a/WatMakefile +++ b/WatMakefile @@ -36,6 +36,7 @@ clean: .SYMBOLIC %erase src/color.obj %erase src/core.obj %erase src/cursor/arrow.obj + %erase src/cursor/bottomright.obj %erase src/cursor/center.obj %erase src/cursor/cross.obj %erase src/cursor/default.obj @@ -350,8 +351,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/direct3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/direct3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/bottomright.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/direct3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/bottomright.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/direct3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -409,6 +410,8 @@ src/core.obj: src/core.c $(CC) $(MW_CFLAGS) -fo=$@ src/core.c src/cursor/arrow.obj: src/cursor/arrow.c $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/arrow.c +src/cursor/bottomright.obj: src/cursor/bottomright.c + $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/bottomright.c src/cursor/center.obj: src/cursor/center.c $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/center.c src/cursor/cross.obj: src/cursor/cross.c diff --git a/src/draw.c b/src/draw.c index b2ab8b148..88c34f098 100644 --- a/src/draw.c +++ b/src/draw.c @@ -975,6 +975,9 @@ void MwPixmapReloadRaw(MwLLPixmap px, unsigned char* rgb) { a /= 255; if(a != 0) { +#if 1 + a = 1; +#endif pout[0] = (unsigned char)(pin[0] * a); pout[1] = (unsigned char)(pin[1] * a); pout[2] = (unsigned char)(pin[2] * a); From 0320cd64ebfd86bac6318ed5299fc871d3cdcfe7 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 18:32:30 +0900 Subject: [PATCH 056/102] better alpha blending --- include/Mw/Draw.h | 6 +++ include/Mw/LowLevel.h | 5 +- include/Mw/TypeDefs.h | 13 +++-- src/backend/cairo.c | 9 ++-- src/backend/cocoa.m | 6 +-- src/backend/gdi.c | 9 ++++ src/backend/wayland/interfaces.c | 26 ++++----- src/backend/wayland/wayland.c | 14 ++--- src/backend/x11.c | 4 ++ src/core.c | 93 ++++++++++++++++++++------------ src/dialog/colorpicker.c | 2 +- src/dialog/filechooser.c | 12 ++--- src/dialog/messagebox.c | 2 +- src/draw.c | 38 +++++++++++-- src/text/ft2.c | 2 +- src/text/gdi.c | 2 +- src/text/stbtt.c | 2 +- src/text/text.c | 2 +- src/widget/calendar.c | 6 +-- src/widget/label.c | 2 +- src/widget/opengl.c | 2 +- 21 files changed, 170 insertions(+), 87 deletions(-) diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 12d3d4534..aec819844 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -184,6 +184,12 @@ MWDECL unsigned char* MWAPI MwPixmapGetRaw(MwLLPixmap pixmap); */ MWDECL void MWAPI MwPixmapGetSize(MwLLPixmap pixmap, MwRect* rect); +/*! + * @brief Destroys the pixmap + * @param pixmap Pixmap + */ +MWDECL void MWAPI MwDestroyPixmap(MwLLPixmap pixmap); + /*! * @brief Creates a pixmap from XPM data * @param handle Widget diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 8822f68ae..6ae7f2c64 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -34,7 +34,7 @@ enum MwLLBackends { }; struct _MwLLCommon { - void* user; + void* internal; int copy_buffer; int type; int coordinate_type; @@ -58,7 +58,8 @@ struct _MwLLCommonPixmap { int width; int height; unsigned char* raw; - void* user; + unsigned char* before_blend; + void* internal; }; #ifdef USE_DBUS diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 7ac9417cd..c9a7575b2 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -99,11 +99,14 @@ struct _MwWidget { int prop_event; int held; - void* internal; - void* opaque; - void* user; - void (*draw_inject)(MwWidget handle); - void (*destroy_inject)(MwWidget handle); + void* internal; + void* opaque; + void* user; + MwHandler draw_inject; + MwHandler destroy_inject; + MwHandlerProp prop_inject_pixmap; /* this is for pixmap; do not use */ + + MwLLPixmap* pixmaps; MwIntegerKeyValue* integer; MwTextKeyValue* text; diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 49f315c7f..6764f6ffd 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -46,10 +46,12 @@ MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, if(width >= INT16_MAX) width = INT16_MAX; if(height >= INT16_MAX) height = INT16_MAX; - r->common.width = width; - r->common.height = height; - r->common.raw = malloc(4 * width * height); + r->common.width = width; + r->common.height = height; + r->common.raw = malloc(4 * width * height); + r->common.before_blend = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); + memcpy(r->common.before_blend, data, 4 * width * height); r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); @@ -80,6 +82,7 @@ void MwLLCairoPixmapUpdate(MwLLPixmap r) { void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) { cairo_surface_destroy(pixmap->wayland.cs); + free(pixmap->common.before_blend); free(pixmap->common.raw); free(pixmap); } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 85b8b5bd8..06e7c0e2d 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -64,7 +64,7 @@ static inline NSPoint localPointFlip(NSPoint point, NSView* view) { /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key, k); if(h) { int i; @@ -78,7 +78,7 @@ static void recursive_dispatch_key(MwLL handle, int* k) { }; /* Recursively dispatch a key released event to a widget and its children */ static void recursive_dispatch_key_released(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key_released, k); if(h) { int i; @@ -637,7 +637,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [topmost_parent->cocoa.real->view setNeedsDisplay:true]; MwLLDispatch(topmost_parent, draw, NULL); - h = (MwWidget)topmost_parent->common.user; + h = (MwWidget)topmost_parent->common.intenral; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 2013b9a11..65432d947 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -665,6 +665,14 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid memcpy(r->common.raw, data, 4 * width * height); + r->common.before_blend = malloc(width * height * 4); + if(!r->common.before_blend) { + printf("Out Of Memory\n"); + return NULL; + } + + memcpy(r->common.before_blend, data, 4 * width * height); + r->common.width = width; r->common.height = height; @@ -740,6 +748,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap->common.before_blend); free(pixmap->common.raw); DeleteObject(pixmap->gdi.hMask); DeleteObject(pixmap->gdi.hMask2); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 1b9fe1a5d..6ad540672 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -23,7 +23,7 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key, k); if(h) { int i; @@ -37,7 +37,7 @@ static void recursive_dispatch_key(MwLL handle, int* k) { }; /* Recursively dispatch a key released event to a widget and its children */ static void recursive_dispatch_key_released(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key_released, k); if(h) { int i; @@ -52,7 +52,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { /* Recursively dispatch a move event to a widget and its children */ static void recursive_dispatch_move(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { @@ -165,8 +165,8 @@ static void wl_data_device_leave(void* data, static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { return MwTRUE; - } else if(self->common.user) { - MwWidget w = self->common.user; + } else if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -190,8 +190,8 @@ static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx static void clipboard_dispatch(MwLL self, char* buf) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { MwLLDispatch(self, drag_and_drop, buf); - } else if(self->common.user) { - MwWidget w = self->common.user; + } else if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -722,7 +722,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time }; static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, down, p); if(h) { int i; @@ -735,7 +735,7 @@ static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { } }; static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, up, p); if(h) { int i; @@ -793,8 +793,8 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { break; } - if(self->common.user) { - MwWidget w = self->common.user; + if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -963,8 +963,8 @@ static void keyboard_leave(void* data, }; void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { - if(self->common.user) { - MwWidget w = self->common.user; + if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 973b6f473..b3dbcac2b 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -14,8 +14,8 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { - if(handle->common.user) { - MwWidget w = handle->common.user; + if(handle->common.intenral) { + MwWidget w = handle->common.intenral; int i; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -30,7 +30,7 @@ static int event_loop(MwLL handle); /* Recursively dispatch a resize event to a widget and its children */ static void recursive_dispatch_resize(MwLL handle) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { @@ -45,7 +45,7 @@ static void recursive_dispatch_resize(MwLL handle) { static void recursive_render(MwLL handle) { int i; - for(i = 0; i < arrlen(((MwWidget)handle->common.user)->children); i++) recursive_render(((MwWidget)handle->common.user)->children[i]->lowlevel); + for(i = 0; i < arrlen(((MwWidget)handle->common.intenral)->children); i++) recursive_render(((MwWidget)handle->common.intenral)->children[i]->lowlevel); MwLLForceRender(handle); } @@ -512,7 +512,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); if(parent) { - MwWidget p = parent->common.user; + MwWidget p = parent->common.intenral; while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; } @@ -1944,11 +1944,11 @@ static void MwLLRaiseImpl(MwLL handle) { MwLL topmost_parent = handle; int children_num; while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - children_num = arrlen(((MwWidget)topmost_parent->common.user)->children); + children_num = arrlen(((MwWidget)topmost_parent->common.intenral)->children); if(children_num > 1) { printf("%d\n", children_num); - MwWidget last_child = ((MwWidget)topmost_parent->common.user)->children[children_num - 1]; + MwWidget last_child = ((MwWidget)topmost_parent->common.intenral)->children[children_num - 1]; wl_subsurface_place_above(handle->wayland.sublevel->subsurface, last_child->lowlevel->wayland.framebuffer.surface); } }*/ diff --git a/src/backend/x11.c b/src/backend/x11.c index b713821e3..e44b3a153 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1097,6 +1097,9 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid r->common.raw = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); + r->common.before_blend = malloc(4 * width * height); + memcpy(r->common.before_blend, data, 4 * width * height); + XGetWindowAttributes(handle->x11.display, handle->x11.window, &attr); r->common.width = width; @@ -1152,6 +1155,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap->common.before_blend); free(pixmap->common.raw); XDestroyImage(pixmap->x11.image); XDestroyImage(pixmap->x11.mask); diff --git a/src/core.c b/src/core.c index 9776c1844..a2e520fd0 100644 --- a/src/core.c +++ b/src/core.c @@ -30,11 +30,17 @@ } \ } +#define PROP(handle, key) \ + { \ + MwDispatch3((handle), prop_change, (key)); \ + if((handle)->prop_inject_pixmap != NULL) handle->prop_inject_pixmap((handle), (key)); \ + } + static void MWAPI MwVaListApply_Internal(MwWidget handle, va_list va, int only_early); static MwWidget MWAPI MwCreateWidget_Internal(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height, int do_prop, va_list prop); static void lldrawhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; #ifdef PERIODIC MwWidget top; #endif @@ -67,7 +73,7 @@ static void lldrawhandler(MwLL handle, void* data) { } static void lluphandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; MwMouse* p = data; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -82,7 +88,7 @@ static void lluphandler(MwLL handle, void* data) { } static void lldownhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; MwMouse* p = data; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -96,7 +102,7 @@ static void lldownhandler(MwLL handle, void* data) { } static void llresizehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; #ifdef RESIZE_ON_TICK MwWidget top; #endif @@ -129,7 +135,7 @@ static void llresizehandler(MwLL handle, void* data) { } static void llclosehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; (void)data; @@ -147,7 +153,7 @@ static void llclosehandler(MwLL handle, void* data) { } static void llmovehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; MwPoint* p = data; h->mouse_point.x = p->x; @@ -158,7 +164,7 @@ static void llmovehandler(MwLL handle, void* data) { } static void llkeyhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int key = *(int*)data; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -168,7 +174,7 @@ static void llkeyhandler(MwLL handle, void* data) { } static void llkeyrelhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -176,7 +182,7 @@ static void llkeyrelhandler(MwLL handle, void* data) { } static void llfocusinhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -184,7 +190,7 @@ static void llfocusinhandler(MwLL handle, void* data) { } static void llfocusouthandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -192,7 +198,7 @@ static void llfocusouthandler(MwLL handle, void* data) { } static void llclipboardhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -201,7 +207,7 @@ static void llclipboardhandler(MwLL handle, void* data) { } static void lldraganddrophandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -222,7 +228,7 @@ static void lldraganddrophandler(MwLL handle, void* data) { #define IsFirstVisible(handle) ((handle)->widget_class != NULL && ((handle)->parent == NULL || (handle)->parent->widget_class == NULL)) static void lldarkthemehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int* ptr = data; int s; @@ -260,16 +266,18 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, } else { h->lowlevel = NULL; } - h->widget_class = widget_class; - h->pressed = 0; - h->close = 0; - h->destroy_queue = NULL; - h->prop_event = 1; - h->draw_inject = NULL; - h->destroy_inject = NULL; - h->tick_list = NULL; - h->destroyed = 0; - h->bgcolor = NULL; + h->widget_class = widget_class; + h->pressed = 0; + h->close = 0; + h->destroy_queue = NULL; + h->prop_event = 1; + h->draw_inject = NULL; + h->destroy_inject = NULL; + h->prop_inject_pixmap = NULL; + h->pixmaps = NULL; + h->tick_list = NULL; + h->destroyed = 0; + h->bgcolor = NULL; h->berserk = 0; h->last_tick = MwTimeGetTick(); @@ -288,7 +296,7 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, if(parent == NULL) h->top_step = 1; if(h->lowlevel != NULL) { - h->lowlevel->common.user = h; + h->lowlevel->common.internal = h; h->lowlevel->common.handler->draw = lldrawhandler; h->lowlevel->common.handler->up = lluphandler; h->lowlevel->common.handler->down = lldownhandler; @@ -456,6 +464,9 @@ void MwFreeWidget(MwWidget handle) { arrfree(handle->destroy_queue); arrfree(handle->tick_list); + while(arrlen(handle->pixmaps) > 0) MwDestroyPixmap(handle->pixmaps[0]); + arrfree(handle->pixmaps); + arrfree(handle->draw_queue); arrfree(handle->resize_queue); @@ -628,6 +639,20 @@ static void force_render_all(MwWidget handle) { if(handle->lowlevel != NULL) MwForceRender(handle); } +static void notify_all_bgfg_prop(MwWidget handle) { + int i; + + for(i = 0; i < arrlen(handle->children); i++) { + notify_all_bgfg_prop(handle->children[i]); + } + + PROP(handle, MwNbackground); + PROP(handle, MwNforeground); + PROP(handle, MwNsubBackground); + PROP(handle, MwNsubForeground); + MwForceRender(handle); +} + void MwSetInteger(MwWidget handle, const char* key, int n) { int xy; int wh = 0; @@ -653,7 +678,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { MwDispatch3(handle, props_change, keys); arrfree(keys); - MwDispatch3(handle, prop_change, key); + PROP(handle, key); } if(handle->parent != NULL && handle->parent->prop_event) { @@ -663,7 +688,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { if(strcmp(key, MwNforceInverted) == 0) { MwForceRender(handle); } - if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNdarkTheme) == 0 || strcmp(key, MwNbitmapFont) == 0) { + if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNbitmapFont) == 0) { force_render_all(handle); } @@ -677,6 +702,8 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { } if(h->lowlevel != NULL) MwLLSetDarkTheme(h->lowlevel, n); + + notify_all_bgfg_prop(handle); } if(strcmp(key, MwNacceptsDnD) == 0 && n) { @@ -706,7 +733,7 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { MwDispatch3(handle, props_change, keys); arrfree(keys); - MwDispatch3(handle, prop_change, key); + PROP(handle, key); } if(handle->parent != NULL && handle->parent->prop_event) { @@ -738,7 +765,7 @@ void MwSetVoid(MwWidget handle, const char* key, void* value) { MwDispatch3(handle, props_change, keys); arrfree(keys); - MwDispatch3(handle, prop_change, key); + PROP(handle, key); } if(handle->parent != NULL && handle->parent->prop_event) { @@ -918,8 +945,8 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(x != MwDEFAULT && y != MwDEFAULT) { MwLLSetXY(handle->lowlevel, x, y); if(handle->prop_event) { - MwDispatch3(handle, prop_change, MwNx); - MwDispatch3(handle, prop_change, MwNy); + PROP(handle, MwNx); + PROP(handle, MwNy); } } else { if(x != MwDEFAULT) { @@ -931,8 +958,8 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(w != MwDEFAULT && h != MwDEFAULT) { MwLLSetWH(handle->lowlevel, w, h); if(handle->prop_event) { - MwDispatch3(handle, prop_change, MwNwidth); - MwDispatch3(handle, prop_change, MwNheight); + PROP(handle, MwNwidth); + PROP(handle, MwNheight); } } else { if(w != MwDEFAULT) { @@ -947,7 +974,7 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(handle->prop_event) { for(i = 0; keys[i] != NULL; i++) { - MwDispatch3(handle, prop_change, keys[i]); + PROP(handle, keys[i]); } MwDispatch3(handle, props_change, keys); diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 378b79603..2019f202a 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -220,7 +220,7 @@ static void MWAPI color_picker_tick(MwWidget handle, void* user, } static void color_picker_destroy(color_picker_t* picker) { - MwLLDestroyPixmap(picker->color_picker_pixmap); + MwDestroyPixmap(picker->color_picker_pixmap); free(picker); } diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index b1fcc9b26..e7f1e28f1 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -43,12 +43,12 @@ static void destroy(MwWidget handle) { for(i = 0; i < arrlen(fc->entries); i++) MwDirectoryFreeEntry(fc->entries[i]); arrfree(fc->entries); - MwLLDestroyPixmap(fc->dir); - MwLLDestroyPixmap(fc->file); - MwLLDestroyPixmap(fc->back); - MwLLDestroyPixmap(fc->forward); - MwLLDestroyPixmap(fc->up); - MwLLDestroyPixmap(fc->computer); + MwDestroyPixmap(fc->dir); + MwDestroyPixmap(fc->file); + MwDestroyPixmap(fc->back); + MwDestroyPixmap(fc->forward); + MwDestroyPixmap(fc->up); + MwDestroyPixmap(fc->computer); free(handle->opaque); } diff --git a/src/dialog/messagebox.c b/src/dialog/messagebox.c index ff72bc848..d536f10f8 100644 --- a/src/dialog/messagebox.c +++ b/src/dialog/messagebox.c @@ -21,7 +21,7 @@ static void spawn_button(MwWidget handle, int x, int y, int id, const char* text static void messagebox_destroy_inject(MwWidget handle) { void* px; - if((px = MwGetVoid(handle, MwNpixmap)) != NULL) MwLLDestroyPixmap(px); + if((px = MwGetVoid(handle, MwNpixmap)) != NULL) MwDestroyPixmap(px); } static void MWAPI messagebox_close(MwWidget handle, void* user, void* call) { diff --git a/src/draw.c b/src/draw.c index 88c34f098..649741a5e 100644 --- a/src/draw.c +++ b/src/draw.c @@ -953,29 +953,43 @@ MwLLPixmap MwLoadImage(MwWidget handle, const char* path) { return px; } +static void pixmap_prop(MwWidget handle, const char* prop) { + if(strcmp(prop, MwNbackground) == 0 || strcmp(prop, MwNsubBackground) == 0) { + int i; + + for(i = 0; i < arrlen(handle->pixmaps); i++) MwPixmapReloadRaw(handle->pixmaps[i], NULL); + } +} + MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) { MwLLPixmap px = MwLLCreatePixmap(handle->lowlevel, rgb, width, height); - px->common.user = handle; + px->common.internal = handle; MwPixmapReloadRaw(px, rgb); + handle->prop_inject_pixmap = pixmap_prop; + + arrput(handle->pixmaps, px); + return px; } void MwPixmapReloadRaw(MwLLPixmap px, unsigned char* rgb) { int i; - MwWidget handle = px->common.user; + MwWidget handle = px->common.internal; MwLLColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor; + if(rgb != NULL) memcpy(px->common.before_blend, rgb, px->common.width * px->common.height * 4); + memset(px->common.raw, 0, px->common.width * px->common.height * 4); for(i = 0; i < px->common.width * px->common.height; i++) { - unsigned char* pin = &rgb[i * 4]; + unsigned char* pin = &px->common.before_blend[i * 4]; unsigned char* pout = &px->common.raw[i * 4]; double a = pin[3]; a /= 255; if(a != 0) { -#if 1 +#if 0 a = 1; #endif pout[0] = (unsigned char)(pin[0] * a); @@ -1003,6 +1017,22 @@ void MwPixmapGetSize(MwLLPixmap pixmap, MwRect* rect) { rect->height = pixmap->common.height; } +void MwDestroyPixmap(MwLLPixmap pixmap) { + int i; + MwWidget handle = pixmap->common.internal; + + for(i = 0; i < arrlen(handle->pixmaps); i++) { + if(handle->pixmaps[i] == pixmap) { + arrdel(handle->pixmaps, i); + break; + } + } + + if(arrlen(handle->pixmaps) == 0) handle->prop_inject_pixmap = NULL; + + MwLLDestroyPixmap(pixmap); +} + void MwColorGet(MwLLColor color, int* red, int* green, int* blue) { *red = color->common.red; *green = color->common.green; diff --git a/src/text/ft2.c b/src/text/ft2.c index 13e8208c1..10cd1ad02 100644 --- a/src/text/ft2.c +++ b/src/text/ft2.c @@ -93,7 +93,7 @@ static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); return 0; diff --git a/src/text/gdi.c b/src/text/gdi.c index 91ccac940..eb7df4ea2 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -103,7 +103,7 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); DeleteObject(hbm); diff --git a/src/text/stbtt.c b/src/text/stbtt.c index bd2674145..67fe0ce6b 100644 --- a/src/text/stbtt.c +++ b/src/text/stbtt.c @@ -80,7 +80,7 @@ static int stbtt_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); return 0; diff --git a/src/text/text.c b/src/text/text.c index 1c9f6e6de..b39f064fb 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -330,7 +330,7 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); } diff --git a/src/widget/calendar.c b/src/widget/calendar.c index 3fa304b98..f5793f25f 100644 --- a/src/widget/calendar.c +++ b/src/widget/calendar.c @@ -191,7 +191,7 @@ static void draw(MwWidget handle) { r2.x = (r.width - r2.width) / 2; r2.y = r2.y + gh * 2; MwLLDrawPixmap(handle->lowlevel, &r2, px); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); px = blit(handle, months[MwGetInteger(handle, MwNmonth)], cb, ct, gh); r2 = r3; @@ -200,7 +200,7 @@ static void draw(MwWidget handle) { r2.x = (r.width - r2.width) / 2; r2.y = r2.y + h - gh * 2 - r2.height; MwLLDrawPixmap(handle->lowlevel, &r2, px); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); MwStringPrintIntoBuffer(buf, 5, "%d", MwGetInteger(handle, MwNyear)); @@ -211,7 +211,7 @@ static void draw(MwWidget handle) { r2.x = (r.width - r2.width) / 2; r2.y = r2.y + h + gh * 6; MwLLDrawPixmap(handle->lowlevel, &r2, px); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); MwLLFreeColor(cf); MwLLFreeColor(ct); diff --git a/src/widget/label.c b/src/widget/label.c index a0be9ca58..eecca474d 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -309,7 +309,7 @@ static void draw_seven_segment(MwWidget handle) { free(raw); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); } static void draw_normal(MwWidget handle) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index c9bb3f496..e3578a76f 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -617,7 +617,7 @@ static void frontbuffer_resize(MwWidget handle) { free(o->frontbuffer_data); } if(o->frontbuffer) { - MwLLDestroyPixmap(o->frontbuffer); + MwDestroyPixmap(o->frontbuffer); } if(o->gbm_surface) { o->gbm_surface_destroy(o->gbm_surface); From 42faa5691a8cf7e570adc50c794d32e3f81e7d1d Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 18:34:07 +0900 Subject: [PATCH 057/102] ok --- src/draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/draw.c b/src/draw.c index 649741a5e..7c8fb0e8e 100644 --- a/src/draw.c +++ b/src/draw.c @@ -954,7 +954,7 @@ MwLLPixmap MwLoadImage(MwWidget handle, const char* path) { } static void pixmap_prop(MwWidget handle, const char* prop) { - if(strcmp(prop, MwNbackground) == 0 || strcmp(prop, MwNsubBackground) == 0) { + if(strcmp(prop, MwNbackground) == 0) { int i; for(i = 0; i < arrlen(handle->pixmaps); i++) MwPixmapReloadRaw(handle->pixmaps[i], NULL); From af472c625cc275b02925b2e99421e1771db79466 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 18:36:17 +0900 Subject: [PATCH 058/102] ok --- src/backend/cocoa.m | 6 +++--- src/backend/wayland/interfaces.c | 26 +++++++++++++------------- src/backend/wayland/wayland.c | 14 +++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 06e7c0e2d..63beff154 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -64,7 +64,7 @@ static inline NSPoint localPointFlip(NSPoint point, NSView* view) { /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; MwLLDispatch(handle, key, k); if(h) { int i; @@ -78,7 +78,7 @@ static void recursive_dispatch_key(MwLL handle, int* k) { }; /* Recursively dispatch a key released event to a widget and its children */ static void recursive_dispatch_key_released(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; MwLLDispatch(handle, key_released, k); if(h) { int i; @@ -637,7 +637,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [topmost_parent->cocoa.real->view setNeedsDisplay:true]; MwLLDispatch(topmost_parent, draw, NULL); - h = (MwWidget)topmost_parent->common.intenral; + h = (MwWidget)topmost_parent->common.internal; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 6ad540672..cd6a1b4b6 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -23,7 +23,7 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; MwLLDispatch(handle, key, k); if(h) { int i; @@ -37,7 +37,7 @@ static void recursive_dispatch_key(MwLL handle, int* k) { }; /* Recursively dispatch a key released event to a widget and its children */ static void recursive_dispatch_key_released(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; MwLLDispatch(handle, key_released, k); if(h) { int i; @@ -52,7 +52,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { /* Recursively dispatch a move event to a widget and its children */ static void recursive_dispatch_move(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { @@ -165,8 +165,8 @@ static void wl_data_device_leave(void* data, static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { return MwTRUE; - } else if(self->common.intenral) { - MwWidget w = self->common.intenral; + } else if(self->common.internal) { + MwWidget w = self->common.internal; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -190,8 +190,8 @@ static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx static void clipboard_dispatch(MwLL self, char* buf) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { MwLLDispatch(self, drag_and_drop, buf); - } else if(self->common.intenral) { - MwWidget w = self->common.intenral; + } else if(self->common.internal) { + MwWidget w = self->common.internal; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -722,7 +722,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time }; static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; MwLLDispatch(handle, down, p); if(h) { int i; @@ -735,7 +735,7 @@ static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { } }; static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; MwLLDispatch(handle, up, p); if(h) { int i; @@ -793,8 +793,8 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { break; } - if(self->common.intenral) { - MwWidget w = self->common.intenral; + if(self->common.internal) { + MwWidget w = self->common.internal; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -963,8 +963,8 @@ static void keyboard_leave(void* data, }; void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { - if(self->common.intenral) { - MwWidget w = self->common.intenral; + if(self->common.internal) { + MwWidget w = self->common.internal; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index b3dbcac2b..e2e96378a 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -14,8 +14,8 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { - if(handle->common.intenral) { - MwWidget w = handle->common.intenral; + if(handle->common.internal) { + MwWidget w = handle->common.internal; int i; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -30,7 +30,7 @@ static int event_loop(MwLL handle); /* Recursively dispatch a resize event to a widget and its children */ static void recursive_dispatch_resize(MwLL handle) { - MwWidget h = (MwWidget)handle->common.intenral; + MwWidget h = (MwWidget)handle->common.internal; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { @@ -45,7 +45,7 @@ static void recursive_dispatch_resize(MwLL handle) { static void recursive_render(MwLL handle) { int i; - for(i = 0; i < arrlen(((MwWidget)handle->common.intenral)->children); i++) recursive_render(((MwWidget)handle->common.intenral)->children[i]->lowlevel); + for(i = 0; i < arrlen(((MwWidget)handle->common.internal)->children); i++) recursive_render(((MwWidget)handle->common.internal)->children[i]->lowlevel); MwLLForceRender(handle); } @@ -512,7 +512,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); if(parent) { - MwWidget p = parent->common.intenral; + MwWidget p = parent->common.internal; while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; } @@ -1944,11 +1944,11 @@ static void MwLLRaiseImpl(MwLL handle) { MwLL topmost_parent = handle; int children_num; while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - children_num = arrlen(((MwWidget)topmost_parent->common.intenral)->children); + children_num = arrlen(((MwWidget)topmost_parent->common.internal)->children); if(children_num > 1) { printf("%d\n", children_num); - MwWidget last_child = ((MwWidget)topmost_parent->common.intenral)->children[children_num - 1]; + MwWidget last_child = ((MwWidget)topmost_parent->common.internal)->children[children_num - 1]; wl_subsurface_place_above(handle->wayland.sublevel->subsurface, last_child->lowlevel->wayland.framebuffer.surface); } }*/ From e1824cffa008c9741eef3b700dc03ad3c2c015e0 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 27 Sep 2026 05:46:28 +0900 Subject: [PATCH 059/102] z-index system for wayland fixes clicks penetrating to widgets behind one another and allows MwLLRaiseImpl to be implemented --- include/Mw/LowLevel/Wayland.h | 8 ++ src/backend/wayland/interfaces.c | 124 +++++++++++++++---------------- src/backend/wayland/wayland.c | 94 +++++++++++++---------- 3 files changed, 121 insertions(+), 105 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 607ff2cae..01f772c31 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -341,6 +341,9 @@ struct _MwLLWayland { MwBool is_toplevel; + /* Stacking order among sibling sublevels. Higher values are drawn on top and get the pointer first. */ + MwI32 z_index; + MwBool is_clipping; MwRect clip; @@ -505,6 +508,11 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ /* Flush Wayland events */ void MwLLWaylandFlush(MwLL handle); +/* Get the sublevel children of a widget ordered from lowest to highest z-index (ties keep creation order). Free the result with arrfree. */ +MwLL* MwLLWaylandSublevelsByZIndex(MwLL handle); +/* Set a sublevel's z-index and schedule a redraw so the new stacking order is shown. */ +void MwLLWaylandSetZIndex(MwLL handle, MwI32 z_index); + /* recursively dispatch the key event to focused widgets. */ void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index cd6a1b4b6..2740c6f3c 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -721,33 +721,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time } }; -static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.internal; - MwLLDispatch(handle, down, p); - if(h) { - int i; - for(i = 0; i < arrlen(h->children); i++) { - MwLLDispatch(h->children[i]->lowlevel, down, p); - if(arrlen(h->children[i]->children) > 0) { - recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); - } - } - } -}; -static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.internal; - MwLLDispatch(handle, up, p); - if(h) { - int i; - for(i = 0; i < arrlen(h->children); i++) { - MwLLDispatch(h->children[i]->lowlevel, up, p); - if(arrlen(h->children[i]->children) > 0) { - recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); - } - } - } -}; - static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) { MwLL topmost_parent = child; MwPoint point; @@ -761,10 +734,8 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP if(topmost_parent) { /* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */ if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { - if(topmost_parent->wayland.x > 0) - absolute_pos.x += topmost_parent->wayland.x; - if(topmost_parent->wayland.y > 0) - absolute_pos.y += topmost_parent->wayland.y; + absolute_pos.x += topmost_parent->wayland.x; + absolute_pos.y += topmost_parent->wayland.y; } } } @@ -783,53 +754,74 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh; } +/* deepest, topmost-z sublevel under the pointer, or self if none */ +static MwLL find_target(MwLL self, MwPoint* local) { + MwLL* children = MwLLWaylandSublevelsByZIndex(self); + MwLL target = self; + int i; + for(i = arrlen(children) - 1; i >= 0; i--) { + MwLL tp; + MwPoint pt, rel, abs; + if(hit_detect(children[i], &tp, &pt, &rel, &abs)) { + *local = rel; + target = find_target(children[i], local); + break; + } + } + arrfree(children); + return target; +} + static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { + MwLL target = find_target(self, &p.point); + switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: - MwLLDispatch(self, down, &p); + MwLLDispatch(target, down, &p); break; case WL_POINTER_BUTTON_STATE_RELEASED: - MwLLDispatch(self, up, &p); - break; + MwLLDispatch(target, up, &p); + return; } - if(self->common.internal) { - MwWidget w = self->common.internal; - int i, n; - for(i = 0; i < arrlen(w->children); i++) { - if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - MwLL topmost_parent = child; - MwPoint point; - MwPoint relative_mouse_pos; - MwPoint absolute_pos; + { + /* walk from the top of the stack down so that only the highest z-index sublevel under the pointer gets the click */ + MwLL* children = MwLLWaylandSublevelsByZIndex(self); + int i, n; + for(i = arrlen(children) - 1; i >= 0; i--) { + MwLL child = children[i]; + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; - if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos)) { - int idx = -1; - for(n = 0; n < arrlen(topmost_parent->wayland.currentlyHeldWidgets); n++) { - if(topmost_parent->wayland.currentlyHeldWidgets[n] == child) { - idx = n; - } + if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos)) { + int idx = -1; + for(n = 0; n < arrlen(topmost_parent->wayland.currentlyHeldWidgets); n++) { + if(topmost_parent->wayland.currentlyHeldWidgets[n] == child) { + idx = n; } - p.point = relative_mouse_pos; - - switch(state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - if(idx == -1) { - arrpush(topmost_parent->wayland.currentlyHeldWidgets, child); - } - break; - case WL_POINTER_BUTTON_STATE_RELEASED: - if(idx != -1) { - arrdel(topmost_parent->wayland.currentlyHeldWidgets, idx); - } - break; - } - - mouse_dispatch(child, p, state); } + p.point = relative_mouse_pos; + + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + if(idx == -1) { + arrpush(topmost_parent->wayland.currentlyHeldWidgets, child); + } + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + if(idx != -1) { + arrdel(topmost_parent->wayland.currentlyHeldWidgets, idx); + } + break; + } + + mouse_dispatch(child, p, state); + break; } } + arrfree(children); } } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index e2e96378a..d23594bfc 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -13,17 +13,48 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; -void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { +MwLL* MwLLWaylandSublevelsByZIndex(MwLL handle) { + MwLL* r = NULL; if(handle->common.internal) { MwWidget w = handle->common.internal; - int i; + int i, j; for(i = 0; i < arrlen(w->children); i++) { - if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - func(handle, child); + MwLL child = w->children[i]->lowlevel; + if(child->wayland.type != MwLL_WAYLAND_SUBLEVEL) continue; + + /* insertion sort, stable so that equal z-indexes keep their creation order */ + arrput(r, child); + for(j = arrlen(r) - 1; j > 0 && r[j - 1]->wayland.z_index > child->wayland.z_index; j--) { + r[j] = r[j - 1]; } + r[j] = child; } } + return r; +} + +void MwLLWaylandSetZIndex(MwLL handle, MwI32 z_index) { + MwLL root = handle; + + if(handle->wayland.z_index == z_index) return; + handle->wayland.z_index = z_index; + + /* sublevels are composited by their root, so that's what needs to redraw */ + while(root->wayland.type == MwLL_WAYLAND_SUBLEVEL && root->wayland.parent) { + root = root->wayland.parent; + } + root->wayland.do_cascading_draw = MwTRUE; + root->wayland.events_pending = 1; +} + +/* Iterate over the sublevel children of a widget, from the bottom of the stack to the top */ +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { + MwLL* children = MwLLWaylandSublevelsByZIndex(handle); + int i; + for(i = 0; i < arrlen(children); i++) { + func(handle, children[i]); + } + arrfree(children); } static int event_loop(MwLL handle); @@ -813,35 +844,21 @@ static void clip(MwLL handle) { cy = 0; mx = toplevel->wayland.ww; my = toplevel->wayland.wh; - // ws is traversed result - // ws[ws.length - 1] is ignored bc it's toplevel + /* ws is traversed result */ + /* ws[arrlen(ws) - 1] is the toplevel, which is the origin */ for(i = arrlen(ws) - 2; i >= 0; i--) { - int j; - int l = 0; - x += ws[i]->wayland.x; y += ws[i]->wayland.y; - for(j = i - 1; j >= 0; j--) { - if(ws[j]->wayland.x > cx) l = 1; - if(ws[j]->wayland.y > cy) l = 1; - if(l) break; - } - - if(!l) { - cx = MAX(cx, ws[i]->wayland.x); - cy = MAX(cy, ws[i]->wayland.y); - } - - mx = MIN(mx, x + ws[i]->wayland.ww); - my = MIN(my, y + ws[i]->wayland.wh); + cx = MAX(cx, x); + cy = MAX(cy, y); + mx = MIN(mx, x + (int)ws[i]->wayland.ww); + my = MIN(my, y + (int)ws[i]->wayland.wh); } - if(mx < cx) mx = cx; - if(my < cy) my = cy; - arrfree(ws); + /* fully hidden, clip to an empty rectangle */ if(mx < cx) mx = cx; if(my < cy) my = cy; @@ -1937,21 +1954,20 @@ static MwBool MwLLDoModernImpl(MwLL handle) { } static void MwLLRaiseImpl(MwLL handle) { - (void)handle; - /* + MwLL* siblings; + int n; - if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL topmost_parent = handle; - int children_num; - while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - children_num = arrlen(((MwWidget)topmost_parent->common.internal)->children); + if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL || !handle->wayland.parent) { + return; + } - if(children_num > 1) { - printf("%d\n", children_num); - MwWidget last_child = ((MwWidget)topmost_parent->common.internal)->children[children_num - 1]; - wl_subsurface_place_above(handle->wayland.sublevel->subsurface, last_child->lowlevel->wayland.framebuffer.surface); - } - }*/ + /* put it one above whichever sibling is currently on top */ + siblings = MwLLWaylandSublevelsByZIndex(handle->wayland.parent); + n = arrlen(siblings); + if(n > 0 && siblings[n - 1] != handle) { + MwLLWaylandSetZIndex(handle, siblings[n - 1]->wayland.z_index + 1); + } + arrfree(siblings); } static void MwLLClipImpl(MwLL handle, MwRect* rect) { From 6e6233edc8bd4fbf8834194648516ce29d7f7cb1 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 05:49:10 +0900 Subject: [PATCH 060/102] migrate MwLLColor and MwLLPixmap --- configure | 3 +- include/Mw/BaseTypes.h | 14 +- include/Mw/Draw.h | 101 +++++++---- include/Mw/LowLevel.h | 6 +- include/Mw/LowLevel/GDI.h | 1 + include/Mw/LowLevel/X11.h | 1 + include/Mw/MachDep.h | 7 + include/Mw/Resource/Font.h | 4 +- include/Mw/TypeDefs.h | 35 +++- include/Mw/Widget/ListBox.h | 2 +- include/Mw/Widget/TreeView.h | 4 +- src/backend/cairo.c | 15 +- src/backend/gdi.c | 19 +- src/backend/haiku.cc | 6 +- src/backend/x11.c | 12 +- src/color.c | 4 +- src/dialog/colorpicker.c | 18 +- src/dialog/filechooser.c | 14 +- src/dialog/messagebox.c | 6 +- src/draw.c | 325 +++++++++++++++++++---------------- src/lowlevel.c | 6 +- src/text/font/boldfont.c | 2 +- src/text/font/font.c | 2 +- src/text/ft2.c | 12 +- src/text/gdi.c | 14 +- src/text/stbtt.c | 12 +- src/text/text.c | 60 +++---- src/widget/box.c | 6 +- src/widget/button.c | 32 ++-- src/widget/calendar.c | 50 +++--- src/widget/chart.c | 94 +++++----- src/widget/checkbox.c | 20 +-- src/widget/clock.c | 52 +++--- src/widget/combobox.c | 8 +- src/widget/document.c | 10 +- src/widget/entry.c | 12 +- src/widget/frame.c | 14 +- src/widget/image.c | 18 +- src/widget/label.c | 88 +++++----- src/widget/listbox.c | 36 ++-- src/widget/menu.c | 8 +- src/widget/numberentry.c | 14 +- src/widget/opengl.c | 4 +- src/widget/progressbar.c | 16 +- src/widget/radiobox.c | 24 +-- src/widget/scrollbar.c | 14 +- src/widget/separator.c | 6 +- src/widget/submenu.c | 12 +- src/widget/subwindow.c | 74 ++++---- src/widget/tab.c | 30 ++-- src/widget/treeview.c | 54 +++--- src/widget/viewport.c | 6 +- src/widget/window.c | 6 +- tools/color.pl | 6 +- tools/font.c | 2 +- 55 files changed, 753 insertions(+), 668 deletions(-) diff --git a/configure b/configure index f06b38ab9..e52de2993 100755 --- a/configure +++ b/configure @@ -44,7 +44,6 @@ require("./pl/utils.pl"); param_set("classic-theme", 0); param_set("stb-image", 1); -param_set("opengl", 0); param_set("vulkan", 0); param_set("vulkan-string-helper", 1); param_set("shared", 1); @@ -114,9 +113,11 @@ sub def_platform { } if ($target eq "Windows") { param_set("gdi-text", 1); + param_set("opengl", 1); } else { param_set("gdi-text", 0); + param_set("opengl", 0); } } diff --git a/include/Mw/BaseTypes.h b/include/Mw/BaseTypes.h index 313215eca..c74b8fadc 100644 --- a/include/Mw/BaseTypes.h +++ b/include/Mw/BaseTypes.h @@ -5,12 +5,12 @@ #ifndef __MW_BASETYPES_H__ #define __MW_BASETYPES_H__ -typedef struct _MwPoint MwPoint; -typedef struct _MwRect MwRect; -typedef struct _MwSizeHints MwSizeHints; -typedef struct _MwFont MwFont; -typedef struct _MwCursor MwCursor; -typedef struct _MwRGB MwRGB; +typedef struct _MwPoint MwPoint; +typedef struct _MwRect MwRect; +typedef struct _MwSizeHints MwSizeHints; +typedef struct _MwFontResource MwFontResource; +typedef struct _MwCursor MwCursor; +typedef struct _MwRGB MwRGB; typedef unsigned char MwBool; #define MwTRUE ((MwBool)1) @@ -98,7 +98,7 @@ struct _MwCursor { unsigned int data[MwCursorDataHeight]; }; -struct _MwFont { +struct _MwFontResource { int left; int top; unsigned char data[16]; diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index aec819844..307fbb26e 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -26,7 +26,7 @@ MWDECL int MWAPI MwGetColorDifference(MwWidget handle); * @param text Color text * @return Color */ -MWDECL MwLLColor MWAPI MwParseColor(MwWidget handle, const char* text); +MWDECL MwColor MWAPI MwParseColor(MwWidget handle, const char* text); /*! * @brief Parses a color text @@ -50,7 +50,7 @@ MWDECL void MWAPI MwColorTableInit(void); * @param b Blue * @return Color */ -MWDECL MwLLColor MWAPI MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b); +MWDECL MwColor MWAPI MwLightenColor(MwWidget handle, MwColor color, int r, int g, int b); /*! * @brief Fix a rectangle @@ -65,7 +65,7 @@ MWDECL void MWAPI MwFixRect(MwRect* rect); * @param rect Rectangle area * @param color Color */ -MWDECL void MWAPI MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); +MWDECL void MWAPI MwDrawRect(MwWidget handle, MwRect* rect, MwColor color); /*! * @brief Draws a rectangle @@ -73,7 +73,7 @@ MWDECL void MWAPI MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); * @param rect Rectangle area * @param color Color */ -MWDECL void MWAPI MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color); +MWDECL void MWAPI MwDrawRectLine(MwWidget handle, MwRect* rect, MwColor color); /*! * @brief Draws a filled rectangle that fades to a darker color @@ -81,7 +81,7 @@ MWDECL void MWAPI MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) * @param rect Rectangle area * @param color Color */ -MWDECL void MWAPI MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color); +MWDECL void MWAPI MwDrawRectFading(MwWidget handle, MwRect* rect, MwColor color); /*! * @brief Draws a frame @@ -91,7 +91,7 @@ MWDECL void MWAPI MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor colo * @param invert Invert the 3D border color or not * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MWAPI MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert); +MWDECL void MWAPI MwDrawFrame(MwWidget handle, MwRect* rect, MwColor color, int invert); /*! * @brief Draws a frame @@ -102,7 +102,7 @@ MWDECL void MWAPI MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, in * @param border Border * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MWAPI MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border); +MWDECL void MWAPI MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwColor color, int invert, int border); /*! * @brief Does the DrawFrame/DrawRect combo used for drawing widget. @@ -112,7 +112,7 @@ MWDECL void MWAPI MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwLLColor * @param invert Invert the 3D border color or not * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MWAPI MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border); +MWDECL void MWAPI MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwColor color, int invert, int border); /*! * @brief Draws a triangle @@ -121,7 +121,7 @@ MWDECL void MWAPI MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor colo * @param color Color * @param invert Invert the 3D border color or not */ -MWDECL void MWAPI MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int direction); +MWDECL void MWAPI MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, int direction); /*! * @brief Draws a frame with specified border width @@ -134,7 +134,7 @@ MWDECL void MWAPI MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, * @param same Same as dark color * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MWAPI MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same); +MWDECL void MWAPI MwDrawFrameEx(MwWidget handle, MwRect* rect, MwColor color, int invert, int border, int diff, int same); /*! * @brief Creates a pixmap from image @@ -142,16 +142,7 @@ MWDECL void MWAPI MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, * @param path Path * @return Pixmap */ -MWDECL MwLLPixmap MWAPI MwLoadImage(MwWidget handle, const char* path); - -/*! - * @brief Get color components - * @param color Color - * @param red Pointer to red color - * @param green Pointer to green color - * @param blue Pointer to blue color - */ -MWDECL void MWAPI MwColorGet(MwLLColor color, int* red, int* green, int* blue); +MWDECL MwPixmap MWAPI MwLoadImage(MwWidget handle, const char* path); /*! * @brief Creates a pixmap from raw data @@ -161,34 +152,82 @@ MWDECL void MWAPI MwColorGet(MwLLColor color, int* red, int* green, int* blue); * @param height Height * @return Pixmap */ -MWDECL MwLLPixmap MWAPI MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height); +MWDECL MwPixmap MWAPI MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height); /*! * @brief Updates a pixmap using raw data * @param pixmap Pixmap to update * @param rgb RGBA data */ -MWDECL void MWAPI MwPixmapReloadRaw(MwLLPixmap pixmap, unsigned char* rgb); +MWDECL void MWAPI MwPixmapReloadRaw(MwPixmap pixmap, unsigned char* rgb); /*! * @brief Gets the raw data of pixmap * @param pixmap Pixmap * @return RGBA data */ -MWDECL unsigned char* MWAPI MwPixmapGetRaw(MwLLPixmap pixmap); +MWDECL unsigned char* MWAPI MwPixmapGetRaw(MwPixmap pixmap); /*! * @brief Gets the size of pixmap * @param pixmap Pixmap * @param rect Size */ -MWDECL void MWAPI MwPixmapGetSize(MwLLPixmap pixmap, MwRect* rect); +MWDECL void MWAPI MwPixmapGetSize(MwPixmap pixmap, MwRect* rect); + +/*! + * @brief Updates the pixmap + * @param pixmap Pixmap + */ +MWDECL void MWAPI MwPixmapUpdate(MwPixmap pixmap); /*! * @brief Destroys the pixmap * @param pixmap Pixmap */ -MWDECL void MWAPI MwDestroyPixmap(MwLLPixmap pixmap); +MWDECL void MWAPI MwDestroyPixmap(MwPixmap pixmap); + +/*! + * @brief Draws the pixmap + * @param handle Handle + * @param rect Size + * @param pixmap Pixmap + */ +MWDECL void MWAPI MwDrawPixmap(MwWidget handle, MwRect* rect, MwPixmap pixmap); + +/*! + * @brief Allocates a color + * @param handle Widget + * @param red Red + * @param green Green + * @param bilue Blue + * @return Color + */ +MWDECL MwColor MWAPI MwAllocColor(MwWidget handle, unsigned int red, unsigned int green, unsigned int blue); + +/*! + * @brief Get color components + * @param color Color + * @param red Pointer to red color + * @param green Pointer to green color + * @param blue Pointer to blue color + */ +MWDECL void MWAPI MwColorGet(MwColor color, int* red, int* green, int* blue); + +/*! + * @brief Update color + * @param color Color + * @param red Pointer to red color + * @param green Pointer to green color + * @param blue Pointer to blue color + */ +MWDECL void MWAPI MwColorUpdate(MwColor c, int r, int g, int b); + +/*! + * @brief Allocates a color + * @param color Color + */ +MWDECL void MWAPI MwFreeColor(MwColor color); /*! * @brief Creates a pixmap from XPM data @@ -196,7 +235,7 @@ MWDECL void MWAPI MwDestroyPixmap(MwLLPixmap pixmap); * @param data Data * @return Pixmap */ -MWDECL MwLLPixmap MWAPI MwLoadXPM(MwWidget handle, char** data); +MWDECL MwPixmap MWAPI MwLoadXPM(MwWidget handle, char** data); /*! * @brief Creates a pixmap from icon data @@ -204,7 +243,7 @@ MWDECL MwLLPixmap MWAPI MwLoadXPM(MwWidget handle, char** data); * @param data Data * @return Pixmap */ -MWDECL MwLLPixmap MWAPI MwLoadIcon(MwWidget handle, MwU32* data); +MWDECL MwPixmap MWAPI MwLoadIcon(MwWidget handle, MwU32* data); /*! * @brief Draws a diamond @@ -213,7 +252,7 @@ MWDECL MwLLPixmap MWAPI MwLoadIcon(MwWidget handle, MwU32* data); * @param color Color * @param invert Invert the 3D border color or not */ -MWDECL void MWAPI MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert); +MWDECL void MWAPI MwDrawDiamond(MwWidget handle, MwRect* rect, MwColor color, int invert); /*! * @brief Draws a circle @@ -224,7 +263,7 @@ MWDECL void MWAPI MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, * @param filled Fill the circle or not * @param outward */ -MWDECL void MWAPI MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor background, int filled); +MWDECL void MWAPI MwDrawCircle(MwWidget handle, MwRect* rect, MwColor color, MwColor background, int filled); /*! * @brief Calculate intersect of 2 rectangles @@ -244,7 +283,7 @@ MWDECL void MwIntersectRect(MwRect* a, const MwRect* b); * @param align Align * @param color Color */ -MWDECL void MWAPI MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int align, MwLLColor color); +MWDECL void MWAPI MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int align, MwColor color); /*! * @brief Calculates a text width @@ -272,7 +311,7 @@ MWDECL int MWAPI MwTextHeight(MwWidget handle, MwFLFont font, const char* text); * @param color Color name * @return Color */ -MWDECL MwLLColor MWAPI MwParseColorName(MwWidget handle, const char* color); +MWDECL MwColor MWAPI MwParseColorName(MwWidget handle, const char* color); /*! * @brief Parses a color name diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 6ae7f2c64..5ef17f688 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -58,8 +58,6 @@ struct _MwLLCommonPixmap { int width; int height; unsigned char* raw; - unsigned char* before_blend; - void* internal; }; #ifdef USE_DBUS @@ -255,7 +253,7 @@ MWDECL void (*MwLLBeginDraw)(MwLL handle); MWDECL void (*MwLLEndDraw)(MwLL handle); MWDECL MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); -MWDECL void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b); +MWDECL void (*MwLLColorUpdate)(MwLLColor c, int r, int g, int b); MWDECL void (*MwLLFreeColor)(MwLLColor color); MWDECL void (*MwLLGetXYWH)(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h); @@ -362,7 +360,7 @@ MWDECL int MwFL_STBTTSetup(void); MWDECL int MwFL_GDISetup(void); #endif -MWDECL int (*MwFLDrawText)(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color); +MWDECL int (*MwFLDrawText)(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwColor color); MWDECL int (*MwFLTextWidth)(MwFLFont ttf, const char* text); MWDECL int (*MwFLTextHeight)(MwFLFont ttf, int count); MWDECL int (*MwFLTextHeightWithText)(MwFLFont ttf, const char* text); diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index d2e247350..a777c2291 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -34,6 +34,7 @@ struct _MwLLGDI { struct _MwLLGDIColor { struct _MwLLCommonColor common; + MwLL handle; HBRUSH brush; }; diff --git a/include/Mw/LowLevel/X11.h b/include/Mw/LowLevel/X11.h index 9663097cb..6467a7f77 100644 --- a/include/Mw/LowLevel/X11.h +++ b/include/Mw/LowLevel/X11.h @@ -88,6 +88,7 @@ struct _MwLLX11 { struct _MwLLX11Color { struct _MwLLCommonColor common; + MwLL handle; unsigned long pixel; }; diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 7313ce2f3..eea67c2c0 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -120,4 +120,11 @@ #define MwInline static __inline +#ifdef __GNUC__ +/* when was this added to gcc? */ +#define MW_DEPRECATE(reason) __attribute__((deprecated((reason)))) +#else +#define MW_DEPRECATE(reason) +#endif + #endif diff --git a/include/Mw/Resource/Font.h b/include/Mw/Resource/Font.h index d178a25b9..744918b19 100644 --- a/include/Mw/Resource/Font.h +++ b/include/Mw/Resource/Font.h @@ -15,12 +15,12 @@ extern "C" { /*! * @brief Default font data */ -MWDECL MwFont MwFontData[]; +MWDECL MwFontResource MwFontData[]; /*! * @brief Default bold font data */ -MWDECL MwFont MwBoldFontData[]; +MWDECL MwFontResource MwBoldFontData[]; /*! * @brief Default TTF font data diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index c9a7575b2..bbd9a5811 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -38,8 +38,14 @@ typedef struct _MwDocument* MwDocument; typedef struct _MwMouse MwMouse; typedef struct _MwTTFInfo* MwTTFInfo; #ifdef _MILSKO +typedef struct _MwPixmap* MwPixmap; +typedef struct _MwColor* MwColor; +typedef struct _MwFont* MwFont; typedef struct _MwWidget* MwWidget; #else +typedef void* MwPixmap; +typedef void* MwColor; +typedef void* MwFont; typedef void* MwWidget; #endif typedef void (*MwHandler)(MwWidget handle); @@ -84,9 +90,26 @@ struct _MwVoidKeyValue { #include #ifdef _MILSKO +struct _MwPixmap { + MwLLPixmap lowlevel; + MwLLCommonPixmap common; + + MwWidget handle; + unsigned char* raw; +}; + +struct _MwColor { + MwLLColor lowlevel; + MwLLCommonColor common; +}; + +struct _MwFont { + MwFLFont lowlevel; +}; + struct _MwWidget { - char* name; - MwLLColor bgcolor; + char* name; + MwColor bgcolor; MwLL lowlevel; MwWidget parent; @@ -106,7 +129,7 @@ struct _MwWidget { MwHandler destroy_inject; MwHandlerProp prop_inject_pixmap; /* this is for pixmap; do not use */ - MwLLPixmap* pixmaps; + MwPixmap* pixmaps; MwIntegerKeyValue* integer; MwTextKeyValue* text; @@ -163,8 +186,8 @@ struct _MwViewport { }; struct _MwListBoxEntry { - char** name; - MwLLPixmap pixmap; + char** name; + MwPixmap pixmap; }; struct _MwListBox { @@ -186,7 +209,7 @@ struct _MwComboBox { struct _MwTreeViewEntry { char* label; - MwLLPixmap pixmap; + MwPixmap pixmap; MwTreeViewEntry** tree; int opened; int selected; diff --git a/include/Mw/Widget/ListBox.h b/include/Mw/Widget/ListBox.h index f4fe48f46..4e06177c1 100644 --- a/include/Mw/Widget/ListBox.h +++ b/include/Mw/Widget/ListBox.h @@ -40,7 +40,7 @@ MwInline int MwListBoxSet(MwWidget handle, int row, int col, const char* text) { * @param index Index * @param icon Icon */ -MwInline void MwListBoxSetIcon(MwWidget handle, int index, MwLLPixmap icon) { +MwInline void MwListBoxSetIcon(MwWidget handle, int index, MwPixmap icon) { MwVaWidgetExecute(handle, "mwListBoxSetIcon", NULL, index, icon); } diff --git a/include/Mw/Widget/TreeView.h b/include/Mw/Widget/TreeView.h index f76f6af0a..0720071be 100644 --- a/include/Mw/Widget/TreeView.h +++ b/include/Mw/Widget/TreeView.h @@ -25,7 +25,7 @@ MWDECL MwClass MwTreeViewClass; * @parma pixmap Pixmap * @param item Item */ -MwInline void* MwTreeViewAdd(MwWidget handle, void* parent, MwLLPixmap pixmap, const char* item) { +MwInline void* MwTreeViewAdd(MwWidget handle, void* parent, MwPixmap pixmap, const char* item) { void* out; MwVaWidgetExecute(handle, "mwTreeViewAdd", &out, parent, pixmap, item); return out; @@ -76,7 +76,7 @@ MwInline void MwTreeViewSetLabel(MwWidget handle, void* item, const char* label) * @param item Item * @param pixmap Pixmap */ -MwInline void MwTreeViewSetPixmap(MwWidget handle, void* item, MwLLPixmap pixmap) { +MwInline void MwTreeViewSetPixmap(MwWidget handle, void* item, MwPixmap pixmap) { MwVaWidgetExecute(handle, "mwTreeViewSetPixmap", NULL, item, pixmap); } diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 6764f6ffd..02ed9d0a6 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -46,12 +46,10 @@ MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, if(width >= INT16_MAX) width = INT16_MAX; if(height >= INT16_MAX) height = INT16_MAX; - r->common.width = width; - r->common.height = height; - r->common.raw = malloc(4 * width * height); - r->common.before_blend = malloc(4 * width * height); + r->common.width = width; + r->common.height = height; + r->common.raw = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); - memcpy(r->common.before_blend, data, 4 * width * height); r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); @@ -82,7 +80,6 @@ void MwLLCairoPixmapUpdate(MwLLPixmap r) { void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) { cairo_surface_destroy(pixmap->wayland.cs); - free(pixmap->common.before_blend); free(pixmap->common.raw); free(pixmap); } @@ -192,13 +189,11 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { MwLLColor c = malloc(sizeof(*c)); - MwLLColorUpdate(handle, c, r, g, b); + MwLLColorUpdate(c, r, g, b); return c; } -static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; - +static void MwLLColorUpdateImpl(MwLLColor c, int r, int g, int b) { c->common.red = r; c->common.green = g; c->common.blue = b; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 65432d947..bd880f922 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -532,15 +532,17 @@ static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { return NULL; } - c->gdi.brush = NULL; + c->gdi.handle = handle; + c->gdi.brush = NULL; - MwLLColorUpdate(handle, c, r, g, b); + MwLLColorUpdate(c, r, g, b); return c; } -static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - HDC dc = GetDC(handle->gdi.hWnd); +static void MwLLColorUpdateImpl(MwLLColor c, int r, int g, int b) { + MwLL handle = c->gdi.handle; + HDC dc = GetDC(handle->gdi.hWnd); COLORREF color; if(r > 255) r = 255; @@ -665,14 +667,6 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid memcpy(r->common.raw, data, 4 * width * height); - r->common.before_blend = malloc(width * height * 4); - if(!r->common.before_blend) { - printf("Out Of Memory\n"); - return NULL; - } - - memcpy(r->common.before_blend, data, 4 * width * height); - r->common.width = width; r->common.height = height; @@ -748,7 +742,6 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - free(pixmap->common.before_blend); free(pixmap->common.raw); DeleteObject(pixmap->gdi.hMask); DeleteObject(pixmap->gdi.hMask2); diff --git a/src/backend/haiku.cc b/src/backend/haiku.cc index 2c796d60f..488480d8f 100644 --- a/src/backend/haiku.cc +++ b/src/backend/haiku.cc @@ -589,14 +589,12 @@ static void MwLLEndDrawImpl(MwLL handle) { static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { MwLLColor c = (MwLLColor)malloc(sizeof(*c)); - MwLLColorUpdate(handle, c, r, g, b); + MwLLColorUpdate(c, r, g, b); return c; } -static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; - +static void MwLLColorUpdateImpl(MwLLColor c, int r, int g, int b) { c->common.red = r; c->common.green = g; c->common.blue = b; diff --git a/src/backend/x11.c b/src/backend/x11.c index e44b3a153..edd5eee48 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -549,13 +549,15 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { - MwLLColor c = malloc(sizeof(*c)); - MwLLColorUpdate(handle, c, r, g, b); + MwLLColor c = malloc(sizeof(*c)); + c->x11.handle = handle; + MwLLColorUpdate(c, r, g, b); return c; } -static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { +static void MwLLColorUpdateImpl(MwLLColor c, int r, int g, int b) { XColor xc; + MwLL handle = c->x11.handle; if(handle->x11.red_mask == 0) { if(r > 255) r = 255; @@ -1097,9 +1099,6 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid r->common.raw = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); - r->common.before_blend = malloc(4 * width * height); - memcpy(r->common.before_blend, data, 4 * width * height); - XGetWindowAttributes(handle->x11.display, handle->x11.window, &attr); r->common.width = width; @@ -1155,7 +1154,6 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - free(pixmap->common.before_blend); free(pixmap->common.raw); XDestroyImage(pixmap->x11.image); XDestroyImage(pixmap->x11.mask); diff --git a/src/color.c b/src/color.c index ae3667ed5..aff50dba2 100644 --- a/src/color.c +++ b/src/color.c @@ -9,10 +9,10 @@ struct color { static struct color* colors = NULL; -MwLLColor MwParseColorName(MwWidget handle, const char* color) { +MwColor MwParseColorName(MwWidget handle, const char* color) { MwRGB rgb; MwParseColorNameNoAllocate(color, &rgb); - return MwLLAllocColor(handle->lowlevel, rgb.red, rgb.green, rgb.blue); + return MwAllocColor(handle, rgb.red, rgb.green, rgb.blue); } void MwParseColorNameNoAllocate(const char* color, MwRGB* rgb) { diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 2019f202a..8e5804946 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -31,7 +31,7 @@ typedef struct color_picker { MwWidget value_slider; MwWidget color_display_text; MwWidget finish; - MwLLPixmap color_picker_pixmap; + MwPixmap color_picker_pixmap; double value; MwRGB chosen_color; unsigned char color_picker_image_data[PICKER_SIZE * PICKER_SIZE * 4]; @@ -239,7 +239,7 @@ static void MWAPI color_display_text_change(MwWidget handle, void* user, color_picker_t* picker = user; char hexColor[9]; char fgColor[9]; - MwLLColor color; + MwColor color; int fr, fg, fb; (void)call; @@ -248,9 +248,9 @@ static void MWAPI color_display_text_change(MwWidget handle, void* user, color = MwParseColor(handle, hexColor); - fr = color->common.red > 128 ? 0 : 255; - fg = color->common.green > 128 ? 0 : 255; - fb = color->common.blue > 128 ? 0 : 255; + fr = color->common->red > 128 ? 0 : 255; + fg = color->common->green > 128 ? 0 : 255; + fb = color->common->blue > 128 ? 0 : 255; MwStringPrintIntoBuffer(fgColor, 9, "#%02X%02X%02X", fr, fg, fb); MwSetText(picker->color_display_text, MwNforeground, fgColor); @@ -258,11 +258,11 @@ static void MWAPI color_display_text_change(MwWidget handle, void* user, MwSetText(picker->color_display_text, MwNbackground, hexColor); MwSetText(picker->color_display_text, MwNtext, hexColor); - picker->chosen_color.red = color->common.red; - picker->chosen_color.green = color->common.green; - picker->chosen_color.blue = color->common.blue; + picker->chosen_color.red = color->common->red; + picker->chosen_color.green = color->common->green; + picker->chosen_color.blue = color->common->blue; - MwLLFreeColor(color); + MwFreeColor(color); } static void MWAPI color_picker_finish(MwWidget handle, void* user, diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index e7f1e28f1..59666c64d 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -22,12 +22,12 @@ typedef struct filechooser { MwWidget okay; MwWidget cancel; - MwLLPixmap dir; - MwLLPixmap file; - MwLLPixmap back; - MwLLPixmap forward; - MwLLPixmap up; - MwLLPixmap computer; + MwPixmap dir; + MwPixmap file; + MwPixmap back; + MwPixmap forward; + MwPixmap up; + MwPixmap computer; } filechooser_t; static void scan(MwWidget handle, const char* path, int record); @@ -506,7 +506,7 @@ static void scan(MwWidget handle, const char* path, int record) { static void setup_fallback_filechooser(MwWidget window, int dir) { char* path; - MwLLPixmap icon; + MwPixmap icon; filechooser_t* fc = malloc(sizeof(*fc)); memset(fc, 0, sizeof(*fc)); diff --git a/src/dialog/messagebox.c b/src/dialog/messagebox.c index d536f10f8..4a319ff14 100644 --- a/src/dialog/messagebox.c +++ b/src/dialog/messagebox.c @@ -68,9 +68,9 @@ MwWidget MwMessageBox(MwWidget handle, const char* text, const char* title, unsi if(flag & MwMB_BUTTONYES) spawn_button(window, w - (x += 8 + 80), h - 8 - 24, MwMB_BUTTONYES, "Yes"); if((flag & MwMB_ICONMASK) != 0) { - MwWidget icon; - MwLLPixmap px; - MwU32* data = NULL; + MwWidget icon; + MwPixmap px; + MwU32* data = NULL; icon = MwCreateWidget(MwImageClass, "image", window, 8, (h - 48) / 2, 48, 48); diff --git a/src/draw.c b/src/draw.c index 7c8fb0e8e..da6e28e37 100644 --- a/src/draw.c +++ b/src/draw.c @@ -38,19 +38,19 @@ static int hex(const char* txt, int len) { return r; } -static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { +static void color_set_disabled_if_disabled(MwWidget handle, MwColor rgb) { int n; if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { - MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { - rgb->common.red = (MwU8)(rgb->common.red + (c->common.red - rgb->common.red) * 0.5); - rgb->common.green = (MwU8)(rgb->common.green + (c->common.green - rgb->common.green) * 0.5); - rgb->common.blue = (MwU8)(rgb->common.blue + (c->common.blue - rgb->common.blue) * 0.5); - MwLLColorUpdate(handle->lowlevel, rgb, rgb->common.red, rgb->common.green, rgb->common.blue); + rgb->common->red = (MwU8)(rgb->common->red + (c->common->red - rgb->common->red) * 0.5); + rgb->common->green = (MwU8)(rgb->common->green + (c->common->green - rgb->common->green) * 0.5); + rgb->common->blue = (MwU8)(rgb->common->blue + (c->common->blue - rgb->common->blue) * 0.5); + MwColorUpdate(rgb, rgb->common->red, rgb->common->green, rgb->common->blue); - MwLLFreeColor(c); + MwFreeColor(c); } } }; @@ -74,7 +74,7 @@ void MwParseColorNoAllocate(const char* text, MwRGB* rgb) { } } -MwLLColor MwParseColor(MwWidget handle, const char* text) { +MwColor MwParseColor(MwWidget handle, const char* text) { MwRGB rgb; rgb.red = 0; @@ -83,13 +83,13 @@ MwLLColor MwParseColor(MwWidget handle, const char* text) { MwParseColorNoAllocate(text, &rgb); - return MwLLAllocColor(handle->lowlevel, rgb.red, rgb.green, rgb.blue); + return MwAllocColor(handle, rgb.red, rgb.green, rgb.blue); } -MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) { - int cr = color->common.red + r; - int cg = color->common.green + g; - int cb = color->common.blue + b; +MwColor MwLightenColor(MwWidget handle, MwColor color, int r, int g, int b) { + int cr = color->common->red + r; + int cg = color->common->green + g; + int cb = color->common->blue + b; if(cr < 0) cr = 0; if(cg < 0) cg = 0; @@ -98,7 +98,7 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) if(cg > 255) cg = 255; if(cb > 255) cb = 255; - return MwLLAllocColor(handle->lowlevel, cr, cg, cb); + return MwAllocColor(handle, cr, cg, cb); } void MwFixRect(MwRect* rect) { @@ -113,7 +113,7 @@ void MwFixRect(MwRect* rect) { } } -void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { +void MwDrawRect(MwWidget handle, MwRect* rect, MwColor color) { MwPoint p[4]; MwRect r = *rect; @@ -131,10 +131,10 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { p[3].x = r.x; p[3].y = r.y + r.height; - MwLLPolygon(handle->lowlevel, p, 4, color); + MwLLPolygon(handle->lowlevel, p, 4, color->lowlevel); } -void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) { +void MwDrawRectLine(MwWidget handle, MwRect* rect, MwColor color) { MwPoint p[5]; MwRect r = *rect; @@ -154,13 +154,13 @@ void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) { p[4] = p[0]; - MwLLLine(handle->lowlevel, &p[0], color); - MwLLLine(handle->lowlevel, &p[1], color); - MwLLLine(handle->lowlevel, &p[2], color); - MwLLLine(handle->lowlevel, &p[3], color); + MwLLLine(handle->lowlevel, &p[0], color->lowlevel); + MwLLLine(handle->lowlevel, &p[1], color->lowlevel); + MwLLLine(handle->lowlevel, &p[2], color->lowlevel); + MwLLLine(handle->lowlevel, &p[3], color->lowlevel); } -void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { +void MwDrawRectFading(MwWidget handle, MwRect* rect, MwColor color) { MwLLPixmap pixmap; int y; double darken = 0.; @@ -184,14 +184,14 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { r.height -= 2; for(y = 0; y < rect->height; y++) { - MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); - int idx = y * 4; + MwColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); + int idx = y * 4; color_set_disabled_if_disabled(handle, col); - data[idx] = col->common.red; - data[idx + 1] = col->common.green; - data[idx + 2] = col->common.blue; + data[idx] = col->common->red; + data[idx + 1] = col->common->green; + data[idx + 2] = col->common->blue; data[idx + 3] = 255; - MwLLFreeColor(col); + MwFreeColor(col); darken += darkenStep; } @@ -202,7 +202,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { free(data); } -void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { +void MwDrawFrame(MwWidget handle, MwRect* rect, MwColor color, int invert) { MwDrawFrameWithBorder(handle, rect, color, invert, MwDefaultBorderWidth(handle)); } @@ -212,7 +212,7 @@ static int translate_border(MwWidget handle, int border) { return border; } -void MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { +void MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwColor color, int invert, int border) { int inv; border = translate_border(handle, border); @@ -236,18 +236,18 @@ void MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwLLColor color, int i } } -void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { - MwLLColor col; +void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwColor color, int invert, int border) { + MwColor col; if(rect->width <= 0 || rect->height <= 0) return; if(border) { if(!handle->lowlevel->common.supports_transparency) { - MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { MwDrawRect(handle, rect, c); - MwLLFreeColor(c); + MwFreeColor(c); } } @@ -273,16 +273,16 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert } else { MwDrawRect(handle, rect, col); } - MwLLFreeColor(col); + MwFreeColor(col); } -void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { - MwPoint p[6]; - int border = MwDefaultBorderWidth(handle); - int ColorDiff = MwGetColorDifference(handle) + (MwGetInteger(handle, MwNmodernLook) ? 48 : 0); - MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); - MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); +void MwDrawDiamond(MwWidget handle, MwRect* rect, MwColor color, int invert) { + MwPoint p[6]; + int border = MwDefaultBorderWidth(handle); + int ColorDiff = MwGetColorDifference(handle) + (MwGetInteger(handle, MwNmodernLook) ? 48 : 0); + MwColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); color_set_disabled_if_disabled(handle, col); color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); @@ -305,7 +305,7 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { p[5].x = rect->x + border; p[5].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); + MwLLPolygon(handle->lowlevel, p, 6, (invert ? darker : lighter)->lowlevel); p[0].x = rect->x; p[0].y = rect->y + rect->height / 2; @@ -325,7 +325,7 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { p[5].x = rect->x + border; p[5].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); p[0].x = rect->x + rect->width / 2; p[0].y = rect->y + border; @@ -339,14 +339,14 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { p[3].x = rect->x + border; p[3].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p, 4, col); + MwLLPolygon(handle->lowlevel, p, 4, col->lowlevel); - MwLLFreeColor(col); - MwLLFreeColor(lighter); - MwLLFreeColor(darker); + MwFreeColor(col); + MwFreeColor(lighter); + MwFreeColor(darker); } -void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor background, int filled) { +void MwDrawCircle(MwWidget handle, MwRect* rect, MwColor color, MwColor background, int filled) { MwLLPixmap pixmap; int width = rect->width; int height = rect->height; @@ -356,9 +356,9 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back int border; int x, y; int ColorDiff = (MwGetColorDifference(handle)); - MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); - MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - MwLLColor base = MwLightenColor(handle, color, 0, 0, 0); + MwColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwColor base = MwLightenColor(handle, color, 0, 0, 0); color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); @@ -394,8 +394,8 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back } if(inside) { - MwLLColor mixColor; - MwLLColor c = background ? background : (handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground))); + MwColor mixColor; + MwColor c = background ? background : (handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground))); double mod; unsigned char* pout = &data[(y * width + x) * 4]; @@ -413,23 +413,23 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back color_set_disabled_if_disabled(handle, mixColor); if(c != NULL) { - mixColor->common.red = (MwU8)(mixColor->common.red + (c->common.red - mixColor->common.red) * mod); - mixColor->common.green = (MwU8)(mixColor->common.green + (c->common.green - mixColor->common.green) * mod); - mixColor->common.blue = (MwU8)(mixColor->common.blue + (c->common.blue - mixColor->common.blue) * mod); - MwLLColorUpdate(handle->lowlevel, mixColor, mixColor->common.red, mixColor->common.green, mixColor->common.blue); + mixColor->common->red = (MwU8)(mixColor->common->red + (c->common->red - mixColor->common->red) * mod); + mixColor->common->green = (MwU8)(mixColor->common->green + (c->common->green - mixColor->common->green) * mod); + mixColor->common->blue = (MwU8)(mixColor->common->blue + (c->common->blue - mixColor->common->blue) * mod); + MwColorUpdate(mixColor, mixColor->common->red, mixColor->common->green, mixColor->common->blue); if(c != background) { - MwLLFreeColor(c); + MwFreeColor(c); } } - pout[0] = (MwU8)mixColor->common.red; - pout[1] = (MwU8)mixColor->common.green; - pout[2] = (MwU8)mixColor->common.blue; + pout[0] = (MwU8)mixColor->common->red; + pout[1] = (MwU8)mixColor->common->green; + pout[2] = (MwU8)mixColor->common->blue; pout[3] = 255; - MwLLFreeColor(mixColor); + MwFreeColor(mixColor); } } } @@ -438,18 +438,18 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back MwLLDrawPixmap(handle->lowlevel, rect, pixmap); MwLLDestroyPixmap(pixmap); - MwLLFreeColor(lighter); - MwLLFreeColor(darker); - MwLLFreeColor(base); + MwFreeColor(lighter); + MwFreeColor(darker); + MwFreeColor(base); free(data); }; -static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { - MwPoint p[7]; - int ColorDiff = MwGetColorDifference(handle); - MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); - MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, ColorDiff - diff, ColorDiff - diff, ColorDiff - diff); +static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwColor color, int invert, int border, int diff, int same) { + MwPoint p[7]; + int ColorDiff = MwGetColorDifference(handle); + MwColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); + MwColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, ColorDiff - diff, ColorDiff - diff, ColorDiff - diff); color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); @@ -469,7 +469,7 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, p[5].x = rect->x; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); + MwLLPolygon(handle->lowlevel, p, 6, (invert ? darker : lighter)->lowlevel); p[0].x = rect->x + rect->width; p[0].y = rect->y; @@ -488,10 +488,10 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, p[5].x = rect->x + rect->width; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); - MwLLFreeColor(lighter); - MwLLFreeColor(darker); + MwFreeColor(lighter); + MwFreeColor(darker); rect->x += border; rect->y += border; @@ -499,7 +499,7 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, rect->height -= border * 2; } -static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { +static void frame_border_complex(MwWidget handle, MwRect* rect, MwColor lighter, MwColor darker, int invert, int border, int diff, int same) { MwPoint p[7]; (void)diff; @@ -521,7 +521,7 @@ static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighte p[5].x = rect->x; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); p[0].x = rect->x + rect->width; p[0].y = rect->y; @@ -540,14 +540,14 @@ static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighte p[5].x = rect->x + rect->width; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); } -static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { - int ColorDiff = MwGetColorDifference(handle); - MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); - MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); - MwRect r = *rect; +static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwColor color, int invert, int border, int diff, int same) { + int ColorDiff = MwGetColorDifference(handle); + MwColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); + MwColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); + MwRect r = *rect; color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); @@ -562,8 +562,8 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same); } - MwLLFreeColor(lighter); - MwLLFreeColor(darker); + MwFreeColor(lighter); + MwFreeColor(darker); rect->x += border; rect->y += border; @@ -571,7 +571,7 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color rect->height -= border * 2; } -void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { +void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwColor color, int invert, int border, int diff, int same) { border = translate_border(handle, border); if(MwGetInteger(handle, MwNmodernLook)) { @@ -581,13 +581,13 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i } } -void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int direction) { +void MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, int direction) { MwPoint p1[4], p2[4], p3[4], p4[3]; const int border = MwGetInteger(handle, MwNmodernLook) ? 2 : MwDefaultBorderWidth(handle); int ColorDiff = MwGetColorDifference(handle); - MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); - MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); + MwColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); double deg = 30 * ((direction == MwEAST || direction == MwWEST) ? 2 : 1); double c = cos(deg / 180 * M_PI); double s = sin(deg / 180 * M_PI); @@ -633,9 +633,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[3].x = (int)(rect->x + rect->width - c * border); p3[3].y = (int)(rect->y + rect->height - s * border); - MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); - MwLLPolygon(handle->lowlevel, p2, 4, invert ? lighter : darker); - MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); + MwLLPolygon(handle->lowlevel, p2, 4, (invert ? lighter : darker)->lowlevel); + MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); p4[0].x = (int)(rect->x + c * border); p4[0].y = (int)(rect->y + rect->height - s * border); @@ -682,9 +682,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[3].x = (int)(rect->x + rect->width - c * border); p3[3].y = (int)(rect->y + s * border); - MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); - MwLLPolygon(handle->lowlevel, p2, 4, invert ? darker : lighter); - MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); + MwLLPolygon(handle->lowlevel, p2, 4, (invert ? darker : lighter)->lowlevel); + MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); p4[0].x = (int)(rect->x + c * border); p4[0].y = (int)(rect->y + s * border); @@ -731,9 +731,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[3].x = (int)(rect->x + rect->width - border); p3[3].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); - MwLLPolygon(handle->lowlevel, p2, 4, invert ? darker : lighter); - MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); + MwLLPolygon(handle->lowlevel, p2, 4, (invert ? darker : lighter)->lowlevel); + MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); p4[0].x = (int)(rect->x + rect->width - border); p4[0].y = rect->y + rect->height / 2; @@ -780,9 +780,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[3].x = rect->x + rect->width; p3[3].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); - MwLLPolygon(handle->lowlevel, p2, 4, invert ? lighter : darker); - MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); + MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); + MwLLPolygon(handle->lowlevel, p2, 4, (invert ? lighter : darker)->lowlevel); + MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); p4[0].x = (int)(rect->x + border); p4[0].y = rect->y + rect->height / 2; @@ -793,11 +793,11 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p4[2].x = (int)(rect->x + rect->width - c * border); p4[2].y = (int)(rect->y + s * border); } - MwLLPolygon(handle->lowlevel, p4, 3, col); + MwLLPolygon(handle->lowlevel, p4, 3, col->lowlevel); - MwLLFreeColor(col); - MwLLFreeColor(lighter); - MwLLFreeColor(darker); + MwFreeColor(col); + MwFreeColor(lighter); + MwFreeColor(darker); } #if defined(NO_IMAGE) @@ -939,10 +939,10 @@ static unsigned char* load_image(const char* path, int* w, int* h) { #endif } -MwLLPixmap MwLoadImage(MwWidget handle, const char* path) { +MwPixmap MwLoadImage(MwWidget handle, const char* path) { int width, height; unsigned char* rgb = load_image(path, &width, &height); - MwLLPixmap px; + MwPixmap px; if(rgb == NULL) return NULL; @@ -961,10 +961,15 @@ static void pixmap_prop(MwWidget handle, const char* prop) { } } -MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) { - MwLLPixmap px = MwLLCreatePixmap(handle->lowlevel, rgb, width, height); +MwPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) { + MwPixmap px = malloc(sizeof(*px)); + + px->lowlevel = MwLLCreatePixmap(handle->lowlevel, rgb, width, height); + px->common = &px->lowlevel->common; + px->handle = handle; + px->raw = malloc(width * height * 4); + memcpy(px->raw, rgb, width * height * 4); - px->common.internal = handle; MwPixmapReloadRaw(px, rgb); handle->prop_inject_pixmap = pixmap_prop; @@ -974,17 +979,17 @@ MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) return px; } -void MwPixmapReloadRaw(MwLLPixmap px, unsigned char* rgb) { - int i; - MwWidget handle = px->common.internal; - MwLLColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor; +void MwPixmapReloadRaw(MwPixmap px, unsigned char* rgb) { + int i; + MwWidget handle = px->handle; + MwColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor; - if(rgb != NULL) memcpy(px->common.before_blend, rgb, px->common.width * px->common.height * 4); + if(rgb != NULL) memcpy(px->raw, rgb, px->common->width * px->common->height * 4); - memset(px->common.raw, 0, px->common.width * px->common.height * 4); - for(i = 0; i < px->common.width * px->common.height; i++) { - unsigned char* pin = &px->common.before_blend[i * 4]; - unsigned char* pout = &px->common.raw[i * 4]; + memset(px->common->raw, 0, px->common->width * px->common->height * 4); + for(i = 0; i < px->common->width * px->common->height; i++) { + unsigned char* pin = &px->raw[i * 4]; + unsigned char* pout = &px->common->raw[i * 4]; double a = pin[3]; a /= 255; @@ -996,30 +1001,34 @@ void MwPixmapReloadRaw(MwLLPixmap px, unsigned char* rgb) { pout[1] = (unsigned char)(pin[1] * a); pout[2] = (unsigned char)(pin[2] * a); - pout[0] += (unsigned char)(base->common.red * (1 - a)); - pout[1] += (unsigned char)(base->common.green * (1 - a)); - pout[2] += (unsigned char)(base->common.blue * (1 - a)); + pout[0] += (unsigned char)(base->common->red * (1 - a)); + pout[1] += (unsigned char)(base->common->green * (1 - a)); + pout[2] += (unsigned char)(base->common->blue * (1 - a)); pout[3] = 255; } } - if(handle->bgcolor == NULL) MwLLFreeColor(base); + if(handle->bgcolor == NULL) MwFreeColor(base); - MwLLPixmapUpdate(px); + MwPixmapUpdate(px); } -unsigned char* MwPixmapGetRaw(MwLLPixmap pixmap) { - return pixmap->common.raw; +unsigned char* MwPixmapGetRaw(MwPixmap pixmap) { + return pixmap->common->raw; } -void MwPixmapGetSize(MwLLPixmap pixmap, MwRect* rect) { - rect->width = pixmap->common.width; - rect->height = pixmap->common.height; +void MwPixmapGetSize(MwPixmap pixmap, MwRect* rect) { + rect->width = pixmap->common->width; + rect->height = pixmap->common->height; } -void MwDestroyPixmap(MwLLPixmap pixmap) { +void MwPixmapUpdate(MwPixmap pixmap) { + MwLLPixmapUpdate(pixmap->lowlevel); +} + +void MwDestroyPixmap(MwPixmap pixmap) { int i; - MwWidget handle = pixmap->common.internal; + MwWidget handle = pixmap->handle; for(i = 0; i < arrlen(handle->pixmaps); i++) { if(handle->pixmaps[i] == pixmap) { @@ -1030,20 +1039,44 @@ void MwDestroyPixmap(MwLLPixmap pixmap) { if(arrlen(handle->pixmaps) == 0) handle->prop_inject_pixmap = NULL; - MwLLDestroyPixmap(pixmap); + MwLLDestroyPixmap(pixmap->lowlevel); + free(pixmap->raw); + free(pixmap); } -void MwColorGet(MwLLColor color, int* red, int* green, int* blue) { - *red = color->common.red; - *green = color->common.green; - *blue = color->common.blue; +void MwDrawPixmap(MwWidget handle, MwRect* rect, MwPixmap pixmap) { + MwLLDrawPixmap(handle->lowlevel, rect, pixmap->lowlevel); } -MwLLPixmap MwLoadIcon(MwWidget handle, MwU32* data) { +MwColor MwAllocColor(MwWidget handle, unsigned int red, unsigned int green, unsigned int blue) { + MwColor color = malloc(sizeof(*color)); + + color->lowlevel = MwLLAllocColor(handle->lowlevel, red, green, blue); + color->common = &color->lowlevel->common; + + return color; +} + +void MwColorGet(MwColor color, int* red, int* green, int* blue) { + *red = color->common->red; + *green = color->common->green; + *blue = color->common->blue; +} + +void MwColorUpdate(MwColor c, int r, int g, int b) { + MwLLColorUpdate(c->lowlevel, r, g, b); +} + +void MwFreeColor(MwColor color) { + MwLLFreeColor(color->lowlevel); + free(color); +} + +MwPixmap MwLoadIcon(MwWidget handle, MwU32* data) { int width = (data[0] >> 16) & 0xffff; int height = (data[0]) & 0xffff; unsigned char* rgba = malloc(width * height * 4); - MwLLPixmap px; + MwPixmap px; int i; if(!rgba) { @@ -1078,10 +1111,10 @@ typedef struct color { int a; } color_t; -MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { +MwPixmap MwLoadXPM(MwWidget handle, char** data) { int col, row, colors, cpp; unsigned char* rgb; - MwLLPixmap px; + MwPixmap px; color_t* c = NULL; int i, y, x; char* comp; @@ -1110,7 +1143,7 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { c[ind].b = 0; c[ind].a = 0; } else { - MwLLColor color = MwParseColor(handle, v); + MwColor color = MwParseColor(handle, v); memcpy(k, data[i + 1], cpp); k[cpp] = 0; @@ -1118,12 +1151,12 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { shput(c, k, v); ind = shgeti(c, k); - c[ind].r = color->common.red; - c[ind].g = color->common.green; - c[ind].b = color->common.blue; + c[ind].r = color->common->red; + c[ind].g = color->common->green; + c[ind].b = color->common->blue; c[ind].a = 255; - MwLLFreeColor(color); + MwFreeColor(color); } } diff --git a/src/lowlevel.c b/src/lowlevel.c index 32070d9e0..d676310a8 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -15,9 +15,9 @@ void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color) = NULL; void (*MwLLBeginDraw)(MwLL handle) = NULL; void (*MwLLEndDraw)(MwLL handle) = NULL; -MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b) = NULL; -void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b) = NULL; -void (*MwLLFreeColor)(MwLLColor color) = NULL; +MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b) = NULL; +void (*MwLLColorUpdate)(MwLLColor c, int r, int g, int b) = NULL; +void (*MwLLFreeColor)(MwLLColor color) = NULL; void (*MwLLGetXYWH)(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) = NULL; void (*MwLLSetXY)(MwLL handle, int x, int y) = NULL; diff --git a/src/text/font/boldfont.c b/src/text/font/boldfont.c index b021adaf8..cca080ab7 100644 --- a/src/text/font/boldfont.c +++ b/src/text/font/boldfont.c @@ -4,7 +4,7 @@ * Copyright notice: * "Public domain font. Share and enjoy." */ -MwFont MwBoldFontData[] = { +MwFontResource MwBoldFontData[] = { {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 0 */ {0, 11, {0, 0, 0, 0, 0, 24, 60, 126, 60, 24, 0, 0, 0}}, /* 1 */ {0, 11, {0, 102, 24, 102, 24, 102, 24, 102, 24, 102, 24, 102, 0}}, /* 2 */ diff --git a/src/text/font/font.c b/src/text/font/font.c index 039db2619..7d8fc4daa 100644 --- a/src/text/font/font.c +++ b/src/text/font/font.c @@ -4,7 +4,7 @@ * Copyright notice: * "(null)" */ -MwFont MwFontData[] = { +MwFontResource MwFontData[] = { {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 0 */ {0, 11, {0, 0, 0, 0, 0, 16, 56, 124, 56, 16, 0, 0, 0}}, /* 1 */ {0, 11, {0, 84, 42, 84, 42, 84, 42, 84, 42, 84, 42, 84, 42}}, /* 2 */ diff --git a/src/text/ft2.c b/src/text/ft2.c index 10cd1ad02..b5c80bfde 100644 --- a/src/text/ft2.c +++ b/src/text/ft2.c @@ -33,10 +33,10 @@ struct _MwFLFont { void* data; int px; }; -static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color) { +static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwColor color) { int tw, th; unsigned char* px; - MwLLPixmap p; + MwPixmap p; MwRect r; int x = 0, y = 0; @@ -62,9 +62,9 @@ static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c int ox = x + cx + ttf->face->glyph->bitmap_left; int oy = y + (ttf->face->height * ttf->px / ttf->face->units_per_EM) - ttf->face->glyph->bitmap_top + cy + (ttf->face->descender * ttf->px / ttf->face->units_per_EM); unsigned char* opx = &px[(oy * tw + ox) * 4]; - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; + opx[0] = color->common->red; + opx[1] = color->common->green; + opx[2] = color->common->blue; /* overflow check */ if(opx[3] + bmp->buffer[cy * bmp->pitch + cx] < opx[3]) { opx[3] = 255; @@ -92,7 +92,7 @@ static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c r.width = tw; r.height = th; - MwLLDrawPixmap(handle->lowlevel, &r, p); + MwDrawPixmap(handle, &r, p); MwDestroyPixmap(p); free(px); diff --git a/src/text/gdi.c b/src/text/gdi.c index eb7df4ea2..19cd3d44e 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -14,7 +14,7 @@ struct _MwFLFont { HDC dc; }; -static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color) { +static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwColor color) { BITMAPINFOHEADER bmih; int tw; int th; @@ -26,7 +26,7 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c wchar_t* t16; int y, x; MwRect r; - MwLLPixmap p; + MwPixmap p; tw = MwTextWidth(handle, ttf, text); th = MwTextHeight(handle, ttf, text); @@ -34,7 +34,7 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c if(handle->lowlevel->common.type == MwLLBackendGDI) { HFONT old_font = SelectObject(handle->lowlevel->gdi.hDC, ttf->font); int old_bkmode = SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT); - COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, RGB(color->common.red, color->common.green, color->common.blue)); + COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, RGB(color->common->red, color->common->green, color->common->blue)); if(_TextOutW == NULL) { t = MwUTF8TextToACPText(text); @@ -89,9 +89,9 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c for(x = 0; x < tw; x++) { unsigned char* opx = &px[(y * tw + x) * 4]; - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; + opx[0] = color->common->red; + opx[1] = color->common->green; + opx[2] = color->common->blue; opx[3] = 255 - bits[y * tw + x].rgbRed; } } @@ -102,7 +102,7 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c r.width = tw; r.height = th; - MwLLDrawPixmap(handle->lowlevel, &r, p); + MwDrawPixmap(handle, &r, p); MwDestroyPixmap(p); free(px); diff --git a/src/text/stbtt.c b/src/text/stbtt.c index 67fe0ce6b..99e6383b0 100644 --- a/src/text/stbtt.c +++ b/src/text/stbtt.c @@ -11,11 +11,11 @@ struct _MwFLFont { int descent; }; -static int stbtt_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color) { +static int stbtt_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwColor color) { unsigned char* px; int tw, th; MwRect r; - MwLLPixmap p; + MwPixmap p; int ax, lsb; int x = 0, y = 0; @@ -47,9 +47,9 @@ static int stbtt_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const int ox = x + ceil(lsb * ttf->scale) + cx; int oy = y + ceil(ttf->ascent * ttf->scale) + y0 + cy; unsigned char* opx = &px[(oy * tw + ox) * 4]; - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; + opx[0] = color->common->red; + opx[1] = color->common->green; + opx[2] = color->common->blue; /* overflow check */ if(opx[3] + out[cy * ow + cx] < opx[3]) { opx[3] = 255; @@ -79,7 +79,7 @@ static int stbtt_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const r.width = tw; r.height = th; - MwLLDrawPixmap(handle->lowlevel, &r, p); + MwDrawPixmap(handle, &r, p); MwDestroyPixmap(p); free(px); diff --git a/src/text/text.c b/src/text/text.c index b39f064fb..327a32cab 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -1,11 +1,11 @@ #include -int (*MwFLDrawText)(MwWidget handle, MwFLFont font, MwPoint* point, const char* text, MwLLColor color) = NULL; -int (*MwFLTextWidth)(MwFLFont font, const char* text) = NULL; -int (*MwFLTextHeight)(MwFLFont font, int count) = NULL; -int (*MwFLTextHeightWithText)(MwFLFont ttf, const char* text) = NULL; -void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px) = NULL; -void (*MwFLFontFree)(void* handle) = NULL; +int (*MwFLDrawText)(MwWidget handle, MwFLFont font, MwPoint* point, const char* text, MwColor color) = NULL; +int (*MwFLTextWidth)(MwFLFont font, const char* text) = NULL; +int (*MwFLTextHeight)(MwFLFont font, int count) = NULL; +int (*MwFLTextHeightWithText)(MwFLFont ttf, const char* text) = NULL; +void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px) = NULL; +void (*MwFLFontFree)(void* handle) = NULL; #if defined(USE_FREETYPE2) || defined(USE_STB_TRUETYPE) || defined(USE_GDI_TEXT) #define TTF @@ -14,7 +14,7 @@ void (*MwFLFontFree)(void* handle) = NULL; #define FontWidth 7 #define FontHeight 13 -static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwLLColor color); +static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwColor color); static int count_nl(const char* text) { int c = 1; @@ -76,25 +76,25 @@ static MwFLFont assume_ttf(MwWidget handle, MwFLFont ttf) { } #endif -void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int align, MwLLColor color) { - MwPoint p = *point; - char* input = (char*)text; - char* last = input; - int cp; - MwLLColor fadedColor = NULL; - int n; +void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int align, MwColor color) { + MwPoint p = *point; + char* input = (char*)text; + char* last = input; + int cp; + MwColor fadedColor = NULL; + int n; if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { - MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { - fadedColor = MwLLAllocColor(handle->lowlevel, color->common.red, color->common.blue, color->common.green); - fadedColor->common.red = (MwU8)(fadedColor->common.red + (c->common.red - fadedColor->common.red) * 0.5); - fadedColor->common.green = (MwU8)(fadedColor->common.green + (c->common.green - fadedColor->common.green) * 0.5); - fadedColor->common.blue = (MwU8)(fadedColor->common.blue + (c->common.blue - fadedColor->common.blue) * 0.5); - MwLLColorUpdate(handle->lowlevel, fadedColor, fadedColor->common.red, fadedColor->common.green, fadedColor->common.blue); + fadedColor = MwAllocColor(handle, color->common->red, color->common->blue, color->common->green); + fadedColor->common->red = (MwU8)(fadedColor->common->red + (c->common->red - fadedColor->common->red) * 0.5); + fadedColor->common->green = (MwU8)(fadedColor->common->green + (c->common->green - fadedColor->common->green) * 0.5); + fadedColor->common->blue = (MwU8)(fadedColor->common->blue + (c->common->blue - fadedColor->common->blue) * 0.5); + MwColorUpdate(fadedColor, fadedColor->common->red, fadedColor->common->green, fadedColor->common->blue); - MwLLFreeColor(c); + MwFreeColor(c); } } @@ -159,13 +159,13 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, l[0].y = l[1].y = p.y; if((n = MwGetInteger(handle, MwNstrikethrough)) != MwDEFAULT && n) { - MwLLLine(handle->lowlevel, l, color); + MwLLLine(handle->lowlevel, l, color->lowlevel); } if((n = MwGetInteger(handle, MwNunderline)) != MwDEFAULT && n) { l[0].y += th / 2; l[1].y += th / 2; - MwLLLine(handle->lowlevel, l, color); + MwLLLine(handle->lowlevel, l, color->lowlevel); } p.y += th; @@ -177,7 +177,7 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, } if(fadedColor) { - MwLLFreeColor(fadedColor); + MwFreeColor(fadedColor); } } @@ -269,12 +269,12 @@ void MwFontFree(void* handle) { if(MwFLFontFree) MwFLFontFree(handle); } -static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwLLColor color) { +static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwColor color) { int i = 0, x, y, sx, sy; int tw, th; unsigned char* px; MwRect r; - MwLLPixmap p; + MwPixmap p; if(strlen(text) == 0) text = " "; tw = MwTextWidth(handle, NULL, text); @@ -307,9 +307,9 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, for(x = 0; x < FontWidth; x++) { unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4]; if((bold ? MwBoldFontData : MwFontData)[out].data[y] & (1 << ((FontWidth - 1) - x))) { - ppx[0] = color->common.red; - ppx[1] = color->common.green; - ppx[2] = color->common.blue; + ppx[0] = color->common->red; + ppx[1] = color->common->green; + ppx[2] = color->common->blue; ppx[3] = 255; } else { ppx[0] = 0; @@ -329,7 +329,7 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, r.width = tw; r.height = th; - MwLLDrawPixmap(handle->lowlevel, &r, p); + MwDrawPixmap(handle, &r, p); MwDestroyPixmap(p); free(px); } diff --git a/src/widget/box.c b/src/widget/box.c index 00b5723e7..0f9c8f52e 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -77,8 +77,8 @@ static void layout(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); r.x = 0; r.y = 0; @@ -91,7 +91,7 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r, base); - MwLLFreeColor(base); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/button.c b/src/widget/button.c index 7f1da57ef..a0857c18a 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -15,11 +15,11 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; MwPoint point; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); const char* str = MwGetText(handle, MwNtext); - MwLLPixmap px = MwGetVoid(handle, MwNpixmap); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap px = MwGetVoid(handle, MwNpixmap); + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); int inv; if(str == NULL) str = ""; @@ -38,7 +38,7 @@ static void draw(MwWidget handle) { } else { MwDrawWidgetBack(handle, &r, base, handle->pressed, MwDEFAULT); } - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); if(MwGetInteger(handle, MwNflat) && !(handle->pressed || ((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv))) { r.x += MwDefaultBorderWidth(handle); r.y += MwDefaultBorderWidth(handle); @@ -51,27 +51,27 @@ static void draw(MwWidget handle) { int oh = r.height; if(MwGetInteger(handle, MwNfillArea)) { - double sw = (double)ow / px->common.width; - double sh = (double)oh / px->common.height; + double sw = (double)ow / px->common->width; + double sh = (double)oh / px->common->height; if(sw < sh) { - r.width = (int)(px->common.width * sw); - r.height = (int)(px->common.height * sw); + r.width = (int)(px->common->width * sw); + r.height = (int)(px->common->height * sw); } else { - r.width = (int)(px->common.width * sh); - r.height = (int)(px->common.height * sh); + r.width = (int)(px->common->width * sh); + r.height = (int)(px->common->height * sh); } r.width -= MwGetInteger(handle, MwNpadding) * 2; r.height -= MwGetInteger(handle, MwNpadding) * 2; } else { - r.width = px->common.width; - r.height = px->common.height; + r.width = px->common->width; + r.height = px->common->height; } r.x += (int)((double)(ow - r.width) / 2); r.y += (int)((double)(oh - r.height) / 2); - MwLLDrawPixmap(handle->lowlevel, &r, px); + MwDrawPixmap(handle, &r, px); } else { point.x = r.x + r.width / 2; point.y = r.x + r.height / 2; @@ -79,8 +79,8 @@ static void draw(MwWidget handle) { MwDrawText(handle, NULL, &point, str, MwALIGNMENT_CENTER, text); } - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static void click(MwWidget handle) { diff --git a/src/widget/calendar.c b/src/widget/calendar.c index f5793f25f..f5c3a80eb 100644 --- a/src/widget/calendar.c +++ b/src/widget/calendar.c @@ -29,10 +29,10 @@ static int wcreate(MwWidget handle) { return 0; } -static MwLLPixmap blit(MwWidget handle, const char* str, MwLLColor bg, MwLLColor fg, int scale) { +static MwPixmap blit(MwWidget handle, const char* str, MwColor bg, MwColor fg, int scale) { int i; unsigned char* buf; - MwLLPixmap px; + MwPixmap px; int w = (5 * strlen(str) + (strlen(str) - 1)) * scale; int h = 5 * scale; int y, x, s; @@ -81,11 +81,11 @@ static MwLLPixmap blit(MwWidget handle, const char* str, MwLLColor bg, MwLLColor } static void draw(MwWidget handle) { - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor cf = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwLLColor cb = MwParseColor(handle, "#fff"); - MwLLColor cb_g = MwParseColor(handle, "#666"); - MwLLColor ct = MwParseColor(handle, "#000"); + MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor cf = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor cb = MwParseColor(handle, "#fff"); + MwColor cb_g = MwParseColor(handle, "#666"); + MwColor ct = MwParseColor(handle, "#000"); MwRect r, r2, r3; MwPoint p[6]; int h = 32 * MwGetInteger(handle, MwNscale); @@ -115,7 +115,7 @@ static void draw(MwWidget handle) { "THU", "FRI", "SAT"}; - MwLLPixmap px; + MwPixmap px; r.x = 0; r.y = 0; @@ -135,7 +135,7 @@ static void draw(MwWidget handle) { p[4].y = p[0].y + gh * 7; p[5].x = p[0].x + h; p[5].y = p[0].y; - MwLLPolygon(handle->lowlevel, p, 6, cb_g); + MwLLPolygon(handle->lowlevel, p, 6, cb_g->lowlevel); p[0].x = (r.width - h) / 2; p[0].y = (r.height - h - sh) / 2; @@ -149,7 +149,7 @@ static void draw(MwWidget handle) { p[4].y = p[0].y + gh * 3; p[5].x = p[0].x + h; p[5].y = p[0].y; - MwLLPolygon(handle->lowlevel, p, 6, ct); + MwLLPolygon(handle->lowlevel, p, 6, ct->lowlevel); r2.width = h; r2.height = h - ph - gh; @@ -175,7 +175,7 @@ static void draw(MwWidget handle) { p[2].y = r2.y + r2.height + ph; p[3].x = r2.x + r2.width; p[3].y = r2.y + r2.height; - MwLLPolygon(handle->lowlevel, p, 4, cb); + MwLLPolygon(handle->lowlevel, p, 4, cb->lowlevel); p[0].x = r.width / 2; p[0].y = (r.height - sh) / 2; @@ -186,38 +186,38 @@ static void draw(MwWidget handle) { px = blit(handle, days[MwGetInteger(handle, MwNday)], cb, ct, gh); r2 = r3; - r2.width = px->common.width; - r2.height = px->common.height; + r2.width = px->common->width; + r2.height = px->common->height; r2.x = (r.width - r2.width) / 2; r2.y = r2.y + gh * 2; - MwLLDrawPixmap(handle->lowlevel, &r2, px); + MwDrawPixmap(handle, &r2, px); MwDestroyPixmap(px); px = blit(handle, months[MwGetInteger(handle, MwNmonth)], cb, ct, gh); r2 = r3; - r2.width = px->common.width; - r2.height = px->common.height; + r2.width = px->common->width; + r2.height = px->common->height; r2.x = (r.width - r2.width) / 2; r2.y = r2.y + h - gh * 2 - r2.height; - MwLLDrawPixmap(handle->lowlevel, &r2, px); + MwDrawPixmap(handle, &r2, px); MwDestroyPixmap(px); MwStringPrintIntoBuffer(buf, 5, "%d", MwGetInteger(handle, MwNyear)); px = blit(handle, buf, c, cf, gh); r2 = r3; - r2.width = px->common.width; - r2.height = px->common.height; + r2.width = px->common->width; + r2.height = px->common->height; r2.x = (r.width - r2.width) / 2; r2.y = r2.y + h + gh * 6; - MwLLDrawPixmap(handle->lowlevel, &r2, px); + MwDrawPixmap(handle, &r2, px); MwDestroyPixmap(px); - MwLLFreeColor(cf); - MwLLFreeColor(ct); - MwLLFreeColor(cb_g); - MwLLFreeColor(cb); - MwLLFreeColor(c); + MwFreeColor(cf); + MwFreeColor(ct); + MwFreeColor(cb_g); + MwFreeColor(cb); + MwFreeColor(c); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/chart.c b/src/widget/chart.c index 40e760da2..6003ff9f7 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -33,7 +33,7 @@ static void destroy(MwWidget handle) { free(handle->internal); } -static void draw_line(MwWidget handle, const char* text, double x, double y, double width, double height, MwLLColor color) { +static void draw_line(MwWidget handle, const char* text, double x, double y, double width, double height, MwColor color) { MwPoint p[2]; int type = MwGetInteger(handle, MwNtype); @@ -53,13 +53,13 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou p2[1].x += height; p2[1].y -= height; - MwLLLine(handle->lowlevel, &p2[0], color); + MwLLLine(handle->lowlevel, &p2[0], color->lowlevel); p[0].x += height; p[0].y -= height; p[1].y -= height; } - MwLLLine(handle->lowlevel, &p[0], color); + MwLLLine(handle->lowlevel, &p[0], color->lowlevel); } #define CALC_VMIN_VMAX \ @@ -75,7 +75,7 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou vmax += (double)width / r.height * (vmax - vmin); \ } -static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int space, const char** colors, int n, MwLLColor border) { +static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int space, const char** colors, int n, MwColor border) { int ColorDiff = MwGetColorDifference(handle); MwChart c = handle->internal; double s = 1.5; @@ -126,22 +126,22 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int p[1].x = node.x; p[1].y = r.height - space; - MwLLLine(handle->lowlevel, &p[0], border); + MwLLLine(handle->lowlevel, &p[0], border->lowlevel); p[0].x = node.x; p[0].y = r.height - space; p[1].x = node.x + twidth; p[1].y = p[0].y; - MwLLLine(handle->lowlevel, &p[0], border); + MwLLLine(handle->lowlevel, &p[0], border->lowlevel); node.width = width; for(i = 0; i < arrlen(c->entries); i++) { - MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); - MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); - MwPoint persp_top[5]; - MwPoint persp_right[5]; + MwColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + MwColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwPoint persp_top[5]; + MwPoint persp_right[5]; node.x += gap; @@ -170,7 +170,7 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int persp_top[4] = persp_top[0]; - MwLLPolygon(handle->lowlevel, persp_top, 4, colorl); + MwLLPolygon(handle->lowlevel, persp_top, 4, colorl->lowlevel); persp_right[0] = *(MwPoint*)&node2; persp_right[1] = *(MwPoint*)&node2; @@ -189,22 +189,22 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int persp_right[4] = persp_right[0]; - MwLLPolygon(handle->lowlevel, persp_right, 4, colord); + MwLLPolygon(handle->lowlevel, persp_right, 4, colord->lowlevel); } if(!modern) { MwDrawRectLine(handle, &node, border); if(type == MwCHART_BAR_3D) { - MwLLLine(handle->lowlevel, &persp_top[0], border); - MwLLLine(handle->lowlevel, &persp_top[1], border); - MwLLLine(handle->lowlevel, &persp_top[2], border); - MwLLLine(handle->lowlevel, &persp_top[3], border); + MwLLLine(handle->lowlevel, &persp_top[0], border->lowlevel); + MwLLLine(handle->lowlevel, &persp_top[1], border->lowlevel); + MwLLLine(handle->lowlevel, &persp_top[2], border->lowlevel); + MwLLLine(handle->lowlevel, &persp_top[3], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_right[0], border); - MwLLLine(handle->lowlevel, &persp_right[1], border); - MwLLLine(handle->lowlevel, &persp_right[2], border); - MwLLLine(handle->lowlevel, &persp_right[3], border); + MwLLLine(handle->lowlevel, &persp_right[0], border->lowlevel); + MwLLLine(handle->lowlevel, &persp_right[1], border->lowlevel); + MwLLLine(handle->lowlevel, &persp_right[2], border->lowlevel); + MwLLLine(handle->lowlevel, &persp_right[3], border->lowlevel); } } @@ -215,13 +215,13 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int node.x += node.width; - MwLLFreeColor(colord); - MwLLFreeColor(colorl); - MwLLFreeColor(color); + MwFreeColor(colord); + MwFreeColor(colorl); + MwFreeColor(color); } } -static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, MwLLColor border) { +static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, MwColor border) { int ColorDiff = MwGetColorDifference(handle); MwChart c = handle->internal; double sum = 0; @@ -242,12 +242,12 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M for(k = 0; k < 4; k++) { for(i = 0; i < arrlen(c->entries); i++) { - MwLLColor color; - MwLLColor colorl; - double angle = c->entries[i].value / sum * 360; - int div = angle / PIE_DIV; - int j; - int count; + MwColor color; + MwColor colorl; + double angle = c->entries[i].value / sum * 360; + int div = angle / PIE_DIV; + int j; + int count; if(c->entries[i].value <= 0) continue; if((k == 0 || k == 1) && type == MwCHART_PIE) continue; @@ -282,27 +282,27 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M p3[2] = p2[1]; if(k == 0) { - MwLLPolygon(handle->lowlevel, p3, count + 2, color); + MwLLPolygon(handle->lowlevel, p3, count + 2, color->lowlevel); } else if(d == 1 && k == 1) { for(j = 3; j < count + 1; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p3[j], border); + if(!modern) MwLLLine(handle->lowlevel, &p3[j], border->lowlevel); } p2[0] = p2[1]; p2[0].y += radius / 8; - if(!modern) MwLLLine(handle->lowlevel, p2, border); + if(!modern) MwLLLine(handle->lowlevel, p2, border->lowlevel); } } } if(k == 2) { - MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_PIE_3D ? colorl : color); + MwLLPolygon(handle->lowlevel, p2, count, (type == MwCHART_PIE_3D ? colorl : color)->lowlevel); } else if(k == 3) { int j; p2[count] = p2[0]; for(j = 0; j < count; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); + if(!modern) MwLLLine(handle->lowlevel, &p2[j], border->lowlevel); } p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; @@ -315,8 +315,8 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M cangle += angle; - MwLLFreeColor(colorl); - MwLLFreeColor(color); + MwFreeColor(colorl); + MwFreeColor(color); } } @@ -325,14 +325,14 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M p[0].y = r.height / 2; p[1] = p[0]; p[1].y += radius / 8; - MwLLLine(handle->lowlevel, p, border); + MwLLLine(handle->lowlevel, p, border->lowlevel); p[0].x = p[1].x = r.width / 2 + radius / 2; - MwLLLine(handle->lowlevel, p, border); + MwLLLine(handle->lowlevel, p, border->lowlevel); } } -static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int space, MwLLColor border) { +static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int space, MwColor border) { MwChart c = handle->internal; char buf[128]; double twidth; @@ -376,7 +376,7 @@ static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, in p[1] = p[0]; p[1].y = r.height - space; - MwLLLine(handle->lowlevel, p, border); + MwLLLine(handle->lowlevel, p, border->lowlevel); for(j = 0; j < 2; j++) { for(i = j == 0 ? 1 : 0; i < arrlen(c->entries); i++) { @@ -386,7 +386,7 @@ static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, in p[1].y = (r.height - space) - (c->entries[i].value - vmin) / (vmax - vmin) * (r.height - space); if(j == 0) { - MwLLLine(handle->lowlevel, p, border); + MwLLLine(handle->lowlevel, p, border->lowlevel); } else { MwDrawText(handle, NULL, &p[1], c->entries[i].name, MwALIGNMENT_CENTER, border); } @@ -395,8 +395,8 @@ static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, in } static void draw(MwWidget handle) { - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwRect r; MwChart c = handle->internal; int i; @@ -437,8 +437,8 @@ static void draw(MwWidget handle) { break; } - MwLLFreeColor(border); - MwLLFreeColor(base); + MwFreeColor(border); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 8e65dc076..0837f028c 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -9,11 +9,11 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwLLColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwRect r; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); + MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; @@ -31,7 +31,7 @@ static void draw(MwWidget handle) { MwDrawFrame(handle, &r, base, 1); MwDrawRect(handle, &r, base2); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); if(handle->pressed || MwGetInteger(handle, MwNchecked)) { MwPoint p[6]; int gap_w = r.width / 4 / 3; @@ -60,12 +60,12 @@ static void draw(MwWidget handle) { p[5] = p[0]; p[5].y -= r.height / 3; - MwLLPolygon(handle->lowlevel, p, 6, text2); + MwLLPolygon(handle->lowlevel, p, 6, text2->lowlevel); } - MwLLFreeColor(text2); - MwLLFreeColor(base2); - MwLLFreeColor(base); + MwFreeColor(text2); + MwFreeColor(base2); + MwFreeColor(base); } static void click(MwWidget handle) { diff --git a/src/widget/clock.c b/src/widget/clock.c index 70471c62f..3ad1862ec 100644 --- a/src/widget/clock.c +++ b/src/widget/clock.c @@ -9,7 +9,7 @@ static int wcreate(MwWidget handle) { return 0; } -static void hand(MwWidget handle, double x, double y, double width, double length, double angle, MwLLColor inside, MwLLColor border) { +static void hand(MwWidget handle, double x, double y, double width, double length, double angle, MwColor inside, MwColor border) { double w = MwGetInteger(handle, MwNwidth); double h = MwGetInteger(handle, MwNheight); MwPoint p[5]; @@ -43,30 +43,30 @@ static void hand(MwWidget handle, double x, double y, double width, double lengt p[4] = p[0]; - MwLLPolygon(handle->lowlevel, p, 4, inside); + MwLLPolygon(handle->lowlevel, p, 4, inside->lowlevel); - MwLLLine(handle->lowlevel, &p[0], border); - MwLLLine(handle->lowlevel, &p[1], border); - MwLLLine(handle->lowlevel, &p[2], border); - MwLLLine(handle->lowlevel, &p[3], border); + MwLLLine(handle->lowlevel, &p[0], border->lowlevel); + MwLLLine(handle->lowlevel, &p[1], border->lowlevel); + MwLLLine(handle->lowlevel, &p[2], border->lowlevel); + MwLLLine(handle->lowlevel, &p[3], border->lowlevel); } static void draw(MwWidget handle) { - int ColorDiff = MwGetColorDifference(handle); - int ShadowDist; - int BaseWidth; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor shadow = MwLightenColor(handle, base, -ColorDiff, -ColorDiff, -ColorDiff); - MwLLColor inside = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); - MwRect r; - int i; - double w; - double fs = (MwGetInteger(handle, MwNsecond) % 60); - double fm = (MwGetInteger(handle, MwNminute) % 60) + (MwGetInteger(handle, MwNsecond) % 60) / 60.0; - double s = (double)(MwGetInteger(handle, MwNsecond) % 60) / 60 * 360; - double m = ((double)(MwGetInteger(handle, MwNminute) % 60) + fs / 60.0) / 60 * 360; - double h = ((double)(MwGetInteger(handle, MwNhour) % 12) + fm / 60.0) / 12 * 360; + int ColorDiff = MwGetColorDifference(handle); + int ShadowDist; + int BaseWidth; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor shadow = MwLightenColor(handle, base, -ColorDiff, -ColorDiff, -ColorDiff); + MwColor inside = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); + MwColor border = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwRect r; + int i; + double w; + double fs = (MwGetInteger(handle, MwNsecond) % 60); + double fm = (MwGetInteger(handle, MwNminute) % 60) + (MwGetInteger(handle, MwNsecond) % 60) / 60.0; + double s = (double)(MwGetInteger(handle, MwNsecond) % 60) / 60 * 360; + double m = ((double)(MwGetInteger(handle, MwNminute) % 60) + fs / 60.0) / 60 * 360; + double h = ((double)(MwGetInteger(handle, MwNhour) % 12) + fm / 60.0) / 12 * 360; r.x = 0; r.y = 0; @@ -96,7 +96,7 @@ static void draw(MwWidget handle) { p[1].x = x; p[1].y = y; - MwLLLine(handle->lowlevel, p, border); + MwLLLine(handle->lowlevel, p, border->lowlevel); } hand(handle, ShadowDist, ShadowDist, BaseWidth, w / 2 * 2 / 3, h, shadow, shadow); @@ -107,10 +107,10 @@ static void draw(MwWidget handle) { hand(handle, 0, 0, BaseWidth, w / 2, m, inside, border); hand(handle, 0, 0, BaseWidth / 4, w / 2, s, inside, border); - MwLLFreeColor(border); - MwLLFreeColor(inside); - MwLLFreeColor(shadow); - MwLLFreeColor(base); + MwFreeColor(border); + MwFreeColor(inside); + MwFreeColor(shadow); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/combobox.c b/src/widget/combobox.c index a6cb87695..36f2e6c58 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -25,8 +25,8 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwRect r, rc; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwComboBox cb = handle->internal; r.x = 0; @@ -59,8 +59,8 @@ static void draw(MwWidget handle) { r.height = MwDefaultBorderWidth(handle) * 2; MwDrawFrame(handle, &r, base, 0); - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static void MWAPI listbox_activate(MwWidget handle, void* user, void* client) { diff --git a/src/widget/document.c b/src/widget/document.c index eb5233d43..f2f430c1e 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -52,8 +52,8 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwDocument d = handle->internal; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwRect r; int i; MwFLFont font = NULL; @@ -138,7 +138,7 @@ static void draw(MwWidget handle) { if(j == 0 || j == 1) { line[0].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); line[1].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); - MwLLLine(handle->lowlevel, line, c ? base : text); + MwLLLine(handle->lowlevel, line, (c ? base : text)->lowlevel); } } } @@ -191,8 +191,8 @@ static void draw(MwWidget handle) { if(IsFontChange(l->type)) font = l->font; } - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static char* in_hitbox(MwWidget handle, MwPoint* p) { diff --git a/src/widget/entry.c b/src/widget/entry.c index 9d423bf8a..6f363f208 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -47,10 +47,10 @@ static void tick(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; MwEntry t = handle->internal; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); const char* str = MwGetText(handle, MwNtext); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); MwFLFont font = MwFLBuildFont(MwFLFlagMonospace); if(str == NULL) str = ""; @@ -60,7 +60,7 @@ static void draw(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); MwDrawWidgetBack(handle, &r, base, 1, MwDEFAULT); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); if(str != NULL) { int w = MwTextWidth(handle, font, "M"); int h = MwTextHeight(handle, font, "M"); @@ -108,8 +108,8 @@ static void draw(MwWidget handle) { } } - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static void key(MwWidget handle, int code) { diff --git a/src/widget/frame.c b/src/widget/frame.c index f2af10802..841fae27f 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -10,11 +10,11 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect fr; - MwRect rr; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - int inverted; - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwRect fr; + MwRect rr; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + int inverted; + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); if(MwGetInteger(handle, MwNhasBorder)) { inverted = MwGetInteger(handle, MwNinverted); @@ -36,9 +36,9 @@ static void draw(MwWidget handle) { } MwDrawRect(handle, &rr, base); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &rr, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &rr, bgpx); - MwLLFreeColor(base); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/image.c b/src/widget/image.c index c8e068002..17c0d3ab6 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -11,9 +11,9 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLPixmap px = MwGetVoid(handle, MwNpixmap); - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; + MwPixmap px = MwGetVoid(handle, MwNpixmap); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); r.x = 0; r.y = 0; @@ -25,16 +25,16 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r, base); if(px != NULL) { if(!MwGetInteger(handle, MwNfillArea)) { - r.x = (r.width - px->common.width) / 2; - r.y = (r.height - px->common.height) / 2; - r.width = px->common.width; - r.height = px->common.height; + r.x = (r.width - px->common->width) / 2; + r.y = (r.height - px->common->height) / 2; + r.width = px->common->width; + r.height = px->common->height; } - MwLLDrawPixmap(handle->lowlevel, &r, px); + MwDrawPixmap(handle, &r, px); } - MwLLFreeColor(base); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/label.c b/src/widget/label.c index eecca474d..7dc8b52d9 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -28,7 +28,7 @@ static void destroy(MwWidget handle) { free(handle->internal); } -static void draw_v(MwWidget handle, unsigned char* raw, int x, int y, int stride, MwLLColor text) { +static void draw_v(MwWidget handle, unsigned char* raw, int x, int y, int stride, MwColor text) { int cy, cx, b; int l_one = MwGetInteger(handle, MwNlength) - (MwGetInteger(handle, MwNlength) % 2); @@ -37,9 +37,9 @@ static void draw_v(MwWidget handle, unsigned char* raw, int x, int y, int stride for(cy = y; cy < y + l_one; cy++) { for(cx = x; cx < x + s_one; cx++) { unsigned char* px = &raw[(cy * stride + cx) * 4]; - px[0] = text->common.red; - px[1] = text->common.green; - px[2] = text->common.blue; + px[0] = text->common->red; + px[1] = text->common->green; + px[2] = text->common->blue; px[3] = 255; } } @@ -52,9 +52,9 @@ static void draw_v(MwWidget handle, unsigned char* raw, int x, int y, int stride unsigned char* px; px = &raw[(cy * stride + cx) * 4]; - px[0] = text->common.red; - px[1] = text->common.green; - px[2] = text->common.blue; + px[0] = text->common->red; + px[1] = text->common->green; + px[2] = text->common->blue; px[3] = 255; } } @@ -67,15 +67,15 @@ static void draw_v(MwWidget handle, unsigned char* raw, int x, int y, int stride unsigned char* px; px = &raw[(cy * stride + cx) * 4]; - px[0] = text->common.red; - px[1] = text->common.green; - px[2] = text->common.blue; + px[0] = text->common->red; + px[1] = text->common->green; + px[2] = text->common->blue; px[3] = 255; } } } -static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride, MwLLColor text) { +static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride, MwColor text) { int cy, cx, b; int l_one = MwGetInteger(handle, MwNlength) - (MwGetInteger(handle, MwNlength) % 2); @@ -84,9 +84,9 @@ static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride for(cx = x; cx < x + l_one; cx++) { for(cy = y; cy < y + s_one; cy++) { unsigned char* px = &raw[(cy * stride + cx) * 4]; - px[0] = text->common.red; - px[1] = text->common.green; - px[2] = text->common.blue; + px[0] = text->common->red; + px[1] = text->common->green; + px[2] = text->common->blue; px[3] = 255; } } @@ -99,9 +99,9 @@ static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride unsigned char* px; px = &raw[(cy * stride + cx) * 4]; - px[0] = text->common.red; - px[1] = text->common.green; - px[2] = text->common.blue; + px[0] = text->common->red; + px[1] = text->common->green; + px[2] = text->common->blue; px[3] = 255; } } @@ -114,9 +114,9 @@ static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride unsigned char* px; px = &raw[(cy * stride + cx) * 4]; - px[0] = text->common.red; - px[1] = text->common.green; - px[2] = text->common.blue; + px[0] = text->common->red; + px[1] = text->common->green; + px[2] = text->common->blue; px[3] = 255; } } @@ -124,16 +124,16 @@ static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride static void draw_seven_segment(MwWidget handle) { MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwLLColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; const char* str = MwGetText(handle, MwNtext); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); MwLabel lab = handle->internal; int l_one = MwGetInteger(handle, MwNlength) - (MwGetInteger(handle, MwNlength) % 2); int s_one = (l_one * 3 / 4) - ((l_one * 3 / 4) % 2) + 1; - MwLLPixmap px; + MwPixmap px; unsigned char* raw; int w = 0, h = s_one * 3 + l_one * 2, i; int x = 0; @@ -146,7 +146,7 @@ static void draw_seven_segment(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); align = MwGetInteger(handle, MwNalignment); @@ -234,7 +234,7 @@ static void draw_seven_segment(MwWidget handle) { } for(j = 1; j >= 0; j--) { - MwLLColor cl = j == 1 ? shadow : text; + MwColor cl = j == 1 ? shadow : text; if(la) draw_h(handle, raw, x + s_one + j, j, w, cl); if(lb) draw_v(handle, raw, x + s_one + l_one + j, s_one + j, w, cl); @@ -250,7 +250,7 @@ static void draw_seven_segment(MwWidget handle) { int cy, cx; int j; for(j = 1; j >= 0; j--) { - MwLLColor cl = j == 1 ? shadow : text; + MwColor cl = j == 1 ? shadow : text; for(cy = 1; cy < h - 1; cy++) { int h = s_one / 2; int c = (l_one - h) / 2 + s_one; @@ -261,9 +261,9 @@ static void draw_seven_segment(MwWidget handle) { if(c1 || c2) { for(cx = x; cx < x + s_one; cx++) { unsigned char* px = &raw[((cy + j) * w + (cx + j)) * 4]; - px[0] = cl->common.red; - px[1] = cl->common.green; - px[2] = cl->common.blue; + px[0] = cl->common->red; + px[1] = cl->common->green; + px[2] = cl->common->blue; px[3] = 255; } } @@ -276,13 +276,13 @@ static void draw_seven_segment(MwWidget handle) { int cy, cx; int j; for(j = 1; j >= 0; j--) { - MwLLColor cl = j == 1 ? shadow : text; + MwColor cl = j == 1 ? shadow : text; for(cy = h - (s_one - 1) / 2 - 1; cy < h; cy++) { for(cx = x - Spacing - (s_one - 1) / 2 - 1; cx < (x - Spacing); cx++) { unsigned char* px = &raw[((cy + j) * w + (cx + j)) * 4]; - px[0] = cl->common.red; - px[1] = cl->common.green; - px[2] = cl->common.blue; + px[0] = cl->common->red; + px[1] = cl->common->green; + px[2] = cl->common->blue; px[3] = 255; } } @@ -305,7 +305,7 @@ static void draw_seven_segment(MwWidget handle) { r.x = r.width - w; } r.width = w; - MwLLDrawPixmap(handle->lowlevel, &r, px); + MwDrawPixmap(handle, &r, px); free(raw); @@ -315,12 +315,12 @@ static void draw_seven_segment(MwWidget handle) { static void draw_normal(MwWidget handle) { MwRect r; MwPoint p; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwLLColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; const char* str = MwGetText(handle, MwNtext); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); if(str == NULL) str = ""; @@ -330,7 +330,7 @@ static void draw_normal(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); align = MwGetInteger(handle, MwNalignment); @@ -359,9 +359,9 @@ static void draw_normal(MwWidget handle) { p.y -= 1; MwDrawText(handle, NULL, &p, str, MwALIGNMENT_CENTER, text); - MwLLFreeColor(shadow); - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(shadow); + MwFreeColor(text); + MwFreeColor(base); } static void draw(MwWidget handle) { diff --git a/src/widget/listbox.c b/src/widget/listbox.c index cc173628a..272909e0f 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -136,10 +136,10 @@ static void MWAPI frame_mouse_move(MwWidget handle, void* user, void* call) { static void frame_draw(MwWidget handle) { MwRect r, r2; MwListBox lb = handle->parent->internal; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwLLColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); int i; MwPoint p; int st = 0; @@ -180,12 +180,12 @@ static void frame_draw(MwWidget handle) { } if(lb->list[i].pixmap != NULL) { MwRect r2; - int h = (lb->list[i].pixmap->common.height > (MwTextHeight(handle, Font, "M") + Padding)) ? (MwTextHeight(handle, Font, "M") + Padding) : lb->list[i].pixmap->common.height; + int h = (lb->list[i].pixmap->common->height > (MwTextHeight(handle, Font, "M") + Padding)) ? (MwTextHeight(handle, Font, "M") + Padding) : lb->list[i].pixmap->common->height; r2.x = MwDefaultBorderWidth(handle); r2.y = p.y + (MwTextHeight(handle, Font, "M") + Padding - h) / 2; - r2.width = h * lb->list[i].pixmap->common.width / lb->list[i].pixmap->common.height; + r2.width = h * lb->list[i].pixmap->common->width / lb->list[i].pixmap->common->height; r2.height = h; - MwLLDrawPixmap(handle->lowlevel, &r2, lb->list[i].pixmap); + MwDrawPixmap(handle, &r2, lb->list[i].pixmap); } p.x = MwDefaultBorderWidth(handle) + MwGetInteger(handle->parent, MwNleftPadding); for(j = 0; j < arrlen(lb->list[i].name); j++) { @@ -259,10 +259,10 @@ static void frame_draw(MwWidget handle) { MwDrawFrame(handle, &r, base, 1); - MwLLFreeColor(text2); - MwLLFreeColor(text); - MwLLFreeColor(base2); - MwLLFreeColor(base); + MwFreeColor(text2); + MwFreeColor(text); + MwFreeColor(base2); + MwFreeColor(base); } static void resize(MwWidget handle, int no_resize) { @@ -359,8 +359,8 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwListBox lb = handle->internal; r.x = 0; @@ -405,8 +405,8 @@ static void draw(MwWidget handle) { } } - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* prop) { @@ -456,7 +456,7 @@ static int mwListBoxSetImpl(MwWidget handle, int row, int col, const char* text) return row; } -static void mwListBoxSetIconImpl(MwWidget handle, int index, MwLLPixmap icon) { +static void mwListBoxSetIconImpl(MwWidget handle, int index, MwPixmap icon) { MwListBox lb = handle->internal; MwListBoxEntry entry; int new = 0; @@ -585,8 +585,8 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v *(int*)out = mwListBoxSetImpl(handle, row, col, text); } if(strcmp(name, "mwListBoxSetIcon") == 0) { - int index = va_arg(va, int); - MwLLPixmap icon = va_arg(va, MwLLPixmap); + int index = va_arg(va, int); + MwPixmap icon = va_arg(va, MwPixmap); mwListBoxSetIconImpl(handle, index, icon); } } diff --git a/src/widget/menu.c b/src/widget/menu.c index 8dd3d7a99..22771e9b5 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -103,8 +103,8 @@ static void destroy(MwWidget handle) { m->sub[i]->cleaned = 0; static void draw(MwWidget handle) { - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MENU_LOOP_DECL; MENU_LOOP_INIT; @@ -120,8 +120,8 @@ static void draw(MwWidget handle) { MwDrawText(handle, MwFLBuildFont((m->sub[i]->wsub != NULL || (in_area && handle->pressed)) ? MwFLFlagBold : 0), &p, m->sub[i]->name + incr, MwALIGNMENT_CENTER, text); END_MENU_LOOP; - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static void parent_resize(MwWidget handle) { diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index f3a80e94c..d0323e513 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -19,12 +19,12 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - int w = MwGetInteger(handle, MwNwidth); - int h = MwGetInteger(handle, MwNheight); - MwEntry e = handle->internal; - MwRect r; - int pr; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + int w = MwGetInteger(handle, MwNwidth); + int h = MwGetInteger(handle, MwNheight); + MwEntry e = handle->internal; + MwRect r; + int pr; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwEntryClass->draw(handle); @@ -60,7 +60,7 @@ static void draw(MwWidget handle) { r.y = r.y + (h / 2 - r.height) / 2; MwDrawTriangle(handle, &r, base, pr, MwSOUTH); - MwLLFreeColor(base); + MwFreeColor(base); } static void key(MwWidget handle, int code) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index e3578a76f..3c9178aa0 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -70,7 +70,7 @@ typedef struct waylandopengl { struct gbm_surface* gbm_surface; struct gbm_bo* previous_bo; int drm_fd; - MwLLPixmap frontbuffer; + MwPixmap frontbuffer; MwU8* frontbuffer_data; void* gllib; @@ -607,7 +607,7 @@ static void frontbuffer_draw(MwWidget handle) { r.y = 0; r.width = handle->lowlevel->wayland.ww; r.height = handle->lowlevel->wayland.wh; - MwLLDrawPixmap(handle->lowlevel, &r, o->frontbuffer); + MwDrawPixmap(handle, &r, o->frontbuffer); } } static void frontbuffer_resize(MwWidget handle) { diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index 8adf02842..97352b0aa 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -12,11 +12,11 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor fill = MwParseColor(handle, MwGetText(handle, MwNforeground)); - double w; - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwRect r; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor fill = MwParseColor(handle, MwGetText(handle, MwNforeground)); + double w; + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; @@ -27,7 +27,7 @@ static void draw(MwWidget handle) { w = w / (MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue)); MwDrawWidgetBack(handle, &r, base, 1, MwDEFAULT); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); r.x += MwDefaultBorderWidth(handle); r.y += MwDefaultBorderWidth(handle); @@ -37,8 +37,8 @@ static void draw(MwWidget handle) { r.width = (int)(r.width * w); MwDrawRect(handle, &r, fill); - MwLLFreeColor(fill); - MwLLFreeColor(base); + MwFreeColor(fill); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index 193025936..6fce85a9b 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -11,16 +11,16 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwRect r; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); if(r.width < r.height) { r.height = r.width; @@ -31,17 +31,17 @@ static void draw(MwWidget handle) { r.y = (MwGetInteger(handle, MwNheight) - r.height) / 2; if(MwGetInteger(handle, MwNmodernLook) == 1) { - int is_checked = (handle->pressed || MwGetInteger(handle, MwNchecked)); - MwLLColor darker; - MwLLColor inner; - MwLLColor innerunsel = base; + int is_checked = (handle->pressed || MwGetInteger(handle, MwNchecked)); + MwColor darker; + MwColor inner; + MwColor innerunsel = base; if(MwGetInteger(handle, MwNdarkTheme) == 1) { - darker = MwLLAllocColor(handle->lowlevel, 255, 255, 255); + darker = MwAllocColor(handle, 255, 255, 255); innerunsel = MwLightenColor(handle, base, 80, 80, 80); inner = darker; } else { - darker = MwLLAllocColor(handle->lowlevel, 0, 0, 0); + darker = MwAllocColor(handle, 0, 0, 0); inner = MwLightenColor(handle, is_checked ? darker : base, -80, -80, -80); } MwDrawCircle(handle, &r, darker, NULL, 1); @@ -57,12 +57,12 @@ static void draw(MwWidget handle) { MwDrawCircle(handle, &r, inner, innerunsel, 1); } } - MwLLFreeColor(darker); + MwFreeColor(darker); } else { MwDrawDiamond(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0); } - MwLLFreeColor(base); + MwFreeColor(base); } static void click(MwWidget handle) { diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 3bd2fdf37..82e82861a 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -55,12 +55,12 @@ static void add_value(MwWidget handle, int mul) { static void draw(MwWidget handle) { MwRect r = {0}, rt = {0}, rbar = {0}; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor dark = MwLightenColor(handle, base, -64, -64, -64); MwScrollBar scr = handle->internal; int or ; - int uy, dy, ux, dx; - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + int uy, dy, ux, dx; + MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; @@ -74,7 +74,7 @@ static void draw(MwWidget handle) { dx = r.width - r.height; MwDrawWidgetBack(handle, &r, dark, 1, MwDEFAULT); - if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + if(bgpx != NULL) MwDrawPixmap(handle, &r, bgpx); rt = r; @@ -133,8 +133,8 @@ static void draw(MwWidget handle) { if(rbar.height >= 0) MwDrawWidgetBack(handle, &rbar, base, 0, MwDEFAULT); - MwLLFreeColor(dark); - MwLLFreeColor(base); + MwFreeColor(dark); + MwFreeColor(base); } static void mouse_move(MwWidget handle) { diff --git a/src/widget/separator.c b/src/widget/separator.c index 4e70ccc7b..84af1a3d9 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -9,8 +9,8 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); r.x = 0; r.y = 0; @@ -27,7 +27,7 @@ static void draw(MwWidget handle) { } MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0); - MwLLFreeColor(base); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 6bc5d550c..e76f0fba6 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -29,10 +29,10 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwRect r; - MwMenu menu = handle->internal; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwRect r; + MwMenu menu = handle->internal; r.x = 0; r.y = 0; @@ -96,8 +96,8 @@ static void draw(MwWidget handle) { } } - MwLLFreeColor(text); - MwLLFreeColor(base); + MwFreeColor(text); + MwFreeColor(base); } static void click(MwWidget handle) { diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index f20f7c926..f955bdced 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -8,33 +8,33 @@ static void resize(MwWidget handle); static void close_draw(MwWidget handle) { - int w = MwGetInteger(handle, MwNwidth); - int h = MwGetInteger(handle, MwNheight); - MwPoint p[2]; - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); - int bw = MwDefaultBorderWidth(handle); + int w = MwGetInteger(handle, MwNwidth); + int h = MwGetInteger(handle, MwNheight); + MwPoint p[2]; + MwColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); + int bw = MwDefaultBorderWidth(handle); p[0].x = bw * 2; p[0].y = bw * 2; p[1].x = w - bw * 2 - 1; p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].x++; p[1].x--; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); 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); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].x--; p[1].x++; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); - MwLLFreeColor(c); + MwFreeColor(c); } static void MWAPI close_activate(MwWidget handle, void* user, void* client) { @@ -49,34 +49,34 @@ static void MWAPI close_activate(MwWidget handle, void* user, void* client) { } static void maximize_draw(MwWidget handle) { - int w = MwGetInteger(handle, MwNwidth); - int h = MwGetInteger(handle, MwNheight); - MwPoint p[2]; - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); - int bw = MwDefaultBorderWidth(handle); + int w = MwGetInteger(handle, MwNwidth); + int h = MwGetInteger(handle, MwNheight); + MwPoint p[2]; + MwColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); + int bw = MwDefaultBorderWidth(handle); p[0].x = bw * 2; p[0].y = bw * 2; p[1].x = w - bw * 2 - 1; p[1].y = bw * 2; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].y = p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].y = p[1].y = bw * 2 + 1; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].x = bw * 2; p[0].y = bw * 2; p[1].x = bw * 2; p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].x = p[1].x = w - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); - MwLLFreeColor(c); + MwFreeColor(c); } static void MWAPI maximize_activate(MwWidget handle, void* user, void* client) { @@ -114,23 +114,23 @@ static void MWAPI maximize_activate(MwWidget handle, void* user, void* client) { } static void minimize_draw(MwWidget handle) { - int w = MwGetInteger(handle, MwNwidth); - int h = MwGetInteger(handle, MwNheight); - MwPoint p[2]; - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); - int bw = MwDefaultBorderWidth(handle); + int w = MwGetInteger(handle, MwNwidth); + int h = MwGetInteger(handle, MwNheight); + MwPoint p[2]; + MwColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); + int bw = MwDefaultBorderWidth(handle); p[0].x = bw * 2; p[0].y = h - bw * 2 - 1; p[1].x = w - bw * 2 - 1; p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); p[0].y--; p[1].y--; - MwLLLine(handle->lowlevel, p, c); + MwLLLine(handle->lowlevel, p, c->lowlevel); - MwLLFreeColor(c); + MwFreeColor(c); } static int sort_subwindow(const void* _a, const void* _b) { @@ -285,13 +285,13 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor tb = MwParseColor(handle, MwGetText(handle, MwNtitleBackground)); - MwLLColor tf = MwParseColor(handle, MwGetText(handle, MwNtitleForeground)); + MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor tb = MwParseColor(handle, MwGetText(handle, MwNtitleBackground)); + MwColor tf = MwParseColor(handle, MwGetText(handle, MwNtitleForeground)); MwRect r, r2, r3; const char* title = MwGetText(handle, MwNtitle); int incr = 0; - MwLLPixmap px = MwGetVoid(handle, MwNiconPixmap); + MwPixmap px = MwGetVoid(handle, MwNiconPixmap); r.x = 0; r.y = 0; @@ -313,7 +313,7 @@ static void draw(MwWidget handle) { r3.y += incr; r3.width = ButtonSize; r3.height = ButtonSize; - MwLLDrawPixmap(handle->lowlevel, &r3, px); + MwDrawPixmap(handle, &r3, px); incr += ButtonSize; } @@ -335,9 +335,9 @@ static void draw(MwWidget handle) { r.height -= TitleHeight; MwDrawFrame(handle, &r, c, 1); - MwLLFreeColor(tf); - MwLLFreeColor(tb); - MwLLFreeColor(c); + MwFreeColor(tf); + MwFreeColor(tb); + MwFreeColor(c); } static void parent_resize(MwWidget handle) { diff --git a/src/widget/tab.c b/src/widget/tab.c index e5d2a3eae..870668903 100644 --- a/src/widget/tab.c +++ b/src/widget/tab.c @@ -45,11 +45,11 @@ static int icon_width(MwWidget handle, const char* text) { for(i = 0; i < arrlen(t->names); i++) { if(strcmp(t->names[i], text) == 0) { - MwLLPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + MwPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); if(px == NULL) return 0; - return px->common.width * tab_height(handle) / px->common.height; + return px->common->width * tab_height(handle) / px->common->height; } } @@ -57,14 +57,14 @@ static int icon_width(MwWidget handle, const char* text) { } static void draw(MwWidget handle) { - MwTab t = handle->internal; - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor ct = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwRect r, r2; - int h = tab_height(handle); - int i; - int n; - int x = 0; + MwTab t = handle->internal; + MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor ct = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwRect r, r2; + int h = tab_height(handle); + int i; + int n; + int x = 0; r.x = 0; r.y = 0; @@ -97,8 +97,8 @@ static void draw(MwWidget handle) { x += r2.width; if(iw > 0) { - MwLLPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); - MwRect rp; + MwPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + MwRect rp; rp = r2; @@ -108,7 +108,7 @@ static void draw(MwWidget handle) { rp.width = iw - 10; rp.height = rp.height * (iw - 10) / iw; - MwLLDrawPixmap(handle->lowlevel, &rp, px); + MwDrawPixmap(handle, &rp, px); } if(render) { @@ -191,8 +191,8 @@ static void draw(MwWidget handle) { } } - MwLLFreeColor(ct); - MwLLFreeColor(c); + MwFreeColor(ct); + MwFreeColor(c); } static void show_frame(MwWidget handle) { diff --git a/src/widget/treeview.c b/src/widget/treeview.c index d07d355e5..79238796c 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -25,7 +25,7 @@ static void set_all(MwTreeViewEntry** root, int v) { } } -static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** root, MwLLColor base, MwLLColor text, MwLLColor base2, MwLLColor text2, MwPoint* p, int next, int shift, int* skip, int* shared, int draw, MwPoint* mouse) { +static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** root, MwColor base, MwColor text, MwColor base2, MwColor text2, MwPoint* p, int next, int shift, int* skip, int* shared, int draw, MwPoint* mouse) { int i; MwPoint l[2]; int skipped = 0; @@ -42,7 +42,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[0] = *p; l[0].x -= LineSpace / 2; l[1] = *p; - if(draw) MwLLLine(handle->lowlevel, &l[0], text2); + if(draw) MwLLLine(handle->lowlevel, &l[0], text2->lowlevel); } if(shift > LineSpace) { @@ -53,7 +53,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** if(next) { l[1].y += MwTextHeight(handle, Font, "M") / 2; } - if(draw) MwLLLine(handle->lowlevel, &l[0], text2); + if(draw) MwLLLine(handle->lowlevel, &l[0], text2->lowlevel); } if(tree->tree != NULL) { r.width = OpenerSize; @@ -61,7 +61,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** r.x = p->x - LineSpace + (LineSpace - r.width) / 2; r.y = p->y - MwTextHeight(handle, Font, "M") / 2 + (MwTextHeight(handle, Font, "M") - r.height) / 2; if(draw) { - MwLLColor col = tree->opened ? MwLightenColor(handle, base, -8, -8, -8) : base; + MwColor col = tree->opened ? MwLightenColor(handle, base, -8, -8, -8) : base; MwRect r2 = r; const int len = 4; @@ -74,7 +74,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[1].x = l[0].x + len; l[1].y = l[0].y; - MwLLLine(handle->lowlevel, &l[0], text); + MwLLLine(handle->lowlevel, &l[0], text->lowlevel); } else { l[0].x = r.x + (r.width - len) / 2; l[0].y = r.y + r.height / 2; @@ -82,7 +82,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[1].x = l[0].x + len; l[1].y = l[0].y; - MwLLLine(handle->lowlevel, &l[0], text); + MwLLLine(handle->lowlevel, &l[0], text->lowlevel); l[0].x = r.x + r.width / 2; l[0].y = r.y + (r.height - len) / 2; @@ -90,12 +90,12 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[1].x = l[0].x; l[1].y = l[0].y + len; - MwLLLine(handle->lowlevel, &l[0], text); + MwLLLine(handle->lowlevel, &l[0], text->lowlevel); } r = r2; MwDrawFrame(handle, &r, base, tree->opened); - if(col != base) MwLLFreeColor(col); + if(col != base) MwFreeColor(col); } else { if(r.x <= mouse->x && mouse->x <= (r.x + r.width) && r.y <= mouse->y && mouse->y <= (r.y + r.height)) { tree->opened = tree->opened ? 0 : 1; @@ -104,12 +104,12 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** } if(tree->pixmap != NULL) { r.height = MwTextHeight(handle, Font, "M"); - r.width = r.height * tree->pixmap->common.width / tree->pixmap->common.height; + r.width = r.height * tree->pixmap->common->width / tree->pixmap->common->height; r.x = p->x + (MwGetInteger(handle->parent, MwNleftPadding) - r.width) / 2; r.y = p->y - MwTextHeight(handle, Font, "M") / 2; - if(draw) MwLLDrawPixmap(handle->lowlevel, &r, tree->pixmap); + if(draw) MwDrawPixmap(handle, &r, tree->pixmap); } p->x += MwGetInteger(handle->parent, MwNleftPadding); if(draw) { @@ -160,17 +160,17 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** if(skipped && p->y > l[0].y) { skipped = 0; } - if(draw && !skipped && i != (arrlen(tree->tree) - 1)) MwLLLine(handle->lowlevel, &l[0], text); + if(draw && !skipped && i != (arrlen(tree->tree) - 1)) MwLLLine(handle->lowlevel, &l[0], text->lowlevel); } } static void frame_draw(MwWidget handle) { MwRect r, r2; MwTreeView tv = handle->parent->internal; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwLLColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); + MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); MwPoint p; int shared = 0; int i; @@ -197,10 +197,10 @@ static void frame_draw(MwWidget handle) { MwDrawFrame(handle, &r, base, 1); - MwLLFreeColor(text2); - MwLLFreeColor(text); - MwLLFreeColor(base2); - MwLLFreeColor(base); + MwFreeColor(text2); + MwFreeColor(text); + MwFreeColor(base2); + MwFreeColor(base); } static int recursive_length(MwTreeViewEntry** e) { @@ -322,8 +322,8 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwRect r; + MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; r.x = 0; r.y = 0; @@ -331,10 +331,10 @@ static void draw(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, c); - MwLLFreeColor(c); + MwFreeColor(c); } -static void* mwTreeViewAddImpl(MwWidget handle, void* parent, MwLLPixmap pixmap, const char* item) { +static void* mwTreeViewAddImpl(MwWidget handle, void* parent, MwPixmap pixmap, const char* item) { MwTreeView tv = handle->internal; MwTreeViewEntry* t = malloc(sizeof(*t)); @@ -412,7 +412,7 @@ static void mwTreeViewSetLabelImpl(MwWidget handle, void* item, const char* labe } } -static void mwTreeViewSetPixmapImpl(MwWidget handle, void* item, MwLLPixmap pixmap) { +static void mwTreeViewSetPixmapImpl(MwWidget handle, void* item, MwPixmap pixmap) { MwTreeView tv = handle->internal; MwTreeViewEntry* e = item; @@ -447,7 +447,7 @@ static int mwTreeViewGetOpenedImpl(MwWidget handle, void* item) { static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwTreeViewAdd") == 0) { void* parent = va_arg(va, void*); - MwLLPixmap pixmap = va_arg(va, MwLLPixmap); + MwPixmap pixmap = va_arg(va, MwPixmap); const char* item = va_arg(va, const char*); *(void**)out = mwTreeViewAddImpl(handle, parent, pixmap, item); } @@ -468,8 +468,8 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v mwTreeViewSetLabelImpl(handle, item, label); } if(strcmp(name, "mwTreeViewSetPixmap") == 0) { - void* item = va_arg(va, void*); - MwLLPixmap pixmap = va_arg(va, MwLLPixmap); + void* item = va_arg(va, void*); + MwPixmap pixmap = va_arg(va, MwPixmap); mwTreeViewSetPixmapImpl(handle, item, pixmap); } if(strcmp(name, "mwTreeViewSetOpened") == 0) { diff --git a/src/widget/viewport.c b/src/widget/viewport.c index 803c42433..8f673a980 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -101,8 +101,8 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; + MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); r.x = 0; r.y = 0; @@ -111,7 +111,7 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r, base); - MwLLFreeColor(base); + MwFreeColor(base); } static void prop_change(MwWidget handle, const char* prop) { diff --git a/src/widget/window.c b/src/widget/window.c index 9ea16a304..3bf3e763f 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -10,8 +10,8 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwRect r; + MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; r.x = 0; r.y = 0; @@ -22,7 +22,7 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r, c); - MwLLFreeColor(c); + MwFreeColor(c); } static void prop_change(MwWidget handle, const char* key) { diff --git a/tools/color.pl b/tools/color.pl index eca072ca1..074819f9c 100755 --- a/tools/color.pl +++ b/tools/color.pl @@ -13,12 +13,10 @@ print(OUT "};\n"); print(OUT "\n"); print(OUT "static struct color* colors = NULL;\n"); print(OUT "\n"); -print(OUT "MwLLColor MwParseColorName(MwWidget handle, const char* color){\n"); +print(OUT "MwColor MwParseColorName(MwWidget handle, const char* color){\n"); print(OUT " MwRGB rgb;\n"); print(OUT " MwParseColorNameNoAllocate(color, &rgb);\n"); -print(OUT -" return MwLLAllocColor(handle->lowlevel, rgb.red, rgb.green, rgb.blue);\n" -); +print(OUT " return MwAllocColor(handle, rgb.red, rgb.green, rgb.blue);\n"); print(OUT "}\n"); print(OUT "\n"); print(OUT "void MwParseColorNameNoAllocate(const char* color, MwRGB* rgb){\n"); diff --git a/tools/font.c b/tools/font.c index 999b47efb..0a1372221 100644 --- a/tools/font.c +++ b/tools/font.c @@ -35,7 +35,7 @@ int main(int argc, char** argv) { printf(" * Copyright notice:\n"); printf(" * \"%s\"\n", rec.u.atom); printf(" */\n"); - printf("MwFont MwFontData[] = {\n"); + printf("MwFontResource MwFontData[] = {\n"); for(i = 0; i < 0x100; i++) { int y, x; FT_Bitmap bitmap; From e59157780178e73864034c599030a01b35633efb Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 06:09:21 +0900 Subject: [PATCH 061/102] use MwPolygon/MwLine instead of lowlevel ones --- include/Mw/Draw.h | 17 +++++++++++++ src/draw.c | 58 ++++++++++++++++++++++++------------------ src/widget/calendar.c | 6 ++--- src/widget/chart.c | 46 ++++++++++++++++----------------- src/widget/checkbox.c | 2 +- src/widget/clock.c | 12 ++++----- src/widget/document.c | 2 +- src/widget/subwindow.c | 22 ++++++++-------- src/widget/treeview.c | 12 ++++----- 9 files changed, 101 insertions(+), 76 deletions(-) diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 307fbb26e..9786dffb0 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -83,6 +83,23 @@ MWDECL void MWAPI MwDrawRectLine(MwWidget handle, MwRect* rect, MwColor color); */ MWDECL void MWAPI MwDrawRectFading(MwWidget handle, MwRect* rect, MwColor color); +/*! + * @brief Draws a polygon + * @param handle Widget + * @param points Points (counter-clockwise) + * @param points_count Amount of points + * @param color Color + */ +MWDECL void MWAPI MwPolygon(MwWidget handle, MwPoint* points, int points_count, MwColor color); + +/*! + * @brief Draws a Line + * @param handle Widget + * @param points Points + * @param color Color + */ +MWDECL void MWAPI MwLine(MwWidget handle, MwPoint* points, MwColor color); + /*! * @brief Draws a frame * @param handle Widget diff --git a/src/draw.c b/src/draw.c index da6e28e37..ca3acec34 100644 --- a/src/draw.c +++ b/src/draw.c @@ -131,7 +131,7 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwColor color) { p[3].x = r.x; p[3].y = r.y + r.height; - MwLLPolygon(handle->lowlevel, p, 4, color->lowlevel); + MwPolygon(handle, p, 4, color); } void MwDrawRectLine(MwWidget handle, MwRect* rect, MwColor color) { @@ -154,10 +154,10 @@ void MwDrawRectLine(MwWidget handle, MwRect* rect, MwColor color) { p[4] = p[0]; - MwLLLine(handle->lowlevel, &p[0], color->lowlevel); - MwLLLine(handle->lowlevel, &p[1], color->lowlevel); - MwLLLine(handle->lowlevel, &p[2], color->lowlevel); - MwLLLine(handle->lowlevel, &p[3], color->lowlevel); + MwLine(handle, &p[0], color); + MwLine(handle, &p[1], color); + MwLine(handle, &p[2], color); + MwLine(handle, &p[3], color); } void MwDrawRectFading(MwWidget handle, MwRect* rect, MwColor color) { @@ -202,6 +202,14 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwColor color) { free(data); } +void MwPolygon(MwWidget handle, MwPoint* points, int points_count, MwColor color) { + MwLLPolygon(handle->lowlevel, points, points_count, color->lowlevel); +} + +void MwLine(MwWidget handle, MwPoint* points, MwColor color) { + MwLLLine(handle->lowlevel, points, color->lowlevel); +} + void MwDrawFrame(MwWidget handle, MwRect* rect, MwColor color, int invert) { MwDrawFrameWithBorder(handle, rect, color, invert, MwDefaultBorderWidth(handle)); } @@ -305,7 +313,7 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwColor color, int invert) { p[5].x = rect->x + border; p[5].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p, 6, (invert ? darker : lighter)->lowlevel); + MwPolygon(handle, p, 6, (invert ? darker : lighter)); p[0].x = rect->x; p[0].y = rect->y + rect->height / 2; @@ -325,7 +333,7 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwColor color, int invert) { p[5].x = rect->x + border; p[5].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p, 6, (invert ? lighter : darker)); p[0].x = rect->x + rect->width / 2; p[0].y = rect->y + border; @@ -339,7 +347,7 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwColor color, int invert) { p[3].x = rect->x + border; p[3].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p, 4, col->lowlevel); + MwPolygon(handle, p, 4, col); MwFreeColor(col); MwFreeColor(lighter); @@ -469,7 +477,7 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwColor color, i p[5].x = rect->x; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, (invert ? darker : lighter)->lowlevel); + MwPolygon(handle, p, 6, (invert ? darker : lighter)); p[0].x = rect->x + rect->width; p[0].y = rect->y; @@ -488,7 +496,7 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwColor color, i p[5].x = rect->x + rect->width; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p, 6, (invert ? lighter : darker)); MwFreeColor(lighter); MwFreeColor(darker); @@ -521,7 +529,7 @@ static void frame_border_complex(MwWidget handle, MwRect* rect, MwColor lighter, p[5].x = rect->x; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p, 6, (invert ? lighter : darker)); p[0].x = rect->x + rect->width; p[0].y = rect->y; @@ -540,7 +548,7 @@ static void frame_border_complex(MwWidget handle, MwRect* rect, MwColor lighter, p[5].x = rect->x + rect->width; p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p, 6, (invert ? lighter : darker)); } static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwColor color, int invert, int border, int diff, int same) { @@ -633,9 +641,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, in p3[3].x = (int)(rect->x + rect->width - c * border); p3[3].y = (int)(rect->y + rect->height - s * border); - MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); - MwLLPolygon(handle->lowlevel, p2, 4, (invert ? lighter : darker)->lowlevel); - MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p1, 4, (invert ? darker : lighter)); + MwPolygon(handle, p2, 4, (invert ? lighter : darker)); + MwPolygon(handle, p3, 4, (invert ? lighter : darker)); p4[0].x = (int)(rect->x + c * border); p4[0].y = (int)(rect->y + rect->height - s * border); @@ -682,9 +690,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, in p3[3].x = (int)(rect->x + rect->width - c * border); p3[3].y = (int)(rect->y + s * border); - MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); - MwLLPolygon(handle->lowlevel, p2, 4, (invert ? darker : lighter)->lowlevel); - MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p1, 4, (invert ? darker : lighter)); + MwPolygon(handle, p2, 4, (invert ? darker : lighter)); + MwPolygon(handle, p3, 4, (invert ? lighter : darker)); p4[0].x = (int)(rect->x + c * border); p4[0].y = (int)(rect->y + s * border); @@ -731,9 +739,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, in p3[3].x = (int)(rect->x + rect->width - border); p3[3].y = rect->y + rect->height / 2; - MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); - MwLLPolygon(handle->lowlevel, p2, 4, (invert ? darker : lighter)->lowlevel); - MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p1, 4, (invert ? darker : lighter)); + MwPolygon(handle, p2, 4, (invert ? darker : lighter)); + MwPolygon(handle, p3, 4, (invert ? lighter : darker)); p4[0].x = (int)(rect->x + rect->width - border); p4[0].y = rect->y + rect->height / 2; @@ -780,9 +788,9 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, in p3[3].x = rect->x + rect->width; p3[3].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p1, 4, (invert ? darker : lighter)->lowlevel); - MwLLPolygon(handle->lowlevel, p2, 4, (invert ? lighter : darker)->lowlevel); - MwLLPolygon(handle->lowlevel, p3, 4, (invert ? lighter : darker)->lowlevel); + MwPolygon(handle, p1, 4, (invert ? darker : lighter)); + MwPolygon(handle, p2, 4, (invert ? lighter : darker)); + MwPolygon(handle, p3, 4, (invert ? lighter : darker)); p4[0].x = (int)(rect->x + border); p4[0].y = rect->y + rect->height / 2; @@ -793,7 +801,7 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwColor color, int invert, in p4[2].x = (int)(rect->x + rect->width - c * border); p4[2].y = (int)(rect->y + s * border); } - MwLLPolygon(handle->lowlevel, p4, 3, col->lowlevel); + MwPolygon(handle, p4, 3, col); MwFreeColor(col); MwFreeColor(lighter); diff --git a/src/widget/calendar.c b/src/widget/calendar.c index f5c3a80eb..7005558dc 100644 --- a/src/widget/calendar.c +++ b/src/widget/calendar.c @@ -135,7 +135,7 @@ static void draw(MwWidget handle) { p[4].y = p[0].y + gh * 7; p[5].x = p[0].x + h; p[5].y = p[0].y; - MwLLPolygon(handle->lowlevel, p, 6, cb_g->lowlevel); + MwPolygon(handle, p, 6, cb_g); p[0].x = (r.width - h) / 2; p[0].y = (r.height - h - sh) / 2; @@ -149,7 +149,7 @@ static void draw(MwWidget handle) { p[4].y = p[0].y + gh * 3; p[5].x = p[0].x + h; p[5].y = p[0].y; - MwLLPolygon(handle->lowlevel, p, 6, ct->lowlevel); + MwPolygon(handle, p, 6, ct); r2.width = h; r2.height = h - ph - gh; @@ -175,7 +175,7 @@ static void draw(MwWidget handle) { p[2].y = r2.y + r2.height + ph; p[3].x = r2.x + r2.width; p[3].y = r2.y + r2.height; - MwLLPolygon(handle->lowlevel, p, 4, cb->lowlevel); + MwPolygon(handle, p, 4, cb); p[0].x = r.width / 2; p[0].y = (r.height - sh) / 2; diff --git a/src/widget/chart.c b/src/widget/chart.c index 6003ff9f7..6a9bba9e7 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -53,13 +53,13 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou p2[1].x += height; p2[1].y -= height; - MwLLLine(handle->lowlevel, &p2[0], color->lowlevel); + MwLine(handle, &p2[0], color); p[0].x += height; p[0].y -= height; p[1].y -= height; } - MwLLLine(handle->lowlevel, &p[0], color->lowlevel); + MwLine(handle, &p[0], color); } #define CALC_VMIN_VMAX \ @@ -126,14 +126,14 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int p[1].x = node.x; p[1].y = r.height - space; - MwLLLine(handle->lowlevel, &p[0], border->lowlevel); + MwLine(handle, &p[0], border); p[0].x = node.x; p[0].y = r.height - space; p[1].x = node.x + twidth; p[1].y = p[0].y; - MwLLLine(handle->lowlevel, &p[0], border->lowlevel); + MwLine(handle, &p[0], border); node.width = width; for(i = 0; i < arrlen(c->entries); i++) { @@ -170,7 +170,7 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int persp_top[4] = persp_top[0]; - MwLLPolygon(handle->lowlevel, persp_top, 4, colorl->lowlevel); + MwPolygon(handle, persp_top, 4, colorl); persp_right[0] = *(MwPoint*)&node2; persp_right[1] = *(MwPoint*)&node2; @@ -189,22 +189,22 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int persp_right[4] = persp_right[0]; - MwLLPolygon(handle->lowlevel, persp_right, 4, colord->lowlevel); + MwPolygon(handle, persp_right, 4, colord); } if(!modern) { MwDrawRectLine(handle, &node, border); if(type == MwCHART_BAR_3D) { - MwLLLine(handle->lowlevel, &persp_top[0], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_top[1], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_top[2], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_top[3], border->lowlevel); + MwLine(handle, &persp_top[0], border); + MwLine(handle, &persp_top[1], border); + MwLine(handle, &persp_top[2], border); + MwLine(handle, &persp_top[3], border); - MwLLLine(handle->lowlevel, &persp_right[0], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_right[1], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_right[2], border->lowlevel); - MwLLLine(handle->lowlevel, &persp_right[3], border->lowlevel); + MwLine(handle, &persp_right[0], border); + MwLine(handle, &persp_right[1], border); + MwLine(handle, &persp_right[2], border); + MwLine(handle, &persp_right[3], border); } } @@ -282,27 +282,27 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M p3[2] = p2[1]; if(k == 0) { - MwLLPolygon(handle->lowlevel, p3, count + 2, color->lowlevel); + MwPolygon(handle, p3, count + 2, color); } else if(d == 1 && k == 1) { for(j = 3; j < count + 1; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p3[j], border->lowlevel); + if(!modern) MwLine(handle, &p3[j], border); } p2[0] = p2[1]; p2[0].y += radius / 8; - if(!modern) MwLLLine(handle->lowlevel, p2, border->lowlevel); + if(!modern) MwLine(handle, p2, border); } } } if(k == 2) { - MwLLPolygon(handle->lowlevel, p2, count, (type == MwCHART_PIE_3D ? colorl : color)->lowlevel); + MwPolygon(handle, p2, count, (type == MwCHART_PIE_3D ? colorl : color)); } else if(k == 3) { int j; p2[count] = p2[0]; for(j = 0; j < count; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p2[j], border->lowlevel); + if(!modern) MwLine(handle, &p2[j], border); } p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; @@ -325,10 +325,10 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M p[0].y = r.height / 2; p[1] = p[0]; p[1].y += radius / 8; - MwLLLine(handle->lowlevel, p, border->lowlevel); + MwLine(handle, p, border); p[0].x = p[1].x = r.width / 2 + radius / 2; - MwLLLine(handle->lowlevel, p, border->lowlevel); + MwLine(handle, p, border); } } @@ -376,7 +376,7 @@ static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, in p[1] = p[0]; p[1].y = r.height - space; - MwLLLine(handle->lowlevel, p, border->lowlevel); + MwLine(handle, p, border); for(j = 0; j < 2; j++) { for(i = j == 0 ? 1 : 0; i < arrlen(c->entries); i++) { @@ -386,7 +386,7 @@ static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, in p[1].y = (r.height - space) - (c->entries[i].value - vmin) / (vmax - vmin) * (r.height - space); if(j == 0) { - MwLLLine(handle->lowlevel, p, border->lowlevel); + MwLine(handle, p, border); } else { MwDrawText(handle, NULL, &p[1], c->entries[i].name, MwALIGNMENT_CENTER, border); } diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 0837f028c..5e9cff135 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -60,7 +60,7 @@ static void draw(MwWidget handle) { p[5] = p[0]; p[5].y -= r.height / 3; - MwLLPolygon(handle->lowlevel, p, 6, text2->lowlevel); + MwPolygon(handle, p, 6, text2); } MwFreeColor(text2); diff --git a/src/widget/clock.c b/src/widget/clock.c index 3ad1862ec..6e03a4c83 100644 --- a/src/widget/clock.c +++ b/src/widget/clock.c @@ -43,12 +43,12 @@ static void hand(MwWidget handle, double x, double y, double width, double lengt p[4] = p[0]; - MwLLPolygon(handle->lowlevel, p, 4, inside->lowlevel); + MwPolygon(handle, p, 4, inside); - MwLLLine(handle->lowlevel, &p[0], border->lowlevel); - MwLLLine(handle->lowlevel, &p[1], border->lowlevel); - MwLLLine(handle->lowlevel, &p[2], border->lowlevel); - MwLLLine(handle->lowlevel, &p[3], border->lowlevel); + MwLine(handle, &p[0], border); + MwLine(handle, &p[1], border); + MwLine(handle, &p[2], border); + MwLine(handle, &p[3], border); } static void draw(MwWidget handle) { @@ -96,7 +96,7 @@ static void draw(MwWidget handle) { p[1].x = x; p[1].y = y; - MwLLLine(handle->lowlevel, p, border->lowlevel); + MwLine(handle, p, border); } hand(handle, ShadowDist, ShadowDist, BaseWidth, w / 2 * 2 / 3, h, shadow, shadow); diff --git a/src/widget/document.c b/src/widget/document.c index f2f430c1e..045605f43 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -138,7 +138,7 @@ static void draw(MwWidget handle) { if(j == 0 || j == 1) { line[0].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); line[1].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); - MwLLLine(handle->lowlevel, line, (c ? base : text)->lowlevel); + MwLine(handle, line, (c ? base : text)); } } } diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index f955bdced..484b998a8 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -18,21 +18,21 @@ static void close_draw(MwWidget handle) { p[0].y = bw * 2; p[1].x = w - bw * 2 - 1; p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); p[0].x++; p[1].x--; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, 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->lowlevel); + MwLine(handle, p, c); p[0].x--; p[1].x++; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); MwFreeColor(c); } @@ -59,22 +59,22 @@ static void maximize_draw(MwWidget handle) { p[0].y = bw * 2; p[1].x = w - bw * 2 - 1; p[1].y = bw * 2; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); p[0].y = p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); p[0].y = p[1].y = bw * 2 + 1; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); p[0].x = bw * 2; p[0].y = bw * 2; p[1].x = bw * 2; p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); p[0].x = p[1].x = w - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); MwFreeColor(c); } @@ -124,11 +124,11 @@ static void minimize_draw(MwWidget handle) { p[0].y = h - bw * 2 - 1; p[1].x = w - bw * 2 - 1; p[1].y = h - bw * 2 - 1; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); p[0].y--; p[1].y--; - MwLLLine(handle->lowlevel, p, c->lowlevel); + MwLine(handle, p, c); MwFreeColor(c); } diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 79238796c..55bc916ec 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -42,7 +42,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[0] = *p; l[0].x -= LineSpace / 2; l[1] = *p; - if(draw) MwLLLine(handle->lowlevel, &l[0], text2->lowlevel); + if(draw) MwLine(handle, &l[0], text2); } if(shift > LineSpace) { @@ -53,7 +53,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** if(next) { l[1].y += MwTextHeight(handle, Font, "M") / 2; } - if(draw) MwLLLine(handle->lowlevel, &l[0], text2->lowlevel); + if(draw) MwLine(handle, &l[0], text2); } if(tree->tree != NULL) { r.width = OpenerSize; @@ -74,7 +74,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[1].x = l[0].x + len; l[1].y = l[0].y; - MwLLLine(handle->lowlevel, &l[0], text->lowlevel); + MwLine(handle, &l[0], text); } else { l[0].x = r.x + (r.width - len) / 2; l[0].y = r.y + r.height / 2; @@ -82,7 +82,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[1].x = l[0].x + len; l[1].y = l[0].y; - MwLLLine(handle->lowlevel, &l[0], text->lowlevel); + MwLine(handle, &l[0], text); l[0].x = r.x + r.width / 2; l[0].y = r.y + (r.height - len) / 2; @@ -90,7 +90,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** l[1].x = l[0].x; l[1].y = l[0].y + len; - MwLLLine(handle->lowlevel, &l[0], text->lowlevel); + MwLine(handle, &l[0], text); } r = r2; MwDrawFrame(handle, &r, base, tree->opened); @@ -160,7 +160,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** if(skipped && p->y > l[0].y) { skipped = 0; } - if(draw && !skipped && i != (arrlen(tree->tree) - 1)) MwLLLine(handle->lowlevel, &l[0], text->lowlevel); + if(draw && !skipped && i != (arrlen(tree->tree) - 1)) MwLine(handle, &l[0], text); } } From 845be77805e72b4d01eb9a52e32f599b811e013c Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 06:15:29 +0900 Subject: [PATCH 062/102] MwSetVoid/MwGetVoid to Pointer --- examples/basic/periodic.c | 4 ++-- include/Mw/Core.h | 8 ++++---- include/Mw/StringDefs.h | 18 +++++++++--------- milsko.xml | 6 +++--- src/core.c | 10 +++++----- src/dialog/messagebox.c | 4 ++-- src/text/text.c | 4 ++-- src/widget/button.c | 4 ++-- src/widget/checkbox.c | 2 +- src/widget/entry.c | 2 +- src/widget/frame.c | 2 +- src/widget/image.c | 2 +- src/widget/label.c | 4 ++-- src/widget/progressbar.c | 2 +- src/widget/radiobox.c | 2 +- src/widget/scrollbar.c | 2 +- src/widget/subwindow.c | 2 +- src/widget/tab.c | 4 ++-- src/widget/vulkan.c | 2 +- 19 files changed, 42 insertions(+), 42 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index fb2fbd9d0..a5bf531d5 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -118,7 +118,7 @@ static MwWidget frame(const char* name, int width, int height, MwClass cl, ...) MwAddUserHandler(frame, MwNresizeHandler, resize_content, NULL); MwVaApply(f, - "VhandledWidget", w, + "PhandledWidget", w, MwNcolumnSpan, MwGetInteger(w, MwNcolumnSpan), MwNrowSpan, MwGetInteger(w, MwNrowSpan), NULL); @@ -132,7 +132,7 @@ static MwWidget frame(const char* name, int width, int height, MwClass cl, ...) } static MwWidget child(MwWidget w) { - return MwGetVoid(w, "VhandledWidget"); + return MwGetPointer(w, "PhandledWidget"); } static void MWAPI menu_handler(MwWidget handle, void* user, void* call) { diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 318a8cab3..66a3372aa 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -162,12 +162,12 @@ MWDECL void MWAPI MwSetInteger(MwWidget handle, const char* key, int n); MWDECL void MWAPI MwSetText(MwWidget handle, const char* key, const char* value); /*! - * @brief Sets a void pointer property + * @brief Sets a pointer property * @param handle Widget * @param key Key * @param value Value */ -MWDECL void MWAPI MwSetVoid(MwWidget handle, const char* key, void* value); +MWDECL void MWAPI MwSetPointer(MwWidget handle, const char* key, void* value); /*! * @brief Gets the integer property @@ -186,12 +186,12 @@ MWDECL int MWAPI MwGetInteger(MwWidget handle, const char* key); MWDECL const char* MWAPI MwGetText(MwWidget handle, const char* key); /*! - * @brief Gets the void pointer property + * @brief Gets the pointer property * @param handle Widget * @param key Key * @return Value */ -MWDECL void* MWAPI MwGetVoid(MwWidget handle, const char* key); +MWDECL void* MWAPI MwGetPointer(MwWidget handle, const char* key); /*! * @brief Sets the default property diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 8d00b409e..d04aee083 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -72,16 +72,16 @@ #define MwNvulkanExtension "SEvulkanExtension" #define MwNvulkanLayer "SEvulkanLayer" -#define MwNvulkanConfig "VEvulkanConfig" +#define MwNvulkanConfig "PEvulkanConfig" -#define MwNpixmap "Vpixmap" -#define MwNiconPixmap "ViconPixmap" -#define MwNsizeHints "VsizeHints" -#define MwNfont "Vfont" -#define MwNboldFont "VboldFont" -#define MwNbackgroundPixmap "VbackgroundPixmap" -#define MwNmonospaceFont "VmonospaceFont" -#define MwNboldMonospaceFont "VboldMonospaceFont" +#define MwNpixmap "Ppixmap" +#define MwNiconPixmap "PiconPixmap" +#define MwNsizeHints "PsizeHints" +#define MwNfont "Pfont" +#define MwNboldFont "PboldFont" +#define MwNbackgroundPixmap "PbackgroundPixmap" +#define MwNmonospaceFont "PmonospaceFont" +#define MwNboldMonospaceFont "PboldMonospaceFont" #define MwNactivateHandler "Cactivate" #define MwNlistBoxActivateHandler "ClistBoxActivate" diff --git a/milsko.xml b/milsko.xml index 81d6e136e..c053bf7b4 100644 --- a/milsko.xml +++ b/milsko.xml @@ -55,7 +55,7 @@ Integer properties must be prefixed with I. String properties must be prefixed with S. Handler properties must be prefixed with C. - Other properties must be prefixed with V. + Other properties must be prefixed with P. "Early" properties must have letter "E" as 2nd letter. e.g. vulkanExtension would be SEvulkanExtension @@ -383,7 +383,7 @@ - + @@ -408,7 +408,7 @@ - + diff --git a/src/core.c b/src/core.c index a2e520fd0..c06241e70 100644 --- a/src/core.c +++ b/src/core.c @@ -745,7 +745,7 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { } } -void MwSetVoid(MwWidget handle, const char* key, void* value) { +void MwSetPointer(MwWidget handle, const char* key, void* value) { if(IsFirstVisible(handle) && strcmp(key, MwNiconPixmap) == 0) { MwLLSetIcon(handle->lowlevel, value); } else if(strcmp(key, MwNsizeHints) == 0) { @@ -851,14 +851,14 @@ const char* MwGetText(MwWidget handle, const char* key) { static void* inherit_void(MwWidget handle, const char* key) { void* v; - if(handle->parent != NULL && (v = MwGetVoid(handle->parent, key)) != NULL) { + if(handle->parent != NULL && (v = MwGetPointer(handle->parent, key)) != NULL) { return v; } return NULL; } #endif -void* MwGetVoid(MwWidget handle, const char* key) { +void* MwGetPointer(MwWidget handle, const char* key) { void* v = shget(handle->data, key); if(v != NULL) return v; @@ -936,10 +936,10 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(only_early && key[1] != 'E') continue; MwAddUserHandler(handle, key, h, NULL); - } else if(key[0] == 'V') { + } else if(key[0] == 'P') { void* v = va_arg(va, void*); if(only_early && key[1] != 'E') continue; - MwSetVoid(handle, key, v); + MwSetPointer(handle, key, v); } } if(x != MwDEFAULT && y != MwDEFAULT) { diff --git a/src/dialog/messagebox.c b/src/dialog/messagebox.c index 4a319ff14..a15421904 100644 --- a/src/dialog/messagebox.c +++ b/src/dialog/messagebox.c @@ -21,7 +21,7 @@ static void spawn_button(MwWidget handle, int x, int y, int id, const char* text static void messagebox_destroy_inject(MwWidget handle) { void* px; - if((px = MwGetVoid(handle, MwNpixmap)) != NULL) MwDestroyPixmap(px); + if((px = MwGetPointer(handle, MwNpixmap)) != NULL) MwDestroyPixmap(px); } static void MWAPI messagebox_close(MwWidget handle, void* user, void* call) { @@ -109,7 +109,7 @@ MwWidget MwMessageBox(MwWidget handle, const char* text, const char* title, unsi px = MwLoadIcon(icon, data); - MwSetVoid(icon, MwNpixmap, px); + MwSetPointer(icon, MwNpixmap, px); left = 8 + 48 + 8; } diff --git a/src/text/text.c b/src/text/text.c index 327a32cab..f7ebd4029 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -71,8 +71,8 @@ static int is_monospace(MwWidget handle, MwFLFont ttf) { static MwFLFont assume_ttf(MwWidget handle, MwFLFont ttf) { if(is_bitmap(handle, ttf)) return NULL; - if(is_monospace(handle, ttf)) return is_bold(handle, ttf) ? MwGetVoid(handle, MwNboldMonospaceFont) : MwGetVoid(handle, MwNmonospaceFont); - return is_bold(handle, ttf) ? MwGetVoid(handle, MwNboldFont) : MwGetVoid(handle, MwNfont); + if(is_monospace(handle, ttf)) return is_bold(handle, ttf) ? MwGetPointer(handle, MwNboldMonospaceFont) : MwGetPointer(handle, MwNmonospaceFont); + return is_bold(handle, ttf) ? MwGetPointer(handle, MwNboldFont) : MwGetPointer(handle, MwNfont); } #endif diff --git a/src/widget/button.c b/src/widget/button.c index a0857c18a..1df224695 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -18,8 +18,8 @@ static void draw(MwWidget handle) { MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); const char* str = MwGetText(handle, MwNtext); - MwPixmap px = MwGetVoid(handle, MwNpixmap); - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap px = MwGetPointer(handle, MwNpixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); int inv; if(str == NULL) str = ""; diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 5e9cff135..2b29ac65a 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -13,7 +13,7 @@ static void draw(MwWidget handle) { MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; diff --git a/src/widget/entry.c b/src/widget/entry.c index 6f363f208..305545c12 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -50,7 +50,7 @@ static void draw(MwWidget handle) { MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); const char* str = MwGetText(handle, MwNtext); - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); MwFLFont font = MwFLBuildFont(MwFLFlagMonospace); if(str == NULL) str = ""; diff --git a/src/widget/frame.c b/src/widget/frame.c index 841fae27f..5ed79f529 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -14,7 +14,7 @@ static void draw(MwWidget handle) { MwRect rr; MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); int inverted; - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); if(MwGetInteger(handle, MwNhasBorder)) { inverted = MwGetInteger(handle, MwNinverted); diff --git a/src/widget/image.c b/src/widget/image.c index 17c0d3ab6..6d5423b57 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -12,7 +12,7 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwPixmap px = MwGetVoid(handle, MwNpixmap); + MwPixmap px = MwGetPointer(handle, MwNpixmap); MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); r.x = 0; diff --git a/src/widget/label.c b/src/widget/label.c index 7dc8b52d9..e11fcc40f 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -129,7 +129,7 @@ static void draw_seven_segment(MwWidget handle) { MwColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; const char* str = MwGetText(handle, MwNtext); - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); MwLabel lab = handle->internal; int l_one = MwGetInteger(handle, MwNlength) - (MwGetInteger(handle, MwNlength) % 2); int s_one = (l_one * 3 / 4) - ((l_one * 3 / 4) % 2) + 1; @@ -320,7 +320,7 @@ static void draw_normal(MwWidget handle) { MwColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; const char* str = MwGetText(handle, MwNtext); - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); if(str == NULL) str = ""; diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index 97352b0aa..879bd42ed 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -16,7 +16,7 @@ static void draw(MwWidget handle) { MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwColor fill = MwParseColor(handle, MwGetText(handle, MwNforeground)); double w; - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index 6fce85a9b..475991fef 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -13,7 +13,7 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 82e82861a..613868bd1 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -60,7 +60,7 @@ static void draw(MwWidget handle) { MwScrollBar scr = handle->internal; int or ; int uy, dy, ux, dx; - MwPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index 484b998a8..37c7b14a5 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -291,7 +291,7 @@ static void draw(MwWidget handle) { MwRect r, r2, r3; const char* title = MwGetText(handle, MwNtitle); int incr = 0; - MwPixmap px = MwGetVoid(handle, MwNiconPixmap); + MwPixmap px = MwGetPointer(handle, MwNiconPixmap); r.x = 0; r.y = 0; diff --git a/src/widget/tab.c b/src/widget/tab.c index 870668903..3ae47dc2a 100644 --- a/src/widget/tab.c +++ b/src/widget/tab.c @@ -45,7 +45,7 @@ static int icon_width(MwWidget handle, const char* text) { for(i = 0; i < arrlen(t->names); i++) { if(strcmp(t->names[i], text) == 0) { - MwPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + MwPixmap px = MwGetPointer(t->frames[i], MwNiconPixmap); if(px == NULL) return 0; @@ -97,7 +97,7 @@ static void draw(MwWidget handle) { x += r2.width; if(iw > 0) { - MwPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + MwPixmap px = MwGetPointer(t->frames[i], MwNiconPixmap); MwRect rp; rp = r2; diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 0bc0703d9..a57e142b8 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -576,7 +576,7 @@ static void prop_change(MwWidget handle, const char* prop) { arrput(o->enabledLayers, str); } else if(strcmp(prop, MwNvulkanConfig) == 0) { - memcpy(&o->vulkan_config, MwGetVoid(handle, MwNvulkanConfig), sizeof(MwVulkanConfig)); + memcpy(&o->vulkan_config, MwGetPointer(handle, MwNvulkanConfig), sizeof(MwVulkanConfig)); } } From 8d91a97dadf69837b809098be6977e5f98197689 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 06:30:16 +0900 Subject: [PATCH 063/102] some migration --- examples/basic/calculator.c | 6 +++--- examples/basic/colorpicker.c | 12 ++++++------ examples/basic/filechooser.c | 2 +- examples/basic/periodic.c | 6 +++--- examples/gldemos/clock.c | 8 ++++---- include/Mw/Core.h | 4 ++-- include/Mw/TypeDefs.h | 15 +++++++++------ milsko.xml | 6 +++--- src/core.c | 36 ++++++++++++++++++++---------------- src/dialog/colorpicker.c | 20 ++++++++++---------- src/dialog/filechooser.c | 4 ++-- src/draw.c | 20 +++++++++++++++----- src/text/text.c | 2 +- src/widget/box.c | 2 +- src/widget/button.c | 6 +++--- src/widget/calendar.c | 4 ++-- src/widget/chart.c | 4 ++-- src/widget/checkbox.c | 6 +++--- src/widget/clock.c | 6 +++--- src/widget/combobox.c | 4 ++-- src/widget/document.c | 6 +++--- src/widget/entry.c | 20 ++++++++++---------- src/widget/frame.c | 2 +- src/widget/image.c | 2 +- src/widget/label.c | 12 ++++++------ src/widget/listbox.c | 12 ++++++------ src/widget/menu.c | 4 ++-- src/widget/numberentry.c | 10 +++++----- src/widget/progressbar.c | 4 ++-- src/widget/radiobox.c | 2 +- src/widget/scrollbar.c | 2 +- src/widget/separator.c | 2 +- src/widget/submenu.c | 4 ++-- src/widget/subwindow.c | 14 +++++++------- src/widget/tab.c | 4 ++-- src/widget/treeview.c | 10 +++++----- src/widget/viewport.c | 2 +- src/widget/vulkan.c | 4 ++-- src/widget/window.c | 2 +- 39 files changed, 154 insertions(+), 137 deletions(-) diff --git a/examples/basic/calculator.c b/examples/basic/calculator.c index 8889e97d3..f066e6ea5 100644 --- a/examples/basic/calculator.c +++ b/examples/basic/calculator.c @@ -31,10 +31,10 @@ static void MWAPI resize(MwWidget handle, void* client, void* user) { } static void MWAPI activate(MwWidget handle, void* client, void* user) { - const char* n = MwGetText(handle, MwNtext); + const char* n = MwGetString(handle, MwNtext); if(('0' <= n[0] && n[0] <= '9') || n[0] == '.') { - const char* s = MwGetText(inp, MwNtext); + const char* s = MwGetString(inp, MwNtext); char* r; if(n[0] == '.' && s != NULL) { @@ -52,7 +52,7 @@ static void MWAPI activate(MwWidget handle, void* client, void* user) { NULL); free(r); } else if(n[0] == 'E') { - const char* s = MwGetText(inp, MwNtext); + const char* s = MwGetString(inp, MwNtext); if(s != NULL) { stack[sp++] = atof(s); diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index d02e3576f..f67589d31 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -15,7 +15,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { rgb->green &= 0xff; rgb->blue &= 0xff; MwStringPrintIntoBuffer(hexColor, 8, "#%02X%02X%02X", rgb->red, rgb->green, rgb->blue); - MwSetText(window, MwNbackground, hexColor); + MwSetString(window, MwNbackground, hexColor); } void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { @@ -27,7 +27,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(cpicker, MwNcolorChosenHandler, file_callback, NULL); - MwSetText(cpicker, MwNbackground, MwGetInteger(cpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetString(cpicker, MwNbackground, MwGetInteger(cpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); } int main() { @@ -35,14 +35,14 @@ int main() { window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); - MwSetText(window, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); + MwSetString(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetString(window, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); - MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); - MwSetText(button, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); + MwSetString(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetString(button, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); MwAddUserHandler(button, MwNactivateHandler, file_picker, NULL); diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index a9a5ec0b5..0251be556 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -48,7 +48,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(fpicker, MwNfileChosenHandler, file_callback, NULL); - MwSetText(fpicker, MwNbackground, MwGetInteger(fpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetString(fpicker, MwNbackground, MwGetInteger(fpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); #ifdef BUG fpicker_wait = MwTRUE; diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index a5bf531d5..f1af2490c 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -354,9 +354,9 @@ int main() { f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, NULL); w = child(f); - MwSetText(MwTabAdd(w, "ABC"), MwNbackground, "#f00"); - MwSetText(MwTabAdd(w, "DEF"), MwNbackground, "#0f0"); - MwSetText(MwTabAdd(w, "GHI"), MwNbackground, "#00f"); + MwSetString(MwTabAdd(w, "ABC"), MwNbackground, "#f00"); + MwSetString(MwTabAdd(w, "DEF"), MwNbackground, "#0f0"); + MwSetString(MwTabAdd(w, "GHI"), MwNbackground, "#00f"); f = frame("TreeView", -PaddingContent, -PaddingContent, MwTreeViewClass, NULL); w = child(f); diff --git a/examples/gldemos/clock.c b/examples/gldemos/clock.c index 9f683b507..2c1c7031e 100644 --- a/examples/gldemos/clock.c +++ b/examples/gldemos/clock.c @@ -33,10 +33,10 @@ void MWAPI tick(MwWidget handle, void* user, void* call) { tm = localtime(&t); MwStringPrintIntoBuffer(buf, 512, "%s %02d %s", mon[tm->tm_mon], tm->tm_mday, wday[tm->tm_wday]); - MwSetText(ldate, MwNtext, buf); + MwSetString(ldate, MwNtext, buf); MwStringPrintIntoBuffer(buf, 512, "%02d:%02d %s", tm->tm_hour % 12, tm->tm_min, tm->tm_hour >= 12 ? "PM" : "AM"); - MwSetText(ltime, MwNtext, buf); + MwSetString(ltime, MwNtext, buf); render = 1; @@ -141,10 +141,10 @@ int main() { MwNtitle, "clock", NULL); - bgcolor = MwParseColor(window, MwGetText(window, MwNbackground)); + bgcolor = MwParseColor(window, MwGetString(window, MwNbackground)); MwColorGet(bgcolor, &br, &bg, &bb); - fgcolor = MwParseColor(window, MwGetText(window, MwNforeground)); + fgcolor = MwParseColor(window, MwGetString(window, MwNforeground)); MwColorGet(fgcolor, &fr, &fg, &fb); opengl = MwCreateWidget(MwOpenGLClass, "clock", window, 0, 0, 100, 100); diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 66a3372aa..c8c5491f7 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -159,7 +159,7 @@ MWDECL void MWAPI MwSetInteger(MwWidget handle, const char* key, int n); * @param key Key * @param value Value */ -MWDECL void MWAPI MwSetText(MwWidget handle, const char* key, const char* value); +MWDECL void MWAPI MwSetString(MwWidget handle, const char* key, const char* value); /*! * @brief Sets a pointer property @@ -183,7 +183,7 @@ MWDECL int MWAPI MwGetInteger(MwWidget handle, const char* key); * @param key Key * @return Value */ -MWDECL const char* MWAPI MwGetText(MwWidget handle, const char* key); +MWDECL const char* MWAPI MwGetString(MwWidget handle, const char* key); /*! * @brief Gets the pointer property diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index bbd9a5811..65700dbb8 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -10,10 +10,10 @@ typedef struct _MwClass * MwClass, MwClassRec; typedef struct _MwIntegerKeyValue MwIntegerKeyValue; -typedef struct _MwTextKeyValue MwTextKeyValue; +typedef struct _MwStringKeyValue MwStringKeyValue; typedef struct _MwUserHandlerArray MwUserHandlerArray; typedef struct _MwUserHandlerKeyValue MwUserHandlerKeyValue; -typedef struct _MwVoidKeyValue MwVoidKeyValue; +typedef struct _MwPointerKeyValue MwPointerKeyValue; typedef struct _MwMenu* MwMenu; typedef struct _MwEntry* MwEntry; typedef struct _MwViewport* MwViewport; @@ -62,7 +62,7 @@ typedef void (*MwHandlerClipboardReceived)(MwWidget handle, const char* data); typedef void(MWAPI* MwUserHandler)(MwWidget handle, void* user_data, void* call_data); typedef void(MWAPI* MwErrorHandler)(int code, const char* message, void* user_data); -struct _MwTextKeyValue { +struct _MwStringKeyValue { char* key; char* value; }; @@ -82,7 +82,7 @@ struct _MwUserHandlerKeyValue { MwUserHandlerArray* value; }; -struct _MwVoidKeyValue { +struct _MwPointerKeyValue { char* key; void* value; }; @@ -101,6 +101,8 @@ struct _MwPixmap { struct _MwColor { MwLLColor lowlevel; MwLLCommonColor common; + + MwWidget handle; }; struct _MwFont { @@ -130,11 +132,12 @@ struct _MwWidget { MwHandlerProp prop_inject_pixmap; /* this is for pixmap; do not use */ MwPixmap* pixmaps; + MwColor* colors; MwIntegerKeyValue* integer; - MwTextKeyValue* text; + MwStringKeyValue* string; MwUserHandlerKeyValue* handler; - MwVoidKeyValue* data; + MwPointerKeyValue* data; MwWidget* destroy_queue; MwWidget* tick_list; diff --git a/milsko.xml b/milsko.xml index c053bf7b4..7624737eb 100644 --- a/milsko.xml +++ b/milsko.xml @@ -376,7 +376,7 @@ - + @@ -399,7 +399,7 @@ - + @@ -408,7 +408,7 @@ - + diff --git a/src/core.c b/src/core.c index c06241e70..f537c5ab3 100644 --- a/src/core.c +++ b/src/core.c @@ -275,6 +275,7 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, h->destroy_inject = NULL; h->prop_inject_pixmap = NULL; h->pixmaps = NULL; + h->colors = NULL; h->tick_list = NULL; h->destroyed = 0; h->bgcolor = NULL; @@ -314,13 +315,13 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, if(parent != NULL) arrput(parent->children, h); - sh_new_strdup(h->text); + sh_new_strdup(h->string); sh_new_strdup(h->integer); sh_new_strdup(h->handler); sh_new_strdup(h->data); shdefault(h->integer, MwDEFAULT); - shdefault(h->text, NULL); + shdefault(h->string, NULL); shdefault(h->handler, NULL); shdefault(h->data, NULL); @@ -450,11 +451,11 @@ void MwFreeWidget(MwWidget handle) { shfree(handle->integer); - for(i = 0; i < shlen(handle->text); i++) { - free(handle->text[i].value); - handle->text[i].value = NULL; + for(i = 0; i < shlen(handle->string); i++) { + free(handle->string[i].value); + handle->string[i].value = NULL; } - shfree(handle->text); + shfree(handle->string); for(i = 0; i < shlen(handle->handler); i++) { arrfree(handle->handler[i].value); } @@ -467,6 +468,9 @@ void MwFreeWidget(MwWidget handle) { while(arrlen(handle->pixmaps) > 0) MwDestroyPixmap(handle->pixmaps[0]); arrfree(handle->pixmaps); + while(arrlen(handle->colors) > 0) MwFreeColor(handle->colors[0]); + arrfree(handle->colors); + arrfree(handle->draw_queue); arrfree(handle->resize_queue); @@ -711,18 +715,18 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { } } -void MwSetText(MwWidget handle, const char* key, const char* value) { +void MwSetString(MwWidget handle, const char* key, const char* value) { if(handle->widget_class == MwWindowClass && strcmp(key, MwNtitle) == 0) { MwLLSetTitle(handle->lowlevel, value); } else { char* v = value == NULL ? NULL : MwStringDuplicate(value); - if(shgeti(handle->text, key) != -1) free(shget(handle->text, key)); + if(shgeti(handle->string, key) != -1) free(shget(handle->string, key)); if(value != NULL) { - shput(handle->text, key, v); + shput(handle->string, key, v); } else { - shdel(handle->text, key); + shdel(handle->string, key); } } if(handle->prop_event) { @@ -814,13 +818,13 @@ int MwGetInteger(MwWidget handle, const char* key) { } } -const char* MwGetText(MwWidget handle, const char* key) { - if((shgeti(handle->text, key) == -1 || strcmp(shget(handle->text, key), "DEFAULT") == 0) && (strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0 || strcmp(key, MwNtitleBackground) == 0 || strcmp(key, MwNtitleForeground) == 0)) { +const char* MwGetString(MwWidget handle, const char* key) { + if((shgeti(handle->string, key) == -1 || strcmp(shget(handle->string, key), "DEFAULT") == 0) && (strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0 || strcmp(key, MwNtitleBackground) == 0 || strcmp(key, MwNtitleForeground) == 0)) { const char* v = NULL; - if(shgeti(handle->text, key) != -1 && strcmp(shget(handle->text, key), "DEFAULT") != 0) { + if(shgeti(handle->string, key) != -1 && strcmp(shget(handle->string, key), "DEFAULT") != 0) { MwWidget h = handle->parent; while(h != NULL) { - if((v = MwGetText(h, key)) != NULL) break; + if((v = MwGetString(h, key)) != NULL) break; h = h->parent; } } @@ -844,7 +848,7 @@ const char* MwGetText(MwWidget handle, const char* key) { return v; } - return shget(handle->text, key); + return shget(handle->string, key); } #if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) @@ -930,7 +934,7 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) char* t = va_arg(va, char*); if(only_early && key[1] != 'E') continue; - MwSetText(handle, key, t); + MwSetString(handle, key, t); } else if(key[0] == 'C') { MwUserHandler h = va_arg(va, MwUserHandler); if(only_early && key[1] != 'E') continue; diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 8e5804946..0c59641f3 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -185,10 +185,10 @@ static void MWAPI color_picker_click(MwWidget handle, void* user, void* call) { fb = picker->chosen_color.blue > 128 ? 0 : 255; MwStringPrintIntoBuffer(fgColor, 8, "#%02X%02X%02X", fr, fg, fb); - MwSetText(picker->color_display_text, MwNforeground, fgColor); + MwSetString(picker->color_display_text, MwNforeground, fgColor); - MwSetText(picker->color_display_text, MwNbackground, hexColor); - MwSetText(picker->color_display_text, MwNtext, hexColor); + MwSetString(picker->color_display_text, MwNbackground, hexColor); + MwSetString(picker->color_display_text, MwNtext, hexColor); } static void MWAPI color_picker_on_change_value(MwWidget handle, void* user, void* call) { @@ -244,7 +244,7 @@ static void MWAPI color_display_text_change(MwWidget handle, void* user, (void)call; - memcpy(&hexColor, MwGetText(handle, MwNtext), 8); + memcpy(&hexColor, MwGetString(handle, MwNtext), 8); color = MwParseColor(handle, hexColor); @@ -253,10 +253,10 @@ static void MWAPI color_display_text_change(MwWidget handle, void* user, fb = color->common->blue > 128 ? 0 : 255; MwStringPrintIntoBuffer(fgColor, 9, "#%02X%02X%02X", fr, fg, fb); - MwSetText(picker->color_display_text, MwNforeground, fgColor); + MwSetString(picker->color_display_text, MwNforeground, fgColor); - MwSetText(picker->color_display_text, MwNbackground, hexColor); - MwSetText(picker->color_display_text, MwNtext, hexColor); + MwSetString(picker->color_display_text, MwNbackground, hexColor); + MwSetString(picker->color_display_text, MwNtext, hexColor); picker->chosen_color.red = color->common->red; picker->chosen_color.green = color->common->green; @@ -302,8 +302,8 @@ color_picker_t* color_picker_setup(MwWidget parent, int w, int h) { MwEntryClass, "colorDisplayText", picker->parent, IMG_POS_X(w) + (PICKER_SIZE / 2) - ((PICKER_SIZE / 4) / 2), IMG_POS_Y(h) - (PICKER_SIZE / 16) - MARGIN, (PICKER_SIZE / 4), PICKER_SIZE / 16); - MwSetText(picker->color_display_text, MwNbackground, "#FFFFFF"); - MwSetText(picker->color_display_text, MwNtext, "#FFFFFF"); + MwSetString(picker->color_display_text, MwNbackground, "#FFFFFF"); + MwSetString(picker->color_display_text, MwNtext, "#FFFFFF"); /* MwSetInteger(picker->color_display_text, Mwnali, MwALIGNMENT_CENTER); */ MwAddUserHandler(picker->color_display_text, MwNactivateHandler, @@ -330,7 +330,7 @@ color_picker_t* color_picker_setup(MwWidget parent, int w, int h) { picker->finish = MwCreateWidget( MwButtonClass, "colorPickerFinish", picker->parent, IMG_POS_X(w), IMG_POS_Y(h) + PICKER_SIZE + MARGIN, PICKER_SIZE, (WIN_SIZE - PICKER_SIZE - MARGIN * 4) / 2); - MwSetText(picker->finish, MwNtext, "Select"); + MwSetString(picker->finish, MwNtext, "Select"); MwSetInteger(picker->finish, MwNhasBorder, 1); MwSetInteger(picker->finish, MwNinverted, 1); diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index 59666c64d..030928763 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -105,7 +105,7 @@ static void MWAPI files_activate(MwWidget handle, void* user, void* call) { static void MWAPI okay_activate(MwWidget handle, void* user, void* call) { filechooser_t* fc = handle->parent->opaque; - char* t = (char*)MwGetText(fc->filename, MwNtext); + char* t = (char*)MwGetString(fc->filename, MwNtext); struct stat s; char* p = NULL; @@ -195,7 +195,7 @@ static void MWAPI addr_activate(MwWidget handle, void* user, void* call) { (void)user; (void)call; - scan(handle->parent, MwGetText(handle, MwNtext), 1); + scan(handle->parent, MwGetString(handle, MwNtext), 1); } static void layout(MwWidget handle) { diff --git a/src/draw.c b/src/draw.c index ca3acec34..46d4a8b7b 100644 --- a/src/draw.c +++ b/src/draw.c @@ -42,7 +42,7 @@ static void color_set_disabled_if_disabled(MwWidget handle, MwColor rgb) { int n; if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { - MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetString(handle->parent, MwNbackground)); if(c != NULL) { rgb->common->red = (MwU8)(rgb->common->red + (c->common->red - rgb->common->red) * 0.5); @@ -251,7 +251,7 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwColor color, int invert, if(border) { if(!handle->lowlevel->common.supports_transparency) { - MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetString(handle->parent, MwNbackground)); if(c != NULL) { MwDrawRect(handle, rect, c); @@ -403,7 +403,7 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwColor color, MwColor backgrou if(inside) { MwColor mixColor; - MwColor c = background ? background : (handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground))); + MwColor c = background ? background : (handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetString(handle->parent, MwNbackground))); double mod; unsigned char* pout = &data[(y * width + x) * 4]; @@ -990,7 +990,7 @@ MwPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) { void MwPixmapReloadRaw(MwPixmap px, unsigned char* rgb) { int i; MwWidget handle = px->handle; - MwColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor; + MwColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetString(handle, MwNbackground)) : handle->bgcolor; if(rgb != NULL) memcpy(px->raw, rgb, px->common->width * px->common->height * 4); @@ -1044,7 +1044,6 @@ void MwDestroyPixmap(MwPixmap pixmap) { break; } } - if(arrlen(handle->pixmaps) == 0) handle->prop_inject_pixmap = NULL; MwLLDestroyPixmap(pixmap->lowlevel); @@ -1061,6 +1060,7 @@ MwColor MwAllocColor(MwWidget handle, unsigned int red, unsigned int green, unsi color->lowlevel = MwLLAllocColor(handle->lowlevel, red, green, blue); color->common = &color->lowlevel->common; + color->handle = handle; return color; } @@ -1076,6 +1076,16 @@ void MwColorUpdate(MwColor c, int r, int g, int b) { } void MwFreeColor(MwColor color) { + int i; + MwWidget handle = color->handle; + + for(i = 0; i < arrlen(handle->colors); i++) { + if(handle->colors[i] == color) { + arrdel(handle->colors, i); + break; + } + } + MwLLFreeColor(color->lowlevel); free(color); } diff --git a/src/text/text.c b/src/text/text.c index f7ebd4029..cd01e852a 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -85,7 +85,7 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int n; if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { - MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + MwColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetString(handle->parent, MwNbackground)); if(c != NULL) { fadedColor = MwAllocColor(handle, color->common->red, color->common->blue, color->common->green); diff --git a/src/widget/box.c b/src/widget/box.c index 0f9c8f52e..7df2447dc 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -78,7 +78,7 @@ static void layout(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); r.x = 0; r.y = 0; diff --git a/src/widget/button.c b/src/widget/button.c index 1df224695..35192e7e3 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -15,9 +15,9 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; MwPoint point; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - const char* str = MwGetText(handle, MwNtext); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); + const char* str = MwGetString(handle, MwNtext); MwPixmap px = MwGetPointer(handle, MwNpixmap); MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); int inv; diff --git a/src/widget/calendar.c b/src/widget/calendar.c index 7005558dc..3e7dfaa2d 100644 --- a/src/widget/calendar.c +++ b/src/widget/calendar.c @@ -81,8 +81,8 @@ static MwPixmap blit(MwWidget handle, const char* str, MwColor bg, MwColor fg, i } static void draw(MwWidget handle) { - MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor cf = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor cf = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwColor cb = MwParseColor(handle, "#fff"); MwColor cb_g = MwParseColor(handle, "#666"); MwColor ct = MwParseColor(handle, "#000"); diff --git a/src/widget/chart.c b/src/widget/chart.c index 6a9bba9e7..dce3bb320 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -395,8 +395,8 @@ static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, in } static void draw(MwWidget handle) { - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor border = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwRect r; MwChart c = handle->internal; int i; diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 2b29ac65a..448070792 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -10,9 +10,9 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor base2 = MwParseColor(handle, MwGetString(handle, MwNsubBackground)); + MwColor text2 = MwParseColor(handle, MwGetString(handle, MwNsubForeground)); MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); r.x = 0; diff --git a/src/widget/clock.c b/src/widget/clock.c index 6e03a4c83..3356776e6 100644 --- a/src/widget/clock.c +++ b/src/widget/clock.c @@ -55,10 +55,10 @@ static void draw(MwWidget handle) { int ColorDiff = MwGetColorDifference(handle); int ShadowDist; int BaseWidth; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwColor shadow = MwLightenColor(handle, base, -ColorDiff, -ColorDiff, -ColorDiff); - MwColor inside = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwColor border = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwColor inside = MwParseColor(handle, MwGetString(handle, MwNsubBackground)); + MwColor border = MwParseColor(handle, MwGetString(handle, MwNsubForeground)); MwRect r; int i; double w; diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 36f2e6c58..a098714aa 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -25,8 +25,8 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwRect r, rc; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwComboBox cb = handle->internal; r.x = 0; diff --git a/src/widget/document.c b/src/widget/document.c index 045605f43..505a26da2 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -52,8 +52,8 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwDocument d = handle->internal; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwRect r; int i; MwFLFont font = NULL; @@ -634,7 +634,7 @@ static void prop_change(MwWidget handle, const char* key) { if(strcmp(key, MwNtext) == 0) { MD_PARSER parser; - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); memset(&parser, 0, sizeof(parser)); diff --git a/src/widget/entry.c b/src/widget/entry.c index 305545c12..3638323af 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -47,9 +47,9 @@ static void tick(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; MwEntry t = handle->internal; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - const char* str = MwGetText(handle, MwNtext); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); + const char* str = MwGetString(handle, MwNtext); MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); MwFLFont font = MwFLBuildFont(MwFLFlagMonospace); if(str == NULL) str = ""; @@ -114,7 +114,7 @@ static void draw(MwWidget handle) { static void key(MwWidget handle, int code) { MwEntry t = handle->internal; - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); char* out; if(str == NULL) str = ""; @@ -127,7 +127,7 @@ static void key(MwWidget handle, int code) { MwUTF8Copy(str, 0, out, 0, t->cursor); MwUTF8Copy(str, t->cursor + 1, out, t->cursor, MwUTF8Length(str) - (t->cursor + 1)); - MwSetText(handle, MwNtext, out); + MwSetString(handle, MwNtext, out); MwDispatchUserHandler(handle, MwNchangedHandler, NULL); free(out); @@ -150,13 +150,13 @@ static void key(MwWidget handle, int code) { t->cursor++; - MwSetText(handle, MwNtext, out); + MwSetString(handle, MwNtext, out); MwDispatchUserHandler(handle, MwNchangedHandler, NULL); free(out); } - if(MwGetText(handle, MwNtext) != NULL) t->length = MwUTF8Length(MwGetText(handle, MwNtext)); + if(MwGetString(handle, MwNtext) != NULL) t->length = MwUTF8Length(MwGetString(handle, MwNtext)); MwForceRender(handle); } @@ -199,7 +199,7 @@ static void prop_change(MwWidget handle, const char* prop) { if(strcmp(prop, MwNtext) == 0) { MwEntry t = handle->internal; - int len = MwUTF8Length(MwGetText(handle, MwNtext)); + int len = MwUTF8Length(MwGetString(handle, MwNtext)); if(len < t->cursor) { t->cursor = len; } else if(t->length == t->cursor) { @@ -211,7 +211,7 @@ static void prop_change(MwWidget handle, const char* prop) { static void clipboard(MwWidget handle, const char* data) { MwEntry t = handle->internal; - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); char* out; if(!str) { str = ""; @@ -226,7 +226,7 @@ static void clipboard(MwWidget handle, const char* data) { t->cursor += MwUTF8Length(data); - MwSetText(handle, MwNtext, out); + MwSetString(handle, MwNtext, out); free(out); MwForceRender(handle); diff --git a/src/widget/frame.c b/src/widget/frame.c index 5ed79f529..ddff2043f 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -12,7 +12,7 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect fr; MwRect rr; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); int inverted; MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); diff --git a/src/widget/image.c b/src/widget/image.c index 6d5423b57..016b4b385 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -13,7 +13,7 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; MwPixmap px = MwGetPointer(handle, MwNpixmap); - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); r.x = 0; r.y = 0; diff --git a/src/widget/label.c b/src/widget/label.c index e11fcc40f..1220e2114 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -124,11 +124,11 @@ static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride static void draw_seven_segment(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); MwLabel lab = handle->internal; int l_one = MwGetInteger(handle, MwNlength) - (MwGetInteger(handle, MwNlength) % 2); @@ -315,11 +315,11 @@ static void draw_seven_segment(MwWidget handle) { static void draw_normal(MwWidget handle) { MwRect r; MwPoint p; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); if(str == NULL) str = ""; diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 272909e0f..68daec18c 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -136,10 +136,10 @@ static void MWAPI frame_mouse_move(MwWidget handle, void* user, void* call) { static void frame_draw(MwWidget handle) { MwRect r, r2; MwListBox lb = handle->parent->internal; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor base2 = MwParseColor(handle, MwGetString(handle, MwNsubBackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); + MwColor text2 = MwParseColor(handle, MwGetString(handle, MwNsubForeground)); int i; MwPoint p; int st = 0; @@ -359,8 +359,8 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwListBox lb = handle->internal; r.x = 0; diff --git a/src/widget/menu.c b/src/widget/menu.c index 22771e9b5..7d2f284ba 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -103,8 +103,8 @@ static void destroy(MwWidget handle) { m->sub[i]->cleaned = 0; static void draw(MwWidget handle) { - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MENU_LOOP_DECL; MENU_LOOP_INIT; diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index d0323e513..2b1d54f12 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -9,7 +9,7 @@ static int wcreate(MwWidget handle) { e = handle->internal; e->right = 32; - MwSetText(handle, MwNtext, "0"); + MwSetString(handle, MwNtext, "0"); return 0; } @@ -24,7 +24,7 @@ static void draw(MwWidget handle) { MwEntry e = handle->internal; MwRect r; int pr; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwEntryClass->draw(handle); @@ -65,7 +65,7 @@ static void draw(MwWidget handle) { static void key(MwWidget handle, int code) { MwEntry e = handle->internal; - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); int ok = 0; if(str == NULL) str = ""; @@ -96,7 +96,7 @@ static void mouse_up(MwWidget handle, void* ptr) { MwEntry e = handle->internal; int w = MwGetInteger(handle, MwNwidth); int h = MwGetInteger(handle, MwNheight); - const char* str = MwGetText(handle, MwNtext); + const char* str = MwGetString(handle, MwNtext); if(((MwMouse*)ptr)->button != MwMOUSE_LEFT) return; @@ -107,7 +107,7 @@ static void mouse_up(MwWidget handle, void* ptr) { } else { MwStringPrintIntoBuffer(s, 512, "%g", atof(str) + 1); } - MwSetText(handle, MwNtext, s); + MwSetString(handle, MwNtext, s); MwDispatchUserHandler(handle, MwNchangedHandler, NULL); } diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index 879bd42ed..a26e902b8 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -13,8 +13,8 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor fill = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor fill = MwParseColor(handle, MwGetString(handle, MwNforeground)); double w; MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index 475991fef..2abe27e63 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -12,7 +12,7 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwPixmap bgpx = MwGetPointer(handle, MwNbackgroundPixmap); r.x = 0; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 613868bd1..840cdb563 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -55,7 +55,7 @@ static void add_value(MwWidget handle, int mul) { static void draw(MwWidget handle) { MwRect r = {0}, rt = {0}, rbar = {0}; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwColor dark = MwLightenColor(handle, base, -64, -64, -64); MwScrollBar scr = handle->internal; int or ; diff --git a/src/widget/separator.c b/src/widget/separator.c index 84af1a3d9..5baa21331 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -10,7 +10,7 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); r.x = 0; r.y = 0; diff --git a/src/widget/submenu.c b/src/widget/submenu.c index e76f0fba6..7ab48ff6b 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -29,8 +29,8 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwRect r; MwMenu menu = handle->internal; diff --git a/src/widget/subwindow.c b/src/widget/subwindow.c index 37c7b14a5..0fee158c6 100644 --- a/src/widget/subwindow.c +++ b/src/widget/subwindow.c @@ -11,7 +11,7 @@ static void close_draw(MwWidget handle) { int w = MwGetInteger(handle, MwNwidth); int h = MwGetInteger(handle, MwNheight); MwPoint p[2]; - MwColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNforeground)); int bw = MwDefaultBorderWidth(handle); p[0].x = bw * 2; @@ -52,7 +52,7 @@ static void maximize_draw(MwWidget handle) { int w = MwGetInteger(handle, MwNwidth); int h = MwGetInteger(handle, MwNheight); MwPoint p[2]; - MwColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNforeground)); int bw = MwDefaultBorderWidth(handle); p[0].x = bw * 2; @@ -117,7 +117,7 @@ static void minimize_draw(MwWidget handle) { int w = MwGetInteger(handle, MwNwidth); int h = MwGetInteger(handle, MwNheight); MwPoint p[2]; - MwColor c = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNforeground)); int bw = MwDefaultBorderWidth(handle); p[0].x = bw * 2; @@ -285,11 +285,11 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor tb = MwParseColor(handle, MwGetText(handle, MwNtitleBackground)); - MwColor tf = MwParseColor(handle, MwGetText(handle, MwNtitleForeground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor tb = MwParseColor(handle, MwGetString(handle, MwNtitleBackground)); + MwColor tf = MwParseColor(handle, MwGetString(handle, MwNtitleForeground)); MwRect r, r2, r3; - const char* title = MwGetText(handle, MwNtitle); + const char* title = MwGetString(handle, MwNtitle); int incr = 0; MwPixmap px = MwGetPointer(handle, MwNiconPixmap); diff --git a/src/widget/tab.c b/src/widget/tab.c index 3ae47dc2a..3a630cecc 100644 --- a/src/widget/tab.c +++ b/src/widget/tab.c @@ -58,8 +58,8 @@ static int icon_width(MwWidget handle, const char* text) { static void draw(MwWidget handle) { MwTab t = handle->internal; - MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor ct = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor ct = MwParseColor(handle, MwGetString(handle, MwNforeground)); MwRect r, r2; int h = tab_height(handle); int i; diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 55bc916ec..0ebaf852b 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -167,10 +167,10 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** static void frame_draw(MwWidget handle) { MwRect r, r2; MwTreeView tv = handle->parent->internal; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); - MwColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - MwColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); + MwColor base2 = MwParseColor(handle, MwGetString(handle, MwNsubBackground)); + MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); + MwColor text2 = MwParseColor(handle, MwGetString(handle, MwNsubForeground)); MwPoint p; int shared = 0; int i; @@ -322,7 +322,7 @@ static void destroy(MwWidget handle) { } static void draw(MwWidget handle) { - MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwRect r; r.x = 0; diff --git a/src/widget/viewport.c b/src/widget/viewport.c index 8f673a980..4255cafd1 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -102,7 +102,7 @@ static void destroy(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); r.x = 0; r.y = 0; diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index a57e142b8..59c3880b2 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -568,11 +568,11 @@ static void prop_change(MwWidget handle, const char* prop) { } if(strcmp(prop, MwNvulkanExtension) == 0) { - char* str = MwStringDuplicate(MwGetText(handle, MwNvulkanExtension)); + char* str = MwStringDuplicate(MwGetString(handle, MwNvulkanExtension)); arrput(o->enabledExtensions, str); } else if(strcmp(prop, MwNvulkanLayer) == 0) { - char* str = MwStringDuplicate(MwGetText(handle, MwNvulkanExtension)); + char* str = MwStringDuplicate(MwGetString(handle, MwNvulkanExtension)); arrput(o->enabledLayers, str); } else if(strcmp(prop, MwNvulkanConfig) == 0) { diff --git a/src/widget/window.c b/src/widget/window.c index 3bf3e763f..bcce35a70 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -10,7 +10,7 @@ static int wcreate(MwWidget handle) { } static void draw(MwWidget handle) { - MwColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwColor c = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwRect r; r.x = 0; From 50171cf92ee9699f5061b4be1660ecbf67a07507 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 06:37:24 +0900 Subject: [PATCH 064/102] fix wayland --- src/backend/wayland/wayland.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d23594bfc..de267748a 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1446,8 +1446,7 @@ static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { return c; } -static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; +static void MwLLColorUpdateImpl(MwLLColor c, int r, int g, int b) { c->common.red = r; c->common.blue = b; c->common.green = g; From 56acbaa78772465587e519acd70f7a9198999016 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 07:23:42 +0900 Subject: [PATCH 065/102] d3d9 header --- include/Mw/Widget/Direct3D9.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index 8e7cb5b3f..6626c7a9e 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -22,8 +22,8 @@ #endif #ifndef _WIN32 -#error D3D9 widget only avaliable for Win32 backends -#undef MW_DIRECT3D9 +typedef void* LPDIRECT3D9; +typedef void* LPDIRECT3DDEVICE9; #else #ifdef __WATCOMC__ #include From a71d5529d7c5164956c95c915fc9f03629b77fbe Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 27 Sep 2026 07:49:49 +0900 Subject: [PATCH 066/102] wayland fix --- src/backend/wayland/interfaces.c | 3 ++- src/widget/menu.c | 31 +++++++++++++++++++++++++++---- src/widget/submenu.c | 26 ++++++++++++-------------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 2740c6f3c..02d5a85d1 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -777,7 +777,8 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: - MwLLDispatch(target, down, &p); + /* otherwise the recursion below reaches the target and dispatches it there */ + if(target == self) MwLLDispatch(target, down, &p); break; case WL_POINTER_BUTTON_STATE_RELEASED: MwLLDispatch(target, up, &p); diff --git a/src/widget/menu.c b/src/widget/menu.c index 7d2f284ba..928205486 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -45,9 +45,22 @@ static void recursive_free(MwMenu m) { free(m); } +/* submenus are freed after us and would otherwise touch the entries we are about to free */ +static void detach_submenus(MwWidget handle) { + int i; + + for(i = 0; i < arrlen(handle->children); i++) { + if(handle->children[i]->widget_class != MwSubMenuClass) continue; + + handle->children[i]->internal = NULL; + detach_submenus(handle->children[i]); + } +} + static void destroy(MwWidget handle) { MwMenu m = handle->internal; + detach_submenus(handle); recursive_free(m); } @@ -92,15 +105,25 @@ static void destroy(MwWidget handle) { p.x += tw / 2 + 5; \ } +/* some backends (e.g. Wayland) dispatch input while creating a widget, which can re-enter these + * handlers; if a submenu for this item appeared meanwhile, drop ours instead of orphaning that one. + * a release handled during creation saw no submenu yet, so keep it open as mouse_up would have */ #define NEW_SUBMENU \ - MwPoint p2; \ + MwPoint p2; \ + MwWidget sw; \ \ p2.x = p.x - 5 - tw / 2; \ p2.y = p.y + th / 2 + 5; \ \ - m->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, MwGetInteger(handle, MwNheight), 0, 0); \ - MwSubMenuAppear(m->sub[i]->wsub, m->sub[i], &p2, 0); \ - m->sub[i]->cleaned = 0; + sw = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, MwGetInteger(handle, MwNheight), 0, 0); \ + if(sw != NULL && m->sub[i]->wsub != NULL) { \ + MwDestroyWidget(sw); \ + } else if(sw != NULL) { \ + m->sub[i]->wsub = sw; \ + m->sub[i]->keep = handle->pressed ? 0 : 1; \ + m->sub[i]->cleaned = 0; \ + MwSubMenuAppear(sw, m->sub[i], &p2, 0); \ + } static void draw(MwWidget handle) { MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 7ab48ff6b..0b320e609 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -13,19 +13,10 @@ static int wcreate(MwWidget handle) { return 0; } -static void null_all(MwMenu menu) { - int i; - for(i = 0; i < arrlen(menu->sub); i++) { - null_all(menu->sub[i]); - } - menu->wsub = NULL; -} - static void destroy(MwWidget handle) { MwMenu menu = handle->internal; - menu->wsub = NULL; - null_all(menu); + if(menu != NULL && menu->wsub == handle) menu->wsub = NULL; } static void draw(MwWidget handle) { @@ -126,8 +117,9 @@ static void click(MwWidget handle) { if(MwGetInteger(handle, MwNleftPadding) <= handle->mouse_point.x && rc.y <= handle->mouse_point.y && handle->mouse_point.y <= (int)(rc.y + rc.height)) { if(menu->sub[i]->wsub == NULL && arrlen(menu->sub[i]->sub) > 0) { - MwPoint p; - int j; + MwPoint p; + MwWidget sw; + int j; for(j = 0; j < arrlen(menu->sub); j++) { if(menu->sub[j]->wsub != NULL) MwDestroyWidget(menu->sub[j]->wsub); @@ -137,8 +129,14 @@ static void click(MwWidget handle) { p.x = MwGetInteger(handle, MwNwidth); p.y = rc.y - 3; - menu->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0); - MwSubMenuAppear(menu->sub[i]->wsub, menu->sub[i], &p, 0); + /* some backends (e.g. Wayland) dispatch input while creating a widget, which can re-enter this handler */ + sw = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0); + if(sw != NULL && (menu->sub[i]->wsub != NULL || handle->destroyed)) { + MwDestroyWidget(sw); + } else if(sw != NULL) { + menu->sub[i]->wsub = sw; + MwSubMenuAppear(sw, menu->sub[i], &p, 0); + } i = -1; } else if(menu->sub[i]->wsub != NULL && arrlen(menu->sub[i]->sub) > 0) { while(w->parent->widget_class == MwSubMenuClass) w = w->parent; From 30ece76ff42c8e3ef3b95e3e020e11ea66776176 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 07:57:26 +0900 Subject: [PATCH 067/102] fix warning --- src/abstract/directory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/abstract/directory.c b/src/abstract/directory.c index 63146b1e6..904e63ce6 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -19,7 +19,9 @@ typedef struct dir { void* MwDirectoryOpen(const char* path) { dir_t* dir = malloc(sizeof(*dir)); +#ifdef _WIN32 char* p; +#endif if(!dir) { printf("Out Of Memory\n"); return NULL; From 5d0606c9a2082e3f064fbbb38f98fb841119f2d2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 17:09:21 -0700 Subject: [PATCH 068/102] simply do not support wslg --- src/backend/wayland/wayland.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index de267748a..ba7473d0c 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -2010,11 +2010,16 @@ static int MwLLWaylandCallInitImpl(void) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } -#ifdef MW_OPENGL - if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - // loadWayland = 0; + if((getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) && (!getenv("WESTON_CONFIG_FILE") || !getenv("MW_WSL_WAYLAND_FORCEFULLY_ENABLE"))) { + printf( + "!!!!! Milsko's Wayland backend has known issues under Microsoft's WSLg !!!!!\n" + "!!!!! (the default method of running GUI apps) that we're not fixing !!!!!\n" + "!!!!! If you want to try the Wayland backend, please either: !!!!!\n" + "!!!!! a.) actually install Weston and run it manually !!!!!\n" + "!!!!! b.) set the env variable to MW_WSL_WAYLAND_FORCEFULLY_ENABLE !!!!!\n"); + + loadWayland = 0; } -#endif if(loadWayland) { if(wayland_load_funcs()) { From bcc99b00bacdb42c188f7f678376bdab2436e20c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 17:11:08 -0700 Subject: [PATCH 069/102] wslg check should do && actually --- src/backend/wayland/wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index ba7473d0c..07039bdc7 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -2010,7 +2010,7 @@ static int MwLLWaylandCallInitImpl(void) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } - if((getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) && (!getenv("WESTON_CONFIG_FILE") || !getenv("MW_WSL_WAYLAND_FORCEFULLY_ENABLE"))) { + if((getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) && (!getenv("WESTON_CONFIG_FILE") && !getenv("MW_WSL_WAYLAND_FORCEFULLY_ENABLE"))) { printf( "!!!!! Milsko's Wayland backend has known issues under Microsoft's WSLg !!!!!\n" "!!!!! (the default method of running GUI apps) that we're not fixing !!!!!\n" From 647b86fd7d9f53fcc008412bbf8392890a1f58d2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 17:24:56 -0700 Subject: [PATCH 070/102] fix popup positions --- include/Mw/TypeDefs.h | 1 + src/backend/wayland/wayland.c | 10 +++++++--- src/widget/submenu.c | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 65700dbb8..2a4093a58 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -158,6 +158,7 @@ struct _MwWidget { long last_tick; MwBool is_menu; + MwBool is_submenu; }; #endif diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 07039bdc7..fea047029 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -549,9 +549,13 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { } if(!topmost_parent->wayland.has_decorations && topmost_parent->wayland.do_csd) { - if(p->is_menu) { - r->wayland.x += round((float)CSD_BORDER_FRAME_LEFT / 2.); - r->wayland.y += ceil((float)CSD_BORDER_FRAME_TOP / 2.); + if(p->is_submenu) { + } else if(p->is_menu) { + r->wayland.x += ((float)CSD_BORDER_FRAME_LEFT / 2.); + r->wayland.y += ((float)CSD_BORDER_FRAME_TOP / 2.); + } else { + r->wayland.x += ((float)CSD_BORDER_FRAME_LEFT); + r->wayland.y += ((float)CSD_BORDER_FRAME_TOP); } } } diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 0b320e609..e2bab1ccd 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -8,7 +8,8 @@ static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNleftPadding, 0); - handle->internal = NULL; + handle->internal = NULL; + handle->is_submenu = MwTRUE; return 0; } From 33ea649d185813334f8da6b290a14e18be57c345 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 17:35:50 -0700 Subject: [PATCH 071/102] fix csd --- src/backend/wayland/buffer.c | 18 ++++++++++-------- src/backend/wayland/wayland.c | 24 +++++++++++------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 2280bd7d2..04ba04b1f 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -10,8 +10,8 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { memset(wayland->framebuffer.buf_back, 255, wayland->framebuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); - if(wayland->framebuffer.fifo) - wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); + // if(wayland->framebuffer.fifo) + // wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); wl_surface_commit(wayland->framebuffer.surface); @@ -25,11 +25,13 @@ void MwLLWaylandFramebufferDestroy(struct _MwLLWayland* wayland) { }; void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { + MwU32 w = wayland->ww; + MwU32 h = wayland->wh; + if(wayland->type != MwLL_WAYLAND_TOPLEVEL) { return; } - MwU32 w = wayland->ww; - MwU32 h = wayland->wh; + if(!wayland->has_decorations && wayland->do_csd) { w += (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); h += (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); @@ -140,8 +142,8 @@ void MwLLWaylandFramebufferResize(struct _MwLLWayland* wayland) { if(wayland->configured) wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); - if(wayland->framebuffer.fifo) - wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); + // if(wayland->framebuffer.fifo) + // wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); wl_surface_commit(wayland->framebuffer.surface); @@ -183,8 +185,8 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { if(self->wayland.configured) { wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); } - if(buffer->fifo) - wp_fifo_v1_wait_barrier(buffer->fifo); + // if(buffer->fifo) + // wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); } } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index fea047029..4ab9a73fd 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -202,21 +202,18 @@ static void xdg_toplevel_configure(void* data, // } // } - if(self->wayland.resizing == 0) { - xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); + xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); + MwLLWaylandFramebufferResize(&self->wayland); + MwLLWaylandBackbufferResize(&self->wayland); - MwLLWaylandFramebufferResize(&self->wayland); + MwLLWaylandRegionSetup(self); + MwLLDispatch(self, resize, NULL); - MwLLWaylandRegionSetup(self); - MwLLDispatch(self, resize, NULL); + recursive_dispatch_resize(self); - recursive_dispatch_resize(self); - - if(self->wayland.pointer_constrained) { - zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP); - wl_surface_commit(self->wayland.framebuffer.surface); - } - self->wayland.resizing = 1; + if(self->wayland.pointer_constrained) { + zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP); + wl_surface_commit(self->wayland.framebuffer.surface); } }; @@ -1414,9 +1411,10 @@ static void MwLLEndDrawImpl(MwLL handle) { if(handle->wayland.configured) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); + MwLLWaylandBackbufferResize(&handle->wayland); } - MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); + MwLLWaylandFramebufferResize(&handle->wayland); } } From 59d9e3dc6eed51fb7a453db3b4d5fee7a1d58665 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 18:16:15 -0700 Subject: [PATCH 072/102] impl showimpl when we don't use subsurfaces anymore --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland/wayland.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 01f772c31..c49af026d 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -462,6 +462,8 @@ struct _MwLLWayland { long end_time; MwBool accepts_dnd; + + MwBool shown; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 4ab9a73fd..8ffd0e187 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1001,6 +1001,10 @@ static void draw_child(MwLL handle, MwLL child) { wl_surface_commit(child->wayland.framebuffer.surface); + if(!child->wayland.shown) { + return; + } + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); c = cairo_create(cs); @@ -1056,6 +1060,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; + /* notably not in widget setup, if a user detaches a widget or whatever it should keep this state */ + r->wayland.shown = MwTRUE; + widget_setup(r, parent, x, y, width, height, MwLL_WAYLAND_UNKNOWN); #ifdef USE_DBUS @@ -1723,6 +1730,8 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { } static void MwLLShowImpl(MwLL handle, int show) { + handle->wayland.shown = show; + if(!handle->wayland.configured) { return; } From 4d5a253a83001db4f451da10b44ea0eb2e704cd5 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 18:44:27 -0700 Subject: [PATCH 073/102] fix csd again, again --- src/backend/wayland/wayland.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 8ffd0e187..4ee0e220a 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1418,10 +1418,8 @@ static void MwLLEndDrawImpl(MwLL handle) { if(handle->wayland.configured) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); - MwLLWaylandBackbufferResize(&handle->wayland); } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - MwLLWaylandFramebufferResize(&handle->wayland); } } From aa46dea301fd444600e644a6eb26f2093e77a843 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 19:03:34 -0700 Subject: [PATCH 074/102] 2.0 changelog --- CHANGELOG.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 83daed86b..79adc08c5 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,26 @@ +========================= 2.0 ========================= +2.0 is not the most significant release, but there are several breaking changes that justify its number: +- There are no longer any public facing functions that use MwLL* types. Said functions now expect MwColor and MwPixmap, which are wrapper types over the LL ones. +- MwSetVoid and MwGetVoid have been renamed to MwSetPointer and MwGetPointer +- MwSetText and MwGetText have been renamed to MwSetStrign and MwGetString + +Other changes include: +- Widgets can now accept drag and dropped files via MwNacceptsDnD and the new MwNdragAndDropHandler handler. + - Currently only works on Wayland and Win32 due to limited ability to test this on X11. +- New environment variables: + - `MW_LIGHT_THEME`/`MW_DARK_THEME`: set to ignore the system's appearence settings and either just use light theme/dark theme. + - `MW_FORCE_CSD` (Linux only): set to force the wayland backend to use CSD instead of SSD + - `MILSKO_BACKEND` has been renamed to `MW_BACKEND` +- Redesigned look for radioboxes and checkboxes in the modern theme +- Clock Widget +- Chart Widgets + - Bar Chart (2D or 3D) + - Pie Chart (2D or 3D) + - Line Chart +- New "Document" widget that supports markdown. +- New Direct3D9 helper widget that allows you to use Direct3D9 (Windows only) +- Stability/performance fixes for the Wayland backend, most likely for the last time. + ========================= 1.4 ========================= - CMakeLists.txt downgraded to version 3.13 to allow compiling on Windows XP - CMake build now generates a pkgconfig file. From e8137f0a81b02e118f0a6c0fd3599ced1c99cf80 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 19:09:35 -0700 Subject: [PATCH 075/102] update bindings docs --- doc/BINDINGS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index ef327be1e..20e87519b 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -7,9 +7,9 @@ | Language | Repo | Version | Notes | | -------- | --------------------------------------------------------------------- | ------- | -------------- | | Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | Auto-generated | -| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 1.5* | Auto-generated | -| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 1.5* | Auto-generated | -| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 1.5* | Auto-generated | +| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0 | Auto-generated | +| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0 | Auto-generated | +| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0 | Auto-generated | # Inactive Bindings From c7ec3b80238fb24c690f87f7100a18c447a6d551 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 19:12:28 -0700 Subject: [PATCH 076/102] update env doc --- doc/ENV.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ENV.md b/doc/ENV.md index b6f572983..2c62af59c 100644 --- a/doc/ENV.md +++ b/doc/ENV.md @@ -1,7 +1,7 @@ # Environment vaiables -Platforms that support both X11 and Wayland (Linux, namely) support launching Milsko programs with following environment variables: +Milsko programs can be optionally configured at runtime using the following environment variables: -- `MW_BACKEND`: set to either `wayland` or `x11` to force which display protocol Wayland uses -- `MW_FORCE_CSD`: set to force the wayland backend to use CSD instead of SSD -- `MW_LIGHT_THEME`/`MW_DARK_THEME`: set to have either wayland or x11 ignore the system's appearence settings and either just use light theme/dark theme. +- `MW_LIGHT_THEME`/`MW_DARK_THEME`: ignore the system's appearence settings and either use light theme or dark theme respectively . +- `MW_BACKEND` (Linux/X11 only): set to either `wayland` or `x11` to force which display protocol Wayland uses +- `MW_FORCE_CSD` (Linux/X11 only): set to force the wayland backend to use CSD instead of SSD From 7efdde3b151e279e1dce0e185958a7cc00ffd3f7 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 11:13:13 +0900 Subject: [PATCH 077/102] respect theme_override --- include/Mw/Default.h | 10 +++++++ include/Mw/LowLevel.h | 2 -- include/Mw/StringDefs.h | 1 + milsko.xml | 1 + src/abstract/directory.c | 2 +- src/backend/gdi.c | 41 +++++++++++++++------------ src/core.c | 4 ++- src/default.c | 4 +++ src/lowlevel.c | 7 ++--- src/widget/document.c | 60 +++++++++++++++++----------------------- 10 files changed, 70 insertions(+), 62 deletions(-) diff --git a/include/Mw/Default.h b/include/Mw/Default.h index 322082b28..bd9967bb3 100644 --- a/include/Mw/Default.h +++ b/include/Mw/Default.h @@ -42,6 +42,11 @@ MWDECL const char* MwDefaultTitleBackground; */ MWDECL const char* MwDefaultTitleForeground; +/*! + * @brief Default link foreground color + */ +MWDECL const char* MwDefaultLinkForeground; + /*! * @brief Default dark theme background color */ @@ -72,6 +77,11 @@ MWDECL const char* MwDefaultDarkTitleBackground; */ MWDECL const char* MwDefaultDarkTitleForeground; +/*! + * @brief Default dark theme link foreground color + */ +MWDECL const char* MwDefaultDarkLinkForeground; + /*! * @brief Default shadow difference */ diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 5ef17f688..d2a8931de 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -42,10 +42,8 @@ struct _MwLLCommon { MwLLHandler handler; -#if defined(USE_WAYLAND) || defined(USE_X11) /* 0 = default, 1 = light, 2 = dark */ int theme_override; -#endif }; struct _MwLLCommonColor { diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index d04aee083..7906c1d05 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -69,6 +69,7 @@ #define MwNforeground "Sforeground" #define MwNsubForeground "SsubForeground" #define MwNtitleForeground "StitleForeground" +#define MwNlinkForeground "SlinkForeground" #define MwNvulkanExtension "SEvulkanExtension" #define MwNvulkanLayer "SEvulkanLayer" diff --git a/milsko.xml b/milsko.xml index 7624737eb..4cf9038a1 100644 --- a/milsko.xml +++ b/milsko.xml @@ -124,6 +124,7 @@ + diff --git a/src/abstract/directory.c b/src/abstract/directory.c index 904e63ce6..e4f62080a 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -20,7 +20,7 @@ typedef struct dir { void* MwDirectoryOpen(const char* path) { dir_t* dir = malloc(sizeof(*dir)); #ifdef _WIN32 - char* p; + char* p; #endif if(!dir) { printf("Out Of Memory\n"); diff --git a/src/backend/gdi.c b/src/backend/gdi.c index bd880f922..248a59b89 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -38,27 +38,32 @@ static void detect_darktheme_classictheme(MwLL handle) { /* Dark theme detection for modern Windows: use the registry to check if dark mode is enabled. */ static void detect_darktheme(MwLL handle) { - DWORD dw; - DWORD sz = sizeof(dw); - int err, t; - HKEY hkey; - DWORD type; + int t; + if(handle->common.theme_override > 0) { + t = handle->common.theme_override - 1; + } else { + DWORD dw; + DWORD sz = sizeof(dw); + int err; + HKEY hkey; + DWORD type; - err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_QUERY_VALUE, &hkey); - if(err != ERROR_SUCCESS) { - detect_darktheme_classictheme(handle); - return; + err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_QUERY_VALUE, &hkey); + if(err != ERROR_SUCCESS) { + detect_darktheme_classictheme(handle); + return; + } + + err = RegQueryValueEx(hkey, "AppsUseLightTheme", NULL, &type, (PBYTE)&dw, &sz); + RegCloseKey(hkey); + if(err != ERROR_SUCCESS || type != REG_DWORD) { + detect_darktheme_classictheme(handle); + return; + } + + t = dw ? 0 : 1; } - err = RegQueryValueEx(hkey, "AppsUseLightTheme", NULL, &type, (PBYTE)&dw, &sz); - RegCloseKey(hkey); - if(err != ERROR_SUCCESS || type != REG_DWORD) { - detect_darktheme_classictheme(handle); - return; - } - - t = dw ? 0 : 1; - /* no don't do this here (nishi) */ #if 0 if(t && DwmSetWindowAttribute != NULL) { diff --git a/src/core.c b/src/core.c index f537c5ab3..547b7b1e0 100644 --- a/src/core.c +++ b/src/core.c @@ -819,7 +819,7 @@ int MwGetInteger(MwWidget handle, const char* key) { } const char* MwGetString(MwWidget handle, const char* key) { - if((shgeti(handle->string, key) == -1 || strcmp(shget(handle->string, key), "DEFAULT") == 0) && (strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0 || strcmp(key, MwNtitleBackground) == 0 || strcmp(key, MwNtitleForeground) == 0)) { + if((shgeti(handle->string, key) == -1 || strcmp(shget(handle->string, key), "DEFAULT") == 0) && (strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0 || strcmp(key, MwNtitleBackground) == 0 || strcmp(key, MwNtitleForeground) == 0 || strcmp(key, MwNlinkForeground) == 0)) { const char* v = NULL; if(shgeti(handle->string, key) != -1 && strcmp(shget(handle->string, key), "DEFAULT") != 0) { MwWidget h = handle->parent; @@ -836,6 +836,7 @@ const char* MwGetString(MwWidget handle, const char* key) { if(strcmp(key, MwNsubForeground) == 0) return MwDefaultDarkSubForeground; if(strcmp(key, MwNtitleBackground) == 0) return MwDefaultDarkTitleBackground; if(strcmp(key, MwNtitleForeground) == 0) return MwDefaultDarkTitleForeground; + if(strcmp(key, MwNlinkForeground) == 0) return MwDefaultDarkLinkForeground; } else { if(strcmp(key, MwNbackground) == 0) return MwDefaultBackground; if(strcmp(key, MwNforeground) == 0) return MwDefaultForeground; @@ -843,6 +844,7 @@ const char* MwGetString(MwWidget handle, const char* key) { if(strcmp(key, MwNsubForeground) == 0) return MwDefaultSubForeground; if(strcmp(key, MwNtitleBackground) == 0) return MwDefaultTitleBackground; if(strcmp(key, MwNtitleForeground) == 0) return MwDefaultTitleForeground; + if(strcmp(key, MwNlinkForeground) == 0) return MwDefaultLinkForeground; } } return v; diff --git a/src/default.c b/src/default.c index 2cb163342..bad4ee135 100644 --- a/src/default.c +++ b/src/default.c @@ -9,6 +9,7 @@ const char* MwDefaultSubBackground = "#9ca0b0"; const char* MwDefaultSubForeground = "#6c6f85"; const char* MwDefaultTitleBackground = "#bcc0cc"; const char* MwDefaultTitleForeground = "#5c5f77"; +const char* MwDefaultLinkForeground = "#8839ef"; #else const char* MwDefaultBackground = "#d2d2d2"; const char* MwDefaultForeground = "#000"; @@ -16,6 +17,7 @@ const char* MwDefaultSubBackground = "#fff"; const char* MwDefaultSubForeground = "#000"; const char* MwDefaultTitleBackground = "#008"; const char* MwDefaultTitleForeground = "#fff"; +const char* MwDefaultLinkForeground = "#008"; #endif #ifdef USE_CATPPUCCIN_DARK @@ -25,6 +27,7 @@ const char* MwDefaultDarkSubBackground = "#313244"; const char* MwDefaultDarkSubForeground = "#a6adc8"; const char* MwDefaultDarkTitleBackground = "#45475a"; const char* MwDefaultDarkTitleForeground = "#bac2de"; +const char* MwDefaultDarkLinkForeground = "#cba6f7"; #else const char* MwDefaultDarkBackground = "#333"; const char* MwDefaultDarkForeground = "#ddd"; @@ -32,6 +35,7 @@ const char* MwDefaultDarkSubBackground = "#333"; const char* MwDefaultDarkSubForeground = "#ddd"; const char* MwDefaultDarkTitleBackground = "#008"; const char* MwDefaultDarkTitleForeground = "#fff"; +const char* MwDefaultDarkLinkForeground = "#008"; #endif const int MwDefaultShadow = -32; diff --git a/src/lowlevel.c b/src/lowlevel.c index d676310a8..6577e35b8 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -66,22 +66,19 @@ void (*MwLLRaise)(MwLL handle) = NULL; void (*MwLLClip)(MwLL handle, MwRect* rect) = NULL; void MwLLCreateCommon(MwLL handle) { -#if defined(USE_WAYLAND) || defined(USE_X11) char* light_theme = getenv("MW_LIGHT_THEME"); char* dark_theme = getenv("MW_DARK_THEME"); -#endif handle->common.handler = malloc(sizeof(*handle->common.handler)); memset(handle->common.handler, 0, sizeof(*handle->common.handler)); handle->common.supports_transparency = 0; -#if defined(USE_WAYLAND) || defined(USE_X11) if(light_theme || dark_theme) { handle->common.theme_override = (light_theme != NULL) ? 1 : ((dark_theme != NULL) ? 2 : 0); + } else { + handle->common.theme_override = 0; } - -#endif } void MwLLDestroyCommon(MwLL handle) { diff --git a/src/widget/document.c b/src/widget/document.c index 505a26da2..797af6e9d 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -54,6 +54,7 @@ static void draw(MwWidget handle) { MwDocument d = handle->internal; MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground)); MwColor text = MwParseColor(handle, MwGetString(handle, MwNforeground)); + MwColor link = MwParseColor(handle, MwGetString(handle, MwNlinkForeground)); MwRect r; int i; MwFLFont font = NULL; @@ -124,28 +125,16 @@ static void draw(MwWidget handle) { if(j == 1) s_p.x = line[1].x; if(j == 2) c_p.x = line[1].x; - if(j == 2) { - MwRect c_r; - - c_r.x = line[0].x; - c_r.y = line[0].y; - c_r.width = line[1].x - line[0].x; - c_r.height = MwTextHeight(handle, font, l->text); - - MwDrawRect(handle, &c_r, text); - } - - if(j == 0 || j == 1) { - line[0].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); - line[1].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); - MwLine(handle, line, (c ? base : text)); + if(j == 0 || j == 1 || j == 2) { + int am = MwTextHeight(handle, font, l->text) / 2 * (2 - (j == 2 ? 0 : j)); + line[0].y += am; + line[1].y += am; + MwLine(handle, line, (c ? link : text)); } } } - handle->bgcolor = c ? text : NULL; - MwDrawText(handle, font, &p, l->text, MwALIGNMENT_BEGINNING, c ? base : text); - handle->bgcolor = NULL; + MwDrawText(handle, font, &p, l->text, MwALIGNMENT_BEGINNING, c ? link : text); break; } case MwDOCUMENT_UNDERLINE: @@ -191,6 +180,7 @@ static void draw(MwWidget handle) { if(IsFontChange(l->type)) font = l->font; } + MwFreeColor(link); MwFreeColor(text); MwFreeColor(base); } @@ -658,23 +648,23 @@ static void resize(MwWidget handle) { } MwClassRec MwDocumentClassRec = { - wcreate, /* create */ - destroy, /* destroy */ - draw, /* draw */ - click, /* click */ - NULL, /* parent_resize */ - prop_change, /* prop_change */ - mouse_move, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - NULL, /* execute */ - NULL, /* tick */ - resize, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + destroy, /* destroy */ + draw, /* draw */ + click, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + mouse_move, /* mouse_move */ + MwForceRender2, /* mouse_up */ + MwForceRender2, /* mouse_down */ + NULL, /* key */ + NULL, /* execute */ + NULL, /* tick */ + resize, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; From 8e019efed937f4ce8adee41563c6a477d5ef94a2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 19:18:26 -0700 Subject: [PATCH 078/102] 2.0 --- CHANGELOG.txt | 16 +++++++++------- README.txt | 2 +- include/Mw/Version.h | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 79adc08c5..3bf997f12 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -12,13 +12,15 @@ Other changes include: - `MW_FORCE_CSD` (Linux only): set to force the wayland backend to use CSD instead of SSD - `MILSKO_BACKEND` has been renamed to `MW_BACKEND` - Redesigned look for radioboxes and checkboxes in the modern theme -- Clock Widget -- Chart Widgets - - Bar Chart (2D or 3D) - - Pie Chart (2D or 3D) - - Line Chart -- New "Document" widget that supports markdown. -- New Direct3D9 helper widget that allows you to use Direct3D9 (Windows only) +- Clock Widget (MwClockClass) +- Chart Widgets (MwChartClass) + - Bar Chart (MwCHART_BAR or MwCHART_BAR3D) + - Pie Chart (MwCHART_PIE or MwCHART_PIE3D) + - Line Chart (MwCHART_LINE) +- Document widget (MwDocumentClass) - text box widget that supports markdown. +- Direct3D9 widget (MwDirect3D9Class) - helper widget that sets up a D3D9 context for you (Windows only) +- Dark theme now uses Catppuccin Mocha theme +- MwNstrikethrough and MwNunderline now work on all text-based widgets - Stability/performance fixes for the Wayland backend, most likely for the last time. ========================= 1.4 ========================= diff --git a/README.txt b/README.txt index 0f57f905d..55c902792 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,5 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version 1.4) +Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0) This document contains a brief summary of the contents of this source distributions and building instructions for Milsko GUI Toolkit. diff --git a/include/Mw/Version.h b/include/Mw/Version.h index 9821dc6a4..2a0c2c04c 100644 --- a/include/Mw/Version.h +++ b/include/Mw/Version.h @@ -8,12 +8,12 @@ /*! * @brief Major version */ -#define MwMAJOR 1 +#define MwMAJOR 2 /*! * @brief Minor version */ -#define MwMINOR 3 +#define MwMINOR 0 /*! * @brief Patchlevel of version, if patchlevel_alphabet is a or bigger, this value is calculated by `patchlevel_alphabet - 'a' + 1`. Otherwise 0 @@ -23,7 +23,7 @@ /*! * @brief Version in string */ -#define MwVERSION "1.4" +#define MwVERSION "2.0" /*! * @brief Version in string From 28a0853fd6c58b2d9507e536b8a3fe00c564325d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 19:20:49 -0700 Subject: [PATCH 079/102] forgot a part of 2.0 changelog. oops. --- CHANGELOG.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3bf997f12..37b8e4d5a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -20,6 +20,7 @@ Other changes include: - Document widget (MwDocumentClass) - text box widget that supports markdown. - Direct3D9 widget (MwDirect3D9Class) - helper widget that sets up a D3D9 context for you (Windows only) - Dark theme now uses Catppuccin Mocha theme +- Better alpha blending for pixmaps (they now respect background color change) - MwNstrikethrough and MwNunderline now work on all text-based widgets - Stability/performance fixes for the Wayland backend, most likely for the last time. From 72a24e935cfcd6d16660b4e6562d75a942ae6bad Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 11:35:24 +0900 Subject: [PATCH 080/102] fix typos in 2.0 --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 37b8e4d5a..c649139dd 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,7 +2,7 @@ 2.0 is not the most significant release, but there are several breaking changes that justify its number: - There are no longer any public facing functions that use MwLL* types. Said functions now expect MwColor and MwPixmap, which are wrapper types over the LL ones. - MwSetVoid and MwGetVoid have been renamed to MwSetPointer and MwGetPointer -- MwSetText and MwGetText have been renamed to MwSetStrign and MwGetString +- MwSetText and MwGetText have been renamed to MwSetString and MwGetString Other changes include: - Widgets can now accept drag and dropped files via MwNacceptsDnD and the new MwNdragAndDropHandler handler. From 0bb760b918e30d3fa89156c9eda2e41f69ced855 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 11:38:34 +0900 Subject: [PATCH 081/102] fix missing underscore --- CHANGELOG.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c649139dd..a791bd7cb 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -14,8 +14,8 @@ Other changes include: - Redesigned look for radioboxes and checkboxes in the modern theme - Clock Widget (MwClockClass) - Chart Widgets (MwChartClass) - - Bar Chart (MwCHART_BAR or MwCHART_BAR3D) - - Pie Chart (MwCHART_PIE or MwCHART_PIE3D) + - Bar Chart (MwCHART_BAR or MwCHART_BAR_3D) + - Pie Chart (MwCHART_PIE or MwCHART_PIE_3D) - Line Chart (MwCHART_LINE) - Document widget (MwDocumentClass) - text box widget that supports markdown. - Direct3D9 widget (MwDirect3D9Class) - helper widget that sets up a D3D9 context for you (Windows only) From 52dc62c4a21d9888173fc447f3c9f6693f0d7400 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 26 Sep 2026 19:59:55 -0700 Subject: [PATCH 082/102] wayland: get_relative_pointer should use topmost_parent's cursor --- src/backend/wayland/wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 4ee0e220a..f5f3e2836 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1797,7 +1797,7 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) { topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); wl_surface_commit(topmost_parent->wayland.backbuffer.surface); zwp_locked_pointer_v1_set_cursor_position_hint(topmost_parent->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP); - handle->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, handle->wayland.pointer); + handle->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, topmost_parent->wayland.pointer); zwp_relative_pointer_v1_add_listener(handle->wayland.relative_pointer, &MwLLWaylandRelativePointerListener, topmost_parent); } else { if(topmost_parent->wayland.locked_pointer) { From ec197c1a1bc44c9879846a8ff5ce4fdc1e949b6d Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 12:40:30 +0900 Subject: [PATCH 083/102] win32 key_released fix --- src/backend/gdi.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 248a59b89..6ae65603c 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -265,7 +265,9 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if(HIBYTE(VkKeyScan(wp)) & 2) n |= MwKEY_CONTROL_FLAG; if(msg == WM_SYSCHAR) n |= MwKEY_ALT_FLAG; - if((0x20 <= n && n <= 0x7f) || (n & MwKEY_FLAG)) MwLLDispatch(u->ll, key, &n); + if((0x20 <= n && n <= 0x7f) || (n & MwKEY_FLAG)) { + MwLLDispatch(u->ll, key, &n); + } break; } case WM_SETFOCUS: @@ -322,6 +324,17 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { break; } + if(n == -1 && (msg == WM_KEYUP || msg == WM_SYSKEYUP)) { + WORD ch; + BYTE state[256]; + + GetKeyboardState(state); + + if(ToAscii(wp, HIWORD(lp) & 0xff, state, &ch, 0)) { + n = ch; + } + } + if((msg == WM_SYSKEYDOWN || msg == WM_SYSKEYUP) && n != -1 && wp != VK_MENU) { n |= MwKEY_ALT_FLAG; } From 8b7a11b71491eb9438c63d760599dacfe12f65f0 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 12:42:50 +0900 Subject: [PATCH 084/102] fix example --- examples/basic/image.c | 4 ++-- examples/basic/listbox.c | 10 +++++----- examples/basic/periodic.c | 16 ++++++++-------- examples/basic/subwindow.c | 6 +++--- examples/basic/tab.c | 6 +++--- examples/basic/treeview.c | 8 ++++---- examples/basic/viewport.c | 4 ++-- examples/gldemos/clock.c | 10 +++++----- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/basic/image.c b/examples/basic/image.c index 7d7f55a2d..e16747c46 100644 --- a/examples/basic/image.c +++ b/examples/basic/image.c @@ -1,8 +1,8 @@ #include int main() { - MwWidget window, image, image2, image3; - MwLLPixmap px, px2, px3; + MwWidget window, image, image2, image3; + MwPixmap px, px2, px3; MwLibraryInit(); diff --git a/examples/basic/listbox.c b/examples/basic/listbox.c index 0ec9fe7cd..ab2935ddf 100644 --- a/examples/basic/listbox.c +++ b/examples/basic/listbox.c @@ -23,11 +23,11 @@ void MWAPI activate(MwWidget handle, void* user, void* call) { } int main() { - MwWidget lb; - int len = sizeof(harvard) / sizeof(harvard[0]) - 1; - int i; - int index; - MwLLPixmap px; + MwWidget lb; + int len = sizeof(harvard) / sizeof(harvard[0]) - 1; + int i; + int index; + MwPixmap px; MwLibraryInit(); diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index f1af2490c..12de1b19a 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -140,13 +140,13 @@ static void MWAPI menu_handler(MwWidget handle, void* user, void* call) { } int main() { - int i, j; - MwWidget f, w, b; - MwLLPixmap px; - int index; - MwMenu m, m2; - void* v; - MwRect rc; + int i, j; + MwWidget f, w, b; + MwPixmap px; + int index; + MwMenu m, m2; + void* v; + MwRect rc; MwLibraryInit(); @@ -383,5 +383,5 @@ int main() { MwLoop(window); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); } diff --git a/examples/basic/subwindow.c b/examples/basic/subwindow.c index 93145923d..fbdc24c42 100644 --- a/examples/basic/subwindow.c +++ b/examples/basic/subwindow.c @@ -11,9 +11,9 @@ static void MWAPI resize(MwWidget handle, void* user, void* client) { } int main() { - MwWidget w; - int i; - MwLLPixmap px[6]; + MwWidget w; + int i; + MwPixmap px[6]; MwLibraryInit(); diff --git a/examples/basic/tab.c b/examples/basic/tab.c index 8ae16c04d..818ec1c8d 100644 --- a/examples/basic/tab.c +++ b/examples/basic/tab.c @@ -10,9 +10,9 @@ static void MWAPI resize(MwWidget handle, void* user, void* client) { } int main() { - MwWidget w; - int i; - MwLLPixmap px[6]; + MwWidget w; + int i; + MwPixmap px[6]; MwLibraryInit(); diff --git a/examples/basic/treeview.c b/examples/basic/treeview.c index 273dd3e2a..791f3708f 100644 --- a/examples/basic/treeview.c +++ b/examples/basic/treeview.c @@ -21,10 +21,10 @@ void MWAPI activate(MwWidget handle, void* user, void* call) { } int main() { - MwWidget tv; - MwLLPixmap px; - int i; - void * p = NULL, *r; + MwWidget tv; + MwPixmap px; + int i; + void * p = NULL, *r; MwLibraryInit(); diff --git a/examples/basic/viewport.c b/examples/basic/viewport.c index 930488d9e..63487bc38 100644 --- a/examples/basic/viewport.c +++ b/examples/basic/viewport.c @@ -16,8 +16,8 @@ static void MWAPI resize(MwWidget handle, void* user, void* call) { } int main() { - MwWidget w; - MwLLPixmap px; + MwWidget w; + MwPixmap px; MwLibraryInit(); diff --git a/examples/gldemos/clock.c b/examples/gldemos/clock.c index 2c1c7031e..2cbdcf83c 100644 --- a/examples/gldemos/clock.c +++ b/examples/gldemos/clock.c @@ -79,7 +79,7 @@ void MWAPI tick(MwWidget handle, void* user, void* call) { if(render && w > 0 && h > 0) { unsigned char* buffer = malloc(w * h * 4); - MwLLPixmap px; + MwPixmap px; int j; glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer); @@ -96,7 +96,7 @@ void MWAPI tick(MwWidget handle, void* user, void* call) { MwVaApply(window, MwNiconPixmap, px, NULL); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); free(buffer); } @@ -133,7 +133,7 @@ void MWAPI resize(MwWidget handle, void* user, void* call) { } int main() { - MwLLColor bgcolor, fgcolor; + MwColor bgcolor, fgcolor; MwLibraryInit(); @@ -164,6 +164,6 @@ int main() { MwLoop(window); - MwLLFreeColor(fgcolor); - MwLLFreeColor(bgcolor); + MwFreeColor(fgcolor); + MwFreeColor(bgcolor); } From 6051c32f5043cc2af992e26828060d2d3f460a52 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 12:45:10 +0900 Subject: [PATCH 085/102] prepare 2.0a --- CHANGELOG.txt | 4 ++++ README.txt | 2 +- include/Mw/Version.h | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a791bd7cb..8997a2918 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,7 @@ +========================= 2.1 ========================= +- Fixes a bug where key_released was not fired in GDI backend +- Fixes examples + ========================= 2.0 ========================= 2.0 is not the most significant release, but there are several breaking changes that justify its number: - There are no longer any public facing functions that use MwLL* types. Said functions now expect MwColor and MwPixmap, which are wrapper types over the LL ones. diff --git a/README.txt b/README.txt index 55c902792..04effb85a 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,5 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0) +Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0a) This document contains a brief summary of the contents of this source distributions and building instructions for Milsko GUI Toolkit. diff --git a/include/Mw/Version.h b/include/Mw/Version.h index 2a0c2c04c..f9bcf879b 100644 --- a/include/Mw/Version.h +++ b/include/Mw/Version.h @@ -18,12 +18,12 @@ /*! * @brief Patchlevel of version, if patchlevel_alphabet is a or bigger, this value is calculated by `patchlevel_alphabet - 'a' + 1`. Otherwise 0 */ -#define MwPATCH 0 +#define MwPATCH 1 /*! * @brief Version in string */ -#define MwVERSION "2.0" +#define MwVERSION "2.0a" /*! * @brief Version in string From 355171f61d8b01bd5ef1051b1a22e911f864047b Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 12:47:17 +0900 Subject: [PATCH 086/102] update bindings --- doc/BINDINGS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index 20e87519b..a950e5b08 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -7,9 +7,9 @@ | Language | Repo | Version | Notes | | -------- | --------------------------------------------------------------------- | ------- | -------------- | | Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | Auto-generated | -| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0 | Auto-generated | -| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0 | Auto-generated | -| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0 | Auto-generated | +| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0a | Auto-generated | +| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0a | Auto-generated | +| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0a | Auto-generated | # Inactive Bindings From ced06702de48dc89f528e4b939b1563362912cab Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 27 Sep 2026 12:49:12 +0900 Subject: [PATCH 087/102] 2.0a --- CHANGELOG.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8997a2918..8d5a148b6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,7 @@ -========================= 2.1 ========================= -- Fixes a bug where key_released was not fired in GDI backend -- Fixes examples +========================= 2.0a ======================== +- Fixed a bug where key_released was not fired in GDI backend +- Fixed examples +- Fixed Wayland backend's cursor lock ========================= 2.0 ========================= 2.0 is not the most significant release, but there are several breaking changes that justify its number: From 56d4d0377c4f676c67b9060de2bf146395ce87d7 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 28 Sep 2026 01:10:59 +0900 Subject: [PATCH 088/102] ok --- examples/basic/periodic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 12de1b19a..2aa6c4318 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -382,6 +382,4 @@ int main() { NULL); MwLoop(window); - - MwDestroyPixmap(px); } From eb8b9459956ce3c8bd86f49be0070f960ac18867 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 28 Sep 2026 10:56:30 +0900 Subject: [PATCH 089/102] fix --- examples/basic/periodic.c | 15 ++++++++++++--- src/core.c | 2 ++ src/widget/scrollbar.c | 9 +++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 2aa6c4318..8ff9811ea 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -341,7 +341,7 @@ int main() { f = frame("Separator", -PaddingContent, -PaddingContent, MwSeparatorClass, NULL); f = frame("SubWindow", -PaddingContent, -PaddingContent, MwViewportClass, - MwNcolumnSpan, 2, + MwNcolumnSpan, 3, NULL); w = child(f); MwViewportSetSize(w, 512, 512); @@ -352,7 +352,9 @@ int main() { MwNtitle, "Sub window 2", NULL); - f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, NULL); + f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, + MwNcolumnSpan, 2, + NULL); w = child(f); MwSetString(MwTabAdd(w, "ABC"), MwNbackground, "#f00"); MwSetString(MwTabAdd(w, "DEF"), MwNbackground, "#0f0"); @@ -364,7 +366,14 @@ int main() { v = MwTreeViewAdd(w, v, NULL, "def"); v = MwTreeViewAdd(w, v, NULL, "ghi"); - f = frame("Viewport", -PaddingContent, -PaddingContent, MwViewportClass, NULL); + f = frame("Text", -PaddingContent, -PaddingContent, MwViewportClass, + MwNcolumnSpan, 2, + NULL); + w = child(f); + + f = frame("Viewport", -PaddingContent, -PaddingContent, MwViewportClass, + MwNcolumnSpan, 2, + NULL); w = child(f); MwViewportSetSize(w, 256, 256); MwVaCreateWidget(MwButtonClass, "btn", MwViewportGetViewport(w), 64, 64, 128, 128, diff --git a/src/core.c b/src/core.c index 547b7b1e0..0618ea3c0 100644 --- a/src/core.c +++ b/src/core.c @@ -267,6 +267,8 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, h->lowlevel = NULL; } h->widget_class = widget_class; + h->mouse_point.x = 0; + h->mouse_point.y = 0; h->pressed = 0; h->close = 0; h->destroy_queue = NULL; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 840cdb563..02832a729 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -27,6 +27,7 @@ static int calc_length(MwWidget handle) { int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue); int area = MwGetInteger(handle, MwNareaShown); if(area > len) area = len; + if(len == 0) return max; return (int)(max * (double)area / len); } @@ -35,6 +36,7 @@ static int calc_position(MwWidget handle) { int max = MwScrollBarGetVisibleLength(handle); int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue); int val = MwGetInteger(handle, MwNvalue); + if(len == 0) return 0; return (int)((max - calc_length(handle)) * (double)val / len); } @@ -49,8 +51,10 @@ static void add_value(MwWidget handle, int mul) { if(val < min) val = min; if(val > max) val = max; - MwSetInteger(handle, MwNvalue, val); - MwDispatchUserHandler(handle, MwNchangedHandler, NULL); + if(MwGetInteger(handle, MwNvalue) != val) { + MwSetInteger(handle, MwNvalue, val); + MwDispatchUserHandler(handle, MwNchangedHandler, NULL); + } } static void draw(MwWidget handle) { @@ -223,6 +227,7 @@ static void mouse_down(MwWidget handle, void* ptr) { static void prop_change(MwWidget handle, const char* key) { if(strcmp(key, MwNminValue) == 0 || strcmp(key, MwNvalue) == 0 || strcmp(key, MwNmaxValue) == 0) { if(MwGetInteger(handle, MwNvalue) > MwGetInteger(handle, MwNmaxValue)) MwSetInteger(handle, MwNvalue, MwGetInteger(handle, MwNmaxValue)); + if(MwGetInteger(handle, MwNvalue) < MwGetInteger(handle, MwNminValue)) MwSetInteger(handle, MwNvalue, MwGetInteger(handle, MwNminValue)); MwForceRender(handle); } if(strcmp(key, MwNshowArrows) == 0 || strcmp(key, MwNareaShown) == 0) { From a6202258b7827724cf87e318cb4ccd083def0317 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 28 Sep 2026 10:58:21 +0900 Subject: [PATCH 090/102] ok --- src/widget/scrollbar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 02832a729..3807f1834 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -89,7 +89,7 @@ static void draw(MwWidget handle) { rt.y = r.y; if(MwGetInteger(handle, MwNshowArrows)) { MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.y <= uy) ? 1 : 0, MwNORTH); - if(handle->pressed && scr->point.y <= uy) { + if(handle->pressed && scr->point.y < uy) { add_value(handle, -1); } } else { @@ -114,7 +114,7 @@ static void draw(MwWidget handle) { rt.x = r.x; if(MwGetInteger(handle, MwNshowArrows)) { MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.x <= ux) ? 1 : 0, MwWEST); - if(handle->pressed && scr->point.x <= ux) { + if(handle->pressed && scr->point.x < ux) { add_value(handle, -1); } } else { From a61c199d5e8b5940de8d4caee583030783bcdedd Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 27 Sep 2026 19:26:52 -0700 Subject: [PATCH 091/102] MwLLWaylandSetToolWindowType --- include/Mw/LowLevel/Wayland.h | 11 +++++++++++ src/backend/wayland/wayland.c | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c49af026d..e94ed9505 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -464,6 +464,8 @@ struct _MwLLWayland { MwBool accepts_dnd; MwBool shown; + + enum zwlr_layer_shell_v1_layer layer_surface_type; }; struct _MwLLWaylandColor { @@ -526,4 +528,13 @@ typedef struct zxdg_decoration_manager_v1_context { extern struct zwp_relative_pointer_v1_listener MwLLWaylandRelativePointerListener; +/* + * function for setting the layer surface type used when creating a tool window + * (assuming layer surfaces are used). + * + * NOTE: Must be called after MwLLMakeToolWindow, as that function sets the type to + * the default of ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY. + */ +MWDECL void MWAPI MwLLWaylandSetToolWindowType(MwLL handle, enum zwlr_layer_shell_v1_layer type); + #endif diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index f5f3e2836..fb8cb0205 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -725,7 +725,7 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); - r->wayland.layer_surface->surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, r->wayland.framebuffer.surface, NULL, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "milsko-surfaces"); + r->wayland.layer_surface->surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, r->wayland.framebuffer.surface, NULL, r->wayland.layer_surface_type, "milsko-surfaces"); zwlr_layer_surface_v1_set_size(r->wayland.layer_surface->surface, width, height); zwlr_layer_surface_v1_set_margin(r->wayland.layer_surface->surface, @@ -1873,9 +1873,15 @@ static void MwLLMakeToolWindowImpl(MwLL handle) { handle->wayland.type_to_be = MwLL_WAYLAND_POPUP; } + handle->wayland.layer_surface_type = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; + handle->wayland.changing = MwTRUE; } +MWDECL void MWAPI MwLLWaylandSetToolWindowType(MwLL handle, enum zwlr_layer_shell_v1_layer type) { + handle->wayland.layer_surface_type = type; +} + static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { MwLL topmost_parent = handle; From a74814f27b5563bb1440b225f6b101af01204101 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 27 Sep 2026 19:29:13 -0700 Subject: [PATCH 092/102] 2.0b --- CHANGELOG.txt | 5 +++++ README.txt | 2 +- include/Mw/Version.h | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8d5a148b6..687a1f846 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +========================= 2.0b ======================== +- Fixed scrollbar bug where it can freeze entire toolkit +- Fixed scroller bug where it bar could appear "empty" +- Added function specific to Wayland backend (MwLLWaylandSetToolWindowType) that changes what type a created layer surface is when using MwLLMakeToolWindow + ========================= 2.0a ======================== - Fixed a bug where key_released was not fired in GDI backend - Fixed examples diff --git a/README.txt b/README.txt index 04effb85a..819e0463a 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,5 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0a) +Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0b) This document contains a brief summary of the contents of this source distributions and building instructions for Milsko GUI Toolkit. diff --git a/include/Mw/Version.h b/include/Mw/Version.h index f9bcf879b..1ac584f7a 100644 --- a/include/Mw/Version.h +++ b/include/Mw/Version.h @@ -18,12 +18,12 @@ /*! * @brief Patchlevel of version, if patchlevel_alphabet is a or bigger, this value is calculated by `patchlevel_alphabet - 'a' + 1`. Otherwise 0 */ -#define MwPATCH 1 +#define MwPATCH 2 /*! * @brief Version in string */ -#define MwVERSION "2.0a" +#define MwVERSION "2.0b" /*! * @brief Version in string From 11aa9e860e4dd868bd0b3a86d5619e37390eaf2f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 27 Sep 2026 19:34:21 -0700 Subject: [PATCH 093/102] update bindings.md oops --- doc/BINDINGS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index a950e5b08..df7cb7034 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -7,9 +7,9 @@ | Language | Repo | Version | Notes | | -------- | --------------------------------------------------------------------- | ------- | -------------- | | Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | Auto-generated | -| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0a | Auto-generated | -| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0a | Auto-generated | -| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0a | Auto-generated | +| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0b | Auto-generated | +| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0b | Auto-generated | +| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0b | Auto-generated | # Inactive Bindings From 4fe57c6d96cfd560c2f37d47880acb1ac9ab5154 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 28 Sep 2026 22:25:16 +0900 Subject: [PATCH 094/102] some bug fix --- configure | 5 +++-- pl/rules.pl | 2 ++ pl/utils.pl | 5 ++++- src/core.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/configure b/configure index e52de2993..ef1037f00 100755 --- a/configure +++ b/configure @@ -36,6 +36,7 @@ our $executable_suffix = ""; our @library_targets = (); our @examples_targets = (); our %examples_libs = (); +our %examples_all = (); our $cross = 0; our $host = ""; @@ -331,11 +332,11 @@ if (param_get("examples")) { if (param_get("shared")) { print(OUT -"${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n" +"${l}: ${s}${object_suffix} ${add} src/${library_prefix}Mw${library_suffix}\n" ); } else { - print(OUT "${l}: ${s}${object_suffix} src/${library_prefix}Mw.a\n"); + print(OUT "${l}: ${s}${object_suffix} ${add} src/${library_prefix}Mw.a\n"); } if (grep(/^cocoa$/, @backends)) { print(OUT diff --git a/pl/rules.pl b/pl/rules.pl index 276eb8871..888ed6d9c 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -221,6 +221,8 @@ new_example("examples/basic/subwindow"); new_example("examples/basic/tab"); new_example("examples/basic/document"); +#new_example("examples/doom/mwdoom", "", 1); + if (param_get("opengl")) { new_example("examples/gldemos/boing", $gl_libs); new_example("examples/gldemos/clock", $gl_libs); diff --git a/pl/utils.pl b/pl/utils.pl index 504e8dcbf..67d233878 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -41,9 +41,12 @@ sub add_libs { } sub new_example { - if (@_ == 2) { + if (@_ >= 2) { $examples_libs{"$_[0]${executable_suffix}"} = $_[1]; } + if (@_ >= 3) { + $examples_all{"$_[0]${executable_suffix}"} = $_[2]; + } push(@examples_targets, "${_[0]}${executable_suffix}"); } diff --git a/src/core.c b/src/core.c index 0618ea3c0..c821359a5 100644 --- a/src/core.c +++ b/src/core.c @@ -753,7 +753,7 @@ void MwSetString(MwWidget handle, const char* key, const char* value) { void MwSetPointer(MwWidget handle, const char* key, void* value) { if(IsFirstVisible(handle) && strcmp(key, MwNiconPixmap) == 0) { - MwLLSetIcon(handle->lowlevel, value); + MwLLSetIcon(handle->lowlevel, ((MwPixmap)value)->lowlevel); } else if(strcmp(key, MwNsizeHints) == 0) { MwSizeHints* sz = value; From 40611124607681b1f597fa7a259425b53ecdf438 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 12:08:32 -0700 Subject: [PATCH 095/102] fix memleaks --- include/Mw/LowLevel/Wayland.h | 2 +- src/backend/cairo.c | 16 ++- src/backend/wayland/buffer.c | 50 +++++++--- src/backend/wayland/interfaces.c | 148 +++++++++++++++++++++++----- src/backend/wayland/wayland.c | 164 +++++++++++++++++++++++-------- src/core.c | 2 +- 6 files changed, 294 insertions(+), 88 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index e94ed9505..6c4a4e652 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -396,7 +396,7 @@ struct _MwLLWayland { struct wl_data_device_manager* wl; struct zwp_primary_selection_device_manager_v1* zwp; } clipboard_manager; - union { + struct { struct wl_data_source* wl; struct zwp_primary_selection_source_v1* zwp; } clipboard_source; diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 02ed9d0a6..4c6a01747 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -134,16 +134,28 @@ void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 cairo->back_cairo = cairo_create(cairo->back_cs); } +/* Pointers are cleared so that destroying twice (or before any setup) is harmless; cairo ignores NULL. */ void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->front_cairo); cairo_destroy(cairo->front_cairo_back); - cairo_surface_destroy(cairo->front_cs); - cairo_surface_destroy(cairo->frontbuffer_cs); cairo_destroy(cairo->frontbuffer_cairo); + cairo_surface_destroy(cairo->front_cs); + cairo_surface_destroy(cairo->front_cs_back); + cairo_surface_destroy(cairo->frontbuffer_cs); + + cairo->front_cairo = NULL; + cairo->front_cairo_back = NULL; + cairo->frontbuffer_cairo = NULL; + cairo->front_cs = NULL; + cairo->front_cs_back = NULL; + cairo->frontbuffer_cs = NULL; }; void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->back_cairo); cairo_surface_destroy(cairo->back_cs); + + cairo->back_cairo = NULL; + cairo->back_cs = NULL; }; void MwLLCairoDestroy(struct _MwLLCairo handle) { diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 04ba04b1f..992b84c27 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -5,6 +5,7 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh); + MwLLCairoFrontDestroy(&wayland->cairo); MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh); memset(wayland->framebuffer.buf_back, 255, wayland->framebuffer.buf_size); @@ -38,6 +39,7 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { } MwLLWaylandBufferSetup(&wayland->backbuffer, w, h); + MwLLCairoBackDestroy(&wayland->cairo); MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h); memset(wayland->backbuffer.buf_back, 0, wayland->backbuffer.buf_size); @@ -57,40 +59,44 @@ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* wayland) { void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { int stride = width * 4; + int err; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXXXX"; char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXXXX"; + MwLLWaylandBufferDestroy(buffer); + buffer->buf_size = width * height * 4; buffer->fd = mkstemp(temp_name); buffer->fd_back = mkstemp(temp_name_back); if(buffer->fd >= 65536) { MwDispatchError(-1, "Amount of allocated buffers has gone above 65536! Cannot continue.\n"); - return; + goto fail; + } + if(buffer->fd == -1 || buffer->fd_back == -1) { + printf("failure setting up wl_shm: could not create file. %s.\n", strerror(errno)); + goto fail; } unlink(temp_name); unlink(temp_name_back); - if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) { - printf("failure setting up wl_shm (front buf): could not fallocate. %s.\n", strerror(errno)); - close(buffer->fd); - return; + /* posix_fallocate returns the error rather than setting errno */ + if((err = posix_fallocate(buffer->fd, 0, buffer->buf_size)) != 0) { + printf("failure setting up wl_shm (front buf): could not fallocate %llu bytes. %s.\n", (unsigned long long)buffer->buf_size, strerror(err)); + goto fail; } - if(posix_fallocate(buffer->fd_back, 0, buffer->buf_size) != 0) { - printf("failure setting up wl_shm (back buf): could not fallocate. %s.\n", strerror(errno)); - close(buffer->fd_back); - return; + if((err = posix_fallocate(buffer->fd_back, 0, buffer->buf_size)) != 0) { + printf("failure setting up wl_shm (back buf): could not fallocate %llu bytes. %s.\n", (unsigned long long)buffer->buf_size, strerror(err)); + goto fail; } if(ftruncate(buffer->fd, buffer->buf_size) != 0) { printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); - close(buffer->fd); - return; + goto fail; } if(ftruncate(buffer->fd_back, buffer->buf_size) != 0) { printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); - close(buffer->fd_back); - return; + goto fail; } buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0); @@ -110,6 +116,13 @@ void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, M buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); buffer->shm_buffer_back = wl_shm_pool_create_buffer(buffer->shm_pool_back, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); buffer->setup = MwTRUE; + return; + +fail: + if(buffer->fd >= 0) close(buffer->fd); + if(buffer->fd_back >= 0) close(buffer->fd_back); + buffer->fd = -1; + buffer->fd_back = -1; } void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { @@ -124,7 +137,16 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back); close(buffer->fd); close(buffer->fd_back); - buffer->setup = MwFALSE; + + buffer->buf = NULL; + buffer->buf_back = NULL; + buffer->shm_buffer = NULL; + buffer->shm_buffer_back = NULL; + buffer->shm_pool = NULL; + buffer->shm_pool_back = NULL; + buffer->fd = -1; + buffer->fd_back = -1; + buffer->setup = MwFALSE; } void MwLLWaylandBufferResize(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 02d5a85d1..e86586afb 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -17,8 +17,8 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat); static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); -static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); -static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); +static void destroy_clipboard(MwLL self); +static void destroy_zwp_clipboard(MwLL self); static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos); /* Recursively dispatch a key event to a widget and its children */ @@ -133,6 +133,9 @@ static void wl_data_device_data_offer(void* data, wl_data_offer_add_listener(offer, &offer_listener, data); + if(self->offer.wl && self->offer.wl != offer) { + wl_data_offer_destroy(self->offer.wl); + } self->offer.wl = offer; }; @@ -320,6 +323,9 @@ static void zwp_primary_selection_device_v1_data_offer(void* data, wl_clipboard_device_context_t* self = data; (void)zwp_primary_selection_device_v1; + if(self->offer.zwp && self->offer.zwp != offer) { + zwp_primary_selection_offer_v1_destroy(self->offer.zwp); + } self->offer.zwp = offer; }; @@ -491,14 +497,15 @@ static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLL static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)data; + destroy_clipboard((MwLL)wayland); + if(wayland->clipboard_source.wl) { + wl_data_source_destroy(wayland->clipboard_source.wl); + wayland->clipboard_source.wl = NULL; + } if(wayland->clipboard_manager.wl != NULL) { wl_data_device_manager_destroy(wayland->clipboard_manager.wl); wayland->clipboard_manager.wl = NULL; } - if(wayland->clipboard_source.wl) { - // wl_data_source_destroy(wayland->clipboard_source.wl); - wayland->clipboard_source.wl = NULL; - } } /* zwp_primary_selection_device_manager_v1 setup function */ @@ -526,8 +533,17 @@ static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 n } static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; (void)data; + destroy_zwp_clipboard((MwLL)wayland); + if(wayland->clipboard_source.zwp) { + zwp_primary_selection_source_v1_destroy(wayland->clipboard_source.zwp); + wayland->clipboard_source.zwp = NULL; + } + if(wayland->clipboard_manager.zwp != NULL) { + zwp_primary_selection_device_manager_v1_destroy(wayland->clipboard_manager.zwp); + wayland->clipboard_manager.zwp = NULL; + } + wayland->supports_zwp = MwFALSE; } /* zwp_primary_selection_device_manager_v1 setup function */ @@ -538,8 +554,15 @@ static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _ } static void zwp_pointer_constraints_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; (void)data; + if(wayland->locked_pointer) { + zwp_locked_pointer_v1_destroy(wayland->locked_pointer); + wayland->locked_pointer = NULL; + } + if(wayland->pointer_constraints) { + zwp_pointer_constraints_v1_destroy(wayland->pointer_constraints); + wayland->pointer_constraints = NULL; + } } static struct wl_surface* curSurface = NULL; @@ -667,8 +690,15 @@ static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, str } static void zwp_relative_pointer_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; (void)data; + if(wayland->relative_pointer) { + zwp_relative_pointer_v1_destroy(wayland->relative_pointer); + wayland->relative_pointer = NULL; + } + if(wayland->relative_pointer_manager) { + zwp_relative_pointer_manager_v1_destroy(wayland->relative_pointer_manager); + wayland->relative_pointer_manager = NULL; + } } /* `wl_pointer.motion` callback */ @@ -918,9 +948,16 @@ static void keyboard_keymap(void* data, struct xkb_state* xkb_state = xkb_state_new(xkb_keymap); + /* the compositor sends a new keymap whenever the layout changes */ + if(self->wayland.xkb_state) xkb_state_unref(self->wayland.xkb_state); + if(self->wayland.xkb_keymap) xkb_keymap_unref(self->wayland.xkb_keymap); + self->wayland.xkb_keymap = xkb_keymap; self->wayland.xkb_state = xkb_state; } else { + /* we don't read it, but the fd is still ours to close */ + close(fd); + self->wayland.xkb_keymap = self->wayland.parent->wayland.xkb_keymap; self->wayland.xkb_state = self->wayland.parent->wayland.xkb_state; } @@ -1159,6 +1196,31 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat) { device_ctx_wl->accepted_types[5] = "text/uri-list"; }; +static void destroy_zwp_clipboard(MwLL self) { + int i; + for(i = 0; i < arrlen(self->wayland.clipboard_devices_zwp); i++) { + wl_clipboard_device_context_t* ctx = self->wayland.clipboard_devices_zwp[i]; + if(ctx->offer.zwp) zwp_primary_selection_offer_v1_destroy(ctx->offer.zwp); + zwp_primary_selection_device_v1_destroy(ctx->device.zwp); + free(ctx); + } + arrfree(self->wayland.clipboard_devices_zwp); +} +static void destroy_clipboard(MwLL self) { + int i; + for(i = 0; i < arrlen(self->wayland.clipboard_devices_wl); i++) { + wl_clipboard_device_context_t* ctx = self->wayland.clipboard_devices_wl[i]; + if(ctx->offer.wl) wl_data_offer_destroy(ctx->offer.wl); + if(wl_proxy_get_version((struct wl_proxy*)ctx->device.wl) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION) { + wl_data_device_release(ctx->device.wl); + } else { + wl_data_device_destroy(ctx->device.wl); + } + free(ctx); + } + arrfree(self->wayland.clipboard_devices_wl); +} + static void keyboard_repeat_info(void* data, struct wl_keyboard* wl_keyboard, int32_t rate, @@ -1307,8 +1369,10 @@ static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_prot wayland->pointer_seat = NULL; } - free(data->listener); - free(data); + if(data) { + free(data->listener); + free(data); + } } /* wl_output setup function */ @@ -1321,8 +1385,11 @@ static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll, MwU32 version) { } static void wl_output_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; (void)data; + if(wayland->output) { + wl_output_destroy(wayland->output); + wayland->output = NULL; + } } /* wl_compositor setup function */ @@ -1334,8 +1401,11 @@ static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* } static void wl_compositor_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; (void)data; + if(wayland->compositor) { + wl_compositor_destroy(wayland->compositor); + wayland->compositor = NULL; + } } /* wl_subcompositor setup function */ @@ -1351,13 +1421,10 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan } static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; (void)data; - if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { - wl_subcompositor_destroy(wayland->toplevel->scompositor); - } - if(wayland->type == MwLL_WAYLAND_SUBSURFACE) { - wl_subcompositor_destroy(wayland->subsurface->subcompositor); - } + /* The subcompositor lives in the toplevel/subsurface struct, which is already freed by the time this runs, + * so destroy_toplevel()/destroy_subsurface() release it instead. */ } /* xdg_wm_base setup function */ @@ -1376,8 +1443,11 @@ static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wa static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; - free(data->listener); - free(data); + if(data) { + xdg_wm_base_destroy(data->context); + free(data->listener); + free(data); + } } /* zxdg_decoration_manager_v1 setup function */ @@ -1387,8 +1457,8 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ (void)version; proto->listener = NULL; - ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1); - ; + ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1); + ctx->decoration = NULL; proto->context = ctx; @@ -1396,8 +1466,15 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ } static void zxdg_decoration_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + zxdg_decoration_manager_v1_context_t* ctx; (void)wayland; - (void)data; + if(!data) return; + + /* the toplevel decoration itself has to go before the xdg_toplevel, so destroy_toplevel() handles that */ + ctx = data->context; + zxdg_decoration_manager_v1_destroy(ctx->manager); + free(ctx); + free(data); } /* wl_shm setup function */ @@ -1411,8 +1488,13 @@ static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland } static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; (void)data; + if(wayland->framebuffer.shm) wl_shm_destroy(wayland->framebuffer.shm); + if(wayland->backbuffer.shm) wl_shm_destroy(wayland->backbuffer.shm); + if(wayland->cursor.shm) wl_shm_destroy(wayland->cursor.shm); + wayland->framebuffer.shm = NULL; + wayland->backbuffer.shm = NULL; + wayland->cursor.shm = NULL; } static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { @@ -1428,8 +1510,11 @@ static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; - free(data->listener); - free(data); + if(data) { + xdg_toplevel_icon_manager_v1_destroy(data->context); + free(data->listener); + free(data); + } } static wayland_protocol_t* zwlr_layer_shell_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { @@ -1443,7 +1528,14 @@ static wayland_protocol_t* zwlr_layer_shell_v1_setup(MwU32 name, struct _MwLLWay static void zwlr_layer_shell_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; + if(!data) return; + /* the destroy request only exists from version 3, before that the proxy is all there is to free */ + if(wl_proxy_get_version(data->context) >= ZWLR_LAYER_SHELL_V1_DESTROY_SINCE_VERSION) { + zwlr_layer_shell_v1_destroy(data->context); + } else { + wl_proxy_destroy(data->context); + } free(data); } @@ -1458,7 +1550,9 @@ static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayl static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; + if(!data) return; + wp_fifo_manager_v1_destroy(data->context); free(data); } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index fb8cb0205..80e0da587 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -342,10 +342,14 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Toplevel destroy function */ static void destroy_toplevel(MwLL r) { - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + /* The toplevel decoration must go before the xdg_toplevel. The manager itself is released in + * zxdg_decoration_manager_v1_interface_destroy along with every other global. */ + if(WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; - zxdg_toplevel_decoration_v1_destroy(dec->decoration); - zxdg_decoration_manager_v1_destroy(dec->manager); + if(dec->decoration) { + zxdg_toplevel_decoration_v1_destroy(dec->decoration); + dec->decoration = NULL; + } } MwLLWaylandFramebufferDestroy(&r->wayland); @@ -355,19 +359,34 @@ static void destroy_toplevel(MwLL r) { xdg_surface_destroy(r->wayland.toplevel->xdg_surface); - wl_compositor_destroy(r->wayland.compositor); + xkb_state_unref(r->wayland.xkb_state); xkb_keymap_unref(r->wayland.xkb_keymap); - xkb_state_unref(r->wayland.xkb_state); - xkb_context_unref(r->wayland.xkb_context); + r->wayland.xkb_state = NULL; + r->wayland.xkb_keymap = NULL; + r->wayland.xkb_context = NULL; + /* wl_pointer/wl_keyboard/wl_seat are torn down centrally in wl_seat_interface_destroy, * after this function returns, so every widget type that binds a seat (toplevel, popup, * layer surface) releases them the same way instead of leaking or double-freeing them. */ + /* framebuffer.surface has the wl_subsurface role, so that has to go first or the compositor raises defunct_role_object. */ + wl_subsurface_destroy(r->wayland.toplevel->ssurface); + wl_subcompositor_destroy(r->wayland.toplevel->scompositor); + + if(r->wayland.framebuffer.fifo) { + wp_fifo_v1_destroy(r->wayland.framebuffer.fifo); + r->wayland.framebuffer.fifo = NULL; + } + wl_surface_destroy(r->wayland.framebuffer.surface); + r->wayland.framebuffer.surface = NULL; + + wl_surface_destroy(r->wayland.backbuffer.surface); + r->wayland.backbuffer.surface = NULL; free(r->wayland.toplevel); @@ -422,6 +441,10 @@ static void destroy_sublevel(MwLL r) { MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); + /* xkb state is borrowed from the parent, so it is not ours to unref */ + wl_surface_destroy(r->wayland.framebuffer.surface); + r->wayland.framebuffer.surface = NULL; + free(r->wayland.sublevel); r->wayland.configured = MwFALSE; @@ -482,7 +505,14 @@ static void destroy_subsurface(MwLL r) { MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); - free(r->wayland.sublevel); + /* role object before the surface */ + wl_subsurface_destroy(r->wayland.subsurface->subsurface); + wl_subcompositor_destroy(r->wayland.subsurface->subcompositor); + + wl_surface_destroy(r->wayland.framebuffer.surface); + r->wayland.framebuffer.surface = NULL; + + free(r->wayland.subsurface); r->wayland.configured = MwFALSE; } @@ -642,8 +672,7 @@ static void destroy_popup(MwLL r) { xdg_positioner_destroy(r->wayland.popup->xdg_positioner); wl_surface_destroy(r->wayland.framebuffer.surface); - - wl_registry_destroy(r->wayland.registry); + r->wayland.framebuffer.surface = NULL; free(r->wayland.popup); @@ -747,24 +776,27 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { } } -/* Toplevel destroy function */ +/* Layer surface destroy function */ static void destroy_layer_surface(MwLL r) { - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { - zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; - zxdg_decoration_manager_v1_destroy(dec->manager); - } + MwLLWaylandFramebufferDestroy(&r->wayland); + + /* The role object has to go before the wl_surface, otherwise the compositor raises defunct_role_object. */ + zwlr_layer_surface_v1_destroy(r->wayland.layer_surface->surface); + + free(r->wayland.layer_surface); wl_surface_destroy(r->wayland.framebuffer.surface); - - wl_compositor_destroy(r->wayland.compositor); - - xkb_keymap_unref(r->wayland.xkb_keymap); + r->wayland.framebuffer.surface = NULL; xkb_state_unref(r->wayland.xkb_state); + xkb_keymap_unref(r->wayland.xkb_keymap); + xkb_context_unref(r->wayland.xkb_context); - wl_registry_destroy(r->wayland.registry); + r->wayland.xkb_state = NULL; + r->wayland.xkb_keymap = NULL; + r->wayland.xkb_context = NULL; r->wayland.configured = MwFALSE; } @@ -793,6 +825,9 @@ static void destroy_widget(MwLL handle) { case MwLL_WAYLAND_LAYER_SURFACE: destroy_layer_surface(handle); break; + case MwLL_WAYLAND_SUBSURFACE: + destroy_subsurface(handle); + break; default: printf("Handle with unknown type(%d) tried to be destroyed (%p)\n", handle->wayland.type, handle); break; @@ -805,18 +840,22 @@ static void destroy_widget(MwLL handle) { } for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) { - void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key); + const char* key = handle->wayland.wl_protocol_setup_map[i].key; - if(ctx != NULL) { - handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx); + /* Many setup functions keep what they bind in the MwLL and store a NULL context, so check + * whether the global was bound at all rather than whether the context is NULL. */ + if(shgeti(handle->wayland.wl_protocol_map, key) != -1) { + handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, shget(handle->wayland.wl_protocol_map, key)); } - shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value); free(handle->wayland.wl_protocol_setup_map[i].value); } shfree(handle->wayland.wl_protocol_map); shfree(handle->wayland.wl_protocol_setup_map); + wl_registry_destroy(handle->wayland.registry); + handle->wayland.registry = NULL; + MwLLWaylandFlush(handle); } @@ -880,6 +919,9 @@ static void clip(MwLL handle) { cairo_clip(handle->wayland.cairo.front_cairo_back); } } + + /* parentless handles skip the branch above (arrfree sets ws to NULL, so this is a no-op otherwise) */ + arrfree(ws); } static void wl_logger(const char* fmt, va_list args) { @@ -949,6 +991,10 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } } + /* widget_setup runs again on every state change, drop the regions from the last one */ + if(r->wayland.region) wl_region_destroy(r->wayland.region); + if(r->wayland.o_region) wl_region_destroy(r->wayland.o_region); + r->wayland.region = wl_compositor_create_region(r->wayland.compositor); r->wayland.o_region = wl_compositor_create_region(r->wayland.compositor); MwLLWaylandRegionSetup(r); @@ -1090,6 +1136,9 @@ static void MwLLDestroyImpl(MwLL handle) { MwLLWaylandFlush(handle); MwLLDestroyCommon(handle); + /* destroy_widget() roundtrips, which can still deliver events (keyboard leave etc.) to this handle; + * MwLLDispatch skips a NULL handler table instead of reading the freed one */ + handle->common.handler = NULL; tv.tv_sec = 0; tv.tv_usec = 1000; @@ -1104,24 +1153,39 @@ static void MwLLDestroyImpl(MwLL handle) { #endif if(handle->wayland.valid) { - MwLLWaylandBufferDestroy(&handle->wayland.cursor); - wl_region_destroy(handle->wayland.region); - - if(handle->wayland.supports_zwp) { - zwp_primary_selection_source_v1_destroy(handle->wayland.clipboard_source.zwp); - } else { - wl_data_source_destroy(handle->wayland.clipboard_source.wl); + if(handle->wayland.cursor.setup) { + MwLLWaylandBufferDestroy(&handle->wayland.cursor); + wl_surface_destroy(handle->wayland.cursor.surface); } + wl_region_destroy(handle->wayland.region); + wl_region_destroy(handle->wayland.o_region); + + /* clipboard sources are released with their managers in destroy_widget */ if(handle->wayland.icon != NULL) { - MwLLWaylandBufferDestroy(handle->wayland.icon); - wl_surface_destroy(handle->wayland.icon->surface); + if(handle->wayland.icon->setup) { + MwLLWaylandBufferDestroy(handle->wayland.icon); + wl_surface_destroy(handle->wayland.icon->surface); + } + free(handle->wayland.icon); } destroy_widget(handle); + + /* Only parentless handles connect (children borrow the parent's display), and children are + * always freed before their parent, so nothing else is using it by now. */ + if(!handle->wayland.parent && handle->wayland.display) { + wl_display_disconnect(handle->wayland.display); + handle->wayland.display = NULL; + } } else { printf("widget invalid\n"); } + if(handle->wayland.icon_pixmap) MwLLDestroyPixmap(handle->wayland.icon_pixmap); + if(handle->wayland.snapshot) cairo_surface_destroy(handle->wayland.snapshot); + free(handle->wayland.clipboard_buffer); + arrfree(handle->wayland.currentlyHeldWidgets); + for(i = 0; i < arrlen(topmost_parent->wayland.currentlyHeldWidgets); i++) { if(topmost_parent->wayland.currentlyHeldWidgets[i] == handle) { arrdel(topmost_parent->wayland.currentlyHeldWidgets, i); @@ -1605,8 +1669,9 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { if(handle->wayland.icon == NULL) { handle->wayland.icon = malloc(sizeof(struct _MwLLWaylandShmBuffer)); memset(handle->wayland.icon, 0, sizeof(struct _MwLLWaylandShmBuffer)); - handle->wayland.icon->shm = handle->wayland.framebuffer.shm; } + /* wl_shm is rebound whenever the widget changes state, so don't hold on to an old one */ + handle->wayland.icon->shm = handle->wayland.framebuffer.shm; if(handle->wayland.icon->setup) { MwLLWaylandBufferDestroy(handle->wayland.icon); @@ -1619,11 +1684,17 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { wl_surface_attach(handle->wayland.icon->surface, handle->wayland.icon->shm_buffer, 0, 0); wl_surface_commit(handle->wayland.icon->surface); - for(; i < size; i += 2) { - handle->wayland.icon->buf_back[i] = pixmap->common.raw[i + 2]; - handle->wayland.icon->buf_back[i + 1] = pixmap->common.raw[i + 1]; - handle->wayland.icon->buf_back[i + 2] = pixmap->common.raw[i + 0]; - handle->wayland.icon->buf_back[i + 3] = 255; + /* RGBA -> BGRA, one pixel (4 bytes) at a time. The icon buffer is line x line, so rows + * have to be placed with its stride rather than the pixmap's. */ + for(; i < size; i += 4) { + int x = (i / 4) % pixmap->common.width; + int y = (i / 4) / pixmap->common.width; + unsigned char* dst = &handle->wayland.icon->buf_back[(y * line + x) * 4]; + + dst[0] = pixmap->common.raw[i + 2]; + dst[1] = pixmap->common.raw[i + 1]; + dst[2] = pixmap->common.raw[i + 0]; + dst[3] = 255; } if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, handle->wayland.icon); @@ -1631,6 +1702,9 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer_back, 1); xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon); + + /* the icon is immutable once set, destroying it doesn't unset it */ + xdg_toplevel_icon_v1_destroy(icon); } } if(!handle->wayland.has_decorations && handle->wayland.do_csd) { @@ -1794,11 +1868,15 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) { while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; if(handle->wayland.pointer_constraints && handle->wayland.relative_pointer_manager) { if(toggle) { - topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); - wl_surface_commit(topmost_parent->wayland.backbuffer.surface); + if(!topmost_parent->wayland.locked_pointer) { + topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + wl_surface_commit(topmost_parent->wayland.backbuffer.surface); + } zwp_locked_pointer_v1_set_cursor_position_hint(topmost_parent->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP); - handle->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, topmost_parent->wayland.pointer); - zwp_relative_pointer_v1_add_listener(handle->wayland.relative_pointer, &MwLLWaylandRelativePointerListener, topmost_parent); + if(!topmost_parent->wayland.relative_pointer) { + topmost_parent->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, topmost_parent->wayland.pointer); + zwp_relative_pointer_v1_add_listener(topmost_parent->wayland.relative_pointer, &MwLLWaylandRelativePointerListener, topmost_parent); + } } else { if(topmost_parent->wayland.locked_pointer) { zwp_locked_pointer_v1_destroy(topmost_parent->wayland.locked_pointer); @@ -1821,7 +1899,7 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty if(handle->wayland.clipboard_buffer != NULL) { free(handle->wayland.clipboard_buffer); } - handle->wayland.clipboard_buffer = malloc(strlen(text)); + handle->wayland.clipboard_buffer = malloc(strlen(text) + 1); strcpy(handle->wayland.clipboard_buffer, text); if(clipboard_type == MwCLIPBOARD_PRIMARY) { diff --git a/src/core.c b/src/core.c index 0618ea3c0..a3d8ae157 100644 --- a/src/core.c +++ b/src/core.c @@ -753,7 +753,7 @@ void MwSetString(MwWidget handle, const char* key, const char* value) { void MwSetPointer(MwWidget handle, const char* key, void* value) { if(IsFirstVisible(handle) && strcmp(key, MwNiconPixmap) == 0) { - MwLLSetIcon(handle->lowlevel, value); + if(value != NULL) MwLLSetIcon(handle->lowlevel, ((MwPixmap)value)->lowlevel); } else if(strcmp(key, MwNsizeHints) == 0) { MwSizeHints* sz = value; From f3cb2fe15a284f2f3ecb7b9636614aa95fee39b4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 12:12:19 -0700 Subject: [PATCH 096/102] while we're at it we haven't needed the 'valid' checks for awhile --- include/Mw/LowLevel/Wayland.h | 1 - src/backend/wayland/wayland.c | 54 ++++++++++++++--------------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 6c4a4e652..239196d37 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -381,7 +381,6 @@ struct _MwLLWayland { struct zwp_relative_pointer_v1* relative_pointer; struct zwp_locked_pointer_v1* locked_pointer; MwBool pointer_constrained; - MwBool valid; #ifdef USE_DBUS MwLLDBusContext dbus; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 80e0da587..04bb8aa39 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -951,7 +951,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.x = x; r->wayland.y = y; r->wayland.parent = parent; - r->wayland.valid = MwTRUE; if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { @@ -1152,33 +1151,29 @@ static void MwLLDestroyImpl(MwLL handle) { } #endif - if(handle->wayland.valid) { - if(handle->wayland.cursor.setup) { - MwLLWaylandBufferDestroy(&handle->wayland.cursor); - wl_surface_destroy(handle->wayland.cursor.surface); - } - wl_region_destroy(handle->wayland.region); - wl_region_destroy(handle->wayland.o_region); + if(handle->wayland.cursor.setup) { + MwLLWaylandBufferDestroy(&handle->wayland.cursor); + wl_surface_destroy(handle->wayland.cursor.surface); + } + wl_region_destroy(handle->wayland.region); + wl_region_destroy(handle->wayland.o_region); - /* clipboard sources are released with their managers in destroy_widget */ - if(handle->wayland.icon != NULL) { - if(handle->wayland.icon->setup) { - MwLLWaylandBufferDestroy(handle->wayland.icon); - wl_surface_destroy(handle->wayland.icon->surface); - } - free(handle->wayland.icon); + /* clipboard sources are released with their managers in destroy_widget */ + if(handle->wayland.icon != NULL) { + if(handle->wayland.icon->setup) { + MwLLWaylandBufferDestroy(handle->wayland.icon); + wl_surface_destroy(handle->wayland.icon->surface); } + free(handle->wayland.icon); + } - destroy_widget(handle); + destroy_widget(handle); - /* Only parentless handles connect (children borrow the parent's display), and children are - * always freed before their parent, so nothing else is using it by now. */ - if(!handle->wayland.parent && handle->wayland.display) { - wl_display_disconnect(handle->wayland.display); - handle->wayland.display = NULL; - } - } else { - printf("widget invalid\n"); + /* Only parentless handles connect (children borrow the parent's display), and children are + * always freed before their parent, so nothing else is using it by now. */ + if(!handle->wayland.parent && handle->wayland.display) { + wl_display_disconnect(handle->wayland.display); + handle->wayland.display = NULL; } if(handle->wayland.icon_pixmap) MwLLDestroyPixmap(handle->wayland.icon_pixmap); @@ -1198,13 +1193,6 @@ static void MwLLDestroyImpl(MwLL handle) { } static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { - if(!handle->wayland.valid) { - *x = 0; - *y = 0; - *w = 1; - *h = 1; - return; - } *x = handle->wayland.x; *y = handle->wayland.y; *w = handle->wayland.ww; @@ -1687,8 +1675,8 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { /* RGBA -> BGRA, one pixel (4 bytes) at a time. The icon buffer is line x line, so rows * have to be placed with its stride rather than the pixmap's. */ for(; i < size; i += 4) { - int x = (i / 4) % pixmap->common.width; - int y = (i / 4) / pixmap->common.width; + int x = (i / 4) % pixmap->common.width; + int y = (i / 4) / pixmap->common.width; unsigned char* dst = &handle->wayland.icon->buf_back[(y * line + x) * 4]; dst[0] = pixmap->common.raw[i + 2]; From 37b1f86fa9f6e2a632389cedffa183563951a138 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 12:18:47 -0700 Subject: [PATCH 097/102] remove some bad comments --- src/backend/cairo.c | 14 +++++++------- src/backend/wayland/wayland.c | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 4c6a01747..94d806d28 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -134,7 +134,6 @@ void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 cairo->back_cairo = cairo_create(cairo->back_cs); } -/* Pointers are cleared so that destroying twice (or before any setup) is harmless; cairo ignores NULL. */ void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->front_cairo); cairo_destroy(cairo->front_cairo_back); @@ -143,6 +142,7 @@ void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { cairo_surface_destroy(cairo->front_cs_back); cairo_surface_destroy(cairo->frontbuffer_cs); + /* set all to null so that cairo ignores future destroys */ cairo->front_cairo = NULL; cairo->front_cairo_back = NULL; cairo->frontbuffer_cairo = NULL; @@ -229,8 +229,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -274,10 +274,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 04bb8aa39..2cf420497 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -990,7 +990,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } } - /* widget_setup runs again on every state change, drop the regions from the last one */ if(r->wayland.region) wl_region_destroy(r->wayland.region); if(r->wayland.o_region) wl_region_destroy(r->wayland.o_region); From 65414190073193c6bcf40153bdd6f6603e90e77e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 14:23:32 -0700 Subject: [PATCH 098/102] wayland: only do pointer adjustments for (all subtypes) --- src/backend/wayland/interfaces.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index e86586afb..c281b2edf 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -762,8 +762,9 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; if(topmost_parent) { - /* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */ - if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + /* if the topmost parent is a popup/subwindow/layer surface then its x/y is irrelevant to us, + * it's the window's position on screen and pointer coordinates are relative to the window. */ + if(topmost_parent->wayland.type == MwLL_WAYLAND_SUBLEVEL || topmost_parent->wayland.type == MwLL_WAYLAND_SUBSURFACE) { absolute_pos.x += topmost_parent->wayland.x; absolute_pos.y += topmost_parent->wayland.y; } From 0c9aaf26dbfa695bbeb1ab70d8404ef840c93ec2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 14:51:18 -0700 Subject: [PATCH 099/102] layer surface fix --- src/backend/wayland/wayland.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 2cf420497..4373af62d 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -616,9 +616,12 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.popup->xdg_positioner = xdg_wm_base_create_positioner(r->wayland.popup->xdg_wm_base); xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); + /* the anchor rect is relative to the parent surface, so a layer surface's position on screen doesn't apply */ xdg_positioner_set_anchor_rect( r->wayland.popup->xdg_positioner, - topmost_parent->wayland.x, topmost_parent->wayland.y, r->wayland.ww, r->wayland.wh); + topmost_parent->wayland.type == MwLL_WAYLAND_LAYER_SURFACE ? 0 : topmost_parent->wayland.x, + topmost_parent->wayland.type == MwLL_WAYLAND_LAYER_SURFACE ? 0 : topmost_parent->wayland.y, + r->wayland.ww, r->wayland.wh); xdg_positioner_set_offset( r->wayland.popup->xdg_positioner, r->wayland.x, r->wayland.y); @@ -1772,7 +1775,8 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { int x = 0, y = 0; while(p != NULL) { - if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + /* a layer surface's x/y is its position on screen, which like a toplevel's isn't part of the offset */ + if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL && p->wayland.type != MwLL_WAYLAND_LAYER_SURFACE) { x += p->wayland.x; y += p->wayland.y; } else { From bbbd2480516e2503f6a0560abd131b411c7e3833 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 16:18:48 -0700 Subject: [PATCH 100/102] wayland fixes --- src/backend/wayland/interfaces.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index c281b2edf..67bd2fe5f 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -736,8 +736,10 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time for(i = 0; i < arrlen(currentlyHeldWidgets); i++) { MwLL new_topmost = currentlyHeldWidgets[i]; - p.point = topmost_parent->wayland.cur_mouse_pos; - while(new_topmost->wayland.parent) { + /* the position is relative to the surface the pointer is on (ours), so only widgets below + * us are offset from it. going further would also subtract e.g. a popup's position */ + p.point = self->wayland.cur_mouse_pos; + while(new_topmost != self && new_topmost->wayland.parent) { p.point.x -= new_topmost->wayland.x; p.point.y -= new_topmost->wayland.y; new_topmost = new_topmost->wayland.parent; @@ -1052,21 +1054,24 @@ static void keyboard_key(void* data, MwU64 syms_num; int i; - if(!self->wayland.xkb_keymap) { + struct xkb_keymap* xkb_keymap = topmost_parent->wayland.xkb_keymap; + struct xkb_state* xkb_state = topmost_parent->wayland.xkb_state; + + if(!xkb_keymap || !xkb_state) { return; } - layout = xkb_state_key_get_layout(self->wayland.xkb_state, keycode); + layout = xkb_state_key_get_layout(xkb_state, keycode); levels = - xkb_keymap_num_levels_for_key(self->wayland.xkb_keymap, keycode, layout); + xkb_keymap_num_levels_for_key(xkb_keymap, keycode, layout); if((((self->wayland.mod_state & 1) == 1) || ((self->wayland.mod_state & 2) == 2)) && levels >= 2) { level = 1; } else if(levels >= 1) { level = 0; } - syms_num = xkb_keymap_key_get_syms_by_level(self->wayland.xkb_keymap, keycode, layout, level, &syms_out); + syms_num = xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms_out); if(syms_out == NULL) { return; From b59ddffce60a1456ff27cb08ba91fe79ea9f540e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 28 Sep 2026 18:46:12 -0700 Subject: [PATCH 101/102] menu fix --- include/Mw/TypeDefs.h | 1 + src/backend/wayland/wayland.c | 9 ++++++++- src/widget/menu.c | 1 + src/widget/submenu.c | 14 ++++++++++---- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 2a4093a58..0ace3fc49 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -169,6 +169,7 @@ struct _MwMenu { MwMenu* sub; void* opaque; int cleaned; + int bold; }; struct _MwEntry { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 4373af62d..74b0df665 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -628,6 +628,8 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE); xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_GRAVITY_NONE); + /* we can't see where we are on screen, so let the compositor keep the popup on it */ + xdg_positioner_set_constraint_adjustment(r->wayland.popup->xdg_positioner, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y); r->wayland.xkb_keymap = topmost_parent->wayland.xkb_keymap; r->wayland.xkb_state = topmost_parent->wayland.xkb_state; @@ -1776,7 +1778,12 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { while(p != NULL) { /* a layer surface's x/y is its position on screen, which like a toplevel's isn't part of the offset */ - if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL && p->wayland.type != MwLL_WAYLAND_LAYER_SURFACE) { + if(p->wayland.type == MwLL_WAYLAND_POPUP) { + /* a popup's x/y is already relative to the topmost surface, so anything above it is counted already */ + x += p->wayland.x; + y += p->wayland.y; + break; + } else if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL && p->wayland.type != MwLL_WAYLAND_LAYER_SURFACE) { x += p->wayland.x; y += p->wayland.y; } else { diff --git a/src/widget/menu.c b/src/widget/menu.c index 928205486..0a4b43774 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -248,6 +248,7 @@ static MwMenu mwMenuAddImpl(MwWidget handle, MwMenu menu, const char* name) { new->wsub = NULL; new->keep = 0; new->cleaned = 0; + new->bold = 0; arrput(m->sub, new); diff --git a/src/widget/submenu.c b/src/widget/submenu.c index e2bab1ccd..74b53ba7c 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -57,8 +57,9 @@ static void draw(MwWidget handle) { p.y += 2 + 1; } else { - int tw = MwTextWidth(handle, NULL, menu->sub[i]->name); - int th = MwTextHeight(handle, NULL, menu->sub[i]->name); + MwFLFont font = MwFLBuildFont(menu->sub[i]->wsub != NULL ? MwFLFlagBold : 0); + int tw = MwTextWidth(handle, font, menu->sub[i]->name); + int th = MwTextHeight(handle, NULL, menu->sub[i]->name); if(menu->sub[i]->wsub != NULL) { r.x = MwGetInteger(handle, MwNleftPadding); @@ -71,7 +72,7 @@ static void draw(MwWidget handle) { p.x = 5 + tw / 2 + MwGetInteger(handle, MwNleftPadding); p.y += th / 2; - MwDrawText(handle, MwFLBuildFont(menu->sub[i]->wsub != NULL ? MwFLFlagBold : 0), &p, menu->sub[i]->name, MwALIGNMENT_CENTER, text); + MwDrawText(handle, font, &p, menu->sub[i]->name, MwALIGNMENT_CENTER, text); if(arrlen(menu->sub[i]->sub) > 0) { MwRect tr; @@ -182,6 +183,11 @@ static void mwSubMenuAppearImpl(MwWidget handle, MwMenu menu, MwPoint* point, in MwLLMakeToolWindow(handle->lowlevel); MwLLDetach(handle->lowlevel, &p); + MwVaApply(handle, + MwNwidth, sz.width, + MwNheight, sz.height, + NULL); + if(handle->lowlevel->common.coordinate_type == MwCOORDINATE_GLOBAL) { if(MwGetInteger(handle, MwNy) + sz.height > rc.height) { MwVaApply(handle, @@ -208,7 +214,7 @@ static void mwSubMenuGetSizeImpl(MwWidget handle, MwMenu menu, MwRect* rect) { if(strcmp(menu->sub[i]->name, "----") == 0) { rect->height += 2 + 2; } else { - int tw = MwTextWidth(handle, NULL, menu->sub[i]->name); + int tw = MwTextWidth(handle, MwFLBuildFont(arrlen(menu->sub[i]->sub) > 0 ? MwFLFlagBold : 0), menu->sub[i]->name); rect->height += MwTextHeight(handle, NULL, menu->sub[i]->name) + 3; if(tw > rect->width) { rect->width = tw; From ff4d72582a6820c94e65dc3e45f920055fb3b9c5 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 29 Sep 2026 17:56:28 +0900 Subject: [PATCH 102/102] change font to normal opensans --- configure | 6 +- resource/font/OpenSans-Bold.ttf | Bin 36548 -> 147264 bytes resource/font/OpenSans-Regular.ttf | Bin 35264 -> 147528 bytes src/text/font/boldmonottf.c | 6033 +++++------ src/text/font/boldttf.c | 15321 +++++++++++++++++++++------ src/text/font/monottf.c | 6033 +++++------ src/text/font/ttf.c | 15236 +++++++++++++++++++++----- tools/ttf.sh | 12 +- 8 files changed, 30615 insertions(+), 12026 deletions(-) diff --git a/configure b/configure index ef1037f00..b69b898fe 100755 --- a/configure +++ b/configure @@ -36,7 +36,7 @@ our $executable_suffix = ""; our @library_targets = (); our @examples_targets = (); our %examples_libs = (); -our %examples_all = (); +our %examples_all = (); our $cross = 0; our $host = ""; @@ -336,7 +336,9 @@ if (param_get("examples")) { ); } else { - print(OUT "${l}: ${s}${object_suffix} ${add} src/${library_prefix}Mw.a\n"); + print(OUT +"${l}: ${s}${object_suffix} ${add} src/${library_prefix}Mw.a\n" + ); } if (grep(/^cocoa$/, @backends)) { print(OUT diff --git a/resource/font/OpenSans-Bold.ttf b/resource/font/OpenSans-Bold.ttf index e62bd81424ea7e6932a58330d058fcc7e6bb559e..b7fadfa4aa59c43b38f7efd87cd438fab49679ca 100644 GIT binary patch literal 147264 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 P*DZObLzDocOV;{7XLP32 literal 36548 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 diff --git a/resource/font/OpenSans-Regular.ttf b/resource/font/OpenSans-Regular.ttf index d9b361f9765892463f692d9e2eef8060d6102d1e..8529c432ce34f0bc582e409c420f6bfa6ad0198b 100644 GIT binary patch literal 147528 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 z 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 ZJu60E;vtPD?b6uQYUF(fEseif_dgf&dl~=$ literal 35264 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

uT3aWZ8e)Np1-^H^@aCOT(ji=eq4IL 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 z' > $out echo '' >> $out - echo '#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2)' >> $out + echo '#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT)' >> $out done -xxd -n MwTTFData -i resource/font/IBMPlexMono.ttf | sed s/_len/Size/ >> src/font/ttf.c -xxd -n MwBoldTTFData -i resource/font/IBMPlexMono-Bold.ttf | sed s/_len/Size/ >> src/font/boldttf.c -for out in src/font/ttf.c src/font/boldttf.c; do +xxd -n MwMonospaceTTFData -i resource/font/IBMPlexMono-Regular.ttf | sed s/_len/Size/ >> src/text/font/monottf.c +xxd -n MwBoldMonospaceTTFData -i resource/font/IBMPlexMono-Bold.ttf | sed s/_len/Size/ >> src/text/font/boldmonottf.c +xxd -n MwTTFData -i resource/font/OpenSans-Regular.ttf | sed s/_len/Size/ >> src/text/font/ttf.c +xxd -n MwBoldTTFData -i resource/font/OpenSans-Bold.ttf | sed s/_len/Size/ >> src/text/font/boldttf.c +for out in src/text/font/ttf.c src/text/font/boldttf.c src/text/font/monottf.c src/text/font/boldmonottf.c; do echo '#endif' >> $out done