Compare commits

...

4 commits

Author SHA1 Message Date
138555f41d auto detect dark theme change via dbus signals 2026-04-17 01:12:44 -05:00
bc942153fe cmacos: working? 2026-04-16 22:58:16 -07:00
3e49278a15 added wip fuzzer, fixed alot of memory leaks with wayland 2026-04-16 18:36:42 -07:00
e41dbd43c1 fix warnings 2026-04-16 13:22:21 -07:00
14 changed files with 461 additions and 146 deletions

View file

@ -309,6 +309,8 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Retro")
set_target_properties(Mw PROPERTIES LINK_FLAGS "-Wl,-gc-sections") set_target_properties(Mw PROPERTIES LINK_FLAGS "-Wl,-gc-sections")
endif() endif()
list(APPEND LIBRARIES InterfaceLib WindowsLib ThreadsLib)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
@ -354,7 +356,7 @@ target_link_libraries(
) )
if(MW_BUILD_OPENGL) if(MW_BUILD_OPENGL)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
MW_OPENGL MW_OPENGL

View file

@ -83,11 +83,15 @@ typedef struct _MwLLDBusContext {
DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant; DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant;
} MwLLDBusContext; } MwLLDBusContext;
typedef void (*MwLLDBusPortalPollListener)(MwLL handle, MwU32 new_value);
/* setup the dbus func table. Returns false and prints a warning if dbus couldn't be found. */ /* setup the dbus func table. Returns false and prints a warning if dbus couldn't be found. */
MWDECL MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl); MWDECL MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl);
MWDECL MwBool MwLLDBusNewContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx); MWDECL MwBool MwLLDBusNewContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx);
MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal, const char* namespace, const char* key, void* out); MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal, const char* namespace, const char* key, void* out);
MWDECL MwBool MwLLDBusPortalWatch(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal);
MWDECL MwBool MwLLDBusPortalPoll(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, MwLL handle, const char* portal, const char* namespace, const char* key, MwLLDBusPortalPollListener);
MWDECL void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx); MWDECL void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx);
#endif #endif

View file

