From 2bea5634b618968593446f3ebf30f8f9a3cfc1b3 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 04:15:02 +0900 Subject: [PATCH 1/6] fix bug --- examples/basic/filechooser.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index 2637f86f..6a86f98e 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -5,13 +5,17 @@ MwWidget window; MwWidget button; MwWidget mb; +#ifdef BUG MwBool fpicker_wait = MwFALSE; MwBool msgbox_wait = MwFALSE; +#endif void MWAPI ok(MwWidget handle, void* user, void* call) { (void)handle; (void)call; +#ifdef BUG msgbox_wait = MwFALSE; +#endif } void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { @@ -22,6 +26,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(MwMessageBoxGetChild(mb, MwMB_BUTTONOK), MwNactivateHandler, ok, mb); MwAddUserHandler(mb, MwNcloseHandler, ok, mb); +#ifdef BUG msgbox_wait = MwTRUE; while(msgbox_wait) { @@ -29,6 +34,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { } fpicker_wait = MwFALSE; +#endif } void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { @@ -42,6 +48,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwSetText(fpicker, MwNbackground, MwGetInteger(fpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); +#ifdef BUG fpicker_wait = MwTRUE; while(fpicker_wait) { @@ -50,6 +57,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwDestroyWidget(fpicker); MwDestroyWidget(mb); +#endif } int main() { From 231df890c1e1f55e49747b76ceef56e68d066591 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 12:52:20 -0700 Subject: [PATCH 2/6] accidentally rounded MwU16 to MwU8 in color picker --- src/dialog/colorpicker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 95fc2838..378b7960 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -127,8 +127,8 @@ static void color_picker_image_update(color_picker_t* picker) { if(hue < 0.0) { hue += 360; } - hsv_v.h = (MwU8)((hue) * (HSV_HUE_STEPS / 360.)); - hsv_v.s = (MwU8)((dist) * (HSV_SAT_MAX / 180.)); + hsv_v.h = (MwU16)((hue) * (HSV_HUE_STEPS / 360.)); + hsv_v.s = (MwU16)((dist) * (HSV_SAT_MAX / 180.)); picker->hue_table[n] = hsv_v; picker->hue_table[n].generated = 1; } From 73833b9e0632fdc990f921214a25dc9cde2dc33a Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 04:53:02 +0900 Subject: [PATCH 3/6] fix some colors --- examples/basic/colorpicker.c | 6 ++++-- examples/basic/filechooser.c | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index dbce7fe2..d02e3576 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -35,12 +35,14 @@ int main() { window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetText(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) ? MwDefaultBackground : MwDefaultDarkBackground); + MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetText(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 6a86f98e..6ad56369 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -64,13 +64,11 @@ int main() { MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, - MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwDEFAULT, 640, 480, MwNtitle, "file chooser", NULL); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "select file", NULL); - MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); MwAddUserHandler(button, MwNactivateHandler, file_picker, NULL); From 2e9aca5d46de22027cdfb49f0f71d1027869db5e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:09:11 -0700 Subject: [PATCH 4/6] fix menu positioning under weston --- src/backend/wayland/wayland.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 839e9ac6..087f48bb 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -180,6 +180,9 @@ static void xdg_toplevel_configure(void* data, if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(width < 50) width = 50; if(height < 50) height = 50; + } else { + if(width < 1) width = 1; + if(height < 1) height = 1; } MwLLWaylandRegionInvalidate(self); @@ -281,7 +284,7 @@ static void setup_toplevel(MwLL r, int x, int y) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -524,7 +527,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -537,10 +540,10 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); xdg_positioner_set_anchor_rect( r->wayland.popup->xdg_positioner, - topmost_parent->wayland.x, 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); + r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); + // xdg_positioner_set_offset( + // r->wayland.popup->xdg_positioner, + // r->wayland.x, r->wayland.y); 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); @@ -1120,6 +1123,9 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(w < 50) w = 50; if(h < 50) h = 50; + } else { + if(w < 1) w = 1; + if(h < 1) h = 1; } handle->wayland.ww = w; From 175827fd9b0bd588fed94d0f38fa627fe9e2f286 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:10:40 -0700 Subject: [PATCH 5/6] wayland: destroy popup surfaces at correct time --- src/backend/wayland/wayland.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 087f48bb..34d2e130 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -584,14 +584,13 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { /* Popup destroy function */ static void destroy_popup(MwLL r) { - MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); - xdg_surface_destroy(r->wayland.popup->xdg_surface); - xdg_popup_destroy(r->wayland.popup->xdg_popup); + xdg_surface_destroy(r->wayland.popup->xdg_surface); + xdg_positioner_destroy(r->wayland.popup->xdg_positioner); wl_surface_destroy(r->wayland.framebuffer.surface); From 9246051de047dd10ffade7cd240c69714c535b85 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:31:37 -0700 Subject: [PATCH 6/6] new envs --- doc/ENV.md | 5 +++++ include/Mw/LowLevel.h | 11 ++++++++--- src/backend/wayland/wayland.c | 35 ++++++++++++++++++++++++----------- src/backend/x11.c | 30 ++++++++++++++++++++++-------- src/lowlevel.c | 18 +++++++++++++++--- 5 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 doc/ENV.md diff --git a/doc/ENV.md b/doc/ENV.md new file mode 100644 index 00000000..001c3011 --- /dev/null +++ b/doc/ENV.md @@ -0,0 +1,5 @@ +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 +- `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. diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 6647672d..8822f68a 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -41,6 +41,11 @@ struct _MwLLCommon { MwBool supports_transparency; MwLLHandler handler; + +#if defined(USE_WAYLAND) || defined(USE_X11) + /* 0 = default, 1 = light, 2 = dark */ + int theme_override; +#endif }; struct _MwLLCommonColor { @@ -364,9 +369,9 @@ MWDECL void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px); MWDECL void (*MwFLFontFree)(void* handle); #ifdef _WIN32 -MWDECL void *MwLL_winmmLib; -MWDECL long (__stdcall* MwLL_PFN_timeGetTime)(void); -MWDECL unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +MWDECL void* MwLL_winmmLib; +MWDECL long(__stdcall* MwLL_PFN_timeGetTime)(void); +MWDECL unsigned int(__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); #endif #ifdef __cplusplus diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 34d2e130..6d34e491 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -942,11 +942,13 @@ static void dark_theme_listener(MwLL handle, MwU32 new_value) { static void detect_dark_theme(MwLL handle) { MwU32 value = 0; - MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); - handle->wayland.dark_theme = (value == 1) ? 1 : 0; - - MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings"); - + if(handle->common.theme_override != 0) { + handle->wayland.dark_theme = (handle->common.theme_override == 2) ? 1 : 0; + } else { + MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); + handle->wayland.dark_theme = (value == 1) ? 1 : 0; + MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings"); + } MwLLDispatch(handle, dark_theme, &handle->wayland.dark_theme); } #endif @@ -1381,9 +1383,8 @@ static int MwLLPendingImpl(MwLL handle) { } #ifdef USE_DBUS - if(wl_call_tbl.has_dbus) { + if(wl_call_tbl.has_dbus || handle->common.theme_override == 0) { if(handle->wayland.dark_theme_detection) { - handle->wayland.dark_theme_detection = MwFALSE; detect_dark_theme(handle); MwLLDispatch(handle, draw, NULL); @@ -1907,10 +1908,22 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { static int MwLLWaylandCallInitImpl(void) { #ifdef __linux__ - MwBool loadWayland = MwFALSE; - if(getenv("MILSKO_BACKEND")) { - loadWayland |= - (strcmp(getenv("MILSKO_BACKEND"), "wayland") == 0); + MwBool loadWayland = MwFALSE; + char* milsko_backend_env = getenv("MILSKO_BACKEND"); + char* mw_backend_env = getenv("MW_BACKEND"); + + if(milsko_backend_env || mw_backend_env) { + if(milsko_backend_env) { + /* + * (deprecated since 1.5+ but we have no reason to ever remove the old variable. + * MW_BACKEND is just the one that's documented) + */ + printf("[WARNING] MILSKO_BACKEND env is deprecated, use MW_BACKEND instead.\n"); + loadWayland |= (strcmp(milsko_backend_env, "wayland") == 0); + } else { + loadWayland |= (strcmp(mw_backend_env, "wayland") == 0); + } + } else if(getenv("WAYLAND_DISPLAY")) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } diff --git a/src/backend/x11.c b/src/backend/x11.c index cc4d22bc..8b908e47 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -327,9 +327,12 @@ static XVisualInfo* get_visual_info(Display* display) { static void detect_dark_theme(MwLL handle) { MwU32 value = 0; MwU32 dark_theme = 0; - MwLLDBusPortalGet(&xsymtbl.dbus, &handle->x11.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); - - dark_theme = (value == 1) ? 1 : 0; + if(handle->common.theme_override != 0) { + dark_theme = (handle->common.theme_override == 2) ? 1 : 0; + } else { + MwLLDBusPortalGet(&xsymtbl.dbus, &handle->x11.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); + dark_theme = (value == 1) ? 1 : 0; + } MwLLDispatch(handle, dark_theme, &dark_theme); } @@ -652,7 +655,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->x11.dark_theme_detection) { handle->x11.dark_theme_detection = MwFALSE; #ifdef USE_DBUS - if(xsymtbl.has_dbus) { + if(xsymtbl.has_dbus || handle->common.theme_override == 0) { detect_dark_theme(handle); MwLLDispatch(handle, draw, NULL); } @@ -1403,10 +1406,21 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { } static int MwLLX11CallInitImpl(void) { - MwBool loadX11 = MwFALSE; - if(getenv("MILSKO_BACKEND")) { - loadX11 |= - (strcmp(getenv("MILSKO_BACKEND"), "x11") == 0); + MwBool loadX11 = MwFALSE; + char* milsko_backend_env = getenv("MILSKO_BACKEND"); + char* mw_backend_env = getenv("MW_BACKEND"); + + if(milsko_backend_env || mw_backend_env) { + if(milsko_backend_env) { + /* + * (deprecated since 1.5+ but we have no reason to ever remove the old variable. + * MW_BACKEND is just the one that's documented) + */ + printf("[WARNING] MILSKO_BACKEND env is deprecated, use MW_BACKEND instead.\n"); + loadX11 |= (strcmp(milsko_backend_env, "x11") == 0); + } else { + loadX11 |= (strcmp(mw_backend_env, "x11") == 0); + } } else if(getenv("DISPLAY")) { loadX11 |= (getenv("DISPLAY") != NULL); } diff --git a/src/lowlevel.c b/src/lowlevel.c index 2fe15356..32070d9e 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -1,9 +1,9 @@ #include #ifdef _WIN32 -void *MwLL_winmmLib; -long (__stdcall* MwLL_PFN_timeGetTime)(void); -unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +void* MwLL_winmmLib; +long(__stdcall* MwLL_PFN_timeGetTime)(void); +unsigned int(__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); #endif MwLL (*MwLLCreate)(MwLL parent, int x, int y, int width, int height) = NULL; @@ -66,10 +66,22 @@ 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); + } + +#endif } void MwLLDestroyCommon(MwLL handle) {