From 2d3bd9213ed5e4f57b1da8396eb453546e1c3bf1 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 9 Jan 2026 14:43:44 -0700 Subject: [PATCH] appkit --- .gitignore | 1 + Makefile.pl | 65 +++++++---- include/Mw/LowLevel.h | 13 +++ include/Mw/LowLevel/AppKit.h | 27 +++++ include/Mw/MachDep.h | 7 +- pl/ostype/Darwin.pl | 8 ++ pl/ostype/Linux.pl | 2 +- pl/rules.pl | 7 ++ pl/utils.pl | 6 +- src/abstract/dynamic.c | 2 +- src/abstract/time.c | 32 +++++- src/backend/appkit.m | 214 +++++++++++++++++++++++++++++++++++ src/lowlevel.c | 87 ++++++++------ 13 files changed, 402 insertions(+), 69 deletions(-) create mode 100644 include/Mw/LowLevel/AppKit.h create mode 100644 pl/ostype/Darwin.pl create mode 100644 src/backend/appkit.m diff --git a/.gitignore b/.gitignore index 2ebdbc2..9b18b9c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ examples/*/*.exe *.so *.dll *.lib +*.dylib *.a /Makefile /build diff --git a/Makefile.pl b/Makefile.pl index 454fd79..cf5c554 100755 --- a/Makefile.pl +++ b/Makefile.pl @@ -18,7 +18,7 @@ our $cflags = "-fPIC -D_MILSKO"; our $libdir = ""; our $ldflags = ""; our $math = "-lm"; -our $shared = "-shared"; +our @shared = "-shared"; our @backends = (); our $library_prefix = "lib"; @@ -45,6 +45,7 @@ param_set("vulkan", 0); param_set("vulkan-string-helper", 1); param_set("shared", 1); param_set("static", 1); +param_set("examples", 1); my %features = ( "classic-theme" => "use classic theme", @@ -166,7 +167,7 @@ print(OUT "LIBDIR = ${libdir}\n"); print(OUT "LDFLAGS = ${ldflags}\n"); print(OUT "LIBS = ${math} ${libs}\n"); print(OUT "MATH = ${math}\n"); -print(OUT "SHARED = ${shared}\n"); +print(OUT "SHARED = @{shared}\n"); print(OUT "\n"); print(OUT ".PHONY: all format clean distclean lib examples install\n"); print(OUT "\n"); @@ -219,7 +220,13 @@ foreach my $l (@library_targets) { my $s = $l; my $o = $object_suffix; $o =~ s/\./\\\./g; - $s =~ s/$o$/.c/; + + if ($l =~ /appkit/) { + $s =~ s/$o$/.m/; + + } else { + $s =~ s/$o$/.c/; + } if ($l =~ /^external\//) { $warn = ""; @@ -230,34 +237,42 @@ foreach my $l (@library_targets) { } print(OUT "\n"); print(OUT "\n"); -print(OUT "examples: " . join(" ", @examples_targets) . "\n"); -print(OUT "\n"); -foreach my $l (@examples_targets) { - my $libs = ""; - my $s = $l; - my $o = $executable_suffix; - $o =~ s/\./\\\./g; - $s =~ s/$o$//; +if(param_get("examples")) { + print(OUT "examples: " . join(" ", @examples_targets) . "\n"); + print(OUT "\n"); + foreach my $l (@examples_targets) { + my $libs = ""; + my $s = $l; + my $o = $executable_suffix; + $o =~ s/\./\\\./g; + $s =~ s/$o$//; - if (defined($examples_libs{$l})) { - $libs = $examples_libs{$l}; - } + if (defined($examples_libs{$l})) { + $libs = $examples_libs{$l}; + } - print(OUT -"${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n" - ); - print(OUT -" \$(CC) -L src -Wl,-R./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" - ); - print(OUT "${s}${object_suffix}: ${s}.c\n"); - print(OUT - " \$(CC) -c \$\(INCDIR) -o ${s}${object_suffix} ${s}.c -lMw ${math}\n" - ); + print(OUT + "${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n" + ); + if (grep(/^appkit$/, @backends)) { + print(OUT + " \$(CC) -L./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" + ); + } else { + print(OUT + " \$(CC) -L src -Wl,-R./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" + ); + } + print(OUT "${s}${object_suffix}: ${s}.c\n"); + print(OUT + " \$(CC) -c \$\(INCDIR) -o ${s}${object_suffix} ${s}.c -lMw ${math}\n" + ); + } } print(OUT "\n"); print(OUT "clean:\n"); print(OUT -" rm -f */*.o */*/*.o */*/*/*.o */*.exe */*/*.exe */*/*/*.exe src/*.so src/*.dll src/*.a " +" rm -f */*.o */*/*.o */*/*/*.o */*.exe */*/*.exe */*/*/*.exe src/*.so src/*.dll src/*.dylib src/*.a " . join(" ", @examples_targets) . "\n"); print(OUT "\n"); diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index c748bf9..e3cf643 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -27,6 +27,7 @@ enum MwLLBackends { MwLLBackendX11 = 0, MwLLBackendGDI, MwLLBackendWayland, + MwLLBackendAppKit, }; struct _MwLLCommon { @@ -61,6 +62,9 @@ struct _MwLLCommonPixmap { #ifdef USE_WAYLAND #include #endif +#ifdef USE_APPKIT +#include +#endif union _MwLL { struct _MwLLCommon common; @@ -73,6 +77,9 @@ union _MwLL { #ifdef USE_WAYLAND struct _MwLLWayland wayland; #endif +#ifdef USE_APPKIT + struct _MwLLAppKit appkit; +#endif }; union _MwLLColor { @@ -86,6 +93,9 @@ union _MwLLColor { #ifdef USE_WAYLAND struct _MwLLWaylandColor wayland; #endif +#ifdef USE_APPKIT + struct _MwLLAppKitColor appkit; +#endif }; union _MwLLPixmap { @@ -99,6 +109,9 @@ union _MwLLPixmap { #ifdef USE_WAYLAND struct _MwLLWaylandPixmap wayland; #endif +#ifdef USE_APPKIT + struct _MwLLAppKitPixmap appkit; +#endif }; #endif #include diff --git a/include/Mw/LowLevel/AppKit.h b/include/Mw/LowLevel/AppKit.h new file mode 100644 index 0000000..985cf5f --- /dev/null +++ b/include/Mw/LowLevel/AppKit.h @@ -0,0 +1,27 @@ +/*! + * @file Mw/LowLevel/AppKit.h + * @brief Work in progress AppKit Backend + * @warning This is used internally. + */ +#ifndef __MW_LOWLEVEL_APPKIT_H__ +#define __MW_LOWLEVEL_APPKIT_H__ + +#include +#include +#include  + +MWDECL int MwLLAppKitCallInit(void); + +struct _MwLLAppKit { + struct _MwLLCommon common; +}; + +struct _MwLLAppKitColor { + struct _MwLLCommonColor common; +}; + +struct _MwLLAppKitPixmap { + struct _MwLLCommonPixmap common; +}; + +#endif diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 6eb37be..1fe1549 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -43,10 +43,15 @@ #include #include #include -#include +#include  #include #endif +#ifdef __APPLE__ +#include +#include +#endif + #ifndef M_PI #define M_PI 3.14159265 #endif diff --git a/pl/ostype/Darwin.pl b/pl/ostype/Darwin.pl new file mode 100644 index 0000000..675bd75 --- /dev/null +++ b/pl/ostype/Darwin.pl @@ -0,0 +1,8 @@ +$library_suffix = ".dylib"; +set_shared_flag("-dynamiclib"); + +use_backend("appkit"); + +add_cflags("-DSTBI_NO_THREAD_LOCALS"); + +1; \ No newline at end of file diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index 155cd4a..b7e074d 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -1,4 +1,4 @@ -if (param_get("experimental-wayland")) { +IF (param_get("experimental-wayland")) { use_backend("wayland", "x11"); } else { diff --git a/pl/rules.pl b/pl/rules.pl index f55fce3..2299e0d 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -46,6 +46,13 @@ if (grep(/^wayland$/, @backends)) { $gl_libs = "-lGL -lGLU"; } +if (grep(/^appkit$/, @backends)) { + add_cflags("-DUSE_APPKIT"); + new_object("src/backend/appkit.m"); + + $gl_libs = "-lGL -lGLU"; +} + if (param_get("stb-image")) { add_cflags("-DUSE_STB_IMAGE"); } diff --git a/pl/utils.pl b/pl/utils.pl index 971c196..264e679 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -40,10 +40,14 @@ sub new_example { push(@examples_targets, "${_[0]}${executable_suffix}"); } +sub set_shared_flag { + @shared = $_[0]; +} + sub new_object { my @l = glob($_[0]); foreach my $e (@l) { - $e =~ s/\.c$/$object_suffix/; + $e =~ s/\.(c|m)$/$object_suffix/; push(@library_targets, $e); } } diff --git a/src/abstract/dynamic.c b/src/abstract/dynamic.c index 7f56e0f..79cad83 100644 --- a/src/abstract/dynamic.c +++ b/src/abstract/dynamic.c @@ -12,7 +12,7 @@ void* MwDynamicSymbol(void* handle, const char* symbol) { void MwDynamicClose(void* handle) { FreeLibrary(handle); } -#elif defined(__unix__) +#elif defined(__unix__) || defined(__APPLE__) void* MwDynamicOpen(const char* path) { return dlopen(path, RTLD_LOCAL | RTLD_LAZY); } diff --git a/src/abstract/time.c b/src/abstract/time.c index 8c85d58..97e6fb3 100644 --- a/src/abstract/time.c +++ b/src/abstract/time.c @@ -1,23 +1,47 @@ -#include +#include  #if defined(_WIN32) long MwTimeGetTick(void) { - return GetTickCount(); + return GetTickCount(); } void MwTimeSleep(int ms) { Sleep(ms); } +#elif defined(__APPLE__) +long MwTimeGetTick(void) { + struct timespec ts; + long n = 0; + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + n += ts.tv_nsec / 1000 / 1000; + n += ts.tv_sec * 1000; + + return n; +} +void MwTimeSleep(int ms) { + struct timespec ts; + + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000 * 1000; + + nanosleep(&ts, NULL); +} #elif defined(__unix__) long MwTimeGetTick(void) { struct timespec ts; long n = 0; - + clock_gettime(CLOCK_MONOTONIC, &ts); n += ts.tv_nsec / 1000 / 1000; n += ts.tv_sec * 1000; - + return n; } diff --git a/src/backend/appkit.m b/src/backend/appkit.m new file mode 100644 index 0000000..772f33a --- /dev/null +++ b/src/backend/appkit.m @@ -0,0 +1,214 @@ +#include  + +#include "../../external/stb_ds.h" + +static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + MwLL r; + (void)x; + (void)y; + (void)width; + (void)height; + + r = malloc(sizeof(*r)); + + + MwLLCreateCommon(r); + + return r; +} + +static void MwLLDestroyImpl(MwLL handle) { + MwLLDestroyCommon(handle); + + free(handle); +} + +static void MwLLBeginDrawImpl(MwLL handle) { + (void)handle; +} + +static void MwLLEndDrawImpl(MwLL handle) { + (void)handle; +} + +static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { + (void)points; + (void)points_count; + (void)color; +} + +static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + (void)handle; + (void)points; + (void)color; +} + +static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { + MwLLColor c = malloc(sizeof(*c)); + MwLLColorUpdate(handle, c, r, g, b); + return c; +} + +static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { + (void)handle; + + c->common.red = r; + c->common.green = g; + c->common.blue = b; +} + +static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { + *x = 0; + *y = 0; + *w = 0; + *h = 0; +} + +static void MwLLSetXYImpl(MwLL handle, int x, int y) { + (void)handle; + (void)x; + (void)y; +} + +static void MwLLSetWHImpl(MwLL handle, int w, int h) { + (void)handle; + (void)w; + (void)h; +} + +static void MwLLFreeColorImpl(MwLLColor color) { + free(color); +} + +static int MwLLPendingImpl(MwLL handle) { + (void)handle; + return 0; +} + +static void MwLLNextEventImpl(MwLL handle) { + (void)handle; +} + +static void MwLLSetTitleImpl(MwLL handle, const char* title) { + (void)title; + (void)handle; +} + +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { + (void)handle; + + MwLLPixmap r = malloc(sizeof(*r)); + + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); + + r->common.width = width; + r->common.height = height; + + MwLLPixmapUpdate(r); + return r; +} + +static void MwLLPixmapUpdateImpl(MwLLPixmap r) { + (void)r; +} + +static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap); +} + +static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + (void)handle; + (void)rect; + (void)pixmap; +} + +static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { + (void)handle; + (void)pixmap; +} + +static void MwLLForceRenderImpl(MwLL handle) { + (void)handle; +} + +static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { + (void)handle; + (void)image; + (void)mask; +} + +static void MwLLDetachImpl(MwLL handle, MwPoint* point) { + (void)handle; + (void)point; +} + +static void MwLLShowImpl(MwLL handle, int show) { + (void)handle; + (void)show; +} + +static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { + (void)handle; + (void)parent; +} + +static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { + (void)handle; + (void)minx; + (void)miny; + (void)maxx; + (void)maxy; +} + +static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { + (void)handle; + (void)toggle; +} + +static void MwLLFocusImpl(MwLL handle) { + (void)handle; +} + +static void MwLLGrabPointerImpl(MwLL handle, int toggle) { + (void)handle; + (void)toggle; +} + +static void MwLLSetClipboardImpl(MwLL handle, const char* text) { + (void)handle; + (void)text; +} + +static void MwLLGetClipboardImpl(MwLL handle) { + (void)handle; +} + +static void MwLLMakeToolWindowImpl(MwLL handle) { + (void)handle; +} + +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { + (void)handle; + (void)point; +} + +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { + (void)handle; + (void)rect; +} + +static void MwLLBeginStateChangeImpl(MwLL handle) { + MwLLShow(handle, 0); +} + +static void MwLLEndStateChangeImpl(MwLL handle) { + MwLLShow(handle, 1); +} + +static int AppKit(void) { + return 0; +} + +#include "call.c" +CALL(AppKit); diff --git a/src/lowlevel.c b/src/lowlevel.c index 30037c8..c3a20c4 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -1,55 +1,70 @@ #include -MwLL (*MwLLCreate)(MwLL parent, int x, int y, int width, int height); -void (*MwLLDestroy)(MwLL handle); +/* Older GCC doesn't like this part of the code because of common sections. + What are common sections? This question is so obscure and unknown + that newer GCC actually compiles with -fno-common by default because + not enough people ever figured this out. But when compiling under + older Mac OS X. specifically the gcc that comes with tigerbrew (this + has not yet been tried under XCode 10.5), this comes up. Furthermore, + adding -fno-common to either the cflags or ldflags doesn't seem to fix this. + But what does fix it is using GNU attributes. So...yeah, sure, we'll just do + this.*/ +#ifdef __APPLE__ +#define NOCOMMON __attribute__((nocommon)) +#else +#define NOCOMMON +#endif -void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color); -void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color); +NOCOMMON MwLL (*MwLLCreate)(MwLL parent, int x, int y, int width, int height); +NOCOMMON void (*MwLLDestroy)(MwLL handle); -void (*MwLLBeginDraw)(MwLL handle); -void (*MwLLEndDraw)(MwLL handle); +NOCOMMON void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color); +NOCOMMON void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color); -MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); -void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b); -void (*MwLLFreeColor)(MwLLColor color); +NOCOMMON void (*MwLLBeginDraw)(MwLL handle); +NOCOMMON void (*MwLLEndDraw)(MwLL handle); -void (*MwLLGetXYWH)(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h); -void (*MwLLSetXY)(MwLL handle, int x, int y); -void (*MwLLSetWH)(MwLL handle, int w, int h); +NOCOMMON MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); +NOCOMMON void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b); +NOCOMMON void (*MwLLFreeColor)(MwLLColor color); -void (*MwLLSetTitle)(MwLL handle, const char* title); +NOCOMMON void (*MwLLGetXYWH)(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h); +NOCOMMON void (*MwLLSetXY)(MwLL handle, int x, int y); +NOCOMMON void (*MwLLSetWH)(MwLL handle, int w, int h); -int (*MwLLPending)(MwLL handle); -void (*MwLLNextEvent)(MwLL handle); +NOCOMMON void (*MwLLSetTitle)(MwLL handle, const char* title); -MwLLPixmap (*MwLLCreatePixmap)(MwLL handle, unsigned char* data, int width, int height); -void (*MwLLPixmapUpdate)(MwLLPixmap pixmap); -void (*MwLLDestroyPixmap)(MwLLPixmap pixmap); -void (*MwLLDrawPixmap)(MwLL handle, MwRect* rect, MwLLPixmap pixmap); -void (*MwLLSetIcon)(MwLL handle, MwLLPixmap pixmap); +NOCOMMON int (*MwLLPending)(MwLL handle); +NOCOMMON void (*MwLLNextEvent)(MwLL handle); -void (*MwLLForceRender)(MwLL handle); +NOCOMMON MwLLPixmap (*MwLLCreatePixmap)(MwLL handle, unsigned char* data, int width, int height); +NOCOMMON void (*MwLLPixmapUpdate)(MwLLPixmap pixmap); +NOCOMMON void (*MwLLDestroyPixmap)(MwLLPixmap pixmap); +NOCOMMON void (*MwLLDrawPixmap)(MwLL handle, MwRect* rect, MwLLPixmap pixmap); +NOCOMMON void (*MwLLSetIcon)(MwLL handle, MwLLPixmap pixmap); -void (*MwLLSetCursor)(MwLL handle, MwCursor* image, MwCursor* mask); -void (*MwLLDetach)(MwLL handle, MwPoint* point); -void (*MwLLShow)(MwLL handle, int show); +NOCOMMON void (*MwLLForceRender)(MwLL handle); -void (*MwLLSetSizeHints)(MwLL handle, int minx, int miny, int maxx, int maxy); -void (*MwLLMakeBorderless)(MwLL handle, int toggle); -void (*MwLLMakeToolWindow)(MwLL handle); -void (*MwLLMakePopup)(MwLL handle, MwLL parent); +NOCOMMON void (*MwLLSetCursor)(MwLL handle, MwCursor* image, MwCursor* mask); +NOCOMMON void (*MwLLDetach)(MwLL handle, MwPoint* point); +NOCOMMON void (*MwLLShow)(MwLL handle, int show); -void (*MwLLBeginStateChange)(MwLL handle); -void (*MwLLEndStateChange)(MwLL handle); +NOCOMMON void (*MwLLSetSizeHints)(MwLL handle, int minx, int miny, int maxx, int maxy); +NOCOMMON void (*MwLLMakeBorderless)(MwLL handle, int toggle); +NOCOMMON void (*MwLLMakeToolWindow)(MwLL handle); +NOCOMMON void (*MwLLMakePopup)(MwLL handle, MwLL parent); -void (*MwLLFocus)(MwLL handle); -void (*MwLLGrabPointer)(MwLL handle, int toggle); +NOCOMMON void (*MwLLBeginStateChange)(MwLL handle); +NOCOMMON void (*MwLLEndStateChange)(MwLL handle); -void (*MwLLSetClipboard)(MwLL handle, const char* text); -void (*MwLLGetClipboard)(MwLL handle); +NOCOMMON void (*MwLLFocus)(MwLL handle); +NOCOMMON void (*MwLLGrabPointer)(MwLL handle, int toggle); -void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); -void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); +NOCOMMON void (*MwLLSetClipboard)(MwLL handle, const char* text); +NOCOMMON void (*MwLLGetClipboard)(MwLL handle); + +NOCOMMON void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); +NOCOMMON void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); void MwLLCreateCommon(MwLL handle) { handle->common.handler = malloc(sizeof(*handle->common.handler));