@ -13,9 +13,12 @@
struct _MwLLClassicMacOS { struct _MwLLClassicMacOS {
struct _MwLLCommon common; struct _MwLLCommon common;
WindowRef window; MwLL parent;
EventRecord event;
Rect winRect; WindowRef window;
ControlHandle control;
EventRecord event;
Rect winRect;
}; };
struct _MwLLClassicMacOSColor { struct _MwLLClassicMacOSColor {

View file

@ -41,6 +41,7 @@ typedef struct wayland_call_table {
MwBool has_dbus; MwBool has_dbus;
#endif #endif
int (*wl_display_dispatch)(struct wl_display* display);
int (*wl_display_dispatch_pending)(struct wl_display* display); int (*wl_display_dispatch_pending)(struct wl_display* display);
void (*wl_display_disconnect)(struct wl_display* display); void (*wl_display_disconnect)(struct wl_display* display);
void (*wl_display_cancel_read)(struct wl_display* display); void (*wl_display_cancel_read)(struct wl_display* display);
@ -58,6 +59,7 @@ typedef struct wayland_call_table {
uint32_t flags, ...); uint32_t flags, ...);
struct wl_display* (*wl_display_connect)(const char* name); struct wl_display* (*wl_display_connect)(const char* name);
uint32_t (*wl_proxy_get_version)(struct wl_proxy* proxy); uint32_t (*wl_proxy_get_version)(struct wl_proxy* proxy);
struct wl_display* (*wl_display_connect_to_fd)(int fd);
struct xkb_context* (*xkb_context_new)(enum xkb_context_flags flags); struct xkb_context* (*xkb_context_new)(enum xkb_context_flags flags);
void (*xkb_context_unref)(struct xkb_context* context); void (*xkb_context_unref)(struct xkb_context* context);
@ -156,6 +158,7 @@ MwInline int wayland_load_funcs() {
return 1; \ return 1; \
}; };
WAYLAND_FUNC(wl_display_dispatch)
WAYLAND_FUNC(wl_display_dispatch_pending) WAYLAND_FUNC(wl_display_dispatch_pending)
WAYLAND_FUNC(wl_display_disconnect) WAYLAND_FUNC(wl_display_disconnect)
WAYLAND_FUNC(wl_display_cancel_read) WAYLAND_FUNC(wl_display_cancel_read)
@ -170,6 +173,7 @@ MwInline int wayland_load_funcs() {
WAYLAND_FUNC(wl_proxy_marshal_flags) WAYLAND_FUNC(wl_proxy_marshal_flags)
WAYLAND_FUNC(wl_display_connect) WAYLAND_FUNC(wl_display_connect)
WAYLAND_FUNC(wl_proxy_get_version) WAYLAND_FUNC(wl_proxy_get_version)
WAYLAND_FUNC(wl_display_connect_to_fd)
#undef WAYLAND_FUNC #undef WAYLAND_FUNC
@ -235,6 +239,7 @@ MwInline int wayland_load_funcs() {
return 0; return 0;
} }
#define wl_display_dispatch wl_call_tbl.wl_display_dispatch
#define wl_display_dispatch_pending wl_call_tbl.wl_display_dispatch_pending #define wl_display_dispatch_pending wl_call_tbl.wl_display_dispatch_pending
#define wl_display_disconnect wl_call_tbl.wl_display_disconnect #define wl_display_disconnect wl_call_tbl.wl_display_disconnect
#define wl_display_cancel_read wl_call_tbl.wl_display_cancel_read #define wl_display_cancel_read wl_call_tbl.wl_display_cancel_read
@ -249,6 +254,7 @@ MwInline int wayland_load_funcs() {
#define wl_proxy_marshal_flags wl_call_tbl.wl_proxy_marshal_flags #define wl_proxy_marshal_flags wl_call_tbl.wl_proxy_marshal_flags
#define wl_display_connect wl_call_tbl.wl_display_connect #define wl_display_connect wl_call_tbl.wl_display_connect
#define wl_proxy_get_version wl_call_tbl.wl_proxy_get_version #define wl_proxy_get_version wl_call_tbl.wl_proxy_get_version
#define wl_display_connect_to_fd wl_call_tbl.wl_display_connect_to_fd
#define xkb_state_unref wl_call_tbl.xkb_state_unref #define xkb_state_unref wl_call_tbl.xkb_state_unref
#define xkb_context_new wl_call_tbl.xkb_context_new #define xkb_context_new wl_call_tbl.xkb_context_new
@ -373,11 +379,11 @@ enum _MwLLWaylandType {
}; };
typedef struct wl_clipboard_device_context { typedef struct wl_clipboard_device_context {
union { struct {
struct wl_data_device* wl; struct wl_data_device* wl;
struct zwp_primary_selection_device_v1* zwp; struct zwp_primary_selection_device_v1* zwp;
} device; } device;
union { struct {
struct wl_data_offer* wl; struct wl_data_offer* wl;
struct zwp_primary_selection_offer_v1* zwp; struct zwp_primary_selection_offer_v1* zwp;
} offer; } offer;
@ -409,13 +415,13 @@ struct _MwLLWayland {
/* Map of Wayland interfaces to their relevant setup functions. */ /* Map of Wayland interfaces to their relevant setup functions. */
struct { struct {
const char* key; char key[255];
wayland_protocol_callback_table_t* value; wayland_protocol_callback_table_t* value;
}* wl_protocol_setup_map; }* wl_protocol_setup_map;
/* Map of Wayland interfaces to any information we keep about them once we've registered them. */ /* Map of Wayland interfaces to any information we keep about them once we've registered them. */
struct { struct {
const char* key; char key[255];
wayland_protocol_t* value; wayland_protocol_t* value;
}* wl_protocol_map; }* wl_protocol_map;

View file

@ -11,7 +11,7 @@
#ifndef __MW_WIDGET_VULKAN_H__ #ifndef __MW_WIDGET_VULKAN_H__
#define __MW_WIDGET_VULKAN_H__ #define __MW_WIDGET_VULKAN_H__
#if !defined(_WIN32) && !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) #if defined(MW_VULKAN) && !defined(_WIN32) && !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#error Vulkan is unsupported on the requested platform. #error Vulkan is unsupported on the requested platform.
#endif #endif

View file

@ -14,33 +14,39 @@ void MwDynamicClose(void* handle) {
} }
#elif defined(CLASSIC_MAC_OS) #elif defined(CLASSIC_MAC_OS)
void* MwDynamicOpen(const char* path) { void* MwDynamicOpen(const char* path) {
CFragConnectionID connID; // CFragConnectionID connID;
Ptr* addr; // Ptr* addr;
unsigned char err[255]; // unsigned char err[255];
if(GetSharedLibrary((ConstStr63Param)path, kPowerPCCFragArch, kPrivateCFragCopy, // if(GetSharedLibrary((ConstStr63Param)path, kPowerPCCFragArch, kPrivateCFragCopy,
&connID, addr, err)) { // &connID, addr, err)) {
printf("Error getting %s: %s\n", path, err); // printf("Error getting %s: %s\n", path, err);
return NULL; // return NULL;
}; // };
return connID; // return connID;
printf("MwDynamicOpen not implemented yet.\n");
getchar();
return NULL;
} }
void* MwDynamicSymbol(void* handle, const char* symbol) { void* MwDynamicSymbol(void* handle, const char* symbol) {
CFragConnectionID connID = (CFragConnectionID)handle; // CFragConnectionID connID = (CFragConnectionID)handle;
Ptr* symAddr; // Ptr* symAddr;
CFragSymbolClass* symClass; // CFragSymbolClass* symClass;
OSErr err; // OSErr err;
if((err = FindSymbol(connID, (ConstStr63Param)symbol, symAddr, symClass))) { // if((err = FindSymbol(connID, (ConstStr63Param)symbol, symAddr, symClass))) {
printf("Error getting %s: %d\n", symbol, err); // printf("Error getting %s: %d\n", symbol, err);
return NULL; // return NULL;
}; // };
return symAddr; // return symAddr;
printf("MwDynamicSymbol not implemented yet.\n");
getchar();
return NULL;
} }
void MwDynamicClose(void* handle) { void MwDynamicClose(void* handle) {
CFragConnectionID connID = (CFragConnectionID)handle; // CFragConnectionID connID = (CFragConnectionID)handle;
CloseConnection(&connID); // CloseConnection(&connID);
} }
#elif defined(__unix__) || defined(__APPLE__) #elif defined(__unix__) || defined(__APPLE__)
void* MwDynamicOpen(const char* path) { void* MwDynamicOpen(const char* path) {

View file

@ -1,12 +1,24 @@
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
#include <Threads.h>
#include <QuickDraw.h>
#include "../../external/stb_ds.h" #include "../../external/stb_ds.h"
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
MwLL r; MwLL r;
r = malloc(sizeof(*r));
memset(r, 0, sizeof(*r));
MwLLCreateCommon(r); MwLLCreateCommon(r);
r->cmacos.parent = parent;
if(x == MwDEFAULT) {
x = (qd.screenBits.bounds.right / 2) - (width / 2);
}
if(y == MwDEFAULT) {
y = (qd.screenBits.bounds.bottom / 2) - (height / 2);
}
/* todo: how do we set parent windows? If we can't, what is our equivalant to MacOS's NSViews, Wayland's subsurfaces, etc.? */ /* todo: how do we set parent windows? If we can't, what is our equivalant to MacOS's NSViews, Wayland's subsurfaces, etc.? */
SetRect(&r->cmacos.winRect, x, y, width, height); SetRect(&r->cmacos.winRect, x, y, width, height);
r->cmacos.window = newcwindow(nil, &r->cmacos.winRect, "", true, r->cmacos.window = newcwindow(nil, &r->cmacos.winRect, "", true,
@ -23,24 +35,26 @@ static void MwLLDestroyImpl(MwLL handle) {
} }
static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLBeginDrawImpl(MwLL handle) {
(void)handle;
} }
static void MwLLEndDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) {
(void)handle;
} }
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
int i; int i;
PolyHandle p = OpenPoly(); PolyHandle p;
RGBColor col; RGBColor col;
col.red = color->common.red; SetPort(handle->cmacos.window);
col.green = color->common.green; BeginUpdate(handle->cmacos.window);
col.blue = color->common.blue;
p = OpenPoly();
col.red = color->common.red * 0x101;
col.green = color->common.green * 0x101;
col.blue = color->common.blue * 0x101;
RGBBackColor(&col);
RGBForeColor(&col); RGBForeColor(&col);
PenMode(patCopy);
for(i = 0; i < points_count; i++) { for(i = 0; i < points_count; i++) {
if(i == 0) { if(i == 0) {
@ -51,20 +65,24 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL
} }
ClosePoly(); ClosePoly();
PaintPoly(p); FillCPoly(p, &qd.ltGray);
KillPoly(p); KillPoly(p);
EndUpdate(handle->cmacos.window);
} }
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
RGBColor col; RGBColor col;
SetPort(handle->cmacos.window);
col.red = color->common.red; col.red = color->common.red;
col.green = color->common.green; col.green = color->common.green;
col.blue = color->common.blue; col.blue = color->common.blue;
RGBBackColor(&col);
RGBForeColor(&col); RGBForeColor(&col);
PenMode(patCopy);
MoveTo(points[0].x, points[0].y); MoveTo(points[0].x, points[0].y);
LineTo(points[1].x, points[1].y); LineTo(points[1].x, points[1].y);
} }
@ -103,10 +121,133 @@ static void MwLLFreeColorImpl(MwLLColor color) {
} }
static int MwLLPendingImpl(MwLL handle) { static int MwLLPendingImpl(MwLL handle) {
return GetNextEvent(everyEvent, &handle->cmacos.event); YieldToAnyThread();
return EventAvail(everyEvent, &handle->cmacos.event);
} }
static void MwLLNextEventImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) {
EventRecord event;
GetNextEvent(everyEvent, &event);
switch(event.what) {
case updateEvt: {
}
// MwLLDispatch(handle, draw, NULL);
break;
case osEvt:
break;
case mouseUp: {
// MwLLMouse m;
// m.button = MwLLMouseLeft;
// if(___curWindow->mouseButtonCallback != NULL) {
// int mods = MacModifiersToGLFWModifiers(event.modifiers);
// if(___curWindow->keyStateMap[MK_LCTRL] == 1) {
// ___curWindow->mouseButtonCallback(
// ___curWindow, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods);
// } else {
// ___curWindow->mouseButtonCallback(
// ___curWindow, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods);
// }
// }
}
case mouseDown: {
// // start with callback stuff
// if(___curWindow->mouseButtonCallback != NULL) {
// int mods = MacModifiersToGLFWModifiers(event.modifiers);
// if(___curWindow->keyStateMap[MK_LCTRL] == 1) {
// ___curWindow->mouseButtonCallback(
// ___curWindow, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);
// } else {
// ___curWindow->mouseButtonCallback(
// ___curWindow, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
// }
// }
// then do system stuff
switch(FindWindow(event.where, &handle->cmacos.window)) {
case inDrag:
DragWindow(handle->cmacos.window, event.where, &qd.screenBits.bounds);
// if(___curWindow->windowPosCallback != NULL) {
// ___curWindow->windowPosCallback(___curWindow, event.where.h,
// event.where.v);
// }
break;
case inGrow: {
long growResult =
GrowWindow(handle->cmacos.window, event.where, &qd.screenBits.bounds);
int width = growResult & 0xFFFF;
int height = growResult >> 16;
SizeWindow(handle->cmacos.window, growResult & 0xFFFF, growResult >> 16, true);
Rect rect;
GetWindowBounds(handle->cmacos.window, kWindowStructureRgn, &rect);
rect.right = width;
rect.bottom = height;
SetWindowBounds(handle->cmacos.window, kWindowStructureRgn, &rect);
// ___curWindow->width = width;
// ___curWindow->height = height;
// if(___curWindow->windowSizeCallback != NULL) {
// ___curWindow->windowSizeCallback(___curWindow, width, height);
// }
// if(___curWindow->windowSetFramebufferSizeCallback != NULL) {
// ___curWindow->windowSetFramebufferSizeCallback(___curWindow,
// width, height);
// }
} break;
case inGoAway: {
if(TrackGoAway(handle->cmacos.window, event.where)) {
MwLLDispatch(handle, close, NULL);
// if(___curWindow->windowCloseCallback != NULL) {
// ___curWindow->windowCloseCallback(___curWindow);
// }
// ___curWindow->shouldClose = true;
}
} break;
}
}
case autoKey:
case keyDown:
case keyUp: {
// // key char stuff
// unsigned char ch = (event.message & charCodeMask);
// if(*___curWindow->charCallback != NULL) {
// ___curWindow->charCallback(___curWindow, ch);
// }
// // key state map
// unsigned char key = (event.message & keyCodeMask) >> 8;
// ___curWindow->keyStateMap[key] = 0;
// if(event.what == keyDown || event.what == autoKey) {
// ___curWindow->keyStateMap[key] &= 1;
// }
// if(*___curWindow->keyCallback != NULL) {
// int key = MacKeyToGLFWKey(event.message);
// int scancode = (event.message & adbAddrMask) >> 16;
// int mods = MacModifiersToGLFWModifiers(event.modifiers);
// int action;
// if(event.what == keyUp) {
// action = GLFW_RELEASE;
// } else {
// action = GLFW_PRESS;
// }
// ___curWindow->keyCallback(___curWindow, key, scancode, action,
// mods);
// }
}
}
FlushEvents(everyEvent, -1);
YieldToAnyThread();
} }
static void MwLLSetTitleImpl(MwLL handle, const char* title) { static void MwLLSetTitleImpl(MwLL handle, const char* title) {
@ -167,14 +308,14 @@ static void MwLLFocusImpl(MwLL handle) {
static void MwLLGrabPointerImpl(MwLL handle, int toggle) { static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
} }
static void MwLLSetClipboardImpl(MwLL handle, const char* text) { static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {
/* TODO */ /* TODO */
(void)handle; (void)handle;
(void)text; (void)text;
} }
static void MwLLGetClipboardImpl(MwLL handle) { static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
} }
static void MwLLMakeToolWindowImpl(MwLL handle) { static void MwLLMakeToolWindowImpl(MwLL handle) {

View file

@ -17,6 +17,8 @@
wayland_call_table_t wl_call_tbl; wayland_call_table_t wl_call_tbl;
MwBool MwWaylandAlwaysRender = MwFALSE; MwBool MwWaylandAlwaysRender = MwFALSE;
MwU32 wl_dark_theme = -1;
/* Standard procedure before most event callbacks in Wayland ("most" because the setup ones don't need this). Wait for the Mutex to be freed, if we're deadlocking for longer then a quarter of a second then do nothing with the event. */ /* Standard procedure before most event callbacks in Wayland ("most" because the setup ones don't need this). Wait for the Mutex to be freed, if we're deadlocking for longer then a quarter of a second then do nothing with the event. */
#define WAYLAND_EVENT_OP_START(self) \ #define WAYLAND_EVENT_OP_START(self) \
do { \ do { \
@ -62,9 +64,7 @@ static void new_protocol(void* data, struct wl_registry* registry,
wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface);
if(cb != NULL) { if(cb != NULL) {
char* inter = malloc(strlen(interface) + 1); shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data));
strcpy(inter, interface);
shput(self->wayland.wl_protocol_map, inter, cb->setup(name, data));
/* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */ /* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */
} else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) {
self->common.supports_transparency = MwTRUE; self->common.supports_transparency = MwTRUE;
@ -132,34 +132,6 @@ static void recursive_dispatch_move(MwLL handle, MwMouse* p) {
} }
}; };
/* 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;
MwLLDispatch(handle, key, k);
if(h) {
int i;
for(i = 0; i < arrlen(h->children); i++) {
MwLLDispatch(h->children[i]->lowlevel, key, k);
if(arrlen(h->children[i]->children) > 0) {
recursive_dispatch_key(h->children[i]->lowlevel, 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;
MwLLDispatch(handle, key_released, k);
if(h) {
int i;
for(i = 0; i < arrlen(h->children); i++) {
MwLLDispatch(h->children[i]->lowlevel, key_released, k);
if(arrlen(h->children[i]->children) > 0) {
recursive_dispatch_key_released(h->children[i]->lowlevel, k);
}
}
}
};
static void wl_offer(void* data, static void wl_offer(void* data,
struct wl_data_offer* wl_data_offer, struct wl_data_offer* wl_data_offer,
const char* mime_type) { const char* mime_type) {
@ -538,6 +510,12 @@ static void relative_pointer_motion(void* data,
MwLL self = data; MwLL self = data;
MwMouse p; MwMouse p;
(void)pointer;
(void)timeHi;
(void)timeLo;
(void)dx;
(void)dy;
WAYLAND_EVENT_OP_START(self); WAYLAND_EVENT_OP_START(self);
p.point.x = wl_fixed_to_int(dxUnaccel); p.point.x = wl_fixed_to_int(dxUnaccel);
@ -609,8 +587,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri
inArea |= self->wayland.backbuffer.surface == curSurface; inArea |= self->wayland.backbuffer.surface == curSurface;
} }
if(inArea) { if(inArea) {
int i;
switch(button) { switch(button) {
case BTN_LEFT: case BTN_LEFT:
p.button = MwMOUSE_LEFT; p.button = MwMOUSE_LEFT;
@ -675,19 +651,24 @@ static void keyboard_keymap(void* data,
MwLL self = data; MwLL self = data;
(void)wl_keyboard; (void)wl_keyboard;
if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) { if(!self->wayland.parent) {
char* map_shm;
struct xkb_keymap* xkb_keymap;
struct xkb_state* xkb_state;
xkb_state = NULL;
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
assert(map_shm != MAP_FAILED); assert(map_shm != MAP_FAILED);
struct xkb_keymap* xkb_keymap = xkb_keymap_new_from_string( xkb_keymap = xkb_keymap_new_from_string(
self->wayland.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, self->wayland.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS); XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(map_shm, size); munmap(map_shm, size);
close(fd); close(fd);
struct xkb_state* xkb_state = xkb_state_new(xkb_keymap); xkb_state = xkb_state_new(xkb_keymap);
self->wayland.xkb_keymap = xkb_keymap; self->wayland.xkb_keymap = xkb_keymap;
self->wayland.xkb_state = xkb_state; self->wayland.xkb_state = xkb_state;
@ -741,8 +722,8 @@ static void keyboard_key(void* data,
MwU32 time, MwU32 time,
MwU32 key, MwU32 key,
MwU32 state) { MwU32 state) {
MwLL self = data; MwLL self = data;
MwBool inArea; MwBool inArea = 0;
(void)wl_keyboard; (void)wl_keyboard;
(void)serial; (void)serial;
@ -760,7 +741,7 @@ static void keyboard_key(void* data,
if(inArea) { if(inArea) {
xkb_layout_index_t layout; xkb_layout_index_t layout;
MwU32 levels; MwU32 levels;
xkb_level_index_t level; xkb_level_index_t level = 0;
const xkb_keysym_t* syms_out; const xkb_keysym_t* syms_out;
MwU32 keycode = key + 8; MwU32 keycode = key + 8;
MwU64 syms_num; MwU64 syms_num;
@ -785,9 +766,8 @@ static void keyboard_key(void* data,
} }
for(i = 0; i < syms_num; i++) { for(i = 0; i < syms_num; i++) {
int sym = syms_out[i]; int sym = syms_out[i];
int key = -1; int key = -1;
const char* name;
switch(sym) { switch(sym) {
case XKB_KEY_BackSpace: case XKB_KEY_BackSpace:
@ -1001,6 +981,7 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) {
static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland; (void)wayland;
free(data->listener); free(data->listener);
free(data);
} }
/* wl_output setup function */ /* wl_output setup function */
@ -1145,6 +1126,8 @@ static int event_loop(MwLL handle) {
if(wl_display_dispatch_pending(wayland->display) < 0) { if(wl_display_dispatch_pending(wayland->display) < 0) {
wl_display_cancel_read(wayland->display); wl_display_cancel_read(wayland->display);
} }
wl_display_flush(handle->wayland.display);
return 1; return 1;
} }
@ -1255,66 +1238,46 @@ static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
} }
static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {
int stride = width * 4; int stride = width * 4;
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX";
char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXX";
buffer->buf_size = width * height * 4; buffer->buf_size = width * height * 4;
buffer->fd = mkstemp(temp_name); buffer->fd = mkstemp(temp_name);
buffer->fd_back = mkstemp(temp_name_back);
unlink(temp_name); unlink(temp_name);
unlink(temp_name_back);
if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) { 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: could not fallocate. %s.\n", strerror(errno));
close(buffer->fd); close(buffer->fd);
return; 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));
close(buffer->fd_back);
return;
}
if(ftruncate(buffer->fd, buffer->buf_size) != 0) { if(ftruncate(buffer->fd, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
close(buffer->fd); close(buffer->fd);
return; return;
} }
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;
}
buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0); 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_back = malloc(buffer->buf_size);
fsync(buffer->fd); fsync(buffer->fd);
fsync(buffer->fd_back);
if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) { if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) {
close(buffer->fd);
printf("failure setting up wl_shm: could not create pool.\n"); printf("failure setting up wl_shm: could not create pool.\n");
return;
} }
if(!(buffer->shm_pool_back = wl_shm_create_pool(buffer->shm, buffer->fd_back, buffer->buf_size))) { buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
printf("failure setting up wl_shm: could not create pool.\n"); buffer->setup = MwTRUE;
}
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;
} }
static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) { static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) {
if(!buffer->setup) { close(buffer->fd);
return; if(buffer->buf) munmap(buffer->buf, buffer->buf_size);
} if(buffer->buf_back) free(buffer->buf_back);
if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer); 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); if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool);
if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back); if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back);
close(buffer->fd);
close(buffer->fd_back);
buffer->setup = MwFALSE; buffer->setup = MwFALSE;
} }
@ -1553,12 +1516,12 @@ static void destroy_toplevel(MwLL r) {
xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level); xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level);
xkb_keymap_unref(r->wayland.xkb_keymap);
xkb_state_unref(r->wayland.xkb_state); xkb_state_unref(r->wayland.xkb_state);
xkb_context_unref(r->wayland.xkb_context); xkb_context_unref(r->wayland.xkb_context);
xkb_keymap_unref(r->wayland.xkb_keymap);
free(r->wayland.toplevel); free(r->wayland.toplevel);
wl_registry_destroy(r->wayland.registry); wl_registry_destroy(r->wayland.registry);
@ -1578,8 +1541,6 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
r->wayland.type = MWLL_WAYLAND_SUBLEVEL; r->wayland.type = MWLL_WAYLAND_SUBLEVEL;
r->wayland.display = parent->wayland.display;
setup_callbacks(&r->wayland); setup_callbacks(&r->wayland);
r->wayland.registry = wl_display_get_registry(parent->wayland.display); r->wayland.registry = wl_display_get_registry(parent->wayland.display);
@ -1617,11 +1578,10 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
/* Sublevel setup function */ /* Sublevel setup function */
static void destroy_sublevel(MwLL r) { static void destroy_sublevel(MwLL r) {
backbuffer_destroy(&r->wayland);
framebuffer_destroy(&r->wayland);
wl_subsurface_destroy(r->wayland.sublevel->subsurface); wl_subsurface_destroy(r->wayland.sublevel->subsurface);
wl_registry_destroy(r->wayland.registry);
free(r->wayland.sublevel); free(r->wayland.sublevel);
r->wayland.configured = MwFALSE; r->wayland.configured = MwFALSE;
@ -1799,6 +1759,9 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
} }
} }
framebuffer_destroy(&r->wayland);
backbuffer_destroy(&r->wayland);
framebuffer_setup(&r->wayland); framebuffer_setup(&r->wayland);
backbuffer_setup(&r->wayland); backbuffer_setup(&r->wayland);
@ -1818,14 +1781,21 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
} }
#ifdef USE_DBUS #ifdef USE_DBUS
static void dark_theme_listener(MwLL handle, MwU32 new_value) {
wl_dark_theme = (new_value == 1) ? 1 : 0;
MwLLDispatch(handle, dark_theme, &wl_dark_theme);
}
static void detect_dark_theme(MwLL handle) { static void detect_dark_theme(MwLL handle) {
MwU32 value = 0; MwU32 value = 0;
MwU32 dark_theme = 0;
MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value);
wl_dark_theme = (value == 1) ? 1 : 0;
dark_theme = (value == 1) ? 1 : 0; MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings");
MwLLDispatch(handle, dark_theme, &dark_theme); MwLLDispatch(handle, dark_theme, &wl_dark_theme);
} }
#endif #endif
@ -1857,8 +1827,6 @@ static void MwLLDestroyImpl(MwLL handle) {
int select_ret; int select_ret;
event_loop(handle); event_loop(handle);
// wl_display_cancel_read(handle->wayland.display);
wl_flush(handle); wl_flush(handle);
if(pthread_mutex_timedlock(&handle->wayland.eventsMutex, &t) != 0) { if(pthread_mutex_timedlock(&handle->wayland.eventsMutex, &t) != 0) {
@ -1884,7 +1852,6 @@ static void MwLLDestroyImpl(MwLL handle) {
} }
#endif #endif
buffer_destroy(&handle->wayland.cursor);
wl_region_destroy(handle->wayland.region); wl_region_destroy(handle->wayland.region);
if(handle->wayland.supports_zwp) { if(handle->wayland.supports_zwp) {
@ -1892,10 +1859,6 @@ static void MwLLDestroyImpl(MwLL handle) {
} else { } else {
wl_data_source_destroy(handle->wayland.clipboard_source.wl); wl_data_source_destroy(handle->wayland.clipboard_source.wl);
} }
if(handle->wayland.icon != NULL) {
buffer_destroy(handle->wayland.icon);
wl_surface_destroy(handle->wayland.icon->surface);
}
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
destroy_toplevel(handle); destroy_toplevel(handle);
@ -1905,6 +1868,20 @@ static void MwLLDestroyImpl(MwLL handle) {
destroy_popup(handle); destroy_popup(handle);
} }
if(handle->wayland.framebuffer.setup) {
framebuffer_destroy(&handle->wayland);
wl_surface_destroy(handle->wayland.framebuffer.surface);
}
if(handle->wayland.backbuffer.setup) {
backbuffer_destroy(&handle->wayland);
wl_surface_destroy(handle->wayland.backbuffer.surface);
}
buffer_destroy(&handle->wayland.cursor);
if(handle->wayland.icon != NULL) {
buffer_destroy(handle->wayland.icon);
wl_surface_destroy(handle->wayland.icon->surface);
}
for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) { 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); void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key);
@ -1912,17 +1889,30 @@ static void MwLLDestroyImpl(MwLL handle) {
handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx); handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx);
} }
shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value); shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value);
free(handle->wayland.wl_protocol_setup_map[i].value);
free(ctx);
} }
shfree(handle->wayland.wl_protocol_map); shfree(handle->wayland.wl_protocol_map);
shfree(handle->wayland.wl_protocol_setup_map); shfree(handle->wayland.wl_protocol_setup_map);
wl_keyboard_destroy(handle->wayland.keyboard); // wl_keyboard_destroy(handle->wayland.keyboard);
wl_pointer_destroy(handle->wayland.pointer); // wl_pointer_destroy(handle->wayland.pointer);
if(handle->wayland.supports_zwp) {
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) {
if(handle->wayland.clipboard_devices_zwp[i]->device.zwp) zwp_primary_selection_device_v1_destroy(handle->wayland.clipboard_devices_zwp[i]->device.zwp);
free(handle->wayland.clipboard_devices_zwp[i]);
}
} else {
printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n");
}
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) {
wl_data_device_destroy(handle->wayland.clipboard_devices_wl[i]->device.wl);
free(handle->wayland.clipboard_devices_wl[i]);
}
wl_flush(handle); wl_flush(handle);
// free(handle);
if(currentlyHeldWidget == handle) { if(currentlyHeldWidget == handle) {
currentlyHeldWidget = NULL; currentlyHeldWidget = NULL;
} }
@ -1975,7 +1965,6 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) {
setup_popup(handle, handle->wayland.x, handle->wayland.y, handle->wayland.parent); setup_popup(handle, handle->wayland.x, handle->wayland.y, handle->wayland.parent);
} }
refresh:
region_setup(handle); region_setup(handle);
framebuffer_destroy(&handle->wayland); framebuffer_destroy(&handle->wayland);
@ -2164,15 +2153,18 @@ static int MwLLPendingImpl(MwLL handle) {
}; };
int pending = 0; int pending = 0;
if(handle->wayland.dark_theme_detection) {
handle->wayland.dark_theme_detection = MwFALSE;
#ifdef USE_DBUS #ifdef USE_DBUS
if(wl_call_tbl.has_dbus) { if(wl_call_tbl.has_dbus) {
if(handle->wayland.dark_theme_detection) {
handle->wayland.dark_theme_detection = MwFALSE;
detect_dark_theme(handle); detect_dark_theme(handle);
MwLLDispatch(handle, draw, NULL); MwLLDispatch(handle, draw, NULL);
} else {
MwLLDBusPortalPoll(&wl_call_tbl.dbus, &handle->wayland.dbus, handle, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &dark_theme_listener);
} }
#endif
} }
#endif
if(!handle->wayland.did_initial_resize) { if(!handle->wayland.did_initial_resize) {
recursive_dispatch_resize(handle); recursive_dispatch_resize(handle);
@ -2185,6 +2177,7 @@ static int MwLLPendingImpl(MwLL handle) {
wl_display_cancel_read(handle->wayland.display); wl_display_cancel_read(handle->wayland.display);
} else { } else {
wl_display_read_events(handle->wayland.display); wl_display_read_events(handle->wayland.display);
wl_display_flush(handle->wayland.display);
if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) {
wl_display_cancel_read(handle->wayland.display); wl_display_cancel_read(handle->wayland.display);
} }
@ -2193,6 +2186,7 @@ static int MwLLPendingImpl(MwLL handle) {
if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) {
wl_display_cancel_read(handle->wayland.display); wl_display_cancel_read(handle->wayland.display);
} }
wl_display_flush(handle->wayland.display);
} }
if(MwWaylandAlwaysRender) { if(MwWaylandAlwaysRender) {
@ -2343,7 +2337,7 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon); if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon);
xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer_back, 1); xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1);
xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon); xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon);
} }

View file

@ -72,7 +72,7 @@ static struct symtbl {
char* (*XSetLocaleModifiers)(const char*); char* (*XSetLocaleModifiers)(const char*);
XIM (*XOpenIM)(Display*, struct _XrmHashBucketRec*, char*, char*); XIM (*XOpenIM)(Display*, struct _XrmHashBucketRec*, char*, char*);
Status (*XCloseIM)(XIM); Status (*XCloseIM)(XIM);
XIC (*XCreateIC)(XIM, ...) _X_SENTINEL(0); XIC (*XCreateIC)(XIM, ...);
void (*XDestroyIC)(XIC); void (*XDestroyIC)(XIC);
void (*XSetICFocus)(XIC); void (*XSetICFocus)(XIC);

View file

@ -878,6 +878,9 @@ int MwLibraryInit(void) {
#endif #endif
#ifdef USE_GDI #ifdef USE_GDI
MwLLGDICallInit, MwLLGDICallInit,
#endif
#ifdef CLASSIC_MAC_OS
MwLLClassicMacOSCallInit,
#endif #endif
NULL}; NULL};
int i; int i;
@ -900,6 +903,9 @@ int MwLibraryInit(void) {
#endif #endif
#ifdef USE_GDI #ifdef USE_GDI
" GDI" " GDI"
#endif
#ifdef CLASSIC_MAC_OS
" ClassicMacOS"
#endif #endif
"\n"); "\n");

View file

@ -176,6 +176,69 @@ MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, co
return MwTRUE; return MwTRUE;
} }
MWDECL MwBool MwLLDBusPortalWatch(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal) {
if(!ctx->dbus_conn) {
return MwFALSE;
}
char filter_string[2048];
MwStringPrintIntoBuffer(filter_string, sizeof(filter_string), "type='%s',interface=%s", "signal", portal);
dbus_bus_add_match(ctx->dbus_conn, filter_string, &ctx->dbus_err);
dbus_connection_flush(ctx->dbus_conn);
return MwTRUE;
}
// Technically this will swallow all other results, so this is not usable multiple times.
// TODO: Use a hashmap instead
MWDECL MwBool MwLLDBusPortalPoll(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, MwLL handle, const char* portal, const char* namespace, const char* key, MwLLDBusPortalPollListener listener) {
DBusMessage* msg;
DBusMessageIter args, msg_value;
const char* msg_namespace;
const char* msg_key;
MwU32 msg_value_content;
if(!ctx->dbus_conn) {
return MwFALSE;
}
dbus_connection_read_write(ctx->dbus_conn, 0);
msg = dbus_connection_pop_message(ctx->dbus_conn);
if (NULL == msg) {
return MwFALSE;
}
// check if the message is a signal from the correct interface and with the correct name
if (dbus_message_is_signal(msg, portal, "SettingChanged")) {
// read the parameters
if (!dbus_message_iter_init(msg, &args))
fprintf(stderr, "[WARNING] Message has no arguments\n");
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "[WARNING] Argument is not string\n");
else {
dbus_message_iter_get_basic(&args, &msg_namespace);
dbus_message_iter_next(&args);
dbus_message_iter_get_basic(&args, &msg_key);
// Check that key and namespace match
if (strcmp(msg_namespace, namespace) == 0 && strcmp(msg_key, key) == 0) {
// Assuming the value is a basic type
dbus_message_iter_next(&args);
dbus_message_iter_recurse(&args, &msg_value);
dbus_message_iter_get_basic(&msg_value, &msg_value_content);
listener(handle, msg_value_content);
}
}
}
// free the message
dbus_message_unref(msg);
}
void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) { void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) {
if(!tbl->lib) { if(!tbl->lib) {
return; return;

2
tools/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
font
fuzzer

View file

@ -6,7 +6,10 @@ LIBS = `freetype-config --libs`
.PHONY: all clean .PHONY: all clean
.SUFFIXES: .c .o .SUFFIXES: .c .o
all: font all: fuzzer font
fuzzer: fuzzer.o
$(CC) -g -L../src/ -Wl,-R../src -lMw -o $@ fuzzer.o
font: font.o font: font.o
$(CC) $(LDFLAGS) -o $@ font.o $(LIBS) $(CC) $(LDFLAGS) -o $@ font.o $(LIBS)
@ -15,4 +18,4 @@ font: font.o
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
clean: clean:
rm -f *.o font rm -f *.o font fuzzer

85
tools/fuzzer.c Normal file
View file

@ -0,0 +1,85 @@
#include <Mw/Milsko.h>
#define WIDGET_AMOUNT 1
int main() {
MwWidget window, widget;
MwLibraryInit();
window = MwCreateWidget(MwWindowClass, "window", NULL, 0, 0, 400, 400);
while(true) {
int r = rand() % WIDGET_AMOUNT;
MwClass cls;
switch(r) {
case 0:
cls = MwBoxClass;
break;
case 1:
cls = MwButtonClass;
break;
case 2:
cls = MwCheckBoxClass;
break;
case 3:
cls = MwComboBoxClass;
break;
case 4:
cls = MwEntryClass;
break;
case 5:
cls = MwFrameClass;
break;
case 6:
cls = MwImageClass;
break;
case 7:
cls = MwLabelClass;
break;
case 8:
cls = MwListBoxClass;
break;
case 9:
cls = MwMenuClass;
break;
case 10:
cls = MwNumberEntryClass;
break;
case 12:
cls = MwProgressBarClass;
break;
case 13:
cls = MwRadioBoxClass;
break;
case 14:
cls = MwScrollBarClass;
break;
case 15:
cls = MwSeparatorClass;
break;
// case 16:
// cls = MwSubMenuClass;
// break;
case 17:
cls = MwTreeViewClass;
break;
case 18:
cls = MwViewportClass;
break;
default:
cls = NULL;
break;
}
if(cls) {
widget = MwCreateWidget(cls, "Cls", window, 0, 0, 100, 100);
}
if(MwPending(window)) {
MwStep(window);
}
if(cls) {
MwDestroyWidget(widget);
}
}
